Skip to content

ram: add latch-based memory architecture with auto-detection#10178

Closed
alokkumardalei-wq wants to merge 1 commit intoThe-OpenROAD-Project:masterfrom
alokkumardalei-wq:feature/ram-latch-support
Closed

ram: add latch-based memory architecture with auto-detection#10178
alokkumardalei-wq wants to merge 1 commit intoThe-OpenROAD-Project:masterfrom
alokkumardalei-wq:feature/ram-latch-support

Conversation

@alokkumardalei-wq
Copy link
Copy Markdown
Contributor

@alokkumardalei-wq alokkumardalei-wq commented Apr 18, 2026

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

  • New feature

Verification

  • I have verified that the local build succeeds (./etc/Build.sh).
  • make_8x8 passes (dlxtp_1 correctly triggers latch mode)
  • dfxtp_1 (flip-flop) does NOT trigger latch mode
  • Full flow completes: netlist → PDN → routing
  • My code follows the repository's formatting guidelines.
  • I have signed my commits (DCO).

@alokkumardalei-wq alokkumardalei-wq changed the title Feature/ram latch support ram: add latch-based memory architecture with auto-detection Apr 18, 2026
Copy link
Copy Markdown
Contributor

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

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 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.

Comment thread src/ram/src/ram.cpp Outdated
Comment on lines +143 to +147
makeCellInst(bit_cell.get(),
prefix,
"clk_inv",
inv_cell_,
{{"A", clock}, {"Y", inv_clock}});
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.

medium

Instantiating a clock inverter for every single bit is highly inefficient in terms of area. Consider moving the clock inversion to the byte or word level (e.g., in makeCellByte) and passing the inverted clock net to makeCellBit to share the inverter across multiple bits.

Comment thread src/ram/src/ram.cpp Outdated
Comment on lines +147 to +161
{{"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}});
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.

medium

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.

Comment thread src/ram/src/ram.cpp
Comment on lines +464 to +473
// 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());
}
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.

medium

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
  1. When analyzing code structure, identify and eliminate redundant operations or calls that can be consolidated based on the execution flow.

Comment thread src/ram/src/ram.cpp Outdated
Comment on lines 665 to 674
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();
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.

medium

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
  1. When analyzing code structure, identify and eliminate redundant operations or calls that can be consolidated based on the execution flow.

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>
@alokkumardalei-wq alokkumardalei-wq force-pushed the feature/ram-latch-support branch from f329ce5 to cb2f9a3 Compare April 18, 2026 08:28
@github-actions
Copy link
Copy Markdown
Contributor

clang-tidy review says "All clean, LGTM! 👍"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant