Skip to content

pdn: connect the supply pins of dont_touch instances - #4782

Closed
oharboe wants to merge 1 commit into
The-OpenROAD-Project:masterfrom
oharboe:pdn-dont-touch-supplies
Closed

oharboe wants to merge 1 commit into
The-OpenROAD-Project:masterfrom
oharboe:pdn-dont-touch-supplies

Conversation

@oharboe

@oharboe oharboe commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Before, an instance marked dont_touch before the PDN step kept its VDD and VSS pins on no net through final, because global_connect skips dont_touch instances (ODB-0383).
Now the PDN step connects them: dont_touch is lifted from those instances while the platform's PDN script makes its global connections, and restored after.

design unpowered instances before
riscv32i, register file generated by generate_ram 896 of 7,089
XiangShan XSTile 406,272 cells

The M1 rails touch these cells, so timing and routing were unaffected; the netlist, LVS and power analysis saw them unpowered.

This wires up more of generate_ram's experimental features in the flow: a register file dissolved into its parent after macro placement (#4781) has its core FIRM and dont_touch by the PDN step. It is one of three changes needed before asap7/coralnpu (#4653) can go in, with #4781 and #4783. The three are independent of each other; this one is a fix for any flow that marks instances dont_touch before PDN.

A supply pin already on a net is left alone. One info message (FLW-0018) gives the count, in place of an ODB-0383 warning per instance.

Tests: flow/test/test_pdn_dont_touch_supplies.py (skipped without openroad) checks that global_connect still skips a dont_touch instance, that only dont_touch instances with a supply pin on no net are named, and that they are connected and dont_touch again afterwards. With the proc returning nothing, two of the three tests fail.

🤖 Generated with Claude Code

global_connect skips dont_touch instances (ODB-0383, deliberate in
odb), so an instance made dont_touch before the PDN step keeps its VDD
and VSS pins on no net through final. A register file built by
generate_ram and dissolved into its parent after macro placement is
that case: its core is FIRM and dont_touch by the PDN step. 896 of
riscv32i's 7,089 instances with its register file generated, 406,272
cells of XiangShan's XSTile, were left unpowered. The M1 rails touch
them, so timing and routing were unaffected; the netlist, LVS and power
analysis saw them unpowered.

The PDN step lifts dont_touch from every dont_touch instance with a
supply pin on no net while the platform's PDN script makes its global
connections, and restores it after: one connection, no ODB-0383 warning
per instance. A supply pin already on a net is left alone.

flow/test/test_pdn_dont_touch_supplies.py checks that global_connect
still skips a dont_touch instance, that only the dont_touch instances
with a supply pin on no net are named, and that they are connected and
dont_touch again afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a mechanism to temporarily lift the dont_touch property from instances with unsupplied supply pins during the PDN step, ensuring that global_connect can connect them properly. This is implemented via a new dont_touch_unsupplied helper in util.tcl and integrated into pdn.tcl, alongside a new Python test suite to verify the behavior. The single review comment was removed because it violates the repository style guide by suggesting a silent fallback (returning an empty list) when no design is loaded, rather than allowing a loud failure. Therefore, there is no further feedback to provide.

oharboe added a commit to oharboe/OpenROAD-flow-scripts that referenced this pull request Nov 3, 2026
CoreMiniAxi.sv is regenerated from coralnpu b50b85a9 by
src/coralnpu/generate, and the design is configured for it:

- The five TCM banks (ITCM one, DTCM four) are coralnpu's Sram, 512 x
  128 with one read-write port and a 16-lane byte mask. sram.memories
  names its pins (ADDITIONAL_MEMORIES) and AUTO_MEMORIES replaces it
  with a generated macro, write mask and all. The previous build swapped
  in USE_ASAP7 fakerams, which have no write mask, so a masked write
  wrote all 16 bytes.
- Regfile and FRegfile keep their words as separate registers, with no
  array for yosys to infer. surgery.py (SYNTH_VERILOG_SURGERY) moves
  them into Regfile_rf and FRegfile_rf, which AUTO_MEMORIES_REGFILES has
  generate_ram build as standard cells, every word with its
  asynchronous reset: Regfile 32 x 32 with x0 reading zero, nine reads
  and six writes; FRegfile 32 x 32, four reads and two writes.
- The clock is 1,900 ps in the platform's picoseconds (it was 10.00),
  with the platform's set_max_delay IO budgets; the asynchronous reset
  is not timed. The kept hierarchy is coralnpu's units by name, with
  OPENROAD_HIERARCHICAL=1.
- The divider's 128 x 83 SRT table is a ROM yosys maps to logic; a
  ROM is not counted against SYNTH_MEMORY_MAX_BITS.

surgery.py recognises each register file token for token and stops the
build on anything else. Each was simulated before and after the
surgery, and generate_ram's netlists against the behavioural modules
the surgery writes, on the same random inputs, every output compared
every cycle, with a negative control for each that is caught.

Needs AUTO_MEMORIES_REGFILES (The-OpenROAD-Project#4781), the supply pins of dont_touch
instances connected (The-OpenROAD-Project#4782) and a parameterized module as a macro
(The-OpenROAD-Project#4783).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@oharboe
oharboe marked this pull request as ready for review November 3, 2026 08:28
@oharboe
oharboe requested a review from gadfort November 3, 2026 08:33
oharboe added a commit to oharboe/OpenROAD-flow-scripts that referenced this pull request Nov 3, 2026
CoreMiniAxi.sv is regenerated from coralnpu b50b85a9 by
src/coralnpu/generate, and the design is configured for it:

- The five TCM banks (ITCM one, DTCM four) are coralnpu's Sram, 512 x
  128 with one read-write port and a 16-lane byte mask. sram.memories
  names its pins (ADDITIONAL_MEMORIES) and AUTO_MEMORIES replaces it
  with a generated macro, write mask and all. The previous build swapped
  in USE_ASAP7 fakerams, which have no write mask, so a masked write
  wrote all 16 bytes.
- Regfile and FRegfile keep their words as separate registers, with no
  array for yosys to infer. surgery.py (SYNTH_VERILOG_SURGERY) moves
  them into Regfile_rf and FRegfile_rf, which AUTO_MEMORIES_REGFILES has
  generate_ram build as standard cells, every word with its
  asynchronous reset: Regfile 32 x 32 with x0 reading zero, nine reads
  and six writes; FRegfile 32 x 32, four reads and two writes.
- The clock is 1,900 ps in the platform's picoseconds (it was 10.00),
  with the platform's set_max_delay IO budgets; the asynchronous reset
  is not timed. The kept hierarchy is coralnpu's units by name, with
  OPENROAD_HIERARCHICAL=1.
- The divider's 128 x 83 SRT table is a ROM yosys maps to logic; a
  ROM is not counted against SYNTH_MEMORY_MAX_BITS.

surgery.py recognises each register file token for token and stops the
build on anything else. Each was simulated before and after the
surgery, and generate_ram's netlists against the behavioural modules
the surgery writes, on the same random inputs, every output compared
every cycle, with a negative control for each that is caught.

Needs AUTO_MEMORIES_REGFILES (The-OpenROAD-Project#4781), the supply pins of dont_touch
instances connected (The-OpenROAD-Project#4782) and a parameterized module as a macro
(The-OpenROAD-Project#4783).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@openroad-ci

Copy link
Copy Markdown
Member

🔍 QoR check

Metrics reflect the PR merge build — i.e. what will land on the target branch.

Commit c862bf5 · Jenkins build #1 · Baseline: build · View build on dashboard

62 design(s) checked — 0 with regression(s), 1 without a comparable baseline.

@gadfort

gadfort commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

@oharboe this feel hacky to me. It seems like the right approach is to create the global connect rules after loading in the netlist and then you can apply the dont_touch after that without having to worry about this.

@oharboe

oharboe commented Nov 3, 2026

Copy link
Copy Markdown
Collaborator Author

Replaced by #4785, following @gadfort's suggestion.

@oharboe oharboe closed this Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants