ram: add latch-based memory architecture with auto-detection#10178
ram: add latch-based memory architecture with auto-detection#10178alokkumardalei-wq wants to merge 1 commit intoThe-OpenROAD-Project:masterfrom
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for latch-based storage cells in the RAM generator by implementing a master-slave latch configuration when a latch is detected. Key improvements suggested include moving the clock inverter from the bit level to the byte or word level to reduce area overhead, and using the Liberty API to dynamically discover pin names instead of hardcoding them. Additionally, the logic for selecting the write latch cell should be consolidated within the generation flow to eliminate a redundant and expensive second call to the cell discovery process.
| makeCellInst(bit_cell.get(), | ||
| prefix, | ||
| "clk_inv", | ||
| inv_cell_, | ||
| {{"A", clock}, {"Y", inv_clock}}); |
There was a problem hiding this comment.
| {{"A", clock}, {"Y", inv_clock}}); | ||
|
|
||
| // Negative latch: transparent when clock is LOW (inv_clock HIGH) | ||
| makeCellInst(bit_cell.get(), | ||
| prefix, | ||
| "wlatch", | ||
| write_latch_cell_, | ||
| {{"GATE", inv_clock}, {"D", data_input}, {"Q", write_latch_net}}); | ||
|
|
||
| // Positive latch (bitcell): transparent when gated clock is HIGH | ||
| makeCellInst(bit_cell.get(), | ||
| prefix, | ||
| "bit", | ||
| storage_cell_, | ||
| {{"GATE", clock}, {"D", write_latch_net}, {"Q", storage_net}}); |
There was a problem hiding this comment.
Hardcoding pin names like "A", "Y", "GATE", "D", and "Q" makes the generator dependent on specific library naming conventions (e.g., Sky130). It is recommended to discover these pin names using the Liberty API (e.g., by checking pin functions or attributes) to ensure compatibility across different standard cell libraries.
| // For latch-based memories, auto-select a write data latch cell. | ||
| // This uses the same storage cell master since both the write latch | ||
| // and bitcell are positive-transparent latches — the write latch is | ||
| // made negative by inverting the clock fed to its GATE pin. | ||
| if (storage_type_ == StorageType::LATCH && !write_latch_cell_) { | ||
| write_latch_cell_ = storage_cell_; | ||
| logger_->info( | ||
| RAM, 23, "Latch-based memory: using {} as write data latch", | ||
| write_latch_cell_->getName()); | ||
| } |
There was a problem hiding this comment.
This logic for selecting write_latch_cell_ depends on storage_type_, which is detected after the first call to findMasters(). Moving this logic to the generate function after detection avoids the need for a second redundant call to findMasters(), which is an expensive operation as it iterates over all library cells.
References
- When analyzing code structure, identify and eliminate redundant operations or calls that can be consolidated based on the execution flow.
| findMasters(); | ||
|
|
||
| // Detect whether the storage cell is a latch or flip-flop | ||
| storage_type_ = detectStorageType(storage_cell_); | ||
| if (storage_type_ == StorageType::LATCH) { | ||
| logger_->info(RAM, 24, "Detected latch-based storage cell: {}", | ||
| storage_cell_->getName()); | ||
| } | ||
| // Re-run findMasters to pick up write_latch_cell_ if needed | ||
| findMasters(); |
There was a problem hiding this comment.
The second call to findMasters() is redundant. By moving the write_latch_cell_ selection logic here after storage_type_ detection, you can resolve all necessary cells in a single pass.
findMasters();
// Detect whether the storage cell is a latch or flip-flop
storage_type_ = detectStorageType(storage_cell_);
if (storage_type_ == StorageType::LATCH) {
logger_->info(RAM, 24, "Detected latch-based storage cell: {}",
storage_cell_->getName());
if (!write_latch_cell_) {
write_latch_cell_ = storage_cell_;
logger_->info(RAM, 23, "Latch-based memory: using {} as write data latch",
write_latch_cell_->getName());
}
}References
- When analyzing code structure, identify and eliminate redundant operations or calls that can be consolidated based on the execution flow.
f32f876 to
353e80a
Compare
353e80a to
f329ce5
Compare
Detect latch vs flip-flop storage cells using OpenSTA's Sequential API and generate master-slave latch arrangements when a latch cell is provided. The write data latch uses an inverted gated clock (shared per slice) to create negative transparency, while the bitcell latch uses the regular gated clock for positive transparency. Key changes: - Add StorageType enum and detectStorageType() using Sequential::isLatch() - Add write_latch_cell_ auto-selection (reuses storage cell master) - Add latch path in makeBit() with shared inverted clock from makeSlice() - Use upstream's buildPortMap() for dynamic pin name discovery Resolves: The-OpenROAD-Project#10153 Signed-off-by: alokkumardalei-wq <alokkumar.dalei@gmail.com> Signed-off-by: alokkumardalei-wq <alokkumardalei2@gmail.com>
f329ce5 to
cb2f9a3
Compare
|
clang-tidy review says "All clean, LGTM! 👍" |
What does this PR do?
Addressed #10153
This adds latch-based memory support to the RAM module, addressing
The existing RAM generator treats every storage cell the same way data goes straight into the bitcell. That works fine for flip-flops, but for latches it misses an important architectural optimization: the master-slave latch arrangement that prevents write-through while keeping the area and power benefits of latches.
Buffer placement optimization is left for a follow-up per #10153 discussion
Type of Change
Verification
./etc/Build.sh).