Repository navigation
Conversation
Fewer register files that need a seam in the RTLSeams are still needed, but yosys can make one for any register file it
How yosys makes the seam. The passes are
One RAM definition per memory.
Where it goes in synthesis. In Opt-in by name. List each memory by its inventory name, Open:
Not measured. The cheap test is picorv32's |
|
Some data for OpenROAD's Claude made the changes and I stared at paint drying: a register file of riscv32i to global route, 950 ps clock, global-route parasitics:
The worst path goes through the decode as three serial AND2 stages, then Questions:
|
Plan: from this PR to upstreamThis PR is integration testing. It carries every change as a patch and Extend
|
| # | Repo | Change | Needs |
|---|---|---|---|
| 1 | OpenROAD | generate_ram: an AND/OR read path in place of tristates, with an asap7 test |
— |
| 2 | OpenROAD | generate_ram: more than one write port, a write select per bit in place of the clock-gated write |
1 |
| 3 | OpenROAD | generate_ram: decode and read trees sized for their fanout (AND3/AND4, AO22, NAND/NOR) |
1 |
| 4 | ORFS | AUTO_MEMORIES_REGFILES: a spec per module mapped onto generate_ram options, blackboxed and placed like an AUTO_MEMORIES macro |
2 |
| 5 | ORFS | the dissolve after macro placement: the macro becomes FIRM cells on the core's rows | 4 |
Spec-only features (RTL port names, zero_word, banks, bit folds) live
in ORFS's mapping (4), not in OpenROAD's arguments, unless a reviewer
wants them there.
Upstream pull requests are opened by a human. This PR stays a draft
until 1 has merged.
Gate: riscv32i must win
riscv32i is the fast-turnaround baseline: it reaches global route in
minutes. Today the generated register file loses to flip-flops:
| to global route, 950 ps clock | flip-flops | register file |
|---|---|---|
| minimum period | 954 ps | 998 ps |
| failing endpoints | 79 | 992 |
| core area | 4 012 um² | 7 573 um² |
The worst path runs through the decode as three serial AND2 stages and
an OR2 read tree: 232 ps from instr to read data.
Experiments to find a structure that wins can continue on 0010, where
the turnaround is already set up. The proof each upstream pull request
links to is riscv32i built with generate_ram and that pull request's
options: minimum period at or below flip-flops', with area reported.
Why register files need this
XiangShan's register files are Reg(Vec). yosys never infers a memory
from them, and it does not finish synthesising them as flip-flops at
this size:
| Register file | Words × bits | Ports |
|---|---|---|
| IntRegFile | 224 × 64 | 12 banked reads, 9 writes |
| FpRegFile | 256 × 64 | 14 reads, 7 writes |
| VfRegFile | 128 × 128 | 14 reads, 7 writes |
| RobEntryFile / RenameBufferFile | 352 × 21 / 20 | 16 reads, 8 writes |
Rules for the upstream pull requests
- One concern per pull request; each one builds, tests and is useful on
its own. - With the new options off,
generate_ram's existing sky130 and
Nangate45 tests pass unchanged. - New tests assert intent and pass or fail: ports as asked, every cell
placed, no overlaps, reads and writes correct in simulation of the
behavioral model against the netlist. No new golden.defok,.lefok
or.libokfiles. - The description gives the evidence and links here.
Reseat: the riscv32i register-file campaignPaused here to carry on on a machine that can run several experiments
Results so far (global route, 950 ps clock)
Nothing reaches parity yet. The register file is 7-13 % smaller in Disregard in this PR's description and earlier commentsThese are superseded or wrong;
Still correct: asap7 has no tristate cell (no Not verified on the branch
To carry on
Lined up, in parallel:
Word groups ( 🤖 Generated with Claude Code |
riscv32i register-file campaign: a clock gate per word reaches the flip-flopsBranch
The write clock gate is the change that reaches the flip-flops. Each word gets one
Never a macro is the shape that wins on area. riscv32i reads the generated netlist in synthesis in place of Negatives:
Not verified:
Next, if this direction holds: never a macro as a flow mode. The memories step would hand synthesis the generated netlist in place of the module. That would retire the dissolve and its row cutting rather than add to them. It changes this PR's design, so it waits for your call. 🤖 Generated with Claude Code |
|
#1187 at aeae86a, XSTile built from source to global route: every block identical to row 12, the parent 3,386 ps against 3,162 (+7.1 %) on row 12's own worst path. Recorded to revisit, not fixed: entry 47's zero-wire census on the checkpoint separates #1184's mechanism, which #1187 includes, from what the dissolve adds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Register-file ladder: ORFS's asap7 designs with a register file
picorv32 at swerv is the one row where the register file costs area and power: its flip-flop baseline already gates the clock per word, and its 992 reset flops are larger cells. What the ladder added
Evidence that the register files compute what the RTL does
Two findings outside the register file
Open
Rows: |
… +3.6 %, placed files beat inlined T1, #1187 at f681c30 from source: Frontend 2,170 -> 1,792 ps and VecRegionModule 1,479 -> 1,278 with generate_regfile's new read path, FltRegionModule 895 -> 951, the parent 3,276 ps (row 12 3,162, entry 48 3,386). The zero-wire census puts the parent's floor lowest of the four measured (2,021 ps); the loss is wire and repeaters, #1184's mechanism in part. T2b, the parent's three files inlined on the same plan: 3,529 ps and 29 % congestion, so the planned, dissolved files stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
|
@maliberty FYI: this PR is the integration test for a register-file feature that spans OpenROAD and ORFS. It shows the OpenROAD and ORFS changes working together on ORFS's own designs. TL;DR: a register-file generator,
Global route, each design's own config and clock; the period is the slowest clock's, port paths included. In every measured design the generated register file matches the RTL it replaces, simulated under random reads, writes and resets. Synthesis time. Trivial for these examples. Yosys synthesis ( On XiangShan, synthesis with flip-flop register files ran forever. With this feature it completes. Together with parallel hierarchical synthesis and macros, XiangShan's run time is tolerable: overnight. I haven't studied exactly where the time went, and don't plan to: measuring "forever" would take days or weeks. OpenROAD
ORFS
Here both are carried as patches on OpenROAD and ORFS. Details and open items are in the comment above. |
A harness property learned simulating generated register files beside their RTL (#1187): in Verilator a reset already asserted at the first eval() never falls, so a cell model that clears on its reset's falling edge never does, while RTL that clears on a clock edge still clears. Release the reset for one evaluation before asserting it; a flop behind a clock gate has no other way to clear. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
A KPI row for a change that is not on main, this once, to show where it stands while its OpenROAD and ORFS parts are in review (OpenROAD#11669, OpenROAD-flow-scripts#4651): #1187 builds the register files with OpenROAD's generate_regfile through ORFS's AUTO_MEMORIES_REGFILES in place of bazel-orfs's structured_gen. Measured on 2026-10-07 at aeae86a, #1187's commit of that day: the blocks unchanged, the parent 3,386 ps, 224 ps slower than run 12, its worst path CtrlBlock's own; the cause is not diagnosed. The README stated the KPI as 3,860 ps, three rows stale; it now states main's 3,162 ps and says run 13 is in flight. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
… +3.6 %, placed files beat inlined T1, #1187 at f681c30 from source: Frontend 2,170 -> 1,792 ps and VecRegionModule 1,479 -> 1,278 with generate_regfile's new read path, FltRegionModule 895 -> 951, the parent 3,276 ps (row 12 3,162, entry 48 3,386). The zero-wire census puts the parent's floor lowest of the four measured (2,021 ps); the loss is wire and repeaters, #1184's mechanism in part. T2b, the parent's three files inlined on the same plan: 3,529 ps and 29 % congestion, so the planned, dissolved files stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
46afcbf to
14e9af1
Compare
|
cva6 (cv32a65x), the last rung: passes. Rebased on main, which now carries #1200: the flip-flop baseline used to stop in slang's elaboration in the Bazel sandbox because a generated BUILD file hid
Global route, ORFS's own Correctness: on the rebased branch all 9 ladder tests pass, including With cva6, every design on the ladder passes: riscv32i −0.1 %, ibex −1.0 %, tinyRocket −8.7 %, picorv32 +1.4 % (mean of 3 seeds), swerv_wrapper +0.2 %, cva6 +0.03 %. Also in the rebase: |
|
coralnpu, rung 7: passes, and it's the first rung where the wrapper around the register file mattered.
Register file: An idiomatic baseline first (ORFS 0102). ORFS's
Two iterations (0103). The first moved
Where the time goes. In the flip-flop arm, Correctness. All 13 ladder tests pass. The coralnpu ones:
Open: the +8.5 % power, where clock skew also rose (306 → 415 ps), points at the per-word clock gates. And the repair long tail: ORFS runs |
|
A correction, a bug fix, and clock gate vs mux per word. Bug: two design directories that shared a Correction: picorv32's seed band. The earlier mean of +1.4 % counted one register-file arm twice. Re-run, all three seeds on one ORFS:
Clock gate per word or mux per word (
The better style depends on the design: muxes for swerv, clock gates for coralnpu. So coralnpu's numbers are now as ORFS draft The-OpenROAD-Project/OpenROAD-flow-scripts#4653 has it, without the |
|
riscv32i in each
On XSTile the order flips (entry 49: inlining +7.7 % against placed arrays). No shape dominates; it is a per-design choice. These numbers answer a review comment on The-OpenROAD-Project/OpenROAD#11669, where |
The measurements so far (results.md), the scripts that took them (measure.sh and the odb-debug queries), the generator variants not yet measured in a flow (predecode.diff, word-groups.diff), golden and shape tools for patch 0010, and the experiments lined up (README.md), so the campaign can carry on, lanes in parallel, on a machine with room for them. odb-debug sessions on each stage of both riscv32i variants are manual targets in test/regfile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
… flops generate_regfile gets write_style clock_gate: one integrated clock gate per word, enabled by its write select, in place of the per-bit AO22 hold mux, as generate_ram writes; riscv32i-regfile uses it at 45 %. At 45 % riscv32i reaches 951 ps, the flops' 954 at 4012 um2 and 951 at the same utilisation. As a macro it does not fit riscv32i's 62 % (MPL-0003). riscv32i with the generated netlist in place of regfile.v, no macro and no dissolve (never_macro.sh), reaches 955 ps on a core 12 % smaller than the flops'. Measured and negative: predecode (1000 against 982), the dissolved array unplaced and placed freely (1012 against 1003). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
The campaign after the clock gate, every arm simulated first by test/regfile/sim and measured inlined at riscv32i's 62 %: predecode, a mux-tree read, a four-input read tree, stronger cells and the two together. None beats 955 ps by more than the noise; results.md has each arm and why the mux tree loses (the address fanout needs as many buffer levels as the decode it replaces). The clock gate's cost: hold clean, 179 clock-tree buffers against 122, no hold repair in either design. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
… yosys makes ORFS patch 0093, carried in bazel-orfs for now: a spec's `memory <module>.<cell>` names a memory yosys infers inside a module, and synthesis makes the seam while it reads the sources -- memory_libmap with a memlib entry and techmap with a wrapper, both written from the spec by gen_memories.py -- then reads the generated netlist as the register file's body. The memory is found by cell and module definition and selected by attribute (no slang $ name spelled); opt -full, scoped to its module, makes Chisel's per-bit write enables one signal, or the array maps as 32 one-bit slices. A memory not found once, or not mapped to one instance, stops the build. asap7/tinyRocket-regfile is Rocket's integer register file (RocketCore's _T_288, 31 x 32, 2R1W) that way, the RTL unchanged: one rocket_rf, 32 clock gates, 3777 um2 at global route against tinyRocket's 3956. test/tinyrocket_regfile checks the inventory: the register file in the array's place, no flip-flop entry left for the array. Patch 0092 takes the upstream review's change (OpenROAD-flow-scripts #4643): memories.v's loop variable local to its block, the same memory inferred with both frontends. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
…gery The register-file campaign on ORFS's asap7 designs, smallest first, each against a -regfile variant at global route: a row passes when the register file's minimum period is at most 3 % above the flip-flops'. - test/regfile/ladder: ladder_row (both arms' stage logs and global route metrics into one JSON row), run_row.sh and report.py for the unattended runs, and regfile_sim_test: a spec's generated netlist simulated beside the RTL module it replaces, or beside a behavioural memory for a seam spec, under random reads, writes and resets. A negative control (ibex's spec with its reset dropped) must mismatch. - OpenROAD 0011: generate_regfile async_reset, storage that resets to zero (DFFASRHQNx1, set tied off per word). - OpenROAD 0012: the port check reads SystemVerilog headers and refuses a declaration it cannot read; `unused <port>`. - ORFS 0094: SYNTH_VERILOG_SURGERY, a hack: a script edits copies of the sources before synthesis reads them. - ORFS 0095, 0096: asap7/picorv32-regfile (seam), asap7/ibex-regfile (module spec with reset). - .regfile specs are exported from ORFS design packages, and SYNTH_VERILOG_SURGERY's script is staged as a source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
…read QoR - OpenROAD 0013: generate_regfile `write_priority last`, the later write port wins a collision (cva6's two commit ports). - ORFS 0097: asap7/swerv_wrapper-yosys and -regfile. A surgery script rewrites dec_gpr_ctl as SweRV's source reads, the array in dec_gpr_ctl_rf. Both arms define OPENROAD_CLKGATE: without it the platform's clock gate is a wire and swerv's register file holds no value, a baseline cheaper than any register file that does. - ORFS 0098: asap7/cva6-regfile, ariane_regfile recognised token for token and its array moved into ariane_regfile_rf. - ORFS 0099: an inlined register file in place of a parameterized module (ibex): the instances' parameters are dropped first. - ORFS 0094: SYNTH_VERILOG_SURGERY's description says why: the RTL changes, so a fix is an operation redone on every version. - Simulation: surgery_cmp_test and cva6's bench compare the module before and after surgery, the register file as generated; colliding writes are driven under write_priority last. The driver releases reset once before asserting it, so a clock-gated flop sees an edge. - Rows: the register-to-register minimum period from ORFS's global route metrics (the jsons output group), macro counts for a like-for-like flag, repair_timing progress, and a worst-path probe per arm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
…rv32 - Rows read each clock's timing__fmax__clock:<name> and gate on the slowest: ORFS's aggregate timing__fmax is the maximum over clocks, and riscv32i, ibex and picorv32 have a virtual I/O clock whose fmax is the more optimistic one. find_clk_min_period's argument is include_port_paths: the period includes port paths, and the report says so. - The worst-path probe reports the period with and without port paths. - ORFS 0100: picorv32 and picorv32-regfile at GPL_RANDOM_SEED 2 and 3, ladder rows of their own: picorv32's difference is read against its seed spread. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
row.py took 5_1_grt.log as the place to read the routed timing from and skipped it when it summed stage times, so every row's total left out global route. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
…verdict gen_cmp_tb reads an ANSI header where one declaration names several ports (firtool writes `input clock,` then `reset,`): the names after the first carry its direction and width. surgery_cmp_test passes surgery_args, the design's SYNTH_VERILOG_SURGERY_ARGS. tb_main judges a negative control on being caught before it asks for a reset: the control stops at its tenth mismatch, which may come first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
ORFS 0101 declares SYNTH_POST_HIERARCHY_SCRIPTS so a config.mk can set it, and config_mk_parser stages it. ORFS 0102 makes asap7/coralnpu a synthesis build of its snapshot: firtool's verification layers removed, the TCM SRAMs as firtool memory modules that AUTO_MEMORIES turns into masked macros instead of USE_ASAP7's maskless fakerams, ClockGate on ASAP7's ICG, the platform's constraints.sdc at 1,900 ps instead of a 10 ps clock, coralnpu's units kept by name. ORFS 0103 is coralnpu-regfile: Regfile's 31 words moved into Regfile_rf, 8 reads and 6 writes ORed on a collision, async reset high, and generated. coralnpu_synth_test checks the synthesis is that build; coralnpu_surgery_test compares Regfile before and after surgery with the generated register file; coralnpu_sim_test the spec against the behavioural Regfile_rf, and coralnpu_write_last_sim_test, the spec with the later write winning, must mismatch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
A variant that includes its base design's config.mk names the base's SYNTH_POST_HIERARCHY_SCRIPTS script from another package (asap7/coralnpu-regfile, coralnpu's clockgate.ys). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
ORFS 0103's surgery also rewrites each of Regfile's eight read bypasses, a select by read address over every word's decoded write data, into a compare of the read address with each write port's. It is the same function (coralnpu_surgery_test) and leaves the per-word write decode, which the generated register file does inside, with no reader. At global route the register file goes from a long tail of repair to meeting 1,900 ps: 2,009 -> 1,899 ps, std-cell area -6.3 %. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
row.py records, per stage, the commands ORFS's log_cmd timed (those of 5 s or more), and repair_timing's progress at CTS as well as at global route: the breakdown that shows a long tail of repair. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
#4653 is coralnpu's upstream draft, and it can only use what will be upstream: the ClockGate mapping onto ASAP7's ICG needs a hook that is only carried here. 0102 drops it and 0101, which declared that hook's variable for it; coralnpu_synth_test no longer expects ICG cells. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
ORFS 0104 adds coralnpu-regfile-mux and swerv_wrapper-regfile-mux, the register files with write_style mux; coralnpu_mux and swerv_wrapper_mux compare them with flops. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@orfs_designs keyed DESIGNS by platform/DESIGN_NICKNAME, adding a directory key only when it differed from the nickname. Variants that include a base design's config.mk share its nickname, so the last one parsed replaced the base's entry, and orfs_design() found it for the base's own package: since the seed variants, asap7/picorv32-regfile ran picorv32-regfile-seed3's config (GPL_RANDOM_SEED 3), and since the mux variants coralnpu-regfile and swerv_wrapper-regfile ran the mux spec. The directory key now always holds the directory's own config; the nickname key is a fallback that never overwrites one. designs_by_directory_test checks the seed and mux variants against their bases; it fails on the old keying. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
repair_timing -verbose marks each progress row's iteration with its phase, `10*` in the main phases and `1500+` in last gasp, and restarts the count per phase. row.py took only plain numbers and kept nothing but the final row; it now keeps every row with its phase, in log order, which is the time axis. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
ORFS 0105 adds riscv32i-regfile-netlist and -macro, the register file macro-placed in mode netlist (dissolved, the periphery the parent's) and in mode macro (fully placed). With riscv32i (flops) and riscv32i-regfile (inlined) they are a few-minute A/B/C of the shapes; riscv32i_netlist and riscv32i_macro compare them with flops. mode macro does not place here (MPL-0003): its edge pins need channels the floorplan does not have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
main carries the base of this branch as one commit: OpenROAD 0010 at OpenROAD#11669's head, which has async_reset, SystemVerilog ports, `unused` and write_priority, and ORFS 0089, 0091 and 0099 as #4651 rebuilt on #4650. Rebased onto it: - OpenROAD 0011, 0012 and 0013 are gone, folded into main's 0010; the designs that needed them (0096, 0097, 0098) say 0010. - 0099 is listed once, where main lists it. - 0093 refreshed onto main's 0089 and 0091: FlowVariables.md's moved row, run_regfiles's black-formatted loop, and the register-file lists in gen_memories_test's flow contract (regfiles.txt, inline.txt, seams.txt). - check_memories_applied.py reads the module from the first field of a blackboxes.txt line, which carries an area since 0090. The whole ORFS series applies at ef421749 (bazel fetch of the ORFS repository) and ORFS's gen_memories_test passes on it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
asap7/coralnpu and asap7/coralnpu-regfile are in The-OpenROAD-Project/OpenROAD-flow-scripts#4653, its files the same as ORFS patches 0102 and 0103 but for black's line breaks in surgery.py and a space in constraint.sdc. The ladder stops carrying them: 0102 and 0103 go, 0104 keeps only swerv_wrapper-regfile-mux, and coralnpu's rows, its synthesis, surgery and simulation tests leave test/regfile/ladder. designs_by_directory_test checks the swerv mux variant against its base. The design DSL stops exporting .ys files: no design in the series names a SYNTH_POST_HIERARCHY_SCRIPTS script from another package since coralnpu took #4653's form. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
0bb6b3d to
7ee797b
Compare
|
Closed as reference only; the branch stays. Main carries the base of this work (1644583: OpenROAD 0010 at #11669's head, ORFS 0089/0091/0099 as ORFS #4651), and #1209 took everything else that stood on main alone. What this branch still held at its tip (7ee797b):
coralnpu lives in OpenROAD-flow-scripts#4653. 🤖 Generated with Claude Code |
…rity under test OpenROAD patch 0010 (OpenROAD#11669) has spec keys nothing on main exercised: async_reset, the port check reading a SystemVerilog header, `unused` inputs and `write_priority last`. OpenROAD's own tests for them do not run from bazel-orfs. Each is now simulated against the RTL it replaces, every read compared under random reads, writes and resets, seconds per test: - ibex_sim_test: ibex's register file, ORFS's src/ibex_sv RTL as it is, with its async reset (29 resets in 20,000 cycles), a parameterised SystemVerilog header and two unused inputs. ibex_no_reset_sim_test, the spec without the reset, must mismatch. - write_last_sim_test: an 8 x 8 file with two write ports that collide, the later port winning. write_first_sim_test, RTL where the earlier port wins, must mismatch, or the stimulus never collides. The harness (sim.bzl, gen_tb.py, tb_main.cc) is the register-file ladder's from the closed #1187, without its surgery comparison. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
The riscv32i register-file campaign of the closed #1187 reached parity with the flip-flops (955 against 954 ps, a 12 % smaller core) with a clock gate per word and inlining; ORFS patch 0091's AutoMemories.md has that. This keeps the rest: predecode, a mux-tree read, wider and stronger read trees, word groups, bit folds, a freely placed array and a macro, each with what it measured and why it lost; what sets the period now; the clock gate's cost; and that inlining loses on XSTile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
The parent's worst paths are a mass of CtrlBlock control (a false-path peel: about 9 ps a register over 40), and the repairs before global route time them with estimated wires. With the route's parasitics the stage's own setup repair takes the parent from 3,276 to 2,406 ps on row 14's build (#1187 at f681c30): 1,525 VT swaps, 74 buffers, 34 pin swaps; its worst path is now CtrlBlock's flush redirect into Frontend. The blocks are unchanged, so the design period is the parent's, 2,406. SKIP_INCREMENTAL_REPAIR goes from the parent; HOLD_SLACK_MARGIN -1000 in its grt stage leaves hold to CTS's repair, as this stage's hold repair took an earlier run of it to 120 GB. Global route costs 84 min against 19 and peaks at 102 GB against 83. KPI row 15 is that measurement, in flight like rows 13 and 14: it was built on #1187's commit, not on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Draft, scaffolding: not for merge as is. This is the integration branch for register files built as placed standard cells (AUTO_MEMORIES_REGFILES). The feature lands upstream, piece by piece. The pieces are carried here as patches so they can be exercised together on real designs. Each patch retires at the
//:bumponto the upstream that carries it, and is left as it is while its upstream pull request settles (upstream-pr, section 6). CI does not have to pass.Upstream
generate_regfile: the array as placed standard cellsmemory <module>.<cell>: a seam yosys makes for an inline arrayWhat is here to work on it
test/regfile: dissolve, clocking and grt build tests, and the register file in simulation.test/structured_gen_lec:generate_regfilechecked against its RTL by kepler-formal.test/regfile/ladder: each design with its register file in eachgenerate_regfilemode, its simulation, and the surgery that gives an inline array a module.test/regfile/campaign: the riscv32i clock-period campaign, paused for a bigger machine. The state and the claims it supersedes are in the reseat comment andtest/regfile/campaign/results.md. Numbers in this pull request's earlier comments are superseded there.Rebased onto main
ef421749.SYNTH_POST_HIERARCHY_SCRIPTSis no longer a source variable: no design here sets it in a config.mk any more, and as one it failed thevariables.yamlcheck for veer, so no package loaded.🤖 Generated with Claude Code