Skip to content

Commit e194d7f

Browse files
authored
Merge pull request The-OpenROAD-Project#8721 from The-OpenROAD-Project-staging/secure-fix-replace-hier-mod2-reg
odb: Fixed a _dbModule::copyModuleInsts() bug that connects to a wrong external net
2 parents a1a2b81 + 2e39b4e commit e194d7f

18 files changed

+4313
-194
lines changed

src/odb/include/odb/db.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2504,6 +2504,13 @@ class dbNet : public dbObject
25042504
///
25052505
void renameWithModNetInHighestHier();
25062506

2507+
///
2508+
/// Check if this net is internal to the given module.
2509+
/// A net is internal if all its iterms belong to instances within the module
2510+
/// and it has no bterms.
2511+
///
2512+
bool isInternalTo(dbModule* module) const;
2513+
25072514
///
25082515
/// Check issues such as multiple drivers, no driver, or dangling net
25092516
///

src/odb/src/db/dbModule.cpp

Lines changed: 70 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ std::vector<dbInst*> dbModule::getLeafInsts()
519519
dbModBTerm* dbModule::findModBTerm(const char* name)
520520
{
521521
std::string modbterm_name(name);
522-
char hier_delimiter = getOwner()->getHierarchyDelimiter();
522+
const char hier_delimiter = getOwner()->getHierarchyDelimiter();
523523
size_t last_idx = modbterm_name.find_last_of(hier_delimiter);
524524
if (last_idx != std::string::npos) {
525525
modbterm_name = modbterm_name.substr(last_idx + 1);
@@ -790,6 +790,7 @@ void _dbModule::copyModuleInsts(dbModule* old_module,
790790
ITMap& it_map)
791791
{
792792
dbBlock* block = new_module->getOwner();
793+
const char hier_delimiter = block->getHierarchyDelimiter();
793794
utl::Logger* logger = old_module->getImpl()->getLogger();
794795

795796
// Create a net name map (key: new net name, value: new dbNet*).
@@ -803,7 +804,7 @@ void _dbModule::copyModuleInsts(dbModule* old_module,
803804
std::string new_inst_name;
804805
if (new_mod_inst) {
805806
new_inst_name = new_mod_inst->getHierarchicalName();
806-
new_inst_name += block->getHierarchyDelimiter();
807+
new_inst_name += hier_delimiter;
807808
}
808809

809810
new_inst_name += block->getBaseName(old_inst->getConstName());
@@ -851,45 +852,74 @@ void _dbModule::copyModuleInsts(dbModule* old_module,
851852
old_iterm->getName(),
852853
new_iterm->getName());
853854
dbNet* old_net = old_iterm->getNet();
854-
if (old_net) {
855-
// Create a local net only if it connects to iterms inside this module
856-
std::string new_net_name;
857-
if (new_mod_inst) {
858-
new_net_name = new_mod_inst->getHierarchicalName();
859-
new_net_name += block->getHierarchyDelimiter();
860-
}
861-
std::string old_net_name = old_net->getName();
862-
new_net_name += block->getBaseName(old_net_name.c_str());
863-
864-
auto it = new_net_name_map.find(new_net_name);
865-
if (it != new_net_name_map.end()) {
866-
// Connect to an existing local net
867-
dbNet* new_net = (*it).second;
868-
new_iterm->connect(new_net);
869-
debugPrint(logger,
870-
utl::ODB,
871-
"replace_design",
872-
1,
873-
" connected iterm '{}' to existing local net '{}'",
874-
new_iterm->getName(),
875-
new_net->getName());
876-
} else {
877-
// Create and connect to a new local net
878-
assert(block->findNet(new_net_name.c_str()) == nullptr);
879-
dbNet* new_net
880-
= dbNet::create(new_module->getOwner(), new_net_name.c_str());
881-
new_iterm->connect(new_net);
882-
debugPrint(logger,
883-
utl::ODB,
884-
"replace_design",
885-
1,
886-
" Connected iterm '{}' to new local net '{}'",
887-
new_iterm->getName(),
888-
new_net->getName());
855+
if (old_net == nullptr) {
856+
continue;
857+
}
889858

890-
// Insert it to the map
891-
new_net_name_map[new_net_name] = new_net;
892-
}
859+
//
860+
// Create a local net only if it connects to iterms inside this module
861+
//
862+
std::string new_net_name;
863+
if (new_mod_inst) {
864+
new_net_name = new_mod_inst->getHierarchicalName();
865+
new_net_name += hier_delimiter;
866+
}
867+
868+
// Check if the flat net is an internal net within old_module
869+
// - If old_module is uninstantiated module, every net in the module is
870+
// an internal net.
871+
// e.g., No module instance.
872+
// net_name = "_001_" <-- Internal net.
873+
//
874+
// - Otherwise, an internal net should have the hierarchy prefix
875+
// (= module instance hierarchical name).
876+
// e.g., modinst_name = "u0/alu0"
877+
// net_name = u0/alu0/_001_ <-- Internal net.
878+
// net_name = u0/_001_ <-- External net crossing module
879+
// boundary.
880+
std::string old_net_name = old_net->getName();
881+
if (old_net->isInternalTo(old_module) == false) {
882+
// Skip external net crossing module boundary.
883+
// It will be connected later.
884+
debugPrint(logger,
885+
utl::ODB,
886+
"replace_design",
887+
3,
888+
" Skip: non-internal dbNet '{}' of old_module '{}'.\n",
889+
old_net_name,
890+
old_module->getHierarchicalName());
891+
continue;
892+
}
893+
894+
new_net_name += block->getBaseName(old_net_name.c_str());
895+
auto it = new_net_name_map.find(new_net_name);
896+
if (it != new_net_name_map.end()) {
897+
// Connect to an existing local net
898+
dbNet* new_net = (*it).second;
899+
new_iterm->connect(new_net);
900+
debugPrint(logger,
901+
utl::ODB,
902+
"replace_design",
903+
1,
904+
" connected iterm '{}' to existing local net '{}'",
905+
new_iterm->getName(),
906+
new_net->getName());
907+
} else {
908+
// Create and connect to a new local net
909+
assert(block->findNet(new_net_name.c_str()) == nullptr);
910+
dbNet* new_net
911+
= dbNet::create(new_module->getOwner(), new_net_name.c_str());
912+
new_iterm->connect(new_net);
913+
debugPrint(logger,
914+
utl::ODB,
915+
"replace_design",
916+
1,
917+
" Connected iterm '{}' to new local net '{}'",
918+
new_iterm->getName(),
919+
new_net->getName());
920+
921+
// Insert it to the map
922+
new_net_name_map[new_net_name] = new_net;
893923
}
894924
}
895925
}

src/odb/src/db/dbNet.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2599,4 +2599,21 @@ void dbNet::renameWithModNetInHighestHier()
25992599
}
26002600
}
26012601

2602+
bool dbNet::isInternalTo(dbModule* module) const
2603+
{
2604+
// If it's connected to any top-level ports (BTerms), it's not internal.
2605+
if (!getBTerms().empty()) {
2606+
return false;
2607+
}
2608+
2609+
// Check all instance terminals (ITerms) it's connected to.
2610+
for (dbITerm* iterm : getITerms()) {
2611+
if (iterm->getInst()->getModule() != module) {
2612+
return false;
2613+
}
2614+
}
2615+
2616+
return true;
2617+
}
2618+
26022619
} // namespace odb

