Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
59b546c
ram: generate_ram with more than one write port
oharboe Oct 13, 2026
bf11c6f
ram: generate_ram reads through AND-OR trees without tristates
oharboe Oct 13, 2026
cf7e10e
ram: generate_ram -zero_word, a word that reads 0
oharboe Oct 13, 2026
530b986
ram: generate_ram -reset_value, an asynchronous reset
oharboe Oct 13, 2026
5621732
ram: generate_ram -banks, -bank_columns, -bank_order
oharboe Oct 13, 2026
ddf44b6
ram: generate_ram -rb_ports, banked read ports
oharboe Oct 13, 2026
f3bcded
ram: generate_ram -read_latency, registered read addresses
oharboe Oct 13, 2026
6324599
ram: generate_ram -write_style mux, a hold mux per bit
oharboe Oct 13, 2026
403f149
ram: generate_ram_netlist -periphery unplaced
oharboe Oct 13, 2026
2a784a5
ram: generate_ram -cells and -name
oharboe Oct 13, 2026
7957723
ram: generate_ram -decoder word, a balanced tree per word
oharboe Oct 13, 2026
654faad
ram: generate_ram -bit_folds, a word's slices in rows
oharboe Oct 13, 2026
61b46c9
ram: generate_ram_netlist -periphery verilog
oharboe Oct 13, 2026
a296682
ram: generate_ram -write_priority or, colliding writes OR'd
oharboe Oct 13, 2026
6adb39e
ram: generate_ram -service_columns, room in the array
oharboe Oct 13, 2026
a9bc376
ram: generate_ram -bank_column_layout, a word's bits contiguous
oharboe Oct 13, 2026
00e99e3
ram: stop on out-of-range option values
oharboe Oct 13, 2026
546f5d3
ram: test BUILD's per-test data in sorted order
oharboe Oct 13, 2026
dd70886
ram: -read_latency is -register_read_address
oharboe Oct 14, 2026
460fe9a
ram: generate_ram routes on asap7
oharboe Oct 14, 2026
3cb6b6d
ram: generate_ram -periphery verilog, the core routed
oharboe Oct 14, 2026
446e0db
ram: the option tests route their blocks through generate_ram
oharboe Oct 14, 2026
d6bb185
ram: generate_ram's help lists its options
oharboe Oct 14, 2026
e36b6de
ram: -periphery verilog keeps no destroyed pins
oharboe Oct 23, 2026
33cdb7f
ram: -cells checks every role's function
oharboe Oct 23, 2026
cc26e72
ram: -reset_value is parsed strictly
oharboe Oct 23, 2026
7888838
ram: reset and the read address find their flops
oharboe Oct 23, 2026
4cdb057
ram: cell search skips dont_use, isolation and level-shifter cells
oharboe Oct 23, 2026
968effd
ram: a tie cell may drive both levels
oharboe Oct 23, 2026
cdd12c1
ram: -write_style mux needs no clock-gate cell
oharboe Oct 23, 2026
92c1775
ram: a clock gate's test enable is tied low
oharboe Oct 23, 2026
ca74189
ram: -periphery verilog stops on logic it cannot write
oharboe Oct 23, 2026
59f3349
ram: several write ports are checked in generate
oharboe Oct 23, 2026
8d8a755
ram: a scan flop is not a plain address flop
oharboe Oct 23, 2026
dfe0d0b
ram: -decoder word's errors name -decoder word
oharboe Oct 23, 2026
cc15070
ram: -bank_column_layout contiguous keeps a word's slices together
oharboe Oct 23, 2026
89a7ee5
ram: -periphery unplaced puts pins on tracks across the layer only
oharboe Oct 23, 2026
c2b9f6d
ram: pins keep a pin's width from the power straps
oharboe Oct 23, 2026
16c1e3f
ram: options that change nothing say so
oharboe Oct 23, 2026
2653a2e
ram: stale comments and empty select nets
oharboe Oct 23, 2026
1170b35
ram: generate_ram's register-file options are experimental
oharboe Oct 23, 2026
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
43 changes: 40 additions & 3 deletions src/ram/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ The `generate_ram` command is an all-in-one command to place and route a RAM.
Standard cell libraries must be loaded before running this command.
The module will create a new design, therefore a design should not be loaded before running the command.

The options marked **Experimental.** below, and more than one write port, were added for register files. They are a baseline to build on: their interface may change, and they may move to a command of their own, such as a `generate_register`, with these `generate_ram` options retired once flows use it. A run that uses any of them names them in RAM-0105, and `-tracks` in RAM-0106.

