diff --git a/src/dbSta/include/db_sta/dbNetwork.hh b/src/dbSta/include/db_sta/dbNetwork.hh index 0b6fb213347..47f3b92c06d 100644 --- a/src/dbSta/include/db_sta/dbNetwork.hh +++ b/src/dbSta/include/db_sta/dbNetwork.hh @@ -65,6 +65,7 @@ using odb::dbModule; using odb::dbMTerm; using odb::dbNet; using odb::dbObject; +using odb::dbObjectType; using odb::dbSet; using odb::dbSigType; using odb::Point; @@ -91,6 +92,7 @@ class dbNetwork : public ConcreteNetwork public: dbNetwork(); ~dbNetwork() override; + void init(dbDatabase* db, Logger* logger); void setBlock(dbBlock* block); void clear() override; @@ -287,6 +289,8 @@ class dbNetwork : public ConcreteNetwork PinVisitor& visitor, NetSet& visited_nets) const override; bool portMsbFirst(const char* port_name, const char* cell_name); + ObjectId getDbNwkObjectId(dbObjectType typ, ObjectId db_id) const; + dbDatabase* db_ = nullptr; Logger* logger_ = nullptr; dbBlock* block_ = nullptr; @@ -294,6 +298,19 @@ class dbNetwork : public ConcreteNetwork Cell* top_cell_ = nullptr; std::set observers_; + // unique addresses for the db objects + static constexpr unsigned DBITERM_ID = 0x0; + static constexpr unsigned DBBTERM_ID = 0x1; + static constexpr unsigned DBINST_ID = 0x2; + static constexpr unsigned DBNET_ID = 0x3; + static constexpr unsigned DBMODITERM_ID = 0x4; + static constexpr unsigned DBMODBTERM_ID = 0x5; + static constexpr unsigned DBMODINST_ID = 0x6; + static constexpr unsigned DBMODNET_ID = 0x7; + static constexpr unsigned DBMODULE_ID = 0x8; + // Number of lower bits used + static constexpr unsigned DBIDTAG_WIDTH = 0x4; + private: bool hierarchy_ = false; }; diff --git a/src/dbSta/src/dbNetwork.cc b/src/dbSta/src/dbNetwork.cc index bdbb260dabe..9078cd2e225 100644 --- a/src/dbSta/src/dbNetwork.cc +++ b/src/dbSta/src/dbNetwork.cc @@ -65,9 +65,12 @@ using odb::dbModBTermObj; using odb::dbModInstObj; using odb::dbModITerm; using odb::dbModITermObj; +using odb::dbModNetObj; using odb::dbModule; +using odb::dbModuleObj; using odb::dbMTerm; using odb::dbNet; +using odb::dbNetObj; using odb::dbObject; using odb::dbObjectType; using odb::dbPlacementStatus; @@ -82,6 +85,69 @@ char* tmpStringCopy(const char* str) return tmp; } +// +// Handling of object ids (Hierachy Mode) +//-------------------------------------- +// +// The database assigns a number to each object. These numbers +// are scoped based on the type. Eg dbModInst 1..N or dbInst 1..N. +// The timer requires a unique id for each object for its visit +// pattern, so we uniquify the numbers by suffixing a discriminating +// address pattern to the lower bits and shifting. +// Everytime a new type of timing related object is added, we +// must update this code, so it is isolated and marked up here. +// +// The id is used by the STA traversers to accumulate visited. +// lower 4 bits used to encode type +// + +ObjectId dbNetwork::getDbNwkObjectId(dbObjectType typ, ObjectId db_id) const +{ + if (db_id > (std::numeric_limits::max() >> DBIDTAG_WIDTH)) { + logger_->error(ORD, 2019, "Error: database id exceeds capacity"); + } + + switch (typ) { + case dbITermObj: { + return ((db_id << DBIDTAG_WIDTH) | DBITERM_ID); + } break; + case dbBTermObj: { + return ((db_id << DBIDTAG_WIDTH) | DBBTERM_ID); + } break; + case dbInstObj: { + return ((db_id << DBIDTAG_WIDTH) | DBINST_ID); + } break; + case dbNetObj: { + return ((db_id << DBIDTAG_WIDTH) | DBNET_ID); + } break; + case dbModITermObj: { + return ((db_id << DBIDTAG_WIDTH) | DBMODITERM_ID); + } break; + case dbModBTermObj: { + return ((db_id << DBIDTAG_WIDTH) | DBMODBTERM_ID); + } break; + case dbModInstObj: { + return ((db_id << DBIDTAG_WIDTH) | DBMODINST_ID); + } break; + case dbModNetObj: { + return ((db_id << DBIDTAG_WIDTH) | DBMODNET_ID); + } break; + case dbModuleObj: { + return ((db_id << DBIDTAG_WIDTH) | DBMODULE_ID); + } break; + default: + logger_->error( + ORD, + 2017, + "Error: unknown database type passed into unique id generation"); + // note the default "exception undefined case" in database is 0. + // so we reasonably expect upstream tools to handle this. + return 0; + break; + } + return 0; +} + class DbLibraryIterator1 : public Iterator { public: @@ -489,6 +555,11 @@ int dbNetwork::metersToDbu(double dist) const ObjectId dbNetwork::id(const Port* port) const { + if (hierarchy_) { + dbObject* obj = reinterpret_cast(const_cast(port)); + dbObjectType type = obj->getObjectType(); + return getDbNwkObjectId(type, obj->getId()); + } if (!port) { // should not match anything else return std::numeric_limits::max(); @@ -504,15 +575,10 @@ ObjectId dbNetwork::id(const Instance* instance) const return 0; } if (hierarchy_) { - dbInst* db_inst; - dbModInst* mod_inst; - staToDb(instance, db_inst, mod_inst); - if (db_inst) { - return db_inst->getId() << 1; - } - if (mod_inst) { - return (mod_inst->getId() << 1) + 1; - } + dbObject* obj + = reinterpret_cast(const_cast(instance)); + dbObjectType type = obj->getObjectType(); + return getDbNwkObjectId(type, obj->getId()); } return staToDb(instance)->getId(); } @@ -760,28 +826,12 @@ ObjectId dbNetwork::id(const Pin* pin) const dbModBTerm* modbterm = nullptr; static std::map id_ptr_map; - staToDb(pin, iterm, bterm, moditerm, modbterm); if (hierarchy_) { - // The id is used by the STA traversers to accumulate visited. - // lower bits used to encode type - // id,00 <- iterm - // id,01 <- bterm - // id,10 <- moditerm - // id,11 <- modbterm - if (iterm != nullptr) { - return iterm->getId() << 2; - } - if (bterm != nullptr) { - return (bterm->getId() << 2) | 0x1; - } - if (moditerm != nullptr) { - return (moditerm->getId() << 2) | 0x2; - } - if (modbterm != nullptr) { - return (modbterm->getId() << 2) | 0x3; - } + dbObject* obj = reinterpret_cast(const_cast(pin)); + dbObjectType type = obj->getObjectType(); + return getDbNwkObjectId(type, obj->getId()); } else { if (iterm != nullptr) { return iterm->getId() << 1; @@ -1067,12 +1117,9 @@ ObjectId dbNetwork::id(const Net* net) const dbNet* dnet = nullptr; staToDb(net, dnet, modnet); if (hierarchy_) { - if (dnet) { - return dnet->getId() << 1; - } - if (modnet) { - return (modnet->getId() << 1) + 1; - } + dbObject* obj = reinterpret_cast(const_cast(net)); + dbObjectType type = obj->getObjectType(); + return getDbNwkObjectId(type, obj->getId()); } else { return dnet->getId(); } @@ -1208,6 +1255,11 @@ const Net* dbNetwork::highestConnectedNet(Net* net) const ObjectId dbNetwork::id(const Term* term) const { + if (hierarchy_) { + dbObject* obj = reinterpret_cast(const_cast(term)); + dbObjectType type = obj->getObjectType(); + return getDbNwkObjectId(type, obj->getId()); + } return staToDb(term)->getId(); } @@ -1886,6 +1938,8 @@ dbMaster* dbNetwork::staToDb(const LibertyCell* cell) const dbMTerm* dbNetwork::staToDb(const Port* port) const { + // Todo fix to use modbterm + const ConcretePort* cport = reinterpret_cast(port); return reinterpret_cast(cport->extPort()); }