src/odb/test/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ COMPULSORY_TESTS = [
189189
"replace_hier_mod3",
190190
"replace_hier_mod4",
191191
"replace_hier_mod5",
192+
"replace_hier_mod6",
192193
"replace_hier_mod_report_checks",
193194
"rounding",
194195
"row_settings",
@@ -308,6 +309,7 @@ filegroup(
308309
"helper.tcl",
309310
"helpers.tcl",
310311
"replace_hier_mod1.v",
312+
"replace_hier_mod6.v",
311313
"replace_hier_mod_undo.tcl",
312314
"replace_hier_mod_undo2.tcl",
313315
"sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib",

src/odb/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ or_integration_tests(
4747
replace_hier_mod3
4848
replace_hier_mod4
4949
replace_hier_mod5
50+
replace_hier_mod6
5051
replace_hier_mod_report_checks
5152
rounding
5253
row_settings

src/odb/test/replace_hier_mod1.ok

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ Corner: slow
109109
-0.409 slack (VIOLATED)
110110

111111

112+
Equivalence check - pre
113+
Repair timing output passed/skipped equivalence test
112114
### swap bc1 to inv_chain ###
113115
[INFO GPL-0006] Execute incremental mode global placement.
114116
[INFO GPL-0002] DBU: 2000
@@ -260,6 +262,8 @@ Corner: slow
260262
-0.336 slack (VIOLATED)
261263

262264

265+
Equivalence check - swap (buffer_chain -> inv_chain)
266+
Repair timing output passed/skipped equivalence test
263267
### swap bc1 back to buffer_chain ###
264268
[INFO GPL-0006] Execute incremental mode global placement.
265269
[INFO GPL-0002] DBU: 2000
@@ -388,6 +392,8 @@ Corner: slow
388392
-0.401 slack (VIOLATED)
389393

390394

395+
Equivalence check - swap for rollback (inv_chain -> buffer_chain)
396+
Repair timing output passed/skipped equivalence test
391397
### swap bc1 back to inv_chain ###
392398
[INFO GPL-0006] Execute incremental mode global placement.
393399
[INFO GPL-0002] DBU: 2000
@@ -516,4 +522,5 @@ Corner: slow
516522
-0.330 slack (VIOLATED)
517523

518524

525+
Equivalence check - redo swap (buffer_chain -> inv_chain)
519526
Repair timing output passed/skipped equivalence test

src/odb/test/replace_hier_mod1.tcl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ detailed_placement
2323
source Nangate45/Nangate45.rc
2424
set_wire_rc -layer metal3
2525

26+
# For eqy, write a verilog before replace_hier_module
27+
write_verilog_for_eqy replace_hier_mod1 before "None"
28+
2629
puts "### Initial bc1 is buffer_chain ###"
2730
report_cell_usage bc1
2831
report_net u1z -digits 3
@@ -32,6 +35,8 @@ report_checks -through r2/D -digits 3
3235
# Using "-through u1z" causes crash.
3336
# - it looks like "-through" creates a cache internally.
3437
#report_checks -through u1z -through r2/D -digits 3
38+
puts "Equivalence check - pre"
39+
run_equivalence_test replace_hier_mod1 ./Nangate45/work_around_yosys/ "None"
3540

3641
puts "### swap bc1 to inv_chain ###"
3742
#set_debug_level ODB replace_design 1
@@ -44,6 +49,8 @@ report_net u3z -digits 3
4449
estimate_parasitics -placement
4550
report_checks -through r2/D -digits 3
4651
#report_checks -through u1z -through r2/D -digits 3
52+
puts "Equivalence check - swap (buffer_chain -> inv_chain)"
53+
run_equivalence_test replace_hier_mod1 ./Nangate45/work_around_yosys/ "None"
4754

4855
puts "### swap bc1 back to buffer_chain ###"
4956
replace_hier_module bc1 buffer_chain
@@ -55,6 +62,8 @@ report_net u3z -digits 3
5562
estimate_parasitics -placement
5663
report_checks -through r2/D -digits 3
5764
#report_checks -through u1z -through r2/D -digits 3
65+
puts "Equivalence check - swap for rollback (inv_chain -> buffer_chain)"
66+
run_equivalence_test replace_hier_mod1 ./Nangate45/work_around_yosys/ "None"
5867

5968
puts "### swap bc1 back to inv_chain ###"
6069
replace_hier_module bc1 inv_chain
@@ -66,5 +75,5 @@ report_net u3z -digits 3
6675
estimate_parasitics -placement
6776
report_checks -through r2/D -digits 3
6877
#report_checks -through u1z -through r2/D -digits 3
69-
78+
puts "Equivalence check - redo swap (buffer_chain -> inv_chain)"
7079
run_equivalence_test replace_hier_mod1 ./Nangate45/work_around_yosys/ "None"

0 commit comments

Comments
 (0)