Repository navigation
Conversation
There was a problem hiding this comment.
Code Review
This pull request simplifies the handling of SDC (Synopsys Design Constraints) files throughout the physical design flow. It refactors the build system and TCL scripts to automatically associate each ODB design file with its corresponding SDC file using a new sdc_file_of utility. This change removes the need to explicitly pass, track, and copy SDC files as separate dependencies in the Makefile and as separate arguments in load_design and other helper procedures. I have no feedback to provide as there are no review comments to assess.
Every step that writes N.odb writes N.sdc beside it, and every step reads the .sdc beside the .odb it loads. Before synthesis the .sdc is the user's (1_2_yosys.sdc); from 1_synth on, every .odb has its own. This deletes find_sdc_file, which picked an .sdc by name order and gave open_*/gui_* another stage's constraints for a .def or a failed .odb; the second argument of load_design, which named by hand which earlier step's .sdc a script borrowed; the separate orfs_write_sdc and flow_write_sdc calls, now part of orfs_write_db, orfs_copy_db and flow_write_db; and every .sdc rule and prerequisite in the Makefile except the user's, since a step's input .odb comes with its .sdc. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
🔍 QoR checkMetrics reflect the PR merge build — i.e. what will land on the target branch. Commit 62 design(s) checked — 0 with regression(s), 0 without a comparable baseline. |
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
maliberty
left a comment
There was a problem hiding this comment.
Nice simplification; the description holds up against the diff. All in-repo load_design callers are updated, find_sdc_file is fully gone, and every skip path goes through orfs_copy_db, which now carries the .sdc. Checked against docs/contrib/MakefileContract.md and docs/contrib/TclContract.md:
1. The .sdc a step reads is not declared to make (MakefileContract: "a step never reads a file it does not declare"). After this PR the only .sdc with a rule is 1_2_yosys.sdc; every step reads X.sdc but depends only on X.odb. Consequences:
- An existing results tree (built before this PR) has no
3_3_place_gp.sdcetc. Rerunning a single step there (config change,make do-3_4_place_resized) fails atread_sdc, and make will not rebuild the missing.sdcbecause the.odbis up to date. Users need a clean. - A deleted
.sdcis never regenerated, andmake $(RESULTS_DIR)/3_place.sdchas no rule.
Suggestion: make the pair a grouped target in do-step and do-copy, e.g. $(RESULTS_DIR)/$(1).odb $(RESULTS_DIR)/$(1).sdc &: $(2). The Makefile already uses &: in GENERATE_ABSTRACT_RULE, so no new make version requirement.
2. Write order. orfs_write_db, orfs_copy_db and the do-copy recipe write the .odb first, then the .sdc, and there is no .DELETE_ON_ERROR. If the .sdc write/copy fails, the .odb is fresh, make considers the step done, and the failure surfaces one step later as a read_sdc error. Writing the .sdc first makes the declared target the last file written.
3. Unmentioned behavior change. synth_metrics.tcl (make synth-report) now reads 1_2_yosys.sdc (the user's raw copy) instead of the canonicalized 1_synth.sdc. Probably equivalent, since synth_odb.tcl reads the same file, but per the TclContract ("a refactor never changes behavior") it belongs in the description next to the open.tcl changes.
4. open.tcl without the SDC_FILE fallback. Stated in the description, but one case not listed: make open_1_synth_lec.v GUI_TIMING=1 now looks for 1_synth_lec.sdc, which is never written (before, it found 1_synth.sdc). Fine under "no fallback" if intended.
5. Nit: docs/contrib/TclContract.md:30 still says a result is written "with orfs_write_db and orfs_write_sdc". orfs_write_db now writes the pair and orfs_write_sdc is only used inside it and by write_ref_sdc.tcl; worth updating in this PR.
6. Nit: failure paths differ. global_route.tcl writes 5_1_grt-failed.odb/.sdc with raw write_db/write_sdc, while pdn.tcl writes 2_4_floorplan_pdn-failed.odb via orfs_write_db (endpoint slack, gated by WRITE_ODB_AND_SDC_EACH_STAGE). Pre-existing, but the line is touched here.
7. Merge order. bazel-orfs must declare the new per-step .sdc outputs; the PR only references the closed bazel-orfs#1418. The bazel-orfs side should be ready to land together with this.
do-step (for .odb results) and do-copy declare the pair as one grouped target, X.odb X.sdc &: deps, and 6_final.odb/6_final.sdc depend on 6_report.log again. A missing .sdc now reruns the step that writes it; a do- target still runs on what is in the tree and stops at read_sdc. orfs_write_db, orfs_copy_db, flow_write_db and do-copy write the .sdc before the .odb, so the target make tracks is the last file written. TclContract: orfs_write_db writes the .odb and its .sdc. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
|
Addressed in f8fac4c:
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com> # Conflicts: # flow/scripts/global_route.tcl
|
@maliberty Good to go? merge w master. |
Every step that writes
N.odbnow writesN.sdcbeside it, and every step reads the.sdcbeside the.odbit loads. The name of the.odbis the name of its constraints; nothing is inferred. Before synthesis the.sdcis the user's (1_2_yosys.sdc, a copy ofSDC_FILE); from1_synthon, every.odbhas its own.This follows the direction in The-OpenROAD-Project/OpenROAD#11260: carry the
write_sdcoutput as text and read it back withread_sdc, the well-established path. No OpenROAD change is needed.27 files, +88/−164.
Deleted
find_sdc_file: the glob ofRESULTS_DIR, the reverse dictionary sort and "the greatest.sdcat or below this.odb's stem".open.tclandgenerate_abstract.tclread the.sdcwith the same stem.load_design, at 21 call sites, each naming by hand which earlier step's.sdcit borrows.orfs_write_sdccalls in the stage scripts:orfs_write_dbwrites the pair,orfs_copy_dbcopies the pair.flow_write_sdcand its 9 calls inflow.tcl:flow_write_dbwrites the pair..sdcbut the user's: five empty-recipeX.sdc: X.odbrules, the three.sdcdo-copyrules and do-copy's extension parameter,do-2_floorplan.sdc,do-5_route.sdcanddo-6_1_fill.sdcin the stage recipes, and the.sdcprerequisites of the steps and stage targets. A step depends on its input.odb, and the.odbcomes with its.sdc.Fixed by construction
Which
.sdca step read was written down twice, once in its script and once in its Makefile prerequisites, and the two had drifted:2_2_floorplan_macrodeclared1_synth.sdcandmacro_place.tclread2_1_floorplan.sdc. Now there is nothing to write down.find_sdc_filepicked by name order, soopen_*/gui_*could pick a different stage's constraints:.sdcread before.sdcread now6_final.def6_1_fill.sdc6_final.sdc5_1_grt-failed.odb4_cts.sdc5_1_grt-failed.sdcThe stem ends at the first dot of the file name, so
4_cts.odb,4_cts.odb.defand4_cts.odb.vall open with4_cts.sdc.load_designandopen.tclstop atread_sdcwhen the.sdcbeside the input is missing; there is no fallback to search for.open.tclreads the.sdconly withGUI_TIMING=1, as before.Two reads change with it:
synth-report(synth_metrics.tcl) reads1_2_yosys.sdc, the.sdcof the1_2_yosys.vit loads, instead of1_synth.sdc;synth_odb.tclreads the same file.make open_1_synth_lec.v GUI_TIMING=1stops atread_sdc:1_synth_lec.vhas no.sdcof its own. Before, it found1_synth.sdc.In the Makefile, a step's
.odband.sdcare one grouped target (X.odb X.sdc &:), so a missing.sdcreruns the step that writes it. Every writer writes the.sdcfirst and the.odblast.Every substep opens on its own
make open_*,gui_*and any script that loads3_3_place_gp.odb, say, get exactly the constraints that step ran with. The Makefile Contract already says a step with nothing to do "copies its.odband.sdcthrough"; now every step does.Paves the way for FLOW_INPUT_VARIANT
FLOW_INPUT_VARIANT(#4475) names the variant a stage reads its inputs from, so stages are shared between variants without copying results: one synthesis and floorplan feeding many experiments. #4475 had to teachfind_sdc_fileto rank candidates across two directories, and each read site had to remember to search them. With the pair, a stage's input is one stem:load_designis the single read of both files, so reading another variant's results is one path in one place.Disk space
11 more
.sdcfiles per flow, each the size of the design's constraints. Measured onsky130hd/aes:.odbfiles2_floorplan,3_place,4_cts,5_route,6_1_fill).sdc.sdcfilesORFS and OpenROAD have chosen maintainability over disk space repeatedly, and the same holds here:
.odbcopies above give every stage the same interface, at 30% of the.odbbytes;.sdcnext to its.odbrather than copy a prior stage's;.odb), odb: write dbTable blocks field-major — 45% off the compressed .odb, no semantics changed OpenROAD#11328 (45% off the compressed.odb) and odb: let a user's ODB_CODEC reformat the .odb files OpenROAD writes OpenROAD#11524 (a codec hook) were closed, and the.odband its read path stayed simple;.odb, was closed in favour ofwrite_sdctext, which is what this pull request carries.For callers outside ORFS
load_designtakes one argument. A script that passes two stops at the call with Tcl'swrong # args.Testing
tclfmt/tclint0.7.0 clean.asap7/gcdthroughfinal,generate_abstract,generate_metadataand the floorplan estimate, built by bazel-orfs on top of the patches it carries, with and without this change: every stage's.odband.sdc(1_synthto6_final),6_final.v,gcd.lefandgcd_typ.libare byte-identical.6_final.spefdiffers only in its*DATEline..sdcfiles carry the constraints they replace:2_floorplan.sdc,3_place.sdcand5_route.sdcnow come from the last substep of their stage and are byte-identical to before.flow.tclfrom the yosys netlist to6_finalwithWRITE_ODB_AND_SDC_EACH_STAGE=0: all 20.odbfiles get their.sdc; within a stage every.sdcis identical, and the constraints change once, at CTS.make do-cts, thenopen_4_1_cts.odb,open_4_cts.odb.defandopen_4_cts.odb.vwithGUI_TIMING=1: each reads4_1_cts.sdcor4_cts.sdc.🤖 Generated with Claude Code