flow: add OpenROAD built-in synth as _syn variant of every flat design#4253
flow: add OpenROAD built-in synth as _syn variant of every flat design#4253oharboe wants to merge 3 commits into
Conversation
Adds OpenROAD's integrated synthesizer (sv_elaborate + synthesize,
OpenROAD #10473) as a universal "_syn" variant of every flat
design driven by design() in flow/designs/design.bzl. Relocates
and generalises the throwaway smoke target from OpenROAD #10479,
which explicitly said the proper home for this was bazel-orfs /
ORFS, not OpenROAD's test tree.
Purely additive: no existing Makefile recipe, bazel rule, design,
or target's behaviour is altered. Pieces:
- flow/scripts/synth_syn.tcl (new) -- povik's driver. Reads
LEF/Liberty/SDC via the ORFS env vars and writes 1_synth.odb +
1_synth.sdc directly, bypassing the Yosys 1_2_yosys.v ->
synth_odb.tcl chain.
- flow/Makefile gains one new phony target do-syn-synth that
invokes openroad on synth_syn.tcl. No existing recipe touched.
- patches/bazel-orfs/0002-...patch adds a parallel
orfs_openroad_synth_rule + orfs_openroad_synth macro in
bazel-orfs. OrfsInfo shape matches orfs_synth_rule, so
orfs_flow(previous_stage = {"floorplan": ":<name>_syn_synth"})
chains downstream stages unchanged. Vendored here until the
integrated syn tool stabilises and this lands upstream.
- flow/designs/design.bzl -- design() now also emits the _syn
chain for every flat design via a DESIGNS lookup + helper.
Hierarchical designs (blocks non-empty) are skipped -- the
built-in synthesizer doesn't handle BLOCKS yet. All _syn
targets are tagged manual so bazel build //... is unaffected.
End state for every flat design:
bazelisk build //flow/designs/asap7/gcd:gcd_syn_synth # OpenROAD synth
bazelisk build //flow/designs/asap7/gcd:gcd_synth # Yosys (unchanged)
Co-Authored-By: Claude Opus 4.7 (1M context) <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 support for OpenROAD's integrated synthesizer as a parallel synthesis path. Key changes include a new Makefile target, a Tcl script for synthesis, and updates to the Bazel build logic to automatically generate a _syn variant for flat designs. Review feedback highlighted several opportunities to improve the robustness of the synth_syn.tcl script, such as adding guards for optional environment variables like DONT_USE_CELLS and SYNTH_SLANG_ARGS, improving path handling for include directories, and replacing design-specific hardcoding with generic configuration variables.
| read_lef $lef | ||
| } | ||
| } | ||
| set_dont_use $::env(DONT_USE_CELLS) |
There was a problem hiding this comment.
| } | ||
| } | ||
|
|
||
| lappend elaborate_args {*}$::env(SYNTH_SLANG_ARGS) |
| set vIdirsArgs "" | ||
| if { [env_var_exists_and_non_empty VERILOG_INCLUDE_DIRS] } { | ||
| foreach dir $::env(VERILOG_INCLUDE_DIRS) { | ||
| lappend vIdirsArgs "-I$dir" | ||
| } | ||
| set vIdirsArgs [join $vIdirsArgs] | ||
| } |
There was a problem hiding this comment.
Joining the list into a string and then using {*} to expand it later is redundant and can lead to issues if any directory paths contain spaces. It is better to keep vIdirsArgs as a list throughout.
set vIdirsArgs [list]
if { [env_var_exists_and_non_empty VERILOG_INCLUDE_DIRS] } {
foreach dir $::env(VERILOG_INCLUDE_DIRS) {
lappend vIdirsArgs "-I$dir"
}
}
| if {$::env(DESIGN_NAME) == "cva6"} { | ||
| syn::remove_ports rvfi_probes_o | ||
| } |
There was a problem hiding this comment.
Hardcoding design-specific logic like this reduces the maintainability and reusability of the script. Consider using a generic environment variable (e.g., SYNTH_REMOVE_PORTS) that can be set in the design's configuration (e.g., in cva6/config.mk).
if { [env_var_exists_and_non_empty SYNTH_REMOVE_PORTS] } {
syn::remove_ports $::env(SYNTH_REMOVE_PORTS)
}
Reformat with tclfmt 0.7.0 — normalize line endings, replace tab
indentation with two spaces, and add spaces inside the `if { ... }`
brace expression. Pure formatting; no behavior change. Fixes the
Tclint CI job on PR The-OpenROAD-Project#4253.
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Build vIdirsArgs with `[list]` + `lappend` and let `{*}` expand it
directly into elaborate_args. The previous code joined the list into
a space-separated string and re-expanded it, which would corrupt any
include directory path containing whitespace.
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
|
@povik Thoughts? You're listed as reviewer. I'll incorporate your feedback + merge with origin/master to fix conflicts in one go. |
|
@oharboe My plan was to control switching on syn with a variable so individual designs can opt in. |
Easy to add. Say the word. I propose that we always add it, but that they are tags = ["manual"] unless designs opt in. This will allow you to explicitly bazelisk test foo_syn_synth, but they are not run with bazelisk test ... |
|
If we merge this, then you can easily run all designs locally with a modified OpenROAD and only those designs that are ready are run in CI. ORFS bazelisk test ... needs to be wired up first in CI though. |
|
We need a solution independent of CI migrating to bazelisk, i.e. if one runs |
That's already supported in bazel-orfs here:
bazel-orfs also allows setting up a tmp folder with make, something like: Then: |
|
@povik I think you have everything you need here, but there's new stuff to learn, or if you have Claude it is able to figure out magic incantations from plain language for all your testing needs of openroad syn. If you have a fast workstation(local or remote) available to you, you can easily do sweeps of testing like "all asap7 designs that are not to big" or "designs that failed in last PR" |
|
I see but the CI will run without any bazelisk setup and I need to make it run syn on the designs with opt-in, hence why I'm asking if I should do a separate PR for that. |
Summary
Adds OpenROAD's integrated synthesizer (
sv_elaborate+synthesize,introduced by OpenROAD #10473)
as a universal
_synvariant of every flat design driven bydesign()inflow/designs/design.bzl. Relocates and generalisesthe throwaway smoke target from
OpenROAD #10479
— that PR explicitly said the proper home for this was
bazel-orfs / ORFS, not OpenROAD's test tree.
End state for every flat design (gcd, aes, ibex, jpeg, …):
Design
Purely additive. No existing Makefile recipe, bazel rule, design,
or target's behaviour is altered. The Yosys path stays exactly as it
is. Pieces:
flow/scripts/synth_syn.tcl(new) — povik's driver. ReadsLEF/Liberty/SDC via the ORFS env vars and writes
1_synth.odb+1_synth.sdcdirectly, bypassing the Yosys1_2_yosys.v→synth_odb.tclchain.flow/Makefile(new targetdo-syn-synth) — one phony recipe thatinvokes
$(OPENROAD_CMD) -no_init -exit $(SCRIPTS_DIR)/synth_syn.tcl.No existing recipe touched.
patches/bazel-orfs/0002-add-orfs_openroad_synth-…patch— parallelorfs_openroad_synth_rule+orfs_openroad_synthmacro inbazel-orfs. OrfsInfo shape matches
orfs_synth_rulesoorfs_flow(previous_stage = {"floorplan": ":<name>_syn_synth"})chains downstream stages unchanged. Vendored here until the
integrated syn tool stabilises and this lands upstream.
flow/designs/design.bzl—design()now also emits the_synchain for every flat design via a
DESIGNSlookup + helper.Hierarchical designs (
blocksnon-empty) are skipped — thebuilt-in synthesizer doesn't handle BLOCKS yet. All
_syntargets are tagged
manualsobazel build //...is unaffected.Test Plan
bazelisk build //flow/designs/asap7/gcd:gcd_syn_synth— runsOpenROAD on
synth_syn.tclviado-syn-synth; produces1_synth.odb+1_synth.sdcunder the_synvariant's resultsdir; log shows
sv_elaborate/synthesize/syn::stats.bazelisk build //flow/designs/asap7/gcd:gcd_synth— unchangedYosys path; no regression.
bazelisk build //flow/designs/asap7/gcd:gcd_syn_final—downstream
_syn_*stages chain from the syn-produced1_synth.odband reach6_final.gds.bazelisk build //...—manual-tagged_synvariants stayout of wildcard builds; pre-existing chains build as before.
Why this layout vs. PR 10479's
genrule + SYNTH_NETLIST_FILESPR 10479 used a genrule to produce a Verilog netlist and fed it
through the existing Yosys-aware
SYNTH_NETLIST_FILESescape hatch.That works for Verilog-emitting drivers like its
synthesize_gcd.tcl. povik'ssynth_syn.tclinstead writes1_synth.odbdirectly — so it slots in cleaner as a separate synthrule alongside
orfs_synth_rulerather than as a netlist feeder.Notes for follow-up
_syn_testbaselines to drift until #10473 stabilises. The
manualtagkeeps that drift out of routine CI.
support in the integrated synthesizer.
patches/bazel-orfs/0002-…patchand bumpBAZEL_ORFS_COMMIT.