@@ -64,6 +64,7 @@ Recommended conclusion: use map for concrete cells. They are invariant.
6464#include " odb/dbObject.h"
6565#include " odb/dbSet.h"
6666#include " odb/dbTypes.h"
67+ #include " odb/dbUtil.h"
6768#include " sta/Liberty.hh"
6869#include " sta/Network.hh"
6970#include " sta/NetworkClass.hh"
@@ -107,6 +108,8 @@ using odb::dbPlacementStatus;
107108using odb::dbSet;
108109using odb::dbSigType;
109110
111+ namespace {
112+
110113// TODO: move to StringUtil
111114char * tmpStringCopy (const char * str)
112115{
@@ -115,6 +118,58 @@ char* tmpStringCopy(const char* str)
115118 return tmp;
116119}
117120
121+ // This struct contains common information about Pins
122+ // (dbITerm, dbBTerm or dbModITerm) for debugging purposes.
123+ struct PinInfo
124+ {
125+ const char * name = " NOT_ALLOC" ; // Pin hierarchical name
126+ int id = 0 ; // dbObject ID
127+ const char * type_name = " NULL" ; // dbObject type name
128+ bool valid = false ; // false if it is a freed dbObject
129+ void * addr = nullptr ;
130+ };
131+
132+ PinInfo getPinInfo (const dbNetwork* network, const Pin* pin)
133+ {
134+ PinInfo info{" NOT_ALLOC" , 0 , " NULL" , false , nullptr };
135+ dbITerm* iterm;
136+ dbBTerm* bterm;
137+ dbModITerm* moditerm;
138+ network->staToDb (pin, iterm, bterm, moditerm);
139+
140+ if (iterm) {
141+ info.id = iterm->getId ();
142+ info.type_name = iterm->getTypeName ();
143+ info.valid = iterm->isValid ();
144+ info.addr = static_cast <void *>(iterm);
145+ } else if (bterm) {
146+ info.id = bterm->getId ();
147+ info.type_name = bterm->getTypeName ();
148+ info.valid = bterm->isValid ();
149+ info.addr = static_cast <void *>(bterm);
150+ } else if (moditerm) {
151+ info.id = moditerm->getId ();
152+ info.type_name = moditerm->getTypeName ();
153+ info.valid = moditerm->isValid ();
154+ info.addr = static_cast <void *>(moditerm);
155+ }
156+
157+ if (info.valid ) {
158+ info.name = network->pathName (pin);
159+ } else {
160+ network->getLogger ()->error (
161+ ORD,
162+ 2014 ,
163+ " Attempted to access invalid pin {}({}). Check if it is "
164+ " deleted." ,
165+ info.type_name ,
166+ info.id );
167+ }
168+
169+ return info;
170+ }
171+ } // namespace
172+
118173//
119174// Handling of object ids (Hierachy Mode)
120175// --------------------------------------
@@ -1554,11 +1609,12 @@ PortDirection* dbNetwork::direction(const Pin* pin) const
15541609 return dir;
15551610 }
15561611 if (moditerm) {
1557- // get the direction off the modbterm
1612+ // get the direction of the modbterm
15581613 std::string pin_name = moditerm->getName ();
15591614 dbModInst* mod_inst = moditerm->getParent ();
15601615 dbModule* module = mod_inst->getMaster ();
15611616 dbModBTerm* modbterm_local = module ->findModBTerm (pin_name.c_str ());
1617+ assert (modbterm_local != nullptr );
15621618 PortDirection* dir
15631619 = dbToSta (modbterm_local->getSigType (), modbterm_local->getIoType ());
15641620 return dir;
@@ -1957,7 +2013,9 @@ void dbNetwork::visitConnectedPins(const Net* net,
19572013 visitor (above_pin);
19582014 // traverse along rest of net
19592015 Net* above_net = this ->net (above_pin);
1960- visitConnectedPins (above_net, visitor, visited_nets);
2016+ if (above_net) {
2017+ visitConnectedPins (above_net, visitor, visited_nets);
2018+ }
19612019 }
19622020 }
19632021 } else if (db_net) {
@@ -2697,13 +2755,31 @@ void dbNetwork::disconnectPin(Pin* pin)
26972755
26982756void dbNetwork::disconnectPinBefore (const Pin* pin)
26992757{
2700- Net* net = this ->net (pin);
2701- // Incrementally update drivers.
2702- if (net && isDriver (pin)) {
2703- PinSet* drvrs = net_drvr_pin_map_.findKey (net);
2704- if (drvrs) {
2705- drvrs->erase (pin);
2758+ if (isDriver (pin) == false ) {
2759+ return ; // No need to update net_drvr_pin_map_ cache.
2760+ }
2761+
2762+ // Get all the related dbNet & dbModNet with the pin.
2763+ // Incrementally update the net-drvr cache.
2764+ dbNet* db_net;
2765+ dbModNet* mod_net;
2766+ net (pin, db_net, mod_net);
2767+
2768+ if (db_net) {
2769+ // A dbNet can be associated with multiple dbModNets.
2770+ // We need to update the cache for all of them.
2771+ std::set<odb::dbModNet*> related_mod_nets;
2772+ db_net->findRelatedModNets (related_mod_nets);
2773+ for (dbModNet* related_mod_net : related_mod_nets) {
2774+ removeDriverFromCache (dbToSta (related_mod_net), pin);
27062775 }
2776+
2777+ removeDriverFromCache (dbToSta (db_net), pin);
2778+ return ;
2779+ }
2780+
2781+ if (mod_net) {
2782+ removeDriverFromCache (dbToSta (mod_net), pin);
27072783 }
27082784}
27092785
@@ -4720,4 +4796,153 @@ void dbNetwork::checkSanityModNetNamesInModule(odb::dbModule* module) const
47204796 }
47214797}
47224798
4799+ void dbNetwork::checkSanityNetDrvrPinMapConsistency () const
4800+ {
4801+ if (block_ == nullptr ) {
4802+ logger_->error (ORD, 2000 , " No block found." );
4803+ return ;
4804+ }
4805+
4806+ // For each cache element
4807+ for (const auto & [net, cached_drivers_ptr] : net_drvr_pin_map_) {
4808+ dbNet* dbnet = nullptr ;
4809+ dbModNet* modnet = nullptr ;
4810+ staToDb (net, dbnet, modnet);
4811+
4812+ if (dbnet == nullptr && modnet == nullptr ) {
4813+ logger_->warn (ORD,
4814+ 2009 ,
4815+ " Found net {} in cache that is not in the netlist." ,
4816+ pathName (net));
4817+ continue ;
4818+ }
4819+
4820+ // Find drivers from the netlist for the current net
4821+ std::vector<odb::dbObject*> drivers;
4822+ if (dbnet) {
4823+ odb::dbUtil::findITermDrivers (dbnet, drivers);
4824+ odb::dbUtil::findBTermDrivers (dbnet, drivers);
4825+ } else if (modnet) {
4826+ odb::dbUtil::findITermDrivers (modnet, drivers);
4827+ odb::dbUtil::findBTermDrivers (modnet, drivers);
4828+ odb::dbUtil::findModITermDrivers (modnet, drivers);
4829+
4830+ // Also, find drivers from the related flat net
4831+ dbNet* related_dbnet = findRelatedDbNet (modnet);
4832+ if (related_dbnet) {
4833+ odb::dbUtil::findITermDrivers (related_dbnet, drivers);
4834+ odb::dbUtil::findBTermDrivers (related_dbnet, drivers);
4835+ }
4836+
4837+ // Remove duplicates
4838+ std::sort (drivers.begin (), drivers.end ());
4839+ drivers.erase (std::unique (drivers.begin (), drivers.end ()), drivers.end ());
4840+ }
4841+
4842+ // Convert to PinSet
4843+ PinSet netlist_drivers (this );
4844+ for (auto driver : drivers) {
4845+ Pin* pin = nullptr ;
4846+ switch (driver->getObjectType ()) {
4847+ case odb::dbITermObj:
4848+ pin = dbToSta (static_cast <odb::dbITerm*>(driver));
4849+ break ;
4850+ case odb::dbBTermObj:
4851+ pin = dbToSta (static_cast <odb::dbBTerm*>(driver));
4852+ break ;
4853+ case odb::dbModITermObj:
4854+ // Skip hierarchical pin.
4855+ break ;
4856+ default :
4857+ // Should not be here
4858+ break ;
4859+ }
4860+ if (pin != nullptr ) {
4861+ netlist_drivers.insert (pin);
4862+ }
4863+ }
4864+
4865+ // Compare netlist drivers with cached drivers
4866+ bool consistent = true ;
4867+ if (cached_drivers_ptr == nullptr
4868+ || netlist_drivers.size () != cached_drivers_ptr->size ()) {
4869+ consistent = false ;
4870+ } else {
4871+ for (const Pin* pin : netlist_drivers) {
4872+ if (cached_drivers_ptr->find (pin) == cached_drivers_ptr->end ()) {
4873+ consistent = false ;
4874+ break ;
4875+ }
4876+ }
4877+ }
4878+
4879+ // Report inconsistent point details
4880+ if (consistent == false ) {
4881+ logger_->warn (ORD, 2006 , " Inconsistency found for net {}" , pathName (net));
4882+ logger_->report (" Netlist drivers:" );
4883+ for (const Pin* pin : netlist_drivers) {
4884+ const PinInfo pin_info = getPinInfo (this , pin);
4885+ logger_->report (" - {} (type: {}, id: {})" ,
4886+ pin_info.name ,
4887+ pin_info.type_name ,
4888+ pin_info.id );
4889+ }
4890+ logger_->report (" Cached drivers:" );
4891+ if (cached_drivers_ptr) {
4892+ for (const Pin* pin : *cached_drivers_ptr) {
4893+ const PinInfo pin_info = getPinInfo (this , pin);
4894+ logger_->report (" - {} (type: {}, id: {})" ,
4895+ pin_info.name ,
4896+ pin_info.type_name ,
4897+ pin_info.id );
4898+ }
4899+ }
4900+ }
4901+ }
4902+ }
4903+
4904+ void dbNetwork::dumpNetDrvrPinMap () const
4905+ {
4906+ const auto & net_drvr_pin_map = net_drvr_pin_map_;
4907+ logger_->report (" --------------------------------------------------" );
4908+ logger_->report (" Dumping net_drvr_pin_map_ cache (size: {})" ,
4909+ net_drvr_pin_map.size ());
4910+
4911+ for (auto const & [net, pin_set] : net_drvr_pin_map) {
4912+ // Get the underlying dbObject for the net to report its type and ID.
4913+ const dbObject* net_obj
4914+ = reinterpret_cast <const dbObject*>(const_cast <Net*>(net));
4915+ logger_->report (" Net: {} {}({}, {:p})" ,
4916+ pathName (net),
4917+ net_obj->getTypeName (),
4918+ net_obj->getId (),
4919+ (void *) net_obj);
4920+ if (pin_set == nullptr ) {
4921+ logger_->report (" Drivers: null pin set" );
4922+ continue ;
4923+ }
4924+ if (pin_set->empty ()) {
4925+ logger_->report (" Drivers: empty pin set" );
4926+ continue ;
4927+ }
4928+ for (const Pin* pin : *pin_set) {
4929+ const PinInfo pin_info = getPinInfo (this , pin);
4930+ logger_->report (" - {} {}({}, {:p})" ,
4931+ pin_info.name ,
4932+ pin_info.type_name ,
4933+ pin_info.id ,
4934+ pin_info.addr );
4935+ }
4936+ }
4937+ logger_->report (" --------------------------------------------------" );
4938+ }
4939+
4940+ void dbNetwork::removeDriverFromCache (const Net* net, const Pin* drvr)
4941+ {
4942+ PinSet* drvrs = net_drvr_pin_map_.findKey (net);
4943+ if (drvrs) {
4944+ drvrs->erase (drvr);
4945+ }
4946+ }
4947+
47234948} // namespace sta
0 commit comments