Skip to content

Cross-chiplet 3DIC static timing analysis#10664

Open
dsengupta0628 wants to merge 9 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:3dic-sta-track-a
Open

Cross-chiplet 3DIC static timing analysis#10664
dsengupta0628 wants to merge 9 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:3dic-sta-track-a

Conversation

@dsengupta0628

@dsengupta0628 dsengupta0628 commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

After read_3dbx, dbNetwork now maps the 3DBlox chip structure (dbChip,
dbChipInst, dbChipNet, bumps) onto OpenSTA's Network, so one timing graph
spans multiple chiplet dbBlocks and report_checks produces real
cross-chiplet flop-to-flop paths:

chipA/ff/CK -> ff/Q -> inv/ZN -> buf/Z -> chipB/buf/Z -> inv/ZN -> chipB/ff/D
constrained setup, slack 0.83 (MET).

Scope: single-level hierarchy, zero-delay bonds. Chip-bump timing identity is
keyed on the per-unfold-path dbUnfoldedChipBumpInst, so a chiplet master
instantiated more than once does not collapse its bumps to one vertex.

How it works

image

Handle mapping (one level up from the 2D master/instance pattern):

OpenSTA 3DBlox object encoding
Pin (chip bump) dbUnfoldedChipBumpInst low-3-bit pointer tag
Net (top net) dbChipNet cast + getObjectType()
Instance dbChipInst cast + getObjectType()
Cell/Port synth per chiplet master makeTopCellForChip (no Liberty)

Boundary crossing (chip-net = "fat net"):

   chipA: ...buf/Z --inner net-- bumpA --- dbChipNet --- bumpB --inner net-- buf/A... :chipB
   term(bumpA) -> chipA inner dbBTerm (descend);  net(bumpA) -> dbChipNet
   makeWireEdgesFromPin aggregates across the fat net -> edge chipA/buf/Z -> chipB/buf/A
image

blockDiscBits stamps a per-chiplet-block discriminator into the upper
ObjectId bits ([block_disc:8][db_id:20][tag:4]) so identically-numbered
pins/nets from different chiplets don't alias in PinSet/NetSet. No-op in 2D.

Diagnostics

STA-3001 WARN (HIER chiplet master, nested support incomplete) ·
STA-3002 ERROR (>255 unique chiplet blocks, discriminator overflow) ·
STA-3003 ERROR (chip-inst with no master). report_3dic_summary prints
structural counts.

odb

_dbChipBumpInst / _dbUnfoldedChipBumpInst get a 4-byte no-serial pad
(sizeof % 8 == 0) required by the low-3-bit Pin* tag, guarded by a
static_assert. No .odb format change.

Tests

3dic_cross.tcl (cross-chiplet setup check) and 3dic_get_cells.tcl
(structural iteration), registered in CMake + Bazel. Full dbSta suite (72)
and odb read_3dbx/write_3dbx/write_3dbv/check_3dblox pass.

Out of scope (follow-ups)

This is the single-level, zero-delay-bond foundation. The items below are
intentional scope boundaries, not regressions — each is gated by a guard or a
loud warning where it could otherwise mislead.

Deferred Follow-up
Duplicated-chiplet interiors (inner cells alias on a shared block; bump identity already fixed) per-path inner-instance object (dbUnfoldedInst)
Nested (HIER) chiplets — gated by STA-3001 unfolded-model callback wiring + path-aware identity
Bond RC (bonds are zero-delay) inter-chip parasitics on the hierarchical dbChip via dbChipNet
Active IO cells — bumps report BIDIRECT (passive-bump model) real port direction from the bound bterm
pin(Term) reverse bridge (forward descent works) inner-net-origin ascent
Map staleness is chip-net-count based; no rebuild once the graph is live dbBlockCallBackObj hook on chip-net/bump mutation
20-bit per-block ObjectId (errors ORD-2019 past the ceiling, never aliases) global id allocator

Spec docs included

specs/mission.md, specs/requirements.md, and
specs/2026-06-11-3dic-sta-track-a/requirements.md.

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
@dsengupta0628 dsengupta0628 self-assigned this Jun 15, 2026

