|
| 1 | +#!/usr/bin/env bash |
| 2 | +# |
| 3 | +# Test whether a failing bazel `_test` is a yosys-environment false |
| 4 | +# positive or a real bazel-vs-make OpenROAD divergence. |
| 5 | +# |
| 6 | +# Usage: bazelisk run //:yosys-check //flow/designs/<plat>/<design>:<n>_test |
| 7 | +# |
| 8 | +# Yosys is sensitive to its build environment (abc version, cxxopts |
| 9 | +# version, compile flags), so bazel-built yosys and make-built yosys |
| 10 | +# produce different `1_2_yosys.v` for the same RTL. Different netlists |
| 11 | +# then push QoR metrics around enough to break rules-base.json |
| 12 | +# thresholds even when OpenROAD is behaving identically. This wrapper |
| 13 | +# feeds bazel's pre-built netlist into a fresh make-flow run (via |
| 14 | +# SYNTH_NETLIST_FILES) and SHA-compares .odb at every stage: |
| 15 | +# |
| 16 | +# all MATCH -> yosys-only false positive, ignore. |
| 17 | +# any DIFFER -> real bazel-vs-make OpenROAD divergence, investigate. |
| 18 | + |
| 19 | +set -e -u -o pipefail |
| 20 | + |
| 21 | +if [[ $# -ne 1 ]]; then |
| 22 | + echo "usage: bazelisk run //:yosys-check <test-label>" >&2 |
| 23 | + echo " e.g. bazelisk run //:yosys-check //flow/designs/asap7/uart:uart_test" >&2 |
| 24 | + exit 2 |
| 25 | +fi |
| 26 | + |
| 27 | +cd "${BUILD_WORKSPACE_DIRECTORY:?must be invoked via bazelisk run}" |
| 28 | + |
| 29 | +LABEL="$1" |
| 30 | + |
| 31 | +# Parse //flow/designs/<plat>/<design>:<name>_test |
| 32 | +case "$LABEL" in |
| 33 | + //flow/designs/*/*:*_test) ;; |
| 34 | + *) |
| 35 | + echo "yosys-check: expected //flow/designs/<plat>/<design>:<name>_test, got $LABEL" >&2 |
| 36 | + exit 2 |
| 37 | + ;; |
| 38 | +esac |
| 39 | + |
| 40 | +PKG="${LABEL#//}"; PKG="${PKG%:*}" # flow/designs/asap7/uart |
| 41 | +NAME="${LABEL##*:}" # uart_test |
| 42 | +DESIGN_DIR="${PKG#flow/designs/}" # asap7/uart |
| 43 | +PLAT="${DESIGN_DIR%%/*}" # asap7 |
| 44 | +DESIGN="${DESIGN_DIR#*/}" # uart |
| 45 | +SYNTH_TARGET="//$PKG:${NAME%_test}_synth" |
| 46 | + |
| 47 | +# bazel-orfs and classic make disagree on which design-config var to |
| 48 | +# put in the results path: bazel uses DESIGN_NAME (the module/top), |
| 49 | +# make uses DESIGN_NICKNAME (the user-friendly tag). For most designs |
| 50 | +# they're equal; aes-block is the canonical exception |
| 51 | +# (DESIGN_NAME=aes_cipher_top vs DESIGN_NICKNAME=aes-block). |
| 52 | +echo "==> Building $SYNTH_TARGET (need bazel's 1_2_yosys.v and the results subdir)" |
| 53 | +SYNTH_TARGET="//$PKG:${NAME%_test}_synth" |
| 54 | +bazelisk build "$SYNTH_TARGET" |
| 55 | + |
| 56 | +# Bazel side: glob the single subdir under bazel-bin/<pkg>/results/<plat>/. |
| 57 | +BAZEL_PLAT_DIR="bazel-bin/$PKG/results/$PLAT" |
| 58 | +BAZEL_NICK=$(basename "$(ls -d "$BAZEL_PLAT_DIR"/*/ 2>/dev/null | head -1)" 2>/dev/null) |
| 59 | +BAZEL_NICK="${BAZEL_NICK:-$DESIGN}" |
| 60 | + |
| 61 | +# Make side: parse DESIGN_NICKNAME out of the design's config.mk. |
| 62 | +MAKE_NICK=$(awk ' |
| 63 | + /^[[:space:]]*export[[:space:]]+DESIGN_NICKNAME[[:space:]]*=/ { |
| 64 | + n = index($0, "="); v = substr($0, n + 1) |
| 65 | + gsub(/^[[:space:]]+|[[:space:]]+$/, "", v); print v; exit |
| 66 | + } |
| 67 | +' "flow/designs/$PLAT/$DESIGN/config.mk") |
| 68 | +MAKE_NICK="${MAKE_NICK:-$DESIGN}" |
| 69 | +echo "==> bazel subdir=$BAZEL_NICK make subdir=$MAKE_NICK" |
| 70 | + |
| 71 | +BAZEL_RES="bazel-bin/$PKG/results/$PLAT/$BAZEL_NICK/base" |
| 72 | +MAKE_RES="flow/results/$PLAT/$MAKE_NICK/base" |
| 73 | + |
| 74 | +echo "==> Building $LABEL (so we have bazel's downstream .odb to compare)" |
| 75 | +bazelisk build "$LABEL" |
| 76 | + |
| 77 | +echo "==> Installing OpenROAD into tools/install/ (idempotent)" |
| 78 | +( cd tools/OpenROAD && bazelisk run //:install ) |
| 79 | + |
| 80 | +BAZEL_NETLIST_RO="$(pwd)/$BAZEL_RES/1_2_yosys.v" |
| 81 | +if [[ ! -f "$BAZEL_NETLIST_RO" ]]; then |
| 82 | + echo "yosys-check: bazel netlist not at $BAZEL_NETLIST_RO" >&2 |
| 83 | + exit 1 |
| 84 | +fi |
| 85 | + |
| 86 | +# synth_preamble.tcl copies SYNTH_NETLIST_FILES with `cp -p`, which |
| 87 | +# carries over the source's perms. bazel-out files are read-only, so |
| 88 | +# the second copy (do-yosys after do-yosys-canonicalize) hits |
| 89 | +# "Permission denied" on the read-only destination. Stage the netlist |
| 90 | +# in a writable temp path so both copies succeed. |
| 91 | +BAZEL_NETLIST="$(mktemp --suffix=-1_2_yosys.v)" |
| 92 | +trap 'rm -f "$BAZEL_NETLIST"' EXIT |
| 93 | +cp --no-preserve=mode "$BAZEL_NETLIST_RO" "$BAZEL_NETLIST" |
| 94 | + |
| 95 | +echo "==> make clean_all + metadata with bazel netlist (SYNTH_NETLIST_FILES)" |
| 96 | +# Run make in a subshell that tolerates non-zero exit codes — metadata-check |
| 97 | +# may fail on QoR thresholds even when the .odb stages are bit-identical to |
| 98 | +# bazel. We only care about SHA equivalence; the QoR comparison is bazel's |
| 99 | +# `_test` job, and the whole point of yosys-check is to look past that. |
| 100 | +( cd flow \ |
| 101 | + && make clean_all DESIGN_CONFIG="designs/$PLAT/$DESIGN/config.mk" ) || true |
| 102 | +( cd flow \ |
| 103 | + && make metadata DESIGN_CONFIG="designs/$PLAT/$DESIGN/config.mk" \ |
| 104 | + SYNTH_NETLIST_FILES="$BAZEL_NETLIST" ) || true |
| 105 | + |
| 106 | +echo "" |
| 107 | +echo "==> .odb SHA matrix (bazel vs make, same netlist)" |
| 108 | +printf '%-22s %-18s %-18s %s\n' stage bazel make outcome |
| 109 | +all_match=1 |
| 110 | +for f in 1_synth.odb 2_floorplan.odb 3_place.odb 4_cts.odb \ |
| 111 | + 5_1_grt.odb 5_route.odb 6_final.odb; do |
| 112 | + bs=$(sha256sum "$BAZEL_RES/$f" 2>/dev/null | cut -c1-16 || true) |
| 113 | + ms=$(sha256sum "$MAKE_RES/$f" 2>/dev/null | cut -c1-16 || true) |
| 114 | + if [[ -n "$bs" && "$bs" == "$ms" ]]; then |
| 115 | + tag=MATCH |
| 116 | + elif [[ -z "$bs" && -z "$ms" ]]; then |
| 117 | + tag=skip |
| 118 | + else |
| 119 | + tag=DIFFER |
| 120 | + all_match=0 |
| 121 | + fi |
| 122 | + printf '%-22s %-18s %-18s %s\n' "$f" "${bs:--}" "${ms:--}" "$tag" |
| 123 | +done |
| 124 | + |
| 125 | +echo "" |
| 126 | +if [[ $all_match -eq 1 ]]; then |
| 127 | + echo "yosys-check: all stages MATCH -> bazel _test failure (if any) is a" |
| 128 | + echo " yosys-environment false positive; OpenROAD is deterministic." |
| 129 | + exit 0 |
| 130 | +else |
| 131 | + echo "yosys-check: some stages DIFFER -> bazel-vs-make OpenROAD divergence." |
| 132 | + echo " Investigate compile flags, abc version, etc." |
| 133 | + exit 1 |
| 134 | +fi |
0 commit comments