Skip to content

Commit 8e388b9

Browse files
oharboeclaude
andcommitted
flow: add OpenROAD built-in synth as _syn variant of every flat design
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>
1 parent bd2a6b6 commit 8e388b9

5 files changed

Lines changed: 412 additions & 1 deletion

File tree

MODULE.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ git_override(
5252
patch_strip = 1,
5353
patches = [
5454
"//patches/bazel-orfs:0001-render_gds-monkey-patch-PDK_CONFIGS-not-gdsii_use_custom_config.patch",
55+
"//patches/bazel-orfs:0002-add-orfs_openroad_synth-rule-and-macro.patch",
5556
],
5657
remote = BAZEL_ORFS_REMOTE,
5758
)

flow/Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,18 @@ clean_synth:
283283
rm -f $(SYNTH_STATS)
284284
rm -f $(SDC_FILE_CLOCK_PERIOD)
285285

286+
# Run Synthesis using OpenROAD's integrated synthesizer (sv_elaborate +
287+
# synthesize, OpenROAD #10473). Drives `synth_syn.tcl`, which reads
288+
# LEF/Liberty/SDC straight from the ORFS env vars and writes 1_synth.odb
289+
# + 1_synth.sdc directly -- bypassing the Yosys + synth_odb chain. Used
290+
# by the bazel-orfs `orfs_openroad_synth_rule` for the `_syn` flow
291+
# variant. Independent of the Yosys recipes above; either path can run.
292+
.PHONY: do-syn-synth
293+
do-syn-synth:
294+
@mkdir -p $(RESULTS_DIR) $(LOG_DIR) $(REPORTS_DIR)
295+
$(RUN_CMD) --log $(abspath $(LOG_DIR)/1_synth.log) --tee -- \
296+
$(OPENROAD_CMD) $(SCRIPTS_DIR)/synth_syn.tcl
297+
286298
# ==============================================================================
287299
# _____ _ ___ ___ ____ ____ _ _ _ _
288300
# | ___| | / _ \ / _ \| _ \| _ \| | / \ | \ | |

flow/designs/design.bzl

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""BUILD boilerplate for flow/designs/."""
22

3-
load("@orfs_designs//:designs.bzl", "orfs_design")
3+
load("@bazel-orfs//:openroad.bzl", "orfs_flow", "orfs_openroad_synth")
4+
load("@orfs_designs//:designs.bzl", "DESIGNS", "orfs_design")
45

56
# Per filegroup target: extensions included in the filegroup.
67
# bazel-orfs's config_mk_parser produces these target names from
@@ -76,6 +77,7 @@ def design(config = "config.mk", user_arguments = [], user_sources = [], local_a
7677
local_arguments = local_arguments,
7778
blender = True,
7879
)
80+
_emit_syn_variant(DESIGNS.get(_design_key()))
7981

8082
def files(group, extra_srcs = None):
8183
"""Named filegroup over conventional extensions.
@@ -94,3 +96,60 @@ def files(group, extra_srcs = None):
9496
visibility = ["//visibility:public"],
9597
)
9698
_export_design_files()
99+
100+
def _design_key():
101+
"""Map this BUILD package to its DESIGNS key.
102+
103+
`native.package_name()` looks like `flow/designs/<platform>/<dir>`;
104+
the DESIGNS dict is keyed by `<platform>/<dir>` (bazel-orfs's
105+
config_mk_parser also indexes by directory name when it differs
106+
from the nickname). Returns "" for packages outside that layout
107+
so the lookup misses cleanly.
108+
"""
109+
parts = native.package_name().split("/")
110+
if len(parts) < 2:
111+
return ""
112+
return "{}/{}".format(parts[-2], parts[-1])
113+
114+
def _emit_syn_variant(entry):
115+
"""Emit the `_syn` variant chain for `entry` from DESIGNS.
116+
117+
Adds `<name>_syn_synth` (built-in OpenROAD synth, driven by
118+
flow/scripts/synth_syn.tcl) plus the downstream `_syn_*` chain
119+
via `orfs_flow(variant = "syn", previous_stage = {...})`.
120+
121+
No-op for hierarchical designs (`entry["blocks"]` non-empty); the
122+
built-in synthesizer doesn't handle BLOCKS yet and those would
123+
just fail. Flat designs pick the variant up for free.
124+
125+
All emitted targets are tagged `manual` so `bazel build //...`
126+
does not pick them up while the OpenROAD synth tool (PR #10473)
127+
matures.
128+
"""
129+
if entry == None or entry.get("blocks"):
130+
return
131+
name = entry["name"]
132+
pdk = "//flow:" + entry["platform"]
133+
syn_args = dict(entry["arguments"])
134+
syn_synth = name + "_syn_synth"
135+
orfs_openroad_synth(
136+
name = syn_synth,
137+
module_top = name,
138+
verilog_files = entry["verilog_files"],
139+
sources = entry["sources"],
140+
arguments = syn_args,
141+
pdk = pdk,
142+
variant = "syn",
143+
tags = ["manual"],
144+
)
145+
orfs_flow(
146+
name = name,
147+
variant = "syn",
148+
verilog_files = entry["verilog_files"],
149+
sources = entry["sources"],
150+
arguments = syn_args,
151+
pdk = pdk,
152+
previous_stage = {"floorplan": ":" + syn_synth},
153+
tags = ["manual"],
154+
test_kwargs = {"tags": ["orfs", "manual"]},
155+
)

