Cross-chiplet 3DIC static timing analysis#10664
Conversation
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
There was a problem hiding this comment.
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.
| 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)); | ||
| } |
There was a problem hiding this comment.
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));
}
}There was a problem hiding this comment.
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>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Summary
After
read_3dbx,dbNetworknow maps the 3DBlox chip structure (dbChip,dbChipInst,dbChipNet, bumps) onto OpenSTA'sNetwork, so one timing graphspans multiple chiplet
dbBlocks andreport_checksproduces realcross-chiplet flop-to-flop paths:
Scope: single-level hierarchy, zero-delay bonds. Chip-bump timing identity is
keyed on the per-unfold-path
dbUnfoldedChipBumpInst, so a chiplet masterinstantiated more than once does not collapse its bumps to one vertex.
How it works
Handle mapping (one level up from the 2D master/instance pattern):
Pin(chip bump)dbUnfoldedChipBumpInstNet(top net)dbChipNetgetObjectType()InstancedbChipInstgetObjectType()Cell/PortmakeTopCellForChip(no Liberty)Boundary crossing (chip-net = "fat net"):
blockDiscBitsstamps a per-chiplet-block discriminator into the upperObjectIdbits ([block_disc:8][db_id:20][tag:4]) so identically-numberedpins/nets from different chiplets don't alias in
PinSet/NetSet. No-op in 2D.Diagnostics
STA-3001WARN (HIER chiplet master, nested support incomplete) ·STA-3002ERROR (>255 unique chiplet blocks, discriminator overflow) ·STA-3003ERROR (chip-inst with no master).report_3dic_summaryprintsstructural counts.
odb
_dbChipBumpInst/_dbUnfoldedChipBumpInstget a 4-byteno-serialpad(
sizeof % 8 == 0) required by the low-3-bitPin*tag, guarded by astatic_assert. No.odbformat change.Tests
3dic_cross.tcl(cross-chiplet setup check) and3dic_get_cells.tcl(structural iteration), registered in CMake + Bazel. Full
dbStasuite (72)and odb
read_3dbx/write_3dbx/write_3dbv/check_3dbloxpass.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.
dbUnfoldedInst)STA-3001dbChipviadbChipNetBIDIRECT(passive-bump model)pin(Term)reverse bridge (forward descent works)dbBlockCallBackObjhook on chip-net/bump mutationObjectId(errorsORD-2019past the ceiling, never aliases)Spec docs included
specs/mission.md,specs/requirements.md, andspecs/2026-06-11-3dic-sta-track-a/requirements.md.