|
| 1 | +load("@bazel-orfs//:openroad.bzl", "orfs_run") |
| 2 | +load("@orfs_designs//:designs.bzl", "DESIGNS") |
| 3 | +load("@rules_shell//shell:sh_test.bzl", "sh_test") |
1 | 4 | load("//flow/designs:design.bzl", "design") |
2 | 5 |
|
3 | | -design(config = "config.mk") |
| 6 | +# SYNTH_USE_SYN is make-only for now: bazel-orfs's synth stage always |
| 7 | +# runs the yosys flow and neither stages the Verilog sources nor sets |
| 8 | +# VERILOG_FILES for the OpenROAD synthesis step, so the built-in |
| 9 | +# synthesizer opt-in must not reach the bazel arguments. |
| 10 | +design( |
| 11 | + config = "config.mk", |
| 12 | + local_arguments = ["SYNTH_USE_SYN"], |
| 13 | +) |
| 14 | + |
| 15 | +# Stage-boundary .odb/.sdc stems shared by the normal per-stage flow |
| 16 | +# targets and the single-process flow below; the gcd_single_flow_test |
| 17 | +# suite compares each of these files pairwise between the two flows. |
| 18 | +SINGLE_FLOW_STAGES = { |
| 19 | + "synth": "1_synth", |
| 20 | + "floorplan": "2_floorplan", |
| 21 | + "place": "3_place", |
| 22 | + "cts": "4_cts", |
| 23 | + "grt": "5_1_grt", |
| 24 | + "route": "5_route", |
| 25 | + "final": "6_final", |
| 26 | +} |
| 27 | + |
| 28 | +# Substep files the single-process flow also writes, declared so the |
| 29 | +# action keeps them and a human can inspect them on failure. |
| 30 | +SINGLE_FLOW_EXTRA_OUTS = [ |
| 31 | + "2_1_floorplan.odb", |
| 32 | + "2_1_floorplan.sdc", |
| 33 | + "2_2_floorplan_macro.odb", |
| 34 | + "2_3_floorplan_tapcell.odb", |
| 35 | + "2_4_floorplan_pdn.odb", |
| 36 | + "3_1_place_gp_skip_io.odb", |
| 37 | + "3_2_place_iop.odb", |
| 38 | + "3_3_place_gp.odb", |
| 39 | + "3_4_place_resized.odb", |
| 40 | + "3_5_place_dp.odb", |
| 41 | + "4_1_cts.odb", |
| 42 | + "5_2_route.odb", |
| 43 | + "5_3_fillcell.odb", |
| 44 | + "6_1_fill.odb", |
| 45 | + "6_1_fill.sdc", |
| 46 | +] |
| 47 | + |
| 48 | +# The whole flow, yosys netlist through finish, as one Tcl script in a |
| 49 | +# single OpenROAD process (scripts/flow.tcl) with |
| 50 | +# WRITE_ODB_AND_SDC_EACH_STAGE=0: the stage scripts write no .odb/.sdc |
| 51 | +# files (flow.tcl errors if one does), the top level writes every file |
| 52 | +# the per-stage flow produces via explicit write_db/write_sdc. The |
| 53 | +# synth stage config only carries synth-scoped variables, so the |
| 54 | +# design's full argument set rides along; FLOW_VARIANT=single keeps the |
| 55 | +# output paths clear of the regular stage targets' declared outputs in |
| 56 | +# this package. |
| 57 | +orfs_run( |
| 58 | + name = "gcd_single_flow", |
| 59 | + src = ":gcd_synth", |
| 60 | + outs = [ |
| 61 | + "results/asap7/gcd/single/{}.{}".format(stem, ext) |
| 62 | + for stem in SINGLE_FLOW_STAGES.values() |
| 63 | + for ext in [ |
| 64 | + "odb", |
| 65 | + "sdc", |
| 66 | + ] |
| 67 | + ] + [ |
| 68 | + "results/asap7/gcd/single/" + name |
| 69 | + for name in SINGLE_FLOW_EXTRA_OUTS |
| 70 | + ], |
| 71 | + arguments = { |
| 72 | + k: v |
| 73 | + for k, v in DESIGNS["asap7/gcd"]["arguments"].items() |
| 74 | + if k != "SYNTH_USE_SYN" |
| 75 | + } | { |
| 76 | + "FLOW_VARIANT": "single", |
| 77 | + }, |
| 78 | + script = ":single_flow.tcl", |
| 79 | + variant = "single", |
| 80 | +) |
| 81 | + |
| 82 | +# Normal-flow stage outputs, one filegroup per compared file. |
| 83 | +[ |
| 84 | + filegroup( |
| 85 | + name = "gcd_base_{}_{}".format(stage, ext), |
| 86 | + srcs = [":gcd_" + stage], |
| 87 | + output_group = "{}.{}".format(stem, ext), |
| 88 | + ) |
| 89 | + for stage, stem in SINGLE_FLOW_STAGES.items() |
| 90 | + for ext in [ |
| 91 | + "odb", |
| 92 | + "sdc", |
| 93 | + ] |
| 94 | +] |
| 95 | + |
| 96 | +# Byte-compare each stage boundary's .odb/.sdc between the per-stage |
| 97 | +# flow and the single-process flow: equal files prove the |
| 98 | +# single-process mode is equivalent to the per-stage flow, not merely |
| 99 | +# that it runs to completion. check_same.sh takes file pairs: |
| 100 | +# file_a file_b ... (.sdc pair first: check_same.sh stops at a binary |
| 101 | +# diff, and the .sdc verdict should be reported before that). |
| 102 | +# |
| 103 | +# The synth through grt boundaries are byte-identical. The grt stage |
| 104 | +# used to diverge (an extra repair_timing buffer): STA endpoint state |
| 105 | +# for CTS dummy-load pins differed between a process that inserted them |
| 106 | +# and a process that read the same design from disk, and |
| 107 | +# resistance-aware global routing consumed the resulting bogus net |
| 108 | +# slacks — fixed by patches/openroad/0001-sta-register-new-instance- |
| 109 | +# pin-vertices-as-endpoints.patch. |
| 110 | +# |
| 111 | +# The route stage used to route differently in-process (net/instance |
| 112 | +# iteration order and via emission order in drt reflected the process |
| 113 | +# history) — fixed by patches/openroad/0002-drt-make-incremental- |
| 114 | +# design-updates-match-a-fresh-read.patch; the routed layout is now |
| 115 | +# identical (equal DEF). |
| 116 | +# |
| 117 | +# The route .odb byte difference was NOT an odb id/freelist issue |
| 118 | +# (free lists serialize and reload): the per-stage flow accumulated |
| 119 | +# stale block-terminal access points on every pin access rerun — fixed |
| 120 | +# by patches/openroad/0003-drt-do-not-duplicate-bterm-access-points. |
| 121 | +# patch; route is byte-identical now. |
| 122 | +# |
| 123 | +# The final stage used to diverge because the per-stage flow writes |
| 124 | +# 6_final.odb mid-final_report (before the RCX extraction reorders |
| 125 | +# every dbWire via odb orderWires) while this flow wrote at end of |
| 126 | +# script — resolved by splitting final_report.tcl around its write so |
| 127 | +# flow.tcl writes at the same point. All seven stage boundaries are |
| 128 | +# byte-identical between the two flows. |
| 129 | +[ |
| 130 | + sh_test( |
| 131 | + name = "gcd_single_flow_{}_test".format(stage), |
| 132 | + srcs = ["@openroad//test/orfs:check_same.sh"], |
| 133 | + args = [ |
| 134 | + arg |
| 135 | + for ext in [ |
| 136 | + "sdc", |
| 137 | + "odb", |
| 138 | + ] |
| 139 | + for arg in [ |
| 140 | + "$(location :gcd_base_{}_{})".format(stage, ext), |
| 141 | + "$(location :results/asap7/gcd/single/{}.{})".format(stem, ext), |
| 142 | + ] |
| 143 | + ], |
| 144 | + data = [ |
| 145 | + ":gcd_base_{}_{}".format(stage, ext) |
| 146 | + for ext in [ |
| 147 | + "sdc", |
| 148 | + "odb", |
| 149 | + ] |
| 150 | + ] + [ |
| 151 | + ":results/asap7/gcd/single/{}.{}".format(stem, ext) |
| 152 | + for ext in [ |
| 153 | + "sdc", |
| 154 | + "odb", |
| 155 | + ] |
| 156 | + ], |
| 157 | + tags = ["orfs"], |
| 158 | + ) |
| 159 | + for stage, stem in SINGLE_FLOW_STAGES.items() |
| 160 | +] |
| 161 | + |
| 162 | +test_suite( |
| 163 | + name = "gcd_single_flow_test", |
| 164 | + tests = [ |
| 165 | + ":gcd_single_flow_{}_test".format(stage) |
| 166 | + for stage in SINGLE_FLOW_STAGES |
| 167 | + ], |
| 168 | +) |
0 commit comments