@@ -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
@@ -3136,6 +3212,9 @@ Instance* dbNetwork::dbToSta(dbModInst* inst) const
31363212
31373213Pin* dbNetwork::dbToSta (dbModITerm* mod_iterm) const
31383214{
3215+ if (mod_iterm == nullptr ) {
3216+ return nullptr ;
3217+ }
31393218 char * unaligned_pointer = reinterpret_cast <char *>(mod_iterm);
31403219 return reinterpret_cast <Pin*>(
31413220 unaligned_pointer
@@ -3184,6 +3263,9 @@ const Net* dbNetwork::dbToSta(const dbModNet* net) const
31843263
31853264Pin* dbNetwork::dbToSta (dbBTerm* bterm) const
31863265{
3266+ if (bterm == nullptr ) {
3267+ return nullptr ;
3268+ }
31873269 char * unaligned_pointer = reinterpret_cast <char *>(bterm);
31883270 return reinterpret_cast <Pin*>(
31893271 unaligned_pointer
@@ -3192,6 +3274,9 @@ Pin* dbNetwork::dbToSta(dbBTerm* bterm) const
31923274
31933275Pin* dbNetwork::dbToSta (dbITerm* iterm) const
31943276{
3277+ if (iterm == nullptr ) {
3278+ return nullptr ;
3279+ }
31953280 char * unaligned_pointer = reinterpret_cast <char *>(iterm);
31963281 return reinterpret_cast <Pin*>(
31973282 unaligned_pointer
@@ -4720,4 +4805,153 @@ void dbNetwork::checkSanityModNetNamesInModule(odb::dbModule* module) const
47204805 }
47214806}
47224807
4808+ void dbNetwork::checkSanityNetDrvrPinMapConsistency () const
4809+ {
4810+ if (block_ == nullptr ) {
4811+ logger_->error (ORD, 2000 , " No block found." );
4812+ return ;
4813+ }
4814+
4815+ // For each cache element
4816+ for (const auto & [net, cached_drivers_ptr] : net_drvr_pin_map_) {
4817+ dbNet* dbnet = nullptr ;
4818+ dbModNet* modnet = nullptr ;
4819+ staToDb (net, dbnet, modnet);
4820+
4821+ if (dbnet == nullptr && modnet == nullptr ) {
4822+ logger_->warn (ORD,
4823+ 2009 ,
4824+ " Found net {} in cache that is not in the netlist." ,
4825+ pathName (net));
4826+ continue ;
4827+ }
4828+
4829+ // Find drivers from the netlist for the current net
4830+ std::vector<odb::dbObject*> drivers;
4831+ if (dbnet) {
4832+ odb::dbUtil::findITermDrivers (dbnet, drivers);
4833+ odb::dbUtil::findBTermDrivers (dbnet, drivers);
4834+ } else if (modnet) {
4835+ odb::dbUtil::findITermDrivers (modnet, drivers);
4836+ odb::dbUtil::findBTermDrivers (modnet, drivers);
4837+ odb::dbUtil::findModITermDrivers (modnet, drivers);
4838+
4839+ // Also, find drivers from the related flat net
4840+ dbNet* related_dbnet = findRelatedDbNet (modnet);
4841+ if (related_dbnet) {
4842+ odb::dbUtil::findITermDrivers (related_dbnet, drivers);
4843+ odb::dbUtil::findBTermDrivers (related_dbnet, drivers);
4844+ }
4845+
4846+ // Remove duplicates
4847+ std::sort (drivers.begin (), drivers.end ());
4848+ drivers.erase (std::unique (drivers.begin (), drivers.end ()), drivers.end ());
4849+ }
4850+
4851+ // Convert to PinSet
4852+ PinSet netlist_drivers (this );
4853+ for (auto driver : drivers) {
4854+ Pin* pin = nullptr ;
4855+ switch (driver->getObjectType ()) {
4856+ case odb::dbITermObj:
4857+ pin = dbToSta (static_cast <odb::dbITerm*>(driver));
4858+ break ;
4859+ case odb::dbBTermObj:
4860+ pin = dbToSta (static_cast <odb::dbBTerm*>(driver));
4861+ break ;
4862+ case odb::dbModITermObj:
4863+ // Skip hierarchical pin.
4864+ break ;
4865+ default :
4866+ // Should not be here
4867+ break ;
4868+ }
4869+ if (pin != nullptr ) {
4870+ netlist_drivers.insert (pin);
4871+ }
4872+ }
4873+
4874+ // Compare netlist drivers with cached drivers
4875+ bool consistent = true ;
4876+ if (cached_drivers_ptr == nullptr
4877+ || netlist_drivers.size () != cached_drivers_ptr->size ()) {
4878+ consistent = false ;
4879+ } else {
4880+ for (const Pin* pin : netlist_drivers) {
4881+ if (cached_drivers_ptr->find (pin) == cached_drivers_ptr->end ()) {
4882+ consistent = false ;
4883+ break ;
4884+ }
4885+ }
4886+ }
4887+
4888+ // Report inconsistent point details
4889+ if (consistent == false ) {
4890+ logger_->warn (ORD, 2006 , " Inconsistency found for net {}" , pathName (net));
4891+ logger_->report (" Netlist drivers:" );
4892+ for (const Pin* pin : netlist_drivers) {
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+ logger_->report (" Cached drivers:" );
4900+ if (cached_drivers_ptr) {
4901+ for (const Pin* pin : *cached_drivers_ptr) {
4902+ const PinInfo pin_info = getPinInfo (this , pin);
4903+ logger_->report (" - {} (type: {}, id: {})" ,
4904+ pin_info.name ,
4905+ pin_info.type_name ,
4906+ pin_info.id );
4907+ }
4908+ }
4909+ }
4910+ }
4911+ }
4912+
4913+ void dbNetwork::dumpNetDrvrPinMap () const
4914+ {
4915+ const auto & net_drvr_pin_map = net_drvr_pin_map_;
4916+ logger_->report (" --------------------------------------------------" );
4917+ logger_->report (" Dumping net_drvr_pin_map_ cache (size: {})" ,
4918+ net_drvr_pin_map.size ());
4919+
4920+ for (auto const & [net, pin_set] : net_drvr_pin_map) {
4921+ // Get the underlying dbObject for the net to report its type and ID.
4922+ const dbObject* net_obj
4923+ = reinterpret_cast <const dbObject*>(const_cast <Net*>(net));
4924+ logger_->report (" Net: {} {}({}, {:p})" ,
4925+ pathName (net),
4926+ net_obj->getTypeName (),
4927+ net_obj->getId (),
4928+ (void *) net_obj);
4929+ if (pin_set == nullptr ) {
4930+ logger_->report (" Drivers: null pin set" );
4931+ continue ;
4932+ }
4933+ if (pin_set->empty ()) {
4934+ logger_->report (" Drivers: empty pin set" );
4935+ continue ;
4936+ }
4937+ for (const Pin* pin : *pin_set) {
4938+ const PinInfo pin_info = getPinInfo (this , pin);
4939+ logger_->report (" - {} {}({}, {:p})" ,
4940+ pin_info.name ,
4941+ pin_info.type_name ,
4942+ pin_info.id ,
4943+ pin_info.addr );
4944+ }
4945+ }
4946+ logger_->report (" --------------------------------------------------" );
4947+ }
4948+
4949+ void dbNetwork::removeDriverFromCache (const Net* net, const Pin* drvr)
4950+ {
4951+ PinSet* drvrs = net_drvr_pin_map_.findKey (net);
4952+ if (drvrs) {
4953+ drvrs->erase (drvr);
4954+ }
4955+ }
4956+
47234957} // namespace sta
0 commit comments