```tcl
generate_ram [-mask_size bits]
-word_size bits
Expand All @@ -43,6 +45,22 @@ generate_ram [-mask_size bits]
[-column_mux_ratio ratio]
[-storage_cell name]
[-tristate_cell name]
[-read_style tristate|and_or]
[-zero_word word]
[-reset_value value]
[-banks count]
[-bank_columns count]
[-bank_order contiguous|interleaved]
[-rb_ports count]
[-register_read_address 0|1]
[-write_style clock_gate|mux]
[-write_priority last|or]
[-service_columns {every sites}]
[-bank_column_layout interleaved|contiguous]
[-cells {role master ...}]
[-name name]
[-decoder row|word]
[-bit_folds count]
[-inv_cell name]
[-power_net_name name]
[-ground_net_name name]
Expand All @@ -53,6 +71,9 @@ generate_ram [-mask_size bits]
[-tapcell name]
[-max_tap_dist value]
[-write_behavioral_verilog filename]
[-periphery placed|verilog]
[-wrapper_verilog file]
[-tracks file]
```

#### Options
Expand All @@ -62,12 +83,27 @@ generate_ram [-mask_size bits]
| `-mask_size` | Determines the number of bits which are grouped together for masking during writes. For example, a mask size of `8` will enable each 8 bits of the word to be masked when writing (commonly known as byte masking). A mask size of `1` will enable each bit to be individually masked. The write enable signal for each port will be `(word_size / mask_size)` bits wide. The word size must be a multiple of the mask size. Default: equal to `-word_size`. |
| `-word_size` | Size of each word in bits. |
| `-num_words` | Number of words in the array. |
| `-rw_ports` | Number of read-write ports for the array. Sum of read-write ports and write ports must equal 1. Default: 1. |
| `-rw_ports` | Number of read-write ports for the array: 0 or 1, and a read-write port is the only write port. Default: 1. |
| `-r_ports` | Number of read ports for the array. Default: 0. |
| `-w_ports` | Number of write ports for the array. Sum of read-write ports and write ports must equal 1. Default: 0. |
| `-w_ports` | Number of write ports for the array. With more than one, each has its own address decoder, data (`D0`, `D1`, ...), write enables (`we0`, ...) and address (`addr_w0`, ...); a word two ports write in the same cycle keeps the last port's data. More than one write port is **experimental**. Not yet with `-use_latch` or `-column_mux_ratio` above 1. Default: 0. |
| `-column_mux_ratio` | Number of words sharing a physical column. Must be `1`, `2`, or `4`. The number of words must be divisible by the column mux ratio. Default: `1` (no column muxing). |
| `-storage_cell` | Name of the master to use for the storage device (i.e. a flip-flop). Must be positive-edge triggered. Default: auto-select from the loaded cell library. |
| `-tristate_cell` | Name of the master to use for the tristate device (i.e. a tristate inverter). It is currently assumed that the device is inverting. Default: auto-select from the loaded cell library. |
| `-read_style` | **Experimental.** The read path: `tristate`, a tristate bitline per bit, or `and_or`, a tree per bit column of an AOI22 over each pair of rows and NAND2 and NOR2 levels above, for a library without a tristate cell. `and_or` also takes a storage flop whose only output is inverted (QN). Default: `tristate` where the library has a tristate cell, `and_or` where it has none. |
| `-zero_word` | **Experimental.** A word that reads 0 and drops its writes, as a RISC-V register file's x0: its row has no flops or clock gate, and the read trees leave it out. Needs `-read_style and_or` and `-column_mux_ratio 1`. Default: none. |
| `-reset_value` | **Experimental.** Resets every word to `value`, decimal, `0x` hexadecimal or `0` octal and no wider than the word, asynchronously, through a reset port at the storage flop's own polarity (`rst_n` or `rst`); each bit's flop is cleared or preset, the other pin held off. The storage cell has both an asynchronous clear and preset, also for a value of 0. A parent adapts a reset of another polarity, or a synchronous one, to it. Not with `-use_latch`. Default: no reset. |
| `-banks`, `-bank_columns`, `-bank_order` | **Experimental.** The words in `banks` banks, contiguous or interleaved in the address, `bank_columns` of them side by side and the rest stacked. With banks each port decodes every word's whole address, so a bank need not be a power of two words. Not with `-column_mux_ratio` above 1 or `-use_latch`. Default: one bank. |
| `-rb_ports` | **Experimental.** Banked read ports, with `-banks`: each an address and a data output per bank (`addr_rb<k>_b<b>`, `Qrb<k>_b<b>`), the address the word's index in its bank, every bank read independently. The block has no mux across the banks: selecting a bank's data, and registering the selection, is the parent's. Default: 0. |
| `-register_read_address` | **Experimental.** `1` registers every read port's address, a plain positive-edge flop per address bit, so the decoders and read trees come after the flop and the data follows a cycle after the address. This is the read address register, not a register on the read data. A read whose address is registered on the clock that writes its word returns the new data (write-first). 0 and 1 only. Not with `-column_mux_ratio` above 1 or read/write ports. Default: 0. |
| `-write_style` | **Experimental.** How a word holds its value between writes: `clock_gate`, a clock gate per word; or `mux`, every flop on the clock and a mux per bit taking the new data or the flop's own value. A clock gate saves a mux per bit; a mux keeps every flop on the plain clock, so every flop is clocked every cycle and clock power grows with the block's bits, not the words written. Not with `-use_latch`. Default: `clock_gate`. |
| `-write_priority` | **Experimental.** Where two write ports write the same word in one cycle: `last`, the last port's data; or `or`, the OR of every writing port's data, as RTL that merges its writes with an OR describes it. `or` drops a word's priority logic, an inverter and an AND2 per port but the last. Default: `last`. |
| `-service_columns {every sites}` | **Experimental.** An empty column `sites` sites wide after every `every` columns of the array, its bits' and selects' alike: room inside the array for the buffers a parent flow inserts on the long nets that cross it, where the array is otherwise full. Default: none. |
| `-bank_column_layout interleaved\|contiguous` | **Experimental.** With banks, how a row's words share its columns: `interleaved`, bit by bit as the column mux lays them out; or `contiguous`, each word's bits side by side with its select column after them. Contiguous keeps a word's selects and write enables as short as its own bits, where interleaved runs them the whole row; the read trees and each write port's data nets then cross the row instead. Default: `interleaved`. |
| `-periphery`, `-pin_layer`, `-wrapper_verilog` | **Experimental.** `unplaced` and `-pin_layer` are `generate_ram_netlist`'s only, for a flow that places the periphery itself; `generate_ram` takes `placed` and `verilog`, routes the core and puts its pins on its edges. `unplaced` leaves the periphery (address inverters and registers, decoders, select buffers, each word's select cell, the input buffers) for a parent to place, size and buffer; the outline is the placed core and a row, and each pin sits where its connections land, on `-pin_layer`'s tracks, for a macro placer before the parent dissolves the core into its rows. `verilog` makes the core a block of its own, `<name>_core`, and writes the periphery to `-wrapper_verilog` as a Verilog module, `<name>`, around it: assigns of the cells' functions, for synthesis to map with the parent. Default: `placed`. |
| `-cells` | **Experimental.** The cell for a role (`inv`, `and2`, `buffer`, `clock_gate`, `aoi22`, `ao22`, `or2`, `nand2`, `nor2`, `tie`, `addr_flop`), instead of the smallest the libraries have of its function. An AOI22 or AO22 given is checked by its truth table. Default: the smallest of each. |
| `-name` | **Experimental.** The block's and the behavioral model's name. Default: `RAM<words>x<bits>`. |
| `-decoder` | **Experimental.** `row`: a decoder per row, an AND2 chain over the row address, the column mux selecting within the row. `word`: a balanced AND2 tree over each word's whole address, as with banks; shallower for the read path. Default: `row`. |
| `-bit_folds` | **Experimental.** A word in `count` rows: its bits in slices of `-mask_size` (the word divided by `count`, rounded up; the last slice may be short), one slice a row, so a wide word with many ports is not a long thin strip. A folded word is written whole, one write enable a port, its write logic built once and shared by its rows. Not with `-use_latch` or the row decoder's `-column_mux_ratio` above 1. Default: 1. |
| `-inv_cell` | Name of the master to use for inverters. Default: auto-select from the loaded cell library. |
| `-routing_layer` | A list of the metal layer and metal width (in microns) for generating standard cell power tracks (followpins). Example: `{met1 0.48}`. |
| `-power_net_name` | Name of the power net to create. Default: `VDD`. |
Expand All @@ -79,6 +115,7 @@ generate_ram [-mask_size bits]
| `-max_tap_dist` | The distance (in microns) that tapcells should be placed apart. Requires `-tapcell`. |
| `-use_latch` | If set to `1`, uses a two-phase latch-based design instead of flip-flops for the storage elements. Functionally equivalent to flip-flop design with smaller storage cell area. Default: `0`. |
| `-write_behavioral_verilog` | Write a behavioral Verilog model of the RAM array to the specified file. |
| `-tracks` | **Experimental.** `generate_ram` only. A Tcl file of `make_tracks` commands, sourced in place of `make_tracks` with the technology LEF's offsets, for a technology whose offsets do not fit the block (asap7's M2 offset is negative). Default: the LEF's tracks. |

## Example scripts

Expand All @@ -96,7 +133,7 @@ Simply run the following script:

## Limitations

This is an experimental module and many basic features may not work yet. Please see [#9392](https://github.com/The-OpenROAD-Project/OpenROAD/issues/9392) for ongoing and future work.
This is an experimental module and many basic features may not work yet. The register-file options are experimental on their own account, see [RAM Generation](#ram-generation). Please see [#9392](https://github.com/The-OpenROAD-Project/OpenROAD/issues/9392) for ongoing and future work.

## Authors

Expand Down
3 changes: 3 additions & 0 deletions src/ram/include/ram/layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class Layout

int getWidth() const;

// a floor on the width, for a column kept empty
void setMinWidth(int width);

private:
odb::Orientation2D orientation_;
odb::Point origin_;
Expand Down
Loading
Loading