flow: test the single-OpenROAD-process flow against the staged flow#4338
flow: test the single-OpenROAD-process flow against the staged flow#4338oharboe wants to merge 3 commits into
Conversation
sv-lang (via tools/OpenROAD) pulls in rules_pycross, whose toolchain extension fails with "Unknown Python version: 3.8" (transitively registered via or-tools -> pybind11_abseil; 3.8 was dropped from rules_python 2.0.0's MINOR_MAPPING). tools/OpenROAD/MODULE.bazel already carries the pycross.configure_environments workaround, but the extension configuration is only honored in the root module, so any bazel analysis in this repository fails without mirroring it here. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
ORFS supports running all OpenROAD stages in a single OpenROAD process by sourcing the per-stage scripts into one Tcl script: load_design skips reloading when a design is already in memory, and KEEP_VARS=1 keeps variables across stages. floorplan_to_place.tcl uses this for floorplan through place; the PR The-OpenROAD-Project#4333 discussion noted the mechanism has no automated test coverage. Add scripts/flow.tcl, which runs floorplan through the final report in one process and mirrors the Makefile do-copy recipes so $RESULTS_DIR ends up with the same .odb/.sdc file set as the stage-per-process flow. Cover it with bazel tests on asap7/gcd: an orfs_run executes the whole flow off the synthesis result under FLOW_VARIANT=single, and per-stage sh_tests byte-compare the stage-boundary .odb/.sdc files against the regular per-stage flow targets, using tools/OpenROAD's existing check_same.sh. Equal bytes proves the single-process mode is equivalent to the per-stage flow, not merely that it runs to completion. bazelisk test //flow/designs/asap7/gcd:gcd_single_flow_test Findings on asap7/gcd, recorded in the BUILD file: - floorplan, place and cts are byte-identical between the two flows; those comparisons are enforced by the gcd_single_flow_test suite. - From grt on the flows diverge: the grt-stage repair_timing inserts one extra buffer (8 vs 7) when the process continues from in-memory CTS state instead of reloading 4_cts.odb, even though the 4_cts.odb/.sdc it starts from are byte-identical. The grt, route and final comparisons are kept as manual test targets so the gap stays measurable. The design's full argument dict rides along on the orfs_run because bazel-orfs scopes each stage config to that stage's variables, so the synth src config lacks the floorplan/place/cts variables the later stages need. SYNTH_USE_SYN is declared make-only (local_arguments): bazel-orfs's synth stage always runs the yosys flow and neither stages the Verilog sources nor sets VERILOG_FILES for the OpenROAD synthesis step, so the built-in synthesizer opt-in must not reach the bazel arguments (with it, bazelisk build :gcd_synth fails outright). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
There was a problem hiding this comment.
Code Review
This pull request introduces a single-process OpenROAD flow variant for the asap7/gcd design, allowing the entire flow to run within a single process. It adds flow.tcl to sequence the stages, updates the Bazel build configuration to run and test this single-process flow against the standard per-stage flow, and adds rules_pycross to MODULE.bazel to resolve a Python toolchain issue. The review feedback recommends replacing external exec cp calls with Tcl's native file copy -force command in both single_flow.tcl and flow.tcl for better portability and efficiency.
Address review feedback on the single-process flow test: - Use Tcl's built-in "file copy -force" instead of "exec cp" for the do-copy mirror steps. Nothing downstream relies on file dates, so cp's attribute preservation isn't needed. - Drop the "manual" tag from the grt/route/final comparisons and include them in the gcd_single_flow_test suite. These tests are not run in CI, and the point of the divergence (grt-stage repair_timing inserts one extra buffer from in-memory CTS state than from a byte-identical reloaded 4_cts.odb) is to be root-caused, not hidden. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a single-process OpenROAD flow for the asap7/gcd design, allowing the entire flow (from floorplan to finish) to run within a single process. It adds the necessary Bazel targets, Tcl scripts, and comparison tests to verify equivalence with the per-stage flow. The reviewer feedback recommends marking the known-divergent test stages (grt, route, and final) as manual and excluding them from the main test suite to prevent wildcard test failures.
| "odb", | ||
| ] | ||
| ], | ||
| tags = ["orfs"], |
There was a problem hiding this comment.
The grt, route, and final stages are known to diverge and are intended to be kept as manual test targets so they do not run and fail during wildcard test execution (e.g., bazel test //...). However, they are currently missing the manual tag. Adding the manual tag to these stages will prevent them from running automatically.
| tags = ["orfs"], | |
| tags = ["orfs"] + (["manual"] if stage in ["grt", "route", "final"] else []), |
| test_suite( | ||
| name = "gcd_single_flow_test", | ||
| tests = [ | ||
| ":gcd_single_flow_{}_test".format(stage) | ||
| for stage in SINGLE_FLOW_STAGES | ||
| ], | ||
| ) |
There was a problem hiding this comment.
The gcd_single_flow_test suite currently includes all stages, including the diverging grt, route, and final stages. This causes the test suite to fail. To ensure the test suite only runs and enforces the passing stages (floorplan, place, cts), we should exclude the manual/diverging stages from the suite.
| test_suite( | |
| name = "gcd_single_flow_test", | |
| tests = [ | |
| ":gcd_single_flow_{}_test".format(stage) | |
| for stage in SINGLE_FLOW_STAGES | |
| ], | |
| ) | |
| test_suite( | |
| name = "gcd_single_flow_test", | |
| tests = [ | |
| ":gcd_single_flow_{}_test".format(stage) | |
| for stage in SINGLE_FLOW_STAGES | |
| if stage not in ["grt", "route", "final"] | |
| ], | |
| ) |
TL;DR single invocation flow diverges from classic flow with multiple invocations. Merits further investigation.
ORFS supports running all OpenROAD stages in a single OpenROAD process by sourcing the per-stage scripts into one Tcl script:
load_designskips reloading when a design is already in memory, andKEEP_VARS=1keeps variables across stages.floorplan_to_place.tcluses this for floorplan through place; the #4333 discussion noted the mechanism has no automated test coverage. This adds that coverage.flow/scripts/flow.tclruns floorplan through the final report in one process and mirrors the Makefiledo-copyrecipes withexec cp, so$RESULTS_DIRends up with the same .odb/.sdc file set as the stage-per-process flow.Bazel test on asap7/gcd: an
orfs_runexecutes the whole flow off the synthesis result underFLOW_VARIANT=single, and per-stagesh_tests byte-compare the stage-boundary .odb/.sdc files against the regular per-stage flow targets, reusing tools/OpenROAD'scheck_same.sh. Equal bytes proves the single-process mode is equivalent to the per-stage flow, not merely that it runs to completion.Findings (recorded in the BUILD file)
gcd_single_flow_testsuite (verified locally: 3/3 pass).repair_timinginserts one extra buffer (8 vs 7 on gcd) when the process continues from the in-memory CTS state instead of reloading4_cts.odb— even though the4_cts.odb/.sdcit starts from are byte-identical and all.sdcfiles match through the whole flow. The grt/route/final comparisons are kept asmanualtest targets so the gap stays measurable; drop the tag once single-process equivalence holds through the flow.Notes
SYNTH_USE_SYNis declared make-only viadesign(local_arguments = ...): bazel-orfs's synth stage always runs the yosys flow and neither stages the Verilog sources nor setsVERILOG_FILESfor the OpenROAD synthesis step, so with the built-in-synthesizer opt-in (439740e) reaching the bazel arguments,bazelisk build :gcd_synthfails outright (sv_elaborate ... no input files).rules_pycrossPython 3.8 workaround into the root MODULE.bazel — extension configuration is root-honored only, and without it every bazel analysis in this repo fails with "Unknown Python version: 3.8".gcd_test(metadata-check) does not pass at master HEAD independently of this PR: withSYNTH_USE_SYN=1the bazel synth doesn't build at all, and with the yosys path the metadata aggregation at the current bazel-orfs pin lacks the synth-stage metrics (synth__design__instance__area__stdcelletc.).toolchains_llvmpin does not compile the gnulib-based tool deps (sed et al.) against very new glibc.🤖 Generated with Claude Code