|
| 1 | +From 58df356479d6d9f04aa0bc3ac3676d3b89d26813 Mon Sep 17 00:00:00 2001 |
| 2 | +From: =?UTF-8?q?=C3=98yvind=20Harboe?= <oyvind@ascenium.com> |
| 3 | +Date: Thu, 14 May 2026 18:48:12 +0200 |
| 4 | +Subject: [PATCH] orfs_design/orfs_flow: add user_sources= for design-private |
| 5 | + path hooks |
| 6 | +MIME-Version: 1.0 |
| 7 | +Content-Type: text/plain; charset=UTF-8 |
| 8 | +Content-Transfer-Encoding: 8bit |
| 9 | + |
| 10 | +Symmetric to user_arguments=, but for source-typed (path-label) vars: |
| 11 | +a variable that the config_mk_parser classifies as a SOURCE_VAR (path |
| 12 | +staged into the sandbox via _map_source_file) but that is read only |
| 13 | +by user-supplied .tcl/.mk and has no entry in ORFS variables.yaml. |
| 14 | + |
| 15 | +Today such a variable bumps into check_variables(sources.keys()) in |
| 16 | +orfs_flow and fails the load phase, even though the file itself is |
| 17 | +staged correctly. user_arguments= doesn't help because it pops from |
| 18 | +arguments, not sources. |
| 19 | + |
| 20 | +The motivating case is SDC_FILE_EXTRA — set by |
| 21 | +flow/designs/asap7/mock-cpu/config.mk and source'd from that design's |
| 22 | +io.tcl, with no ORFS-side consumer. SDC_FILE_EXTRA is in this file's |
| 23 | +SOURCE_VARS list, so its value is path-staged; making it work without |
| 24 | +declaring it as a global ORFS variable is what user_sources= is for. |
| 25 | + |
| 26 | +API: |
| 27 | +- orfs_design() gains user_sources=[VAR, ...]. Each named var is |
| 28 | + popped from sources and forwarded as orfs_flow(user_sources={...}). |
| 29 | +- orfs_flow() gains user_sources={VAR: [label, ...]}. Merged into |
| 30 | + sources before _orfs_pass so files are still staged, but the key |
| 31 | + set skips check_variables. Same shadowing guard as user_arguments=: |
| 32 | + collision with a known ORFS variable fails fast. |
| 33 | + |
| 34 | +Mirrors user_arguments= in both surface and intent. |
| 35 | + |
| 36 | +Signed-off-by: Øyvind Harboe <oyvind@ascenium.com> |
| 37 | +--- |
| 38 | + private/flow.bzl | 19 +++++++++++++++++-- |
| 39 | + private/orfs_design.bzl | 19 ++++++++++++++++++- |
| 40 | + 2 files changed, 35 insertions(+), 3 deletions(-) |
| 41 | + |
| 42 | +diff --git a/private/flow.bzl b/private/flow.bzl |
| 43 | +index fd9001f..b59d059 100644 |
| 44 | +--- a/private/flow.bzl |
| 45 | ++++ b/private/flow.bzl |
| 46 | +@@ -171,6 +171,7 @@ def orfs_flow( |
| 47 | + verilog_files = [], |
| 48 | + macros = [], |
| 49 | + sources = {}, |
| 50 | ++ user_sources = {}, |
| 51 | + stage_sources = {}, |
| 52 | + stage_arguments = {}, |
| 53 | + renamed_inputs = {}, |
| 54 | +@@ -213,6 +214,12 @@ def orfs_flow( |
| 55 | + validating against ORFS variables.yaml. Use for vars read only by user-supplied .tcl/.mk |
| 56 | + (e.g. ARRAY_COLS in a project's MACRO_PLACEMENT_TCL). Keys that collide with known ORFS |
| 57 | + variables are rejected — route those through 'arguments' instead. |
| 58 | ++ user_sources: dictionary of project-specific source-typed (path-label) env vars to expose |
| 59 | ++ to every stage without validating against ORFS variables.yaml. The path is still staged |
| 60 | ++ into the sandbox like a normal source — only the variable name skips the validator. |
| 61 | ++ Use for path hooks read only by user-supplied .tcl/.mk (e.g. an extra-SDC hook |
| 62 | ++ source'd from the design's own io.tcl). Keys that collide with known ORFS variables |
| 63 | ++ are rejected — route those through 'sources' instead. |
| 64 | + extra_arguments: dictionary keyed by ORFS stages with lists of .json argument file labels. |
| 65 | + These .json files are merged into the stage config, providing computed arguments |
| 66 | + that flow through OrfsInfo to subsequent stages. |
| 67 | +@@ -269,6 +276,14 @@ def orfs_flow( |
| 68 | + ) + |
| 69 | + "Use arguments= for ORFS variables; reserve user_arguments= for project-specific env vars.", |
| 70 | + ) |
| 71 | ++ shadowed_srcs = sorted([k for k in user_sources if k in ALL_VARIABLE_TO_STAGES]) |
| 72 | ++ if shadowed_srcs: |
| 73 | ++ fail( |
| 74 | ++ "user_sources contains known ORFS variable(s): {shadowed}. ".format( |
| 75 | ++ shadowed = ", ".join(shadowed_srcs), |
| 76 | ++ ) + |
| 77 | ++ "Use sources= for ORFS variables; reserve user_sources= for project-specific path hooks.", |
| 78 | ++ ) |
| 79 | + if abstract_stage and last_stage: |
| 80 | + fail("abstract_stage and last_stage are mutually exclusive") |
| 81 | + if variant == "base": |
| 82 | +@@ -281,7 +296,7 @@ def orfs_flow( |
| 83 | + top = top, |
| 84 | + verilog_files = verilog_files, |
| 85 | + macros = macros, |
| 86 | +- sources = sources, |
| 87 | ++ sources = sources | user_sources, |
| 88 | + stage_sources = stage_sources, |
| 89 | + stage_arguments = stage_arguments, |
| 90 | + renamed_inputs = renamed_inputs, |
| 91 | +@@ -319,7 +334,7 @@ def orfs_flow( |
| 92 | + top = top, |
| 93 | + verilog_files = verilog_files, |
| 94 | + macros = macros, |
| 95 | +- sources = sources, |
| 96 | ++ sources = sources | user_sources, |
| 97 | + stage_sources = stage_sources, |
| 98 | + stage_arguments = stage_arguments, |
| 99 | + renamed_inputs = {}, |
| 100 | +diff --git a/private/orfs_design.bzl b/private/orfs_design.bzl |
| 101 | +index 554da44..d53d4bd 100644 |
| 102 | +--- a/private/orfs_design.bzl |
| 103 | ++++ b/private/orfs_design.bzl |
| 104 | +@@ -47,7 +47,7 @@ def _convert_sources(sources, pkg): |
| 105 | + result[var] = converted |
| 106 | + return result |
| 107 | + |
| 108 | +-def orfs_design(name = None, config = "config.mk", platform = None, design = None, designs = None, mock_openroad = None, mock_yosys = None, user_arguments = [], local_arguments = []): # buildifier: disable=unused-variable |
| 109 | ++def orfs_design(name = None, config = "config.mk", platform = None, design = None, designs = None, mock_openroad = None, mock_yosys = None, user_arguments = [], user_sources = [], local_arguments = []): # buildifier: disable=unused-variable |
| 110 | + """Create orfs_flow() targets for a design based on its parsed config.mk. |
| 111 | + |
| 112 | + Usage: |
| 113 | +@@ -79,6 +79,13 @@ def orfs_design(name = None, config = "config.mk", platform = None, design = Non |
| 114 | + Routed through orfs_flow(user_arguments=...) to bypass the |
| 115 | + variables.yaml validator instead of being checked as known |
| 116 | + ORFS arguments. |
| 117 | ++ user_sources: List of source-typed variable names (vars in |
| 118 | ++ SOURCE_VARS) that are project-specific path hooks read only |
| 119 | ++ by user-supplied .tcl/.mk, not by ORFS itself (e.g. a |
| 120 | ++ per-design extra-SDC hook source'd from the design's own |
| 121 | ++ io.tcl). Routed through orfs_flow(user_sources=...) so the |
| 122 | ++ file is still staged into the sandbox, but the variable |
| 123 | ++ name bypasses the variables.yaml validator. |
| 124 | + local_arguments: List of variable names that are only used for |
| 125 | + $(VAR) expansion within the same config.mk and are not read |
| 126 | + by ORFS or by any user .tcl/.mk (e.g. VERILOG_FILES_BLACKBOX, |
| 127 | +@@ -195,6 +202,15 @@ def orfs_design(name = None, config = "config.mk", platform = None, design = Non |
| 128 | + if var in arguments: |
| 129 | + user_args[var] = arguments.pop(var) |
| 130 | + |
| 131 | ++ # Same idea for source-typed (path-label) project-specific knobs: |
| 132 | ++ # variables that are in SOURCE_VARS (so the parser staged the path |
| 133 | ++ # as a label) but are read only by user .tcl/.mk and have no |
| 134 | ++ # variables.yaml entry. |
| 135 | ++ user_srcs = {} |
| 136 | ++ for var in user_sources: |
| 137 | ++ if var in sources: |
| 138 | ++ user_srcs[var] = sources.pop(var) |
| 139 | ++ |
| 140 | + # Default SYNTH_NUM_PARTITIONS to a static value so that the action graph |
| 141 | + # is identical across machines and remote cache hits are possible. Users |
| 142 | + # who prefer local parallelism over caching can pass NUM_CPUS explicitly. |
| 143 | +@@ -213,6 +229,7 @@ def orfs_design(name = None, config = "config.mk", platform = None, design = Non |
| 144 | + arguments = arguments, |
| 145 | + user_arguments = user_args, |
| 146 | + sources = sources, |
| 147 | ++ user_sources = user_srcs, |
| 148 | + macros = macros if macros else [], |
| 149 | + stage_data = {"synth": extra_data} if extra_data else {}, |
| 150 | + tags = tags, |
| 151 | +-- |
| 152 | +2.51.0 |
| 153 | + |
0 commit comments