Skip to content

Commit a5f58fc

Browse files
Merge pull request #9697 from ahmed532/feat/odb-dbTerm-dbChipBump
odb: create dbBTerm::getChipBump
2 parents 362a91a + db3857d commit a5f58fc

8 files changed

Lines changed: 169 additions & 25 deletions

File tree

src/odb/include/odb/db.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,6 +1546,12 @@ class dbBTerm : public dbObject
15461546
///
15471547
dbBlock* getBlock() const;
15481548

1549+
///
1550+
/// Get the chip bump associated with this block-terminal.
1551+
/// Returns nullptr if no chip bump is associated.
1552+
///
1553+
dbChipBump* getChipBump() const;
1554+
15491555
///
15501556
/// Get the hierarchical parent iterm of this bterm.
15511557
///

src/odb/src/3dblox/3dblox.cpp

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -114,25 +114,6 @@ void ThreeDBlox::buildChipNetsFromVerilog(dbChip* chip, const DbxData& data)
114114
return;
115115
}
116116

117-
// Pre-process master chips to map port names to bumps
118-
std::map<dbChip*, std::map<std::string, dbChipBump*>> master_bump_map;
119-
for (auto* inst : chip->getChipInsts()) {
120-
dbChip* master = inst->getMasterChip();
121-
122-
// Skip if already processed
123-
if (master_bump_map.contains(master)) {
124-
continue;
125-
}
126-
127-
for (auto* region : master->getChipRegions()) {
128-
for (auto* bump : region->getChipBumps()) {
129-
if (auto* bterm = bump->getBTerm()) {
130-
master_bump_map[master][bterm->getName()] = bump;
131-
}
132-
}
133-
}
134-
}
135-
136117
// Process nets
137118
std::unique_ptr<sta::NetIterator> net_iter(
138119
temp_network.netIterator(top_inst));
@@ -167,12 +148,14 @@ void ThreeDBlox::buildChipNetsFromVerilog(dbChip* chip, const DbxData& data)
167148
const char* port_name = temp_network.name(temp_network.port(pin));
168149
dbChip* master = chip_inst->getMasterChip();
169150

170-
auto bump_it = master_bump_map[master].find(port_name);
171-
if (bump_it == master_bump_map[master].end()) {
151+
dbBTerm* bterm = master->getBlock()->findBTerm(port_name);
152+
if (!bterm) {
153+
continue;
154+
}
155+
dbChipBump* bump = bterm->getChipBump();
156+
if (!bump) {
172157
continue;
173158
}
174-
175-
dbChipBump* bump = bump_it->second;
176159
auto* region_inst = chip_inst->findChipRegionInst(bump->getChipRegion());
177160
if (!region_inst) {
178161
continue;

src/odb/src/db/dbBTerm.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "dbBox.h"
1616
#include "dbBoxItr.h"
1717
#include "dbChip.h"
18+
#include "dbChipBump.h"
19+
#include "dbChipRegion.h"
1820
#include "dbCommon.h"
1921
#include "dbCore.h"
2022
#include "dbDatabase.h"
@@ -74,7 +76,9 @@ _dbBTerm::_dbBTerm(_dbDatabase*, const _dbBTerm& b)
7476
ground_pin_(b.ground_pin_),
7577
supply_pin_(b.supply_pin_),
7678
sta_vertex_id_(0),
77-
constraint_region_(b.constraint_region_)
79+
constraint_region_(b.constraint_region_),
80+
chip_region_(b.chip_region_),
81+
chip_bump_(b.chip_bump_)
7882
{
7983
if (b.name_) {
8084
name_ = safe_strdup(b.name_);
@@ -159,6 +163,14 @@ bool _dbBTerm::operator==(const _dbBTerm& rhs) const
159163
return false;
160164
}
161165

166+
if (chip_region_ != rhs.chip_region_) {
167+
return false;
168+
}
169+
170+
if (chip_bump_ != rhs.chip_bump_) {
171+
return false;
172+
}
173+
162174
return true;
163175
}
164176

@@ -183,6 +195,8 @@ dbOStream& operator<<(dbOStream& stream, const _dbBTerm& bterm)
183195
stream << bterm.constraint_region_;
184196
stream << bterm.mirrored_bterm_;
185197
stream << bterm.is_mirrored_;
198+
stream << bterm.chip_region_;
199+
stream << bterm.chip_bump_;
186200

187201
return stream;
188202
}
@@ -218,6 +232,10 @@ dbIStream& operator>>(dbIStream& stream, _dbBTerm& bterm)
218232
if (bterm.getDatabase()->isSchema(kSchemaBtermIsMirrored)) {
219233
stream >> bterm.is_mirrored_;
220234
}
235+
if (bterm.getDatabase()->isSchema(kSchemaBtermChipBump)) {
236+
stream >> bterm.chip_region_;
237+
stream >> bterm.chip_bump_;
238+
}
221239

222240
return stream;
223241
}
@@ -508,6 +526,18 @@ dbBlock* dbBTerm::getBlock() const
508526
return (dbBlock*) getImpl()->getOwner();
509527
}
510528

529+
dbChipBump* dbBTerm::getChipBump() const
530+
{
531+
const _dbBTerm* obj = (const _dbBTerm*) this;
532+
if (obj->chip_bump_ == 0) {
533+
return nullptr;
534+
}
535+
_dbBlock* block = (_dbBlock*) getImpl()->getOwner();
536+
_dbChip* chip = (_dbChip*) block->getOwner();
537+
_dbChipRegion* region = chip->chip_region_tbl_->getPtr(obj->chip_region_);
538+
return (dbChipBump*) region->chip_bump_tbl_->getPtr(obj->chip_bump_);
539+
}
540+
511541
Rect dbBTerm::getBBox()
512542
{
513543
Rect bbox;

src/odb/src/db/dbBTerm.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class _dbBlock;
2020
class _dbBPin;
2121
class _dbITerm;
2222
class _dbDatabase;
23+
class _dbChipRegion;
24+
class _dbChipBump;
2325
class dbIStream;
2426
class dbOStream;
2527

@@ -81,6 +83,8 @@ class _dbBTerm : public _dbObject
8183
Rect constraint_region_;
8284
dbId<_dbBTerm> mirrored_bterm_;
8385
bool is_mirrored_;
86+
dbId<_dbChipRegion> chip_region_;
87+
dbId<_dbChipBump> chip_bump_;
8488
};
8589

8690
dbOStream& operator<<(dbOStream& stream, const _dbBTerm& bterm);

src/odb/src/db/dbChipBump.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ void dbChipBump::setBTerm(dbBTerm* bterm)
138138
{
139139
_dbChipBump* obj = (_dbChipBump*) this;
140140
obj->bterm_ = bterm->getId();
141+
_dbBTerm* _bterm = (_dbBTerm*) bterm;
142+
_bterm->chip_region_ = obj->chip_region_;
143+
_bterm->chip_bump_ = obj->getOID();
141144
}
142145

143146
dbChipBump* dbChipBump::create(dbChipRegion* chip_region, dbInst* inst)

src/odb/src/db/dbDatabase.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ namespace odb {
5050
inline constexpr uint32_t kSchemaMajor = 0; // Not used...
5151
inline constexpr uint32_t kSchemaInitial = 57;
5252

53-
inline constexpr uint32_t kSchemaMinor = 126; // Current revision number
53+
inline constexpr uint32_t kSchemaMinor = 127; // Current revision number
54+
55+
// Revision where chip_bump_ back-reference was added to dbBTerm
56+
inline constexpr uint32_t kSchemaBtermChipBump = 127;
5457

5558
// Revision where dbTechLayer::wrong_way_min_width_ was added
5659
inline constexpr uint32_t kSchemaTechLayerMinWidthWrongway = 126;

src/odb/test/cpp/Test3DBloxParser.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,5 +389,51 @@ TEST_F(SimpleDbFixture, test_bump_map_reader_no_bterms)
389389
EXPECT_THROW(parser.readBMap(path), std::runtime_error);
390390
}
391391

392+
TEST_F(SimpleDbFixture, test_bterm_get_chip_bump)
393+
{
394+
createSimpleDB();
395+
396+
dbChip* chip = db_->getChip();
397+
dbBlock* block = chip->getBlock();
398+
399+
// Create a chip region on the chip
400+
dbChipRegion* region = dbChipRegion::create(
401+
chip, "bump_region", dbChipRegion::Side::BACK, nullptr);
402+
ASSERT_NE(region, nullptr);
403+
404+
// Create an inst to back the bump
405+
dbLib* lib = db_->findLib("lib1");
406+
dbMaster* bump_master = dbMaster::create(lib, "BUMP_CELL");
407+
bump_master->setType(dbMasterType::COVER_BUMP);
408+
bump_master->setFrozen();
409+
dbInst* bump_inst = dbInst::create(block, bump_master, "bump1");
410+
ASSERT_NE(bump_inst, nullptr);
411+
412+
// Create a chip bump
413+
dbChipBump* bump = dbChipBump::create(region, bump_inst);
414+
ASSERT_NE(bump, nullptr);
415+
416+
// Create bterms: one that will be associated with the bump, one that won't
417+
dbBTerm* sig1 = dbBTerm::create(dbNet::create(block, "SIG1"), "SIG1");
418+
dbBTerm* sig2 = dbBTerm::create(dbNet::create(block, "SIG2"), "SIG2");
419+
ASSERT_NE(sig1, nullptr);
420+
ASSERT_NE(sig2, nullptr);
421+
422+
// Before setBTerm: both bterms return nullptr for getChipBump
423+
EXPECT_EQ(sig1->getChipBump(), nullptr);
424+
EXPECT_EQ(sig2->getChipBump(), nullptr);
425+
426+
// Associate sig1 with the bump
427+
bump->setBTerm(sig1);
428+
429+
// After setBTerm: sig1 returns the bump, sig2 still returns nullptr
430+
EXPECT_EQ(sig1->getChipBump(), bump);
431+
EXPECT_EQ(sig2->getChipBump(), nullptr);
432+
433+
// Verify the reverse link is also consistent
434+
EXPECT_EQ(bump->getBTerm(), sig1);
435+
EXPECT_EQ(bump->getChipRegion(), region);
436+
}
437+
392438
} // namespace
393439
} // namespace odb

src/odb/test/cpp/TestChips.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#include <exception>
2+
#include <filesystem>
3+
#include <fstream>
4+
#include <ios>
25
#include <set>
36
#include <vector>
47

@@ -343,10 +346,14 @@ TEST_F(ChipHierarchyFixture, test_chip_bumps)
343346
EXPECT_EQ(io_bump->getBTerm(), nullptr);
344347
dbNet* net = dbNet::create(io_chip->getBlock(), "net1");
345348
dbBTerm* bterm = dbBTerm::create(net, "bterm1");
349+
// Before setBTerm, getChipBump returns nullptr
350+
EXPECT_EQ(bterm->getChipBump(), nullptr);
346351
io_bump->setNet(net);
347352
io_bump->setBTerm(bterm);
348353
EXPECT_EQ(io_bump->getNet(), net);
349354
EXPECT_EQ(io_bump->getBTerm(), bterm);
355+
// After setBTerm, getChipBump returns the bump (back-reference)
356+
EXPECT_EQ(bterm->getChipBump(), io_bump);
350357

351358
EXPECT_EQ(io_chip_region_r1->getChipBumps().size(), 1);
352359
EXPECT_EQ(*io_chip_region_r1->getChipBumps().begin(), io_bump);
@@ -389,5 +396,67 @@ TEST_F(ChipHierarchyFixture, test_chip_bumps)
389396
EXPECT_THROW(dbChipBump::create(io_chip_region_r1, io_cell), std::exception);
390397
}
391398

399+
TEST_F(SimpleDbFixture, test_chip_bump_bterm_serialization)
400+
{
401+
createSimpleDB();
402+
403+
dbChip* chip = db_->getChip();
404+
dbBlock* block = chip->getBlock();
405+
406+
// Create a chip region and a bump backed by an inst
407+
dbChipRegion* region = dbChipRegion::create(
408+
chip, "bump_region", dbChipRegion::Side::BACK, nullptr);
409+
dbLib* lib = db_->findLib("lib1");
410+
dbMaster* bump_master = dbMaster::create(lib, "BUMP_CELL");
411+
bump_master->setType(dbMasterType::COVER_BUMP);
412+
bump_master->setFrozen();
413+
dbInst* bump_inst = dbInst::create(block, bump_master, "bump1");
414+
dbChipBump* bump = dbChipBump::create(region, bump_inst);
415+
ASSERT_NE(bump, nullptr);
416+
417+
// Associate a bterm with the bump
418+
dbBTerm* bterm = dbBTerm::create(dbNet::create(block, "SIG1"), "SIG1");
419+
bump->setBTerm(bterm);
420+
ASSERT_EQ(bterm->getChipBump(), bump);
421+
422+
// Write the database to a temp file
423+
std::filesystem::create_directory("results");
424+
const std::string tmp_path = "results/test_chip_bump_bterm_serialization.odb";
425+
{
426+
std::ofstream out;
427+
out.exceptions(std::ifstream::failbit | std::ifstream::badbit
428+
| std::ios::eofbit);
429+
out.open(tmp_path, std::ios::binary);
430+
db_->write(out);
431+
}
432+
433+
// Read it back into a fresh database
434+
dbDatabase* db2 = dbDatabase::create();
435+
{
436+
std::ifstream in;
437+
in.exceptions(std::ifstream::failbit | std::ifstream::badbit
438+
| std::ios::eofbit);
439+
in.open(tmp_path, std::ios::binary);
440+
db2->read(in);
441+
}
442+
443+
// Locate the deserialized objects
444+
dbBlock* block2 = db2->getChip()->getBlock();
445+
ASSERT_NE(block2, nullptr);
446+
447+
dbBTerm* bterm2 = block2->findBTerm("SIG1");
448+
ASSERT_NE(bterm2, nullptr);
449+
450+
dbChipRegion* region2 = db2->getChip()->findChipRegion("bump_region");
451+
ASSERT_NE(region2, nullptr);
452+
ASSERT_EQ(region2->getChipBumps().size(), 1);
453+
dbChipBump* bump2 = *region2->getChipBumps().begin();
454+
ASSERT_NE(bump2, nullptr);
455+
456+
// Verify the back-reference survived serialization
457+
EXPECT_EQ(bterm2->getChipBump(), bump2);
458+
EXPECT_EQ(bump2->getBTerm(), bterm2);
459+
}
460+
392461
} // namespace
393462
} // namespace odb

0 commit comments

Comments
 (0)