flow/scripts/synth_syn.tcl

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
utl::set_metrics_stage "synthesis__{}"
2+
source $::env(SCRIPTS_DIR)/load.tcl
3+
erase_non_stage_variables synth
4+
5+
source_env_var_if_exists PLATFORM_TCL
6+
source $::env(SCRIPTS_DIR)/read_liberty.tcl
7+
8+
read_lef $::env(TECH_LEF)
9+
read_lef $::env(SC_LEF)
10+
if { [env_var_exists_and_non_empty ADDITIONAL_LEFS] } {
11+
foreach lef $::env(ADDITIONAL_LEFS) {
12+
read_lef $lef
13+
}
14+
}
15+
set_dont_use $::env(DONT_USE_CELLS)
16+
17+
# Setup verilog include directories
18+
set vIdirsArgs ""
19+
if { [env_var_exists_and_non_empty VERILOG_INCLUDE_DIRS] } {
20+
foreach dir $::env(VERILOG_INCLUDE_DIRS) {
21+
lappend vIdirsArgs "-I$dir"
22+
}
23+
set vIdirsArgs [join $vIdirsArgs]
24+
}
25+
26+
set elaborate_args [list \
27+
-D SYNTHESIS --compat=vcs --ignore-assertions --no-implicit-memories --top $::env(DESIGN_NAME) \
28+
{*}$vIdirsArgs {*}[env_var_or_empty VERILOG_DEFINES]]
29+
30+
lappend elaborate_args {*}$::env(VERILOG_FILES)
31+
32+
# Apply top-level parameters
33+
dict for {key value} [env_var_or_empty VERILOG_TOP_PARAMS] {
34+
lappend elaborate_args -G "$key=$value"
35+
}
36+
37+
# Apply module blackboxing based on module names as they appear
38+
# in the input, that is before any module name mangling done
39+
# by elaboration and synthesis
40+
if { [env_var_exists_and_non_empty SYNTH_BLACKBOXES] } {
41+
foreach m $::env(SYNTH_BLACKBOXES) {
42+
lappend elaborate_args --blackboxed-module "$m"
43+
}
44+
}
45+
46+
lappend elaborate_args {*}$::env(SYNTH_SLANG_ARGS)
47+
48+
# If the sources are solely .v files, enable Verilog compatibility
49+
set has_non_v_files false
50+
foreach fn $::env(VERILOG_FILES) {
51+
if { [file extension [string trim $fn]] != ".v" } {
52+
set has_non_v_files true
53+
}
54+
}
55+
if { !$has_non_v_files } {
56+
lappend elaborate_args --std=1364-2005
57+
}
58+
59+
sv_elaborate {*}$elaborate_args
60+
syn::stats
61+
62+
if {$::env(DESIGN_NAME) == "cva6"} {
63+
syn::remove_ports rvfi_probes_o
64+
}
65+
synthesize
66+
67+
read_sdc $::env(SDC_FILE)
68+
69+
orfs_write_db $::env(RESULTS_DIR)/1_synth.odb
70+
# Canonicalize 1_synth.sdc. The original SDC_FILE provided by
71+
# the user could have dependencies, such as sourcing util.tcl,
72+
# which are read in here and a canonicalized version is written
73+
# out by OpenSTA that has no dependencies.
74+
orfs_write_sdc $::env(RESULTS_DIR)/1_synth.sdc

0 commit comments

Comments
 (0)