Skip to content

FakeRAM asap7: build the macro from the declared pins, with write-mask lanes - #4711

Open
oharboe wants to merge 1 commit into
The-OpenROAD-Project:masterfrom
oharboe:fakeram-declared-pins
Open

oharboe wants to merge 1 commit into
The-OpenROAD-Project:masterfrom
oharboe:fakeram-declared-pins

Conversation

@oharboe

@oharboe oharboe commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator

AUTO_MEMORIES on asap7 turns each memory into a FakeRAM macro, but the macro always had FakeRAM's own pin names (rd_out, addr_in, we_in, wd_in, clk, ce_in) and no write mask. The module the flow blackboxes has the memory's own names, such as firtool's RW0_clk, RW0_addr, RW0_en, RW0_wmode, RW0_wdata, RW0_rdata and RW0_wmask. So the liberty view could not link to the netlist, and a masked memory had nothing to map its mask onto.

memory before after
firtool read-write port, no mask macro with FakeRAM's names: does not link macro with the module's names
byte mask (coralnpu's TCMs: 128 bits, 16 lanes) no mask pin wmask bus, per-lane writes
per-bit mask (76 lanes on a 128x76 memory) pins do not fit the left edge: FakeRAM fails macro made tall enough for a track per pin
detector-synthesized pins (no port convention) FakeRAM's names unchanged, byte-identical
several declared ports wrong macro, silently refused with a message

coralnpu and XiangShan both need masks: coralnpu's two TCMs are byte-masked, and XiangShan's firtool memories carry 57-bit lanes and per-bit masks in the branch predictor's tables.

One commit: FakeRAM asap7 builds the macro from the pins memories.json declares, write mask lanes included, and grows the macro so every pin gets a track. The height is part of the same change because the extra pins come from the mask lanes.

Tests: the new tools/FakeRAM2.0/test/spsram_mask_test.py checks the declared names and the mask in the liberty and LEF views, per-lane writes in the Verilog model, a per-bit mask getting a track per pin, that a mask which does not divide the word is refused, and that a memory declared as separate ports is refused. The existing FakeRAM tests, golden-file flow tests included, pass unchanged.

🤖 Generated with Claude Code

…k lanes

The orfs_asap7 backend read only rows and bits from memories.json and
emitted the single-port RAM FakeRAM has always emitted: rd_out, addr_in,
we_in, wd_in, clk, ce_in. The module the flow blackboxes has its own
port names -- for a firtool memory RW0_clk, RW0_addr, RW0_en, RW0_wmode,
RW0_wdata, RW0_rdata and RW0_wmask -- and a liberty view with different
pin names is one the netlist cannot link to. So conversion produced a
macro nothing could instantiate, for every memory, and the flow did not
say so.

The macro is now built from the pins the inventory declares. A memory
declared as one read-write port maps clock, address, enable, write
mode, data in and data out onto the single-port RAM's ports under the
module's names; a memory declared with any other port configuration is
refused with a message rather than emitted wrong. A memory whose pins
the detector synthesized (no port convention) keeps FakeRAM's
historical names, so nothing that worked before changes.

Write masks. SRAM compilers offer byte or lane write enables, and the
memories of real designs use them: coralnpu's two TCMs are 128 bits
wide with a byte mask, 16 lanes; XiangShan's firtool memories carry
57-bit lanes (two across 114 bits) and per-bit masks in the branch
predictor's tables. FakeRAM had no mask at all. RWPortGroup gains a
write mask bus with a lane count; the port creator, liberty exporter (a
bus type per mask, setup/hold against the port clock), LEF exporter and
the single-port Verilog model (per-lane writes) carry it; MemoryConfig
takes `pin_names` and `mask_lanes`; SinglePortRAM counts the lanes among
its pins. A memory without a mask emits byte-identically to before: the
golden-file flow tests pass unchanged.

Pin tracks. FakeRAM sizes a macro from its bit cells and then fails
when the pins do not fit the left edge, which a 128x76 memory with 76
mask lanes does. The backend computes the height the pins need, for
the column mux factor FakeRAM picks for that memory, and passes the
difference as additional_height instead of leaving each macro to fail
on its own.

test/spsram_mask_test.py covers the declared names and the mask in the
liberty and LEF views, the per-lane writes of the Verilog model, a
per-bit mask getting a track per pin, a mask that does not divide the
word being refused, and a memory declared as separate ports being
refused.

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 support for custom pin names and write-mask lanes in single-port RAM generation for the ORFS asap7 backend, updating memory configuration, port creation, and exporters (LEF, Liberty, and Verilog) to handle these features. Feedback suggests adding defensive checks in single_port_pins to prevent potential exceptions when parsing memories.json.

Comment thread tools/FakeRAM2.0/orfs_asap7/generate.py
@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 763d1e5 · Jenkins build #1 · Baseline: build · View build on dashboard

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

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.

2 participants