From 8ee3bbf84b11db2394acaaee4acd1e0a67c0ef89 Mon Sep 17 00:00:00 2001 From: andyfox-rushc Date: Sun, 27 Oct 2024 14:30:09 -0700 Subject: [PATCH] Reformatted, support for modnets in dbJournal Signed-off-by: andyfox-rushc --- src/odb/include/odb/db.h | 1 + src/odb/src/db/dbITerm.cpp | 40 +++- src/odb/src/db/dbJournal.cpp | 48 +++- src/odb/src/db/dbModNet.cpp | 7 + src/odb/src/db/dbModuleBusPortModBTermItr.cpp | 1 - src/odb/src/db/dbModuleModBTermItr.cpp | 1 - src/odb/src/db/dbModuleModInstItr.cpp | 1 - src/odb/src/db/dbModuleModInstModITermItr.cpp | 1 - src/odb/src/db/dbModuleModNetItr.cpp | 1 - src/odb/src/db/dbModulePortItr.cpp | 1 - src/rsz/src/OdbCallBack.cc | 6 +- src/rsz/src/RepairSetup.cc | 219 +++++++++++++++++- 12 files changed, 307 insertions(+), 20 deletions(-) diff --git a/src/odb/include/odb/db.h b/src/odb/include/odb/db.h index f2b32864f77..566d1754d65 100644 --- a/src/odb/include/odb/db.h +++ b/src/odb/include/odb/db.h @@ -8150,6 +8150,7 @@ class dbModNet : public dbObject const char* getName() const; void reName(const char* new_name); + static dbModNet* getModNet(dbBlock* block, uint id); static dbModNet* create(dbModule* parentModule, const char* name); static void destroy(dbModNet*); diff --git a/src/odb/src/db/dbITerm.cpp b/src/odb/src/db/dbITerm.cpp index 019dcda030c..bcaade924fd 100644 --- a/src/odb/src/db/dbITerm.cpp +++ b/src/odb/src/db/dbITerm.cpp @@ -442,6 +442,8 @@ void dbITerm::connect(dbNet* net_) block->_journal->pushParam(dbITermObj); block->_journal->pushParam(getId()); block->_journal->pushParam(net_->getId()); + // put in a fake modnet here + block->_journal->pushParam(0); block->_journal->endAction(); } @@ -500,6 +502,22 @@ void dbITerm::connect(dbModNet* mod_net) inst->_name); } + if (block->_journal) { + debugPrint(iterm->getImpl()->getLogger(), + utl::ODB, + "DB_ECO", + 1, + "ECO: connect Iterm {} to modnet {}", + getId(), + _mod_net->getId()); + block->_journal->beginAction(dbJournal::CONNECT_OBJECT); + block->_journal->pushParam(dbITermObj); + block->_journal->pushParam(getId()); + block->_journal->pushParam(0); + block->_journal->pushParam(_mod_net->getId()); + block->_journal->endAction(); + } + if (_mod_net->_iterms != 0) { _dbITerm* head = block->_iterm_tbl->getPtr(_mod_net->_iterms); iterm->_next_modnet_iterm = _mod_net->_iterms; @@ -552,7 +570,6 @@ void dbITerm::disconnect() block->_journal->pushParam(dbITermObj); block->_journal->pushParam(getId()); block->_journal->pushParam(net->getOID()); - block->_journal->endAction(); } uint id = iterm->getOID(); @@ -580,9 +597,30 @@ void dbITerm::disconnect() // the modnet part if (iterm->_mnet == 0) { + if (block->_journal) { + debugPrint(iterm->getImpl()->getLogger(), + utl::ODB, + "DB_ECO", + 1, + "ECO: disconnect modnet from Iterm {}", + getId()); + block->_journal->pushParam(0); + block->_journal->endAction(); + } return; } + _dbModNet* mod_net = block->_modnet_tbl->getPtr(iterm->_mnet); + if (block->_journal) { + debugPrint(iterm->getImpl()->getLogger(), + utl::ODB, + "DB_ECO", + 1, + "ECO: disconnect Iterm -- modnet part {}", + getId()); + block->_journal->pushParam(mod_net->getOID()); + block->_journal->endAction(); + } if (mod_net->_iterms == id) { mod_net->_iterms = iterm->_next_modnet_iterm; diff --git a/src/odb/src/db/dbJournal.cpp b/src/odb/src/db/dbJournal.cpp index 0514f750797..d2651f40683 100644 --- a/src/odb/src/db/dbJournal.cpp +++ b/src/odb/src/db/dbJournal.cpp @@ -571,15 +571,30 @@ void dbJournal::redo_connectObject() dbITerm* iterm = dbITerm::getITerm(_block, iterm_id); uint net_id; _log.pop(net_id); - dbNet* net = dbNet::getNet(_block, net_id); - debugPrint(_logger, - utl::ODB, - "DB_ECO", - 2, - "REDO ECO: connect dbITermObj, iterm_id {}, net_id {}", - iterm_id, - net_id); - iterm->connect(net); + if (net_id != 0) { + dbNet* net = dbNet::getNet(_block, net_id); + debugPrint(_logger, + utl::ODB, + "DB_ECO", + 2, + "REDO ECO: connect dbITermObj, iterm_id {}, net_id {}", + iterm_id, + net_id); + iterm->connect(net); + } + uint mod_net_id; + _log.pop(mod_net_id); + if (mod_net_id != 0) { + dbModNet* mod_net = dbModNet::getModNet(_block, mod_net_id); + debugPrint(_logger, + utl::ODB, + "DB_ECO", + 2, + "REDO ECO: connect dbITermObj, iterm_id {}, mod_net_id {}", + iterm_id, + mod_net_id); + iterm->connect(mod_net); + } break; } @@ -622,6 +637,7 @@ void dbJournal::redo_disconnectObject() 2, "REDO ECO: disconnect dbITermObj, iterm_id {}", iterm_id); + // note: this will disconnect the modnet and the dbNet iterm->disconnect(); break; } @@ -1618,6 +1634,7 @@ void dbJournal::undo_connectObject() dbITerm* iterm = dbITerm::getITerm(_block, iterm_id); uint net_id; _log.pop(net_id); + // disconnects everything modnet and bnet) iterm->disconnect(); break; } @@ -1653,8 +1670,17 @@ void dbJournal::undo_disconnectObject() dbITerm* iterm = dbITerm::getITerm(_block, iterm_id); uint net_id; _log.pop(net_id); - dbNet* net = dbNet::getNet(_block, net_id); - iterm->connect(net); + if (net_id != 0) { + dbNet* net = dbNet::getNet(_block, net_id); + iterm->connect(net); + } + uint mnet_id; + _log.pop(mnet_id); + if (mnet_id != 0) { + dbModNet* mod_net = dbModNet::getModNet(_block, mnet_id); + iterm->connect(mod_net); + } + break; } diff --git a/src/odb/src/db/dbModNet.cpp b/src/odb/src/db/dbModNet.cpp index 1459dceb1b9..211bc412547 100644 --- a/src/odb/src/db/dbModNet.cpp +++ b/src/odb/src/db/dbModNet.cpp @@ -240,6 +240,13 @@ void dbModNet::reName(const char* new_name) parent->_modnet_hash[new_name] = obj->getOID(); } +dbModNet* dbModNet::getModNet(dbBlock* block, uint id) +{ + _dbBlock* block_ = (_dbBlock*) block; + _dbModNet* ret = block_->_modnet_tbl->getPtr(id); + return (dbModNet*) ret; +} + dbModNet* dbModNet::create(dbModule* parentModule, const char* name) { // give illusion of scoping. diff --git a/src/odb/src/db/dbModuleBusPortModBTermItr.cpp b/src/odb/src/db/dbModuleBusPortModBTermItr.cpp index bb931274bd6..208f1dae070 100644 --- a/src/odb/src/db/dbModuleBusPortModBTermItr.cpp +++ b/src/odb/src/db/dbModuleBusPortModBTermItr.cpp @@ -35,7 +35,6 @@ #include "dbBusPort.h" #include "dbModBTerm.h" -#include "dbModBTerm.h" #include "dbModule.h" #include "dbTable.h" diff --git a/src/odb/src/db/dbModuleModBTermItr.cpp b/src/odb/src/db/dbModuleModBTermItr.cpp index e29828350c9..d02e1aa42d1 100644 --- a/src/odb/src/db/dbModuleModBTermItr.cpp +++ b/src/odb/src/db/dbModuleModBTermItr.cpp @@ -35,7 +35,6 @@ #include "dbBusPort.h" #include "dbModBTerm.h" -#include "dbModBTerm.h" #include "dbModule.h" #include "dbTable.h" diff --git a/src/odb/src/db/dbModuleModInstItr.cpp b/src/odb/src/db/dbModuleModInstItr.cpp index 63b47fac964..f891745da9f 100644 --- a/src/odb/src/db/dbModuleModInstItr.cpp +++ b/src/odb/src/db/dbModuleModInstItr.cpp @@ -33,7 +33,6 @@ // Generator Code Begin Cpp #include "dbModuleModInstItr.h" -#include "dbModInst.h" #include "dbModInst.h" #include "dbModule.h" #include "dbTable.h" diff --git a/src/odb/src/db/dbModuleModInstModITermItr.cpp b/src/odb/src/db/dbModuleModInstModITermItr.cpp index 7499b0a0ff6..e9ce6804018 100644 --- a/src/odb/src/db/dbModuleModInstModITermItr.cpp +++ b/src/odb/src/db/dbModuleModInstModITermItr.cpp @@ -33,7 +33,6 @@ // Generator Code Begin Cpp #include "dbModuleModInstModITermItr.h" -#include "dbModITerm.h" #include "dbModITerm.h" #include "dbModInst.h" #include "dbModule.h" diff --git a/src/odb/src/db/dbModuleModNetItr.cpp b/src/odb/src/db/dbModuleModNetItr.cpp index 327e729ec04..81e5a6db054 100644 --- a/src/odb/src/db/dbModuleModNetItr.cpp +++ b/src/odb/src/db/dbModuleModNetItr.cpp @@ -33,7 +33,6 @@ // Generator Code Begin Cpp #include "dbModuleModNetItr.h" -#include "dbModNet.h" #include "dbModNet.h" #include "dbModule.h" #include "dbTable.h" diff --git a/src/odb/src/db/dbModulePortItr.cpp b/src/odb/src/db/dbModulePortItr.cpp index 94738f27c12..38de40fcc84 100644 --- a/src/odb/src/db/dbModulePortItr.cpp +++ b/src/odb/src/db/dbModulePortItr.cpp @@ -36,7 +36,6 @@ #include "dbBlock.h" #include "dbBusPort.h" #include "dbModBTerm.h" -#include "dbModBTerm.h" #include "dbModule.h" #include "dbTable.h" diff --git a/src/rsz/src/OdbCallBack.cc b/src/rsz/src/OdbCallBack.cc index ba64da2f17a..4e0dc402484 100644 --- a/src/rsz/src/OdbCallBack.cc +++ b/src/rsz/src/OdbCallBack.cc @@ -150,7 +150,11 @@ void OdbCallBack::inDbInstSwapMasterAfter(dbInst* inst) while (pin_iter->hasNext()) { Pin* pin = pin_iter->next(); Net* net = network_->net(pin); - resizer_->parasiticsInvalid(net); + // we can only update parasitics for low level net + odb::dbNet* db_net = nullptr; + odb::dbModNet* db_modnet = nullptr; + db_network_->staToDb(net, db_net, db_modnet); + resizer_->parasiticsInvalid(db_network_->dbToSta(db_net)); } } diff --git a/src/rsz/src/RepairSetup.cc b/src/rsz/src/RepairSetup.cc index f79fecc11d0..d985b7ac8d4 100644 --- a/src/rsz/src/RepairSetup.cc +++ b/src/rsz/src/RepairSetup.cc @@ -611,7 +611,7 @@ bool RepairSetup::repairPath(PathRef& path, if (!skip_buffering) { // Don't split loads on low fanout nets. - if (fanout > 1000 /*split_load_min_fanout_*/ && !tristate_drvr + if (fanout > split_load_min_fanout_ && !tristate_drvr && !resizer_->dontTouch(net) && !db_net->isConnectedByAbutment()) { const int init_buffer_count = inserted_buffer_count_; splitLoads(drvr_path, drvr_index, path_slack, &expanded); @@ -1322,6 +1322,7 @@ bool RepairSetup::cloneDriver(const PathRef* drvr_path, return true; } +/* void RepairSetup::splitLoads(const PathRef* drvr_path, const int drvr_index, const Slack drvr_slack, @@ -1416,6 +1417,222 @@ void RepairSetup::splitLoads(const PathRef* drvr_path, resizer_->parasiticsInvalid(net); resizer_->parasiticsInvalid(out_net); } +*/ + +void RepairSetup::splitLoads(const PathRef* drvr_path, + const int drvr_index, + const Slack drvr_slack, + PathExpanded* expanded) +{ + static int debug; + debug++; + Pin* drvr_pin = drvr_path->pin(this); + + const PathRef* load_path = expanded->path(drvr_index + 1); + Vertex* load_vertex = load_path->vertex(sta_); + Pin* load_pin = load_vertex->pin(); + // Divide and conquer. + debugPrint(logger_, + RSZ, + "repair_setup", + 3, + "split loads {} -> {}", + network_->pathName(drvr_pin), + network_->pathName(load_pin)); + + Vertex* drvr_vertex = drvr_path->vertex(sta_); + const RiseFall* rf = drvr_path->transition(sta_); + // Sort fanouts of the drvr on the critical path by slack margin + // wrt the critical path slack. + vector> fanout_slacks; + VertexOutEdgeIterator edge_iter(drvr_vertex, graph_); + while (edge_iter.hasNext()) { + Edge* edge = edge_iter.next(); + // Watch out for problematic asap7 output->output timing arcs. + if (edge->isWire()) { + Vertex* fanout_vertex = edge->to(graph_); + const Slack fanout_slack = sta_->vertexSlack(fanout_vertex, rf, max_); + const Slack slack_margin = fanout_slack - drvr_slack; + debugPrint(logger_, + RSZ, + "repair_setup", + 4, + " fanin {} slack_margin = {}", + network_->pathName(fanout_vertex->pin()), + delayAsString(slack_margin, sta_, 3)); + fanout_slacks.emplace_back(fanout_vertex, slack_margin); + } + } + + sort(fanout_slacks.begin(), + fanout_slacks.end(), + [=](const pair& pair1, + const pair& pair2) { + return (pair1.second > pair2.second + || (pair1.second == pair2.second + && network_->pathNameLess(pair1.first->pin(), + pair2.first->pin()))); + }); + + // H-fix get both the mod net and db net (if present). + dbNet* db_drvr_net; + odb::dbModNet* db_mod_drvr_net; + db_network_->net(drvr_pin, db_drvr_net, db_mod_drvr_net); + + const string buffer_name = resizer_->makeUniqueInstName("split"); + + // H-Fix Use driver parent for hierarchy, not the top instance + Instance* parent = db_network_->getOwningInstanceParent(drvr_pin); + + LibertyCell* buffer_cell = resizer_->buffer_lowest_drive_; + const Point drvr_loc = db_network_->location(drvr_pin); + + // H-Fix make the buffer in the parent of the driver pin + Instance* buffer = resizer_->makeBuffer( + buffer_cell, buffer_name.c_str(), parent, drvr_loc); + inserted_buffer_count_++; + + // H-fix make the out net in the driver parent + std::string out_net_name = resizer_->makeUniqueNetName(); + Net* out_net = db_network_->makeNet(out_net_name.c_str(), parent); + + LibertyPort *input, *output; + buffer_cell->bufferPorts(input, output); + + Pin* buffer_ip_pin; + Pin* buffer_op_pin; + resizer_->getBufferPins(buffer, buffer_ip_pin, buffer_op_pin); + (void) buffer_ip_pin; + + // Split the loads with extra slack to an inserted buffer. + // before + // drvr_pin -> net -> load_pins + // after + // drvr_pin -> net -> load_pins with low slack + // -> buffer_in -> net -> rest of loads + + // Hierarchical case: + // If the driver was hooked to a modnet. + // + // If the loads are partitioned then we introduce new modnets + // punch through. + // + // Create the buffer in the driver module. + // + // For non-buffered loads, use original modnet (if any). + // + // For buffered loads use dbNetwork::hierarchicalConnect + // which may introduce new modnets. + // + // Before: + // drvr_pin -> modnet -> load pins {Partition1, Partition2} + // + // after + // drvr_pin -> mod_net -> load pins with low slack {Partition1} + // -> buffer_in -> mod_net* -> rest of loads {Partition2} + // + + // connect input of buffer to the original driver db net + sta_->connectPin(buffer, input, db_network_->dbToSta(db_drvr_net)); + + // invalidate the dbNet + resizer_->parasiticsInvalid(db_network_->dbToSta(db_drvr_net)); + + // out_net is the db net + sta_->connectPin(buffer, output, out_net); + + const int split_index = fanout_slacks.size() / 2; + for (int i = 0; i < split_index; i++) { + pair fanout_slack = fanout_slacks[i]; + Vertex* load_vertex = fanout_slack.first; + Pin* load_pin = load_vertex->pin(); + + odb::dbITerm* load_iterm; + odb::dbBTerm* load_bterm; + odb::dbModITerm* load_moditerm; + odb::dbModBTerm* load_modbterm; + + db_network_->staToDb( + load_pin, load_iterm, load_bterm, load_moditerm, load_modbterm); + + // Leave ports connected to original net so verilog port names are + // preserved. + if (!network_->isTopLevelPort(load_pin)) { + LibertyPort* load_port = network_->libertyPort(load_pin); + Instance* load = network_->instance(load_pin); + + // stash the modnet for the load + dbNet* db_load_net; + odb::dbModNet* db_mod_load_net; + db_network_->net(load_pin, db_load_net, db_mod_load_net); + (void) db_load_net; + + // This will kill both the dbNet and modnet connection + load_iterm->disconnect(); + + // Flat connection to dbNet + load_iterm->connect(db_network_->staToDb(out_net)); + + // + // H-Fix. Support connecting across hierachy. + // This is a hack: way too much punch through... clean up + // + Instance* load_parent = db_network_->getOwningInstanceParent(load_pin); + + if (load_parent != parent) { + printf("Got split load across hierarchy !\n"); + + std::string unique_connection_name = resizer_->makeUniqueNetName(); + + odb::dbITerm* load_pin_iterm; + odb::dbBTerm* load_pin_bterm; + odb::dbModITerm* load_pin_moditerm; + odb::dbModBTerm* load_pin_modbterm; + + db_network_->staToDb(load_pin, + load_pin_iterm, + load_pin_bterm, + load_pin_moditerm, + load_pin_modbterm); + + odb::dbITerm* buffer_op_pin_iterm; + odb::dbBTerm* buffer_op_pin_bterm; + odb::dbModITerm* buffer_op_pin_moditerm; + odb::dbModBTerm* buffer_op_pin_modbterm; + + db_network_->staToDb(buffer_op_pin, + buffer_op_pin_iterm, + buffer_op_pin_bterm, + buffer_op_pin_moditerm, + buffer_op_pin_modbterm); + + if (load_pin_iterm && buffer_op_pin_iterm) { + db_network_->hierarchicalConnect(buffer_op_pin_iterm, + load_pin_iterm, + unique_connection_name.c_str()); + } + } else { + // everything in same module, no worries, share the dbModNet. + // get iterm for load and connect to the modnet + odb::dbITerm* iterm; + odb::dbBTerm* bterm; + odb::dbModITerm* moditerm; + odb::dbModBTerm* modbterm; + db_network_->staToDb(load_pin, iterm, bterm, moditerm, modbterm); + if (iterm && db_mod_load_net) { + iterm->connect(db_mod_load_net); + } + } + } + } + + Pin* buffer_out_pin = network_->findPin(buffer, output); + resizer_->resizeToTargetSlew(buffer_out_pin); + // H-Fix, only invalidate db nets. + // resizer_->parasiticsInvalid(net); + resizer_->parasiticsInvalid(db_network_->dbToSta(db_drvr_net)); + resizer_->parasiticsInvalid(out_net); +} int RepairSetup::fanout(Vertex* vertex) {