Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion private/orfs_design.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def _convert_sources(sources, pkg):
result[var] = converted
return result

def orfs_design(name = None, platform = None, design = None, designs = None, mock_openroad = None, mock_yosys = None): # buildifier: disable=unused-variable
def orfs_design(name = None, platform = None, design = None, designs = None, mock_openroad = None, mock_yosys = None, user_arguments = []): # buildifier: disable=unused-variable
"""Create orfs_flow() targets for a design based on its parsed config.mk.

Call this from a design's BUILD.bazel:
Expand All @@ -66,6 +66,12 @@ def orfs_design(name = None, platform = None, design = None, designs = None, moc
mock_yosys: Label for mock-yosys binary. When set, lint flow uses
this instead of real Yosys for synthesis.
Example: "//mock/yosys/src/bin:yosys".
user_arguments: List of variable names from config.mk that are
project-specific (read by user-supplied .tcl/.mk, not by
ORFS itself, e.g. FP_PDN_RAIL_OFFSET in a custom pdn.cfg).
Routed through orfs_flow(user_arguments=...) to bypass the
variables.yaml validator instead of being checked as known
ORFS arguments.
"""
if designs == None:
fail("orfs_design() requires designs argument: pass DESIGNS from @orfs_designs//:designs.bzl")
Expand Down Expand Up @@ -158,6 +164,13 @@ def orfs_design(name = None, platform = None, design = None, designs = None, moc
# Real flow — uses Docker image with real OpenROAD/Yosys
arguments = dict(config["arguments"])

# Move caller-flagged design-specific knobs out of arguments and into
# user_arguments so they bypass the variables.yaml validator.
user_args = {}
for var in user_arguments:
if var in arguments:
user_args[var] = arguments.pop(var)

# Default SYNTH_NUM_PARTITIONS to a static value so that the action graph
# is identical across machines and remote cache hits are possible. Users
# who prefer local parallelism over caching can pass NUM_CPUS explicitly.
Expand All @@ -174,6 +187,7 @@ def orfs_design(name = None, platform = None, design = None, designs = None, moc
verilog_files = verilog_files,
pdk = "//flow:" + platform,
arguments = arguments,
user_arguments = user_args,
sources = sources,
macros = macros if macros else [],
stage_data = {"synth": extra_data} if extra_data else {},
Expand Down
29 changes: 26 additions & 3 deletions private/stages.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,31 @@ load("//private:utils.bzl", "flatten", "set", "union")
# A stage argument is used in one or more stages. This is metainformation
# about the ORFS code that there is no known nice way for ORFS to
# provide.
BAZEL_VARIABLE_TO_STAGES = {}
#
# Variables auto-injected by bazel-orfs (not present in ORFS variables.yaml)
# are registered here so that check_variables() does not flag them as
# unknown when downstream callers see them in arguments.
BAZEL_VARIABLE_TO_STAGES = {
# Set in orfs_design.bzl when SYNTH_HIERARCHICAL=1.
"SYNTH_NUM_PARTITIONS": ["synth"],
}

BAZEL_STAGE_TO_VARIABLES = {}
BAZEL_STAGE_TO_VARIABLES = {
stage: [v for v, stages in BAZEL_VARIABLE_TO_STAGES.items() if stage in stages]
for stage in [
"synth",
"floorplan",
"place",
"cts",
"grt",
"route",
"final",
"generate_abstract",
"generate_metadata",
"test",
"update_rules",
]
}

ALL_STAGES = [
"synth",
Expand Down Expand Up @@ -135,7 +157,8 @@ ORFS_STAGE_TO_VARIABLES = {
}

ALL_STAGE_TO_VARIABLES = {
stage: ORFS_STAGE_TO_VARIABLES.get(stage, [])
stage: ORFS_STAGE_TO_VARIABLES.get(stage, []) +
BAZEL_STAGE_TO_VARIABLES.get(stage, [])
for stage in ALL_STAGES
}

Expand Down
15 changes: 10 additions & 5 deletions synth_partition.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@ NUM_PARTITIONS=${SYNTH_NUM_PARTITIONS:?}
KEPT_JSON="$RESULTS_DIR/kept_modules.json"
OUTPUT="$RESULTS_DIR/partition_${PARTITION_ID}.v"

# Parse module list from JSON using sed (avoids python wrapper issues)
# JSON format: {"modules": ["mod1", "mod2", ...]}
ALL_MODULES=$(sed 's/.*\[//;s/\].*//;s/"//g;s/,/\n/g;s/ //g' "$KEPT_JSON")
# Parse module list from JSON. Module names can contain '[' and ']'
# (slang elaborates parameterized instances to names like
# 'foo$bar.gen_tiles[0].i_tile.gen_banks[3]'), so a greedy sed regex is
# unsafe. Module names cannot contain '"', so extracting all quoted
# strings and skipping the first ("modules" key) is correct.
ALL_MODULES=$(grep -oE '"[^"]+"' "$KEPT_JSON" | tail -n +2 | sed 's/"//g')

# When SYNTH_SKIP_KEEP is set, the keep-hierarchy discovery was skipped.
# When SYNTH_SKIP_KEEP=1, the keep-hierarchy discovery was skipped.
# Partitions read from canonical RTLIL and run full synthesis (coarse+fine).
if [ -n "${SYNTH_SKIP_KEEP:-}" ]; then
# ORFS variables.yaml defaults SYNTH_SKIP_KEEP to "0", so test for "1"
# explicitly rather than -n (which is true for any non-empty string).
if [ "${SYNTH_SKIP_KEEP:-0}" = "1" ]; then
CHECKPOINT="$RESULTS_DIR/1_1_yosys_canonicalize.rtlil"
# Validate that every SYNTH_KEEP_MODULES entry exists in the canonical RTLIL
RTLIL_MODULES_FILE=$(mktemp)
Expand Down
Loading