@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 brings up 3DIC (3DBlox) cross-chiplet Static Timing Analysis (STA) in OpenROAD. It integrates the OpenDB unfolded model with OpenSTA, allowing independent timing of unique chiplet instances. Key changes include implementing 3D-aware network iterators, synthetic top-cell generation for hierarchical chips, and padding dbUnfoldedChipBumpInst to guarantee 8-byte alignment for pointer-tagging. Feedback on the changes highlights a potential issue in dbSta::postRead3Dbx where registering multiple callbacks for the same shared master block can unhook previously registered callbacks due to the single-owner semantics of dbBlockCallBackObj. Using a std::set to track and prevent redundant callback registrations is recommended.

Comment thread src/dbSta/src/dbSta.cc
Comment on lines +408 to +422
for (odb::dbChipInst* chip_inst : chip->getChipInsts()) {
odb::dbChip* master = chip_inst->getMasterChip();
if (master != nullptr
&& master->getChipType() == odb::dbChip::ChipType::HIER) {
hier_master_seen = true;
}
odb::dbBlock* chiplet_block = db_network_->blockOf(chip_inst);
if (chiplet_block == nullptr) {
continue;
}
auto cbk = std::make_unique<dbStaCbk>(this);
cbk->setNetwork(db_network_);
cbk->addOwner(chiplet_block);
chiplet_cbks_.push_back(std::move(cbk));
}

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

Since dbBlockCallBackObj is single-owner (where addOwner removes the previous owner), registering multiple callbacks for the same shared master block will unhook the previously registered callbacks, leaving them dead/inactive in chiplet_cbks_. We should keep track of already hooked blocks using a std::set to avoid registering redundant callbacks for the same block.

  std::set<odb::dbBlock*> hooked_blocks;
  for (odb::dbChipInst* chip_inst : chip->getChipInsts()) {
    odb::dbChip* master = chip_inst->getMasterChip();
    if (master != nullptr
        && master->getChipType() == odb::dbChip::ChipType::HIER) {
      hier_master_seen = true;
    }
    odb::dbBlock* chiplet_block = db_network_->blockOf(chip_inst);
    if (chiplet_block == nullptr) {
      continue;
    }
    if (hooked_blocks.insert(chiplet_block).second) {
      auto cbk = std::make_unique<dbStaCbk>(this);
      cbk->setNetwork(db_network_);
      cbk->addOwner(chiplet_block);
      chiplet_cbks_.push_back(std::move(cbk));
    }
  }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Your premise is incorrect. dbBlockCallBackObj::addOwner is:
if (owner_) { removeOwner(); } // removes THIS cbk from ITS prior block
block->callbacks_.insert(end(), this); // appends to the block's callback LIST
owner_ = new_owner;
A dbBlock holds a list of callbacks. addOwner only unhooks this callback from its own previous owner (a fresh dbStaCbk has owner_==null, so nothing is removed). It does not unhook other callbacks already on the block. So registering cbk1 then cbk2 on shared block B leaves B.callbacks = [cbk1, cbk2] — both live, neither dead/unhooked.

(The "single-owner" rule is real but means one callback owns one block at a time — not one block has one callback. That's why the original per-chiplet loop is correct: it's the inverse case — one cbk reused across N blocks would unhook itself from all but the last.)

The real issue (different fromyour reasoning, same fix): for a duplicated master — e.g. example.3dbx's soc_inst + soc_inst_duplicate sharing block SoC — blockOf returns the same B for both, so the loop hooks two callbacks on B. Not dead — redundant: every db edit on B fires both, so STA processes each edit twice (wasteful, and unsafe if any handler isn't idempotent). 3dic_get_cells hits this today (passes, so not crashing — but doubled).

So your suggested fix is correct, for the redundancy reason, not the unhook reason. I adopted it.

…from earlier version

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
@dsengupta0628 dsengupta0628 marked this pull request as ready for review June 15, 2026 20:09
@dsengupta0628 dsengupta0628 requested review from a team as code owners June 15, 2026 20:09
@dsengupta0628 dsengupta0628 changed the title # dbSta: cross-chiplet 3DIC static timing analysis dbSta: cross-chiplet 3DIC static timing analysis Jun 15, 2026
@dsengupta0628 dsengupta0628 changed the title dbSta: cross-chiplet 3DIC static timing analysis Cross-chiplet 3DIC static timing analysis Jun 15, 2026
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
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