Skip to content

Commit 5dd69b9

Browse files
authored
Merge pull request #8338 from The-OpenROAD-Project-staging/secure-fix-undo-issue
Fixed EQY fails in hierarchical flow
2 parents bfb53d0 + c8e599d commit 5dd69b9

File tree

10 files changed

+192
-118
lines changed

10 files changed

+192
-118
lines changed

src/dbSta/src/dbEditHierarchy.cc

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ void PinModuleConnection::operator()(const Pin* pin)
9999
}
100100
}
101101

102-
bool dbEditHierarchy::ConnectionToModuleExists(dbITerm* source_pin,
102+
bool dbEditHierarchy::connectionToModuleExists(dbITerm* source_pin,
103103
dbModule* dest_module,
104104
dbModBTerm*& dest_modbterm,
105105
dbModITerm*& dest_moditerm) const
@@ -145,18 +145,17 @@ void dbEditHierarchy::createHierarchyBottomUp(dbITerm* pin,
145145
dbModNet* db_mod_net = nullptr;
146146
const char* io_type_str = (io_type == dbIoType::OUTPUT) ? "o" : "i";
147147

148-
while (cur_module != highest_common_module) {
149-
// Decide a new unique pin/net name
150-
std::string unique_name
151-
= fmt::format("{}_{}", connection_name, io_type_str);
152-
int id = 0;
153-
while (cur_module->findModBTerm(unique_name.c_str())
154-
|| cur_module->getModNet(unique_name.c_str())) {
155-
id++;
156-
unique_name = fmt::format("{}_{}_{}", connection_name, io_type_str, id);
157-
}
158-
const char* new_term_net_name = unique_name.c_str();
148+
// Decide a new unique pin/net name
149+
std::string unique_name = fmt::format("{}_{}", connection_name, io_type_str);
150+
int id = 0;
151+
while (cur_module->findModBTerm(unique_name.c_str())
152+
|| cur_module->getModNet(unique_name.c_str())) {
153+
id++;
154+
unique_name = fmt::format("{}_{}_{}", connection_name, io_type_str, id);
155+
}
156+
const char* new_term_net_name = unique_name.c_str();
159157

158+
while (cur_module != highest_common_module) {
160159
// Create BTerm & ModNet and connect them
161160
dlogCreateHierBTermAndModNet(level, cur_module, new_term_net_name);
162161
dbModBTerm* mod_bterm = dbModBTerm::create(cur_module, new_term_net_name);
@@ -190,6 +189,14 @@ void dbEditHierarchy::createHierarchyBottomUp(dbITerm* pin,
190189
dbModITerm* mod_iterm
191190
= dbModITerm::create(parent_inst, new_term_net_name, mod_bterm);
192191

192+
// Retry to get a new unique pin/net name in the new hierarchy
193+
while (cur_module->findModBTerm(unique_name.c_str())
194+
|| cur_module->getModNet(unique_name.c_str())) {
195+
id++;
196+
unique_name = fmt::format("{}_{}_{}", connection_name, io_type_str, id);
197+
}
198+
new_term_net_name = unique_name.c_str();
199+
193200
// Create ModNet for the ITerm
194201
if (io_type == dbIoType::OUTPUT
195202
|| (io_type == dbIoType::INPUT
@@ -220,7 +227,7 @@ connection_name should be a base name, not a full name.
220227
*/
221228
void dbEditHierarchy::hierarchicalConnect(dbITerm* source_pin,
222229
dbITerm* dest_pin,
223-
const char* connection_name) const
230+
const char* connection_name)
224231
{
225232
assert(source_pin != nullptr);
226233
assert(dest_pin != nullptr);
@@ -308,7 +315,7 @@ void dbEditHierarchy::hierarchicalConnect(dbITerm* source_pin,
308315
dbModITerm* dest_moditerm = nullptr;
309316
// Check do we already have a connection between the source and destination
310317
// pins? If so, reuse it.
311-
if (ConnectionToModuleExists(
318+
if (connectionToModuleExists(
312319
source_pin, dest_db_module, dest_modbterm, dest_moditerm)) {
313320
dbModNet* dest_mod_net = nullptr;
314321
if (dest_modbterm) {
@@ -381,11 +388,21 @@ void dbEditHierarchy::hierarchicalConnect(dbITerm* source_pin,
381388
// Get base name of source_pin_flat_net
382389
Pin* sta_source_pin = db_network_->dbToSta(source_pin);
383390
dbNet* source_pin_flat_net = db_network_->flatNet(sta_source_pin);
384-
const char* base_name
385-
= db_network_->name(db_network_->dbToSta(source_pin_flat_net));
391+
std::string base_name = fmt::format(
392+
"{}", db_network_->name(db_network_->dbToSta(source_pin_flat_net)));
393+
394+
// Decide a new unique net name to avoid collisions.
395+
std::string unique_name = base_name;
396+
int id = 0;
397+
while (highest_common_module->findModBTerm(unique_name.c_str())
398+
|| highest_common_module->getModNet(unique_name.c_str())) {
399+
id++;
400+
unique_name = fmt::format("{}_{}", base_name, id);
401+
}
386402

387403
// Create and connect dbModNet
388-
source_db_mod_net = dbModNet::create(highest_common_module, base_name);
404+
source_db_mod_net
405+
= dbModNet::create(highest_common_module, unique_name.c_str());
389406
top_mod_dest->connect(source_db_mod_net);
390407
db_network_->disconnectPin(sta_source_pin);
391408
db_network_->connectPin(sta_source_pin,

src/dbSta/src/dbEditHierarchy.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ class dbEditHierarchy
4242
std::vector<dbModule*>& parent_hierarchy) const;
4343
dbModule* findHighestCommonModule(std::vector<dbModule*>& itree1,
4444
std::vector<dbModule*>& itree2) const;
45-
bool ConnectionToModuleExists(dbITerm* source_pin,
45+
bool connectionToModuleExists(dbITerm* source_pin,
4646
dbModule* dest_module,
4747
dbModBTerm*& dest_modbterm,
4848
dbModITerm*& dest_moditerm) const;
4949
void hierarchicalConnect(dbITerm* source_pin,
5050
dbITerm* dest_pin,
51-
const char* connection_name = "net") const;
51+
const char* connection_name = "net");
5252

5353
private:
5454
void createHierarchyBottomUp(dbITerm* pin,

src/dbSta/src/dbNetwork.cc

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ Recommended conclusion: use map for concrete cells. They are invariant.
6565
#include "sta/Liberty.hh"
6666
#include "sta/PatternMatch.hh"
6767
#include "sta/PortDirection.hh"
68+
#include "sta/Search.hh"
6869
#include "utl/Logger.h"
6970

7071
namespace sta {
@@ -3790,6 +3791,10 @@ void dbNetwork::reassociateHierFlatNet(dbModNet* mod_net,
37903791

37913792
void dbNetwork::reassociateFromDbNetView(dbNet* flat_net, dbModNet* mod_net)
37923793
{
3794+
if (flat_net == nullptr || mod_net == nullptr) {
3795+
return;
3796+
}
3797+
37933798
DbModNetAssociation visitordb(this, mod_net);
37943799
NetSet visited_dbnets(this);
37953800
visitConnectedPins(dbToSta(flat_net), visitordb, visited_dbnets);
@@ -4055,13 +4060,13 @@ void dbNetwork::checkAxioms()
40554060
{
40564061
checkSanityModBTerms();
40574062
checkSanityModITerms();
4058-
checkSanityModuleInsts();
40594063
checkSanityModInstTerms();
40604064
checkSanityUnusedModules();
40614065
checkSanityTermConnectivity();
40624066
checkSanityNetConnectivity();
40634067
checkSanityInstNames();
40644068
checkSanityNetNames();
4069+
checkSanityModuleInsts();
40654070
}
40664071

40674072
// Given a net that may be hierarchical, find the corresponding flat net.
@@ -4296,8 +4301,7 @@ void dbNetwork::checkSanityTermConnectivity()
42964301

42974302
for (odb::dbInst* inst : block_->getInsts()) {
42984303
for (odb::dbITerm* iterm : inst->getITerms()) {
4299-
if (iterm->getSigType() == dbSigType::POWER
4300-
|| iterm->getSigType() == dbSigType::GROUND) {
4304+
if (iterm->getSigType().isSupply()) {
43014305
continue; // Skip power/ground pins
43024306
}
43034307

@@ -4323,27 +4327,58 @@ void dbNetwork::checkSanityNetConnectivity()
43234327
}
43244328

43254329
// Check for incomplete flat net connections
4326-
for (odb::dbNet* net : block_->getNets()) {
4327-
const auto iterm_count = net->getITerms().size();
4328-
const auto bterm_count = net->getBTerms().size();
4330+
for (odb::dbNet* net_db : block_->getNets()) {
4331+
// Check for multiple drivers.
4332+
Net* net = dbToSta(net_db);
4333+
PinSeq loads;
4334+
PinSeq drvrs;
4335+
PinSet visited_drvrs(this);
4336+
FindNetDrvrLoads visitor(nullptr, visited_drvrs, loads, drvrs, this);
4337+
NetSet visited_nets(this);
4338+
visitConnectedPins(net, visitor, visited_nets);
4339+
4340+
if (drvrs.size() > 1) {
4341+
bool all_tristate = true;
4342+
for (const Pin* drvr : drvrs) {
4343+
LibertyPort* port = libertyPort(drvr);
4344+
if (!port || !port->direction()->isAnyTristate()) {
4345+
all_tristate = false;
4346+
break;
4347+
}
4348+
}
4349+
4350+
if (!all_tristate) {
4351+
std::string drivers_str;
4352+
for (const Pin* drvr : drvrs) {
4353+
drivers_str += " " + std::string(pathName(drvr));
4354+
}
4355+
logger_->error(
4356+
ORD,
4357+
2049,
4358+
"SanityCheck: Net '{}' has multiple non-tristate drivers:{}",
4359+
name(net),
4360+
drivers_str);
4361+
}
4362+
}
4363+
const auto iterm_count = net_db->getITerms().size();
4364+
const auto bterm_count = net_db->getBTerms().size();
43294365
if (iterm_count + bterm_count >= 2) {
43304366
continue;
43314367
}
43324368

43334369
// Skip power/ground net
4334-
if (net->getSigType() == odb::dbSigType::POWER
4335-
|| net->getSigType() == odb::dbSigType::GROUND) {
4370+
if (net_db->getSigType().isSupply()) {
43364371
continue; // OK: Unconnected power/ground net
43374372
}
43384373

43394374
// A net connected to 1 terminal
43404375
if (iterm_count == 1) {
4341-
odb::dbITerm* iterm = *(net->getITerms().begin());
4376+
odb::dbITerm* iterm = *(net_db->getITerms().begin());
43424377
if (iterm->getIoType() == odb::dbIoType::OUTPUT) {
43434378
continue; // OK: Unconnected output pin
43444379
}
43454380
} else if (bterm_count == 1) { // This is a top level port
4346-
odb::dbBTerm* bterm = *(net->getBTerms().begin());
4381+
odb::dbBTerm* bterm = *(net_db->getBTerms().begin());
43474382
if (bterm->getIoType() == odb::dbIoType::INPUT) {
43484383
continue; // OK: Unconnected input port
43494384
}
@@ -4353,7 +4388,7 @@ void dbNetwork::checkSanityNetConnectivity()
43534388
2039,
43544389
"SanityCheck: Net '{}' has less than 2 connections (# of "
43554390
"ITerms = {}, # of BTerms = {}).",
4356-
net->getName(),
4391+
net_db->getName(),
43574392
iterm_count,
43584393
bterm_count);
43594394
}

src/dbSta/test/check_axioms.ok

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
11
[INFO ODB-0227] LEF file: Nangate45/Nangate45.lef, created 22 layers, 27 vias, 135 library cells
2-
[WARNING ORD-2038] SanityCheck: Module 'i_empty' has no instances.
3-
[WARNING ORD-2038] SanityCheck: Module 'u1' has no instances.
4-
[WARNING ORD-2038] SanityCheck: Module 'u2' has no instances.
52
[ERROR ORD-2039] SanityCheck: Net 'out_unconnected' has less than 2 connections (# of ITerms = 0, # of BTerms = 1).

src/odb/include/odb/db.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,12 +1736,12 @@ class dbNet : public dbObject
17361736
///
17371737
/// Get the net name.
17381738
///
1739-
std::string getName();
1739+
std::string getName() const;
17401740

17411741
///
17421742
/// Get the net name.
17431743
///
1744-
const char* getConstName();
1744+
const char* getConstName() const;
17451745

17461746
///
17471747
/// Print net name with or without id and newline
@@ -1949,7 +1949,7 @@ class dbNet : public dbObject
19491949
///
19501950
/// Get the block this net belongs to.
19511951
///
1952-
dbBlock* getBlock();
1952+
dbBlock* getBlock() const;
19531953

19541954
///
19551955
/// Get all the instance-terminals of this net.
@@ -2428,6 +2428,20 @@ class dbNet : public dbObject
24282428
///
24292429
void mergeNet(dbNet* in_net);
24302430

2431+
///
2432+
/// Find the parent module instance of this net by parsing its hierarchical
2433+
/// name.
2434+
/// Returns nullptr if the parent is the top module.
2435+
/// Note that a dbNet can be located at multiple hierarchical modules.
2436+
///
2437+
dbModInst* findMainParentModInst() const;
2438+
2439+
///
2440+
/// Find the parent module of this net by parsing its hierarchical name.
2441+
/// Returns the top module if the parent is the top module.
2442+
///
2443+
dbModule* findMainParentModule() const;
2444+
24312445
dbSet<dbGuide> getGuides() const;
24322446

24332447
void clearGuides();
@@ -8245,6 +8259,12 @@ class dbModInst : public dbObject
82458259

82468260
void removeUnusedPortsAndPins();
82478261

8262+
dbModNet* findHierNet(const char* base_name) const;
8263+
dbNet* findFlatNet(const char* base_name) const;
8264+
bool findNet(const char* base_name,
8265+
dbNet*& flat_net,
8266+
dbModNet*& hier_net) const;
8267+
82488268
/// Swap the module of this instance.
82498269
/// Returns new mod inst if the operations succeeds.
82508270
/// Old mod inst is deleted along with its child insts.

src/odb/src/db/dbModInst.cpp

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
// User Code Begin Includes
2525
#include "dbGroup.h"
2626
#include "dbModBTerm.h"
27+
#include "dbModNet.h"
2728
#include "dbModuleModInstItr.h"
2829
#include "dbModuleModInstModITermItr.h"
2930
#include "odb/dbBlockCallBackObj.h"
31+
#include "utl/Logger.h"
3032
// User Code End Includes
3133
namespace odb {
3234
template class dbTable<_dbModInst>;
@@ -326,12 +328,15 @@ std::string dbModInst::getHierarchicalName() const
326328
{
327329
_dbModInst* _obj = (_dbModInst*) this;
328330
dbBlock* block = (dbBlock*) _obj->getOwner();
329-
std::string inst_name = std::string(getName());
331+
const char* inst_name = getName();
330332
dbModule* parent = getParent();
331333
if (parent == block->getTopModule()) {
332334
return inst_name;
333335
}
334-
return parent->getModInst()->getHierarchicalName() + "/" + inst_name;
336+
return fmt::format("{}{}{}",
337+
parent->getModInst()->getHierarchicalName(),
338+
block->getHierarchyDelimiter(),
339+
inst_name);
335340
}
336341

337342
dbModITerm* dbModInst::findModITerm(const char* name)
@@ -346,6 +351,37 @@ dbModITerm* dbModInst::findModITerm(const char* name)
346351
return nullptr;
347352
}
348353

354+
dbModNet* dbModInst::findHierNet(const char* base_name) const
355+
{
356+
dbModule* master = getMaster();
357+
return master->getModNet(base_name);
358+
}
359+
360+
dbNet* dbModInst::findFlatNet(const char* base_name) const
361+
{
362+
dbModule* parent = getParent();
363+
if (parent) {
364+
dbBlock* block = parent->getOwner();
365+
fmt::memory_buffer full_name_buf;
366+
fmt::format_to(std::back_inserter(full_name_buf),
367+
"{}{}{}",
368+
getHierarchicalName(),
369+
block->getHierarchyDelimiter(),
370+
base_name);
371+
return block->findNet(full_name_buf.data());
372+
}
373+
return nullptr;
374+
}
375+
376+
bool dbModInst::findNet(const char* base_name,
377+
dbNet*& flat_net,
378+
dbModNet*& hier_net) const
379+
{
380+
flat_net = findFlatNet(base_name);
381+
hier_net = findHierNet(base_name);
382+
return (flat_net || hier_net);
383+
}
384+
349385
void dbModInst::removeUnusedPortsAndPins()
350386
{
351387
_dbModInst* obj = (_dbModInst*) this;
@@ -428,20 +464,16 @@ void dbModInst::removeUnusedPortsAndPins()
428464
mod_bterm->disconnect();
429465

430466
// First destroy the net
431-
if (moditerm_m_net && moditerm_m_net->getBTerms().size() == 0
432-
&& moditerm_m_net->getITerms().size() == 0
433-
&& moditerm_m_net->getModITerms().size() == 0
434-
&& moditerm_m_net->getModBTerms().size() == 0) {
467+
if (moditerm_m_net && moditerm_m_net->getModITerms().empty()
468+
&& moditerm_m_net->getModBTerms().empty()) {
435469
dbModNet::destroy(moditerm_m_net);
436470
}
437471

438472
// Now destroy the iterm
439473
dbModITerm::destroy(mod_iterm);
440474

441-
if (modbterm_m_net && modbterm_m_net->getBTerms().size() == 0
442-
&& modbterm_m_net->getITerms().size() == 0
443-
&& modbterm_m_net->getModITerms().size() == 0
444-
&& modbterm_m_net->getModBTerms().size() == 0) {
475+
if (modbterm_m_net && modbterm_m_net->getModITerms().empty()
476+
&& modbterm_m_net->getModBTerms().empty()) {
445477
dbModNet::destroy(modbterm_m_net);
446478
}
447479

0 commit comments

Comments
 (0)