Skip to content

Commit de622b2

Browse files
authored
Merge pull request #9142 from The-OpenROAD-Project-staging/secure-fix-restore-odb-hash-in-module
odb: Fixed a bug where `_dbModule::modbterm_hash_` is emtpy after `read_db` is executed
2 parents 668f6e7 + f5d91b0 commit de622b2

File tree

7 files changed

+119
-47
lines changed

7 files changed

+119
-47
lines changed

src/odb/src/db/dbBlock.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <set>
2626
#include <sstream>
2727
#include <string>
28+
#include <unordered_map>
2829
#include <utility>
2930
#include <vector>
3031

@@ -859,6 +860,43 @@ dbOStream& operator<<(dbOStream& stream, const _dbBlock& block)
859860
return stream;
860861
}
861862

863+
/**
864+
* @brief Rebuilds the name-to-ID hash maps for hierarchical objects within
865+
* their respective modules.
866+
*
867+
* This function is used during database loading (operator>>) to restore the
868+
* fast-lookup hashes that were stored in the ODB.
869+
*
870+
* @tparam T The public ODB object type (e.g., dbInst, dbModNet).
871+
* @tparam T_impl The internal implementation type (e.g., _dbInst, _dbModNet).
872+
* @param block The database block containing the objects.
873+
* @param table The internal database table storing the object implementations.
874+
* @param module_field Member pointer to the field storing the parent module ID
875+
* (e.g., &_dbInst::module_ or &_dbModInst::parent_).
876+
* @param hash_field Member pointer to the hash map member in _dbModule where
877+
* the object ID should be stored.
878+
*/
879+
template <typename T, typename T_impl>
880+
static void rebuildModuleHash(
881+
_dbBlock& block,
882+
dbTable<T_impl>* table,
883+
dbId<_dbModule> T_impl::*module_field,
884+
std::unordered_map<std::string, dbId<T_impl>> _dbModule::*hash_field)
885+
{
886+
dbSet<T> items((dbBlock*) &block, table);
887+
for (T* obj : items) {
888+
T_impl* _obj = (T_impl*) obj;
889+
dbId<_dbModule> mid = _obj->*module_field;
890+
if (mid == 0) {
891+
mid = block.top_module_;
892+
}
893+
_dbModule* module = block.module_tbl_->getPtr(mid);
894+
if (module && _obj->name_) {
895+
(module->*hash_field)[_obj->name_] = _obj->getId();
896+
}
897+
}
898+
}
899+
862900
dbIStream& operator>>(dbIStream& stream, _dbBlock& block)
863901
{
864902
_dbDatabase* db = block.getImpl()->getDatabase();
@@ -950,17 +988,43 @@ dbIStream& operator>>(dbIStream& stream, _dbBlock& block)
950988
stream >> *block.inst_tbl_;
951989
stream >> *block.module_tbl_;
952990
}
991+
if (db->isSchema(kSchemaDbRemoveHash)) {
992+
// Construct dbinst_hash_
993+
rebuildModuleHash<dbInst>(
994+
block, block.inst_tbl_, &_dbInst::module_, &_dbModule::dbinst_hash_);
995+
}
953996
if (db->isSchema(kSchemaBlockOwnsScanInsts)) {
954997
stream >> *block.scan_inst_tbl_;
955998
}
956999
stream >> *block.modinst_tbl_;
1000+
if (db->isSchema(kSchemaDbRemoveHash)) {
1001+
// Construct modinst_hash_
1002+
rebuildModuleHash<dbModInst>(block,
1003+
block.modinst_tbl_,
1004+
&_dbModInst::parent_,
1005+
&_dbModule::modinst_hash_);
1006+
}
9571007
if (db->isSchema(kSchemaUpdateHierarchy)) {
9581008
stream >> *block.modbterm_tbl_;
1009+
if (db->isSchema(kSchemaDbRemoveHash)) {
1010+
// Construct modbterm_hash_
1011+
rebuildModuleHash<dbModBTerm>(block,
1012+
block.modbterm_tbl_,
1013+
&_dbModBTerm::parent_,
1014+
&_dbModule::modbterm_hash_);
1015+
}
9591016
if (db->isSchema(kSchemaDbRemoveHash)) {
9601017
stream >> *block.busport_tbl_;
9611018
}
9621019
stream >> *block.moditerm_tbl_;
9631020
stream >> *block.modnet_tbl_;
1021+
if (db->isSchema(kSchemaDbRemoveHash)) {
1022+
// Construct modnet_hash_
1023+
rebuildModuleHash<dbModNet>(block,
1024+
block.modnet_tbl_,
1025+
&_dbModNet::parent_,
1026+
&_dbModule::modnet_hash_);
1027+
}
9641028
}
9651029
stream >> *block.powerdomain_tbl_;
9661030
stream >> *block.logicport_tbl_;

src/odb/src/db/dbInst.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -191,24 +191,6 @@ dbIStream& operator>>(dbIStream& stream, _dbInst& inst)
191191
stream >> inst.iterms_;
192192
stream >> inst.halo_;
193193
stream >> inst.pin_access_idx_;
194-
195-
dbDatabase* db = (dbDatabase*) (inst.getDatabase());
196-
if (((_dbDatabase*) db)->isSchema(kSchemaDbRemoveHash)) {
197-
_dbBlock* block = (_dbBlock*) (db->getChip()->getBlock());
198-
_dbModule* module = nullptr;
199-
// if the instance has no module parent put in the top module
200-
// We sometimes see instances with _module set to 0 (possibly
201-
// introduced downstream) so we stick them in the hash for the
202-
// top module.
203-
if (inst.module_ == 0) {
204-
module = (_dbModule*) (((dbBlock*) block)->getTopModule());
205-
} else {
206-
module = block->module_tbl_->getPtr(inst.module_);
207-
}
208-
if (inst.name_) {
209-
module->dbinst_hash_[inst.name_] = dbId<_dbInst>(inst.getId());
210-
}
211-
}
212194
return stream;
213195
}
214196

src/odb/src/db/dbModBTerm.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,16 +107,6 @@ dbIStream& operator>>(dbIStream& stream, _dbModBTerm& obj)
107107
if (obj.getDatabase()->isSchema(kSchemaHierPortRemoval)) {
108108
stream >> obj.prev_entry_;
109109
}
110-
// User Code Begin >>
111-
if (obj.getDatabase()->isSchema(kSchemaDbRemoveHash)) {
112-
dbDatabase* db = (dbDatabase*) (obj.getDatabase());
113-
_dbBlock* block = (_dbBlock*) (db->getChip()->getBlock());
114-
_dbModule* module = block->module_tbl_->getPtr(obj.parent_);
115-
if (obj.name_) {
116-
module->modbterm_hash_[obj.name_] = obj.getId();
117-
}
118-
}
119-
// User Code End >>
120110
return stream;
121111
}
122112

src/odb/src/db/dbModInst.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,6 @@ dbIStream& operator>>(dbIStream& stream, _dbModInst& obj)
106106
if (db_->isSchema(kSchemaUpdateHierarchy)) {
107107
stream >> obj.moditerms_;
108108
}
109-
if (db_->isSchema(kSchemaDbRemoveHash)) {
110-
_dbBlock* block = (_dbBlock*) (((dbDatabase*) db_)->getChip()->getBlock());
111-
_dbModule* module = block->module_tbl_->getPtr(obj.parent_);
112-
if (obj.name_) {
113-
module->modinst_hash_[obj.name_] = obj.getId();
114-
}
115-
}
116109
// User Code End >>
117110
return stream;
118111
}

src/odb/src/db/dbModNet.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,16 +106,6 @@ dbIStream& operator>>(dbIStream& stream, _dbModNet& obj)
106106
if (obj.getDatabase()->isSchema(kSchemaUpdateHierarchy)) {
107107
stream >> obj.bterms_;
108108
}
109-
// User Code Begin >>
110-
if (obj.getDatabase()->isSchema(kSchemaDbRemoveHash)) {
111-
dbDatabase* db = (dbDatabase*) (obj.getDatabase());
112-
_dbBlock* block = (_dbBlock*) (db->getChip()->getBlock());
113-
_dbModule* module = block->module_tbl_->getPtr(obj.parent_);
114-
if (obj.name_) {
115-
module->modnet_hash_[obj.name_] = dbId<_dbModNet>(obj.getId());
116-
}
117-
}
118-
// User Code End >>
119109
return stream;
120110
}
121111

src/odb/test/cpp/TestWriteReadDbHier.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,58 @@ TEST_F(TestWriteReadDbHier, WriteReadOdb)
178178
ASSERT_NE(db2_mi1, nullptr);
179179
}
180180

181+
// Construct hierarchical netlist with multiple blocks and write/read it back.
182+
// The hierarchical netlist should be read back successfully.
183+
TEST_F(TestWriteReadDbHier, WriteReadOdbMultiBlocks)
184+
{
185+
SetUpTmpPath("WriteReadOdbMultiBlocks");
186+
db_->setHierarchy(true);
187+
188+
// Create masters
189+
dbMaster* buf_master = db_->findMaster("BUF_X1");
190+
ASSERT_TRUE(buf_master);
191+
192+
// Create child block
193+
dbBlock* child_block = dbBlock::create(block_, "CHILD_BLOCK");
194+
ASSERT_TRUE(child_block);
195+
196+
// Create module in child block
197+
dbModule* mod0 = dbModule::create(child_block, "MOD0");
198+
ASSERT_TRUE(mod0);
199+
200+
dbModBTerm* mod0_a = dbModBTerm::create(mod0, "A");
201+
ASSERT_TRUE(mod0_a);
202+
203+
// Create instance in child block
204+
dbInst* child_inst
205+
= dbInst::create(child_block, buf_master, "child_inst", false, mod0);
206+
ASSERT_TRUE(child_inst);
207+
208+
//--------------------------------------------------------------
209+
// Write ODB and read back
210+
//--------------------------------------------------------------
211+
dbDatabase* db2 = writeReadDb();
212+
ASSERT_TRUE(db2->hasHierarchy());
213+
dbBlock* top_block2 = db2->getChip()->getBlock();
214+
215+
// Find child block
216+
dbBlock* child_block2 = top_block2->findChild("CHILD_BLOCK");
217+
ASSERT_NE(child_block2, nullptr);
218+
219+
// Find module in child block
220+
dbModule* mod0_2 = child_block2->findModule("MOD0");
221+
ASSERT_NE(mod0_2, nullptr);
222+
223+
// Verify ModBTerm hash is populated
224+
dbModBTerm* mod0_a_2 = mod0_2->findModBTerm("A");
225+
ASSERT_NE(mod0_a_2, nullptr);
226+
EXPECT_STREQ(mod0_a_2->getName(), "A");
227+
228+
// Verify Inst hash is populated
229+
dbInst* child_inst_2 = mod0_2->findDbInst("child_inst");
230+
ASSERT_NE(child_inst_2, nullptr);
231+
EXPECT_EQ(child_inst_2->getName(), "child_inst");
232+
}
233+
181234
} // namespace
182235
} // namespace odb

src/tst/include/tst/IntegratedFixture.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ class IntegratedFixture : public tst::Fixture
3535
void removeFile(const std::string& path);
3636

3737
protected:
38-
odb::dbLib* lib_;
38+
odb::dbLib* lib_{nullptr};
3939
odb::dbBlock* block_{nullptr};
40-
sta::dbNetwork* db_network_;
40+
sta::dbNetwork* db_network_{nullptr};
4141

4242
stt::SteinerTreeBuilder stt_;
4343
utl::CallBackHandler callback_handler_;

0 commit comments

Comments
 (0)