diff --git a/src/dbSta/include/db_sta/dbNetwork.hh b/src/dbSta/include/db_sta/dbNetwork.hh index a76ee353af7..ec715ab8e35 100644 --- a/src/dbSta/include/db_sta/dbNetwork.hh +++ b/src/dbSta/include/db_sta/dbNetwork.hh @@ -162,6 +162,7 @@ class dbNetwork : public ConcreteNetwork Pin* dbToSta(dbITerm* iterm) const; Pin* dbToSta(dbModITerm* iterm) const; + Pin* dbToStaPin(dbModBTerm* modbterm) const; Instance* dbToSta(dbInst* inst) const; Instance* dbToSta(dbModInst* inst) const; @@ -172,6 +173,7 @@ class dbNetwork : public ConcreteNetwork Cell* dbToSta(dbModule* master) const; Port* dbToSta(dbMTerm* mterm) const; Port* dbToSta(dbModBTerm* modbterm) const; + PortDirection* dbToSta(const dbSigType& sig_type, const dbIoType& io_type) const; // dbStaCbk::inDbBTermCreate diff --git a/src/dbSta/src/dbNetwork.cc b/src/dbSta/src/dbNetwork.cc index e8d39564d34..c91e39a5273 100644 --- a/src/dbSta/src/dbNetwork.cc +++ b/src/dbSta/src/dbNetwork.cc @@ -81,11 +81,7 @@ using odb::dbSet; using odb::dbSigType; // Turns out OR use full port names (instance name + port name) -// on DbITerms. -// So we have this duplicated helper to build the port names. -// This is just plain stupid. (Originally we used STL and indexes) -// so could always quickly go from port to index and fish out -// the port. +// So we have this helper to build the port names. std::string makePinName(std::string inst_name, std::string port_name) { @@ -407,6 +403,8 @@ Pin* DbNetPinIterator::next() //////////////////////////////////////////////////////////////// +// A term is either a bterm or a modbterm +// class DbNetTermIterator : public NetTermIterator { public: @@ -418,6 +416,8 @@ class DbNetTermIterator : public NetTermIterator const dbNetwork* network_; dbSet::iterator iter_; dbSet::iterator end_; + dbSet::iterator mod_iter_; + dbSet::iterator mod_end_; }; DbNetTermIterator::DbNetTermIterator(const Net* net, const dbNetwork* network) @@ -425,6 +425,7 @@ DbNetTermIterator::DbNetTermIterator(const Net* net, const dbNetwork* network) { dbModNet* modnet = nullptr; dbNet* dnet = nullptr; + network_->staToDb(net, dnet, modnet); if (dnet && !modnet) { dbSet terms = dnet->getBTerms(); @@ -434,6 +435,9 @@ DbNetTermIterator::DbNetTermIterator(const Net* net, const dbNetwork* network) dbSet terms = modnet->getBTerms(); iter_ = terms.begin(); end_ = terms.end(); + dbSet modbterms = modnet->getModBTerms(); + mod_iter_ = modbterms.begin(); + mod_end_ = modbterms.end(); } else { dbSet terms; iter_ = terms.begin(); @@ -443,14 +447,23 @@ DbNetTermIterator::DbNetTermIterator(const Net* net, const dbNetwork* network) bool DbNetTermIterator::hasNext() { - return iter_ != end_; + if (mod_iter_ != mod_end_ || iter_ != end_) + return true; + return false; } Term* DbNetTermIterator::next() { - dbBTerm* bterm = *iter_; - iter_++; - return network_->dbToStaTerm(bterm); + if (iter_ != end_) { + dbBTerm* bterm = *iter_; + iter_++; + return network_->dbToStaTerm(bterm); + } else if (mod_iter_ != mod_end_) { + dbModBTerm* modbterm = *mod_iter_; + mod_iter_++; + return network_->dbToStaTerm(modbterm); + } + return nullptr; } //////////////////////////////////////////////////////////////// @@ -946,6 +959,9 @@ Instance* dbNetwork::instance(const Pin* pin) const return dbToSta(mod_inst); } if (modbterm) { + dbModule* module = modbterm->getParent(); + dbModInst* mod_inst = module->getModInst(); + return dbToSta(mod_inst); #ifdef DEBUG_DBNWK printf( "Unsupported modbter to inst conversion. Ports don't have instances\n"); @@ -1007,6 +1023,7 @@ Net* dbNetwork::net(const Pin* pin) const dbBTerm* bterm; dbModITerm* moditerm; dbModBTerm* modbterm; + #ifdef DEBUG_DBNW printf("Getting net for pin %s\n", name(pin)); #endif @@ -1029,6 +1046,19 @@ Net* dbNetwork::net(const Pin* pin) const return dbToSta(dnet); } + if (bterm) { + dbNet* dnet = bterm->getNet(); + dbModNet* mnet = bterm->getModNet(); + + if (dnet && mnet) { + return dbToSta(mnet); + } + if (mnet) + return dbToSta(mnet); + if (dnet) + return dbToSta(dnet); + } + if (moditerm) { dbModNet* mnet = moditerm->getNet(); return dbToSta(mnet); @@ -1043,10 +1073,10 @@ Net* dbNetwork::net(const Pin* pin) const Term* dbNetwork::term(const Pin* pin) const { - dbITerm* iterm; - dbBTerm* bterm; - dbModITerm* moditerm; - dbModBTerm* modbterm; + dbITerm* iterm = nullptr; + dbBTerm* bterm = nullptr; + dbModITerm* moditerm = nullptr; + dbModBTerm* modbterm = nullptr; staToDb(pin, iterm, bterm, moditerm, modbterm); if (iterm) { @@ -1055,9 +1085,12 @@ Term* dbNetwork::term(const Pin* pin) const if (bterm) { return dbToStaTerm(bterm); } - if (moditerm) - return dbToStaTerm(moditerm); + // probably wrong: term should be modbterm for this moditerm + if (moditerm) { + return dbToStaTerm(moditerm); + } + // ok if (modbterm) return dbToStaTerm(modbterm); @@ -1090,7 +1123,9 @@ Port* dbNetwork::port(const Pin* pin) const dbModITerm* moditerm; dbModBTerm* modbterm; Port* ret = nullptr; - + static int debug; + debug++; + // Will return the bterm for a top level pin staToDb(pin, iterm, bterm, moditerm, modbterm); if (iterm) { @@ -1326,44 +1361,63 @@ NetTermIterator* dbNetwork::termIterator(const Net* net) const } // override ConcreteNetwork::visitConnectedPins +// This traverses through the module hierarchy void dbNetwork::visitConnectedPins(const Net* net, PinVisitor& visitor, NetSet& visited_nets) const { static int debug; debug++; - - dbNet* db_net = nullptr; - dbModNet* mod_net = nullptr; - staToDb(net, db_net, mod_net); - - if (db_net && !mod_net) { - for (dbITerm* iterm : db_net->getITerms()) { - Pin* pin = dbToSta(iterm); - visitor(pin); - debug++; - } - for (dbBTerm* bterm : db_net->getBTerms()) { - Pin* pin = dbToSta(bterm); - visitor(pin); - debug++; - } - } else if (mod_net) { - for (dbITerm* iterm : mod_net->getITerms()) { - Pin* pin = dbToSta(iterm); - visitor(pin); - debug++; - } - for (dbBTerm* bterm : mod_net->getBTerms()) { - Pin* pin = dbToSta(bterm); - visitor(pin); - debug++; - } - - for (dbModITerm* moditerm : mod_net->getModITerms()) { - Pin* pin = dbToSta(moditerm); - visitor(pin); - debug++; + if (!visited_nets.hasKey(net)) { + visited_nets.insert(net); + + dbNet* db_net = nullptr; + dbModNet* mod_net = nullptr; + staToDb(net, db_net, mod_net); + + if (db_net && !mod_net) { + for (dbITerm* iterm : db_net->getITerms()) { + Pin* pin = dbToSta(iterm); + visitor(pin); + debug++; + } + for (dbBTerm* bterm : db_net->getBTerms()) { + Pin* pin = dbToSta(bterm); + visitor(pin); + debug++; + } + } else if (mod_net) { + for (dbITerm* iterm : mod_net->getITerms()) { + Pin* pin = dbToSta(iterm); + visitor(pin); + debug++; + } + for (dbBTerm* bterm : mod_net->getBTerms()) { + Pin* pin = dbToSta(bterm); + visitor(pin); + debug++; + } + for (dbModITerm* moditerm : mod_net->getModITerms()) { + Pin* pin = dbToSta(moditerm); + visitor(pin); + debug++; + } + // visit below nets + for (dbModITerm* moditerm : mod_net->getModITerms()) { + dbModInst* mod_inst = moditerm->getParent(); + // note we are deailing with a uniquified hierarchy + // so one master per instance.. + dbModule* module = mod_inst->getMaster(); + std::string pin_name = moditerm->getName(); + dbModBTerm* mod_bterm = module->findModBTerm(pin_name.c_str()); + Pin* below_pin = dbToStaPin(mod_bterm); + pin_name = name(below_pin); + visitor(below_pin); + // traverse along rest of net + Net* below_net = this->net(below_pin); + visitConnectedPins(below_net, visitor, visited_nets); + debug++; + } } } } @@ -1383,7 +1437,27 @@ ObjectId dbNetwork::id(const Term* term) const Pin* dbNetwork::pin(const Term* term) const { // Only terms are for top level instance pins, which are also BTerms. - return reinterpret_cast(const_cast(term)); + // Note this will screw up hierarchical level when starting from top + // net + dbBTerm* bterm = nullptr; + dbModBTerm* modbterm = nullptr; + dbITerm* iterm = nullptr; + dbModITerm* moditerm = nullptr; + staToDb(term, iterm, bterm, moditerm, modbterm); + if (bterm) { + return (dbToSta(bterm)); + } else if (modbterm) { + // get the moditerm + dbModule* cur_module = modbterm->getParent(); + dbModInst* cur_mod_inst = cur_module->getModInst(); + dbModITerm* parent_moditerm = nullptr; + ; + std::string pin_name + = makePinName(cur_mod_inst->getName(), modbterm->getName()); + if (cur_mod_inst->findModITerm(pin_name.c_str(), parent_moditerm)) + return dbToSta(parent_moditerm); + } + return nullptr; } // @@ -1398,6 +1472,9 @@ Net* dbNetwork::net(const Term* term) const staToDb(term, iterm, bterm, moditerm, modbterm); if (moditerm) { + // need to push down in hierachy + // get modbterm + // get net off mod bterm return dbToSta(moditerm->getNet()); } if (modbterm) { @@ -2003,7 +2080,8 @@ void dbNetwork::staToDb(const Pin* pin, } else if (type == dbModITermObj) { moditerm = static_cast(obj); } else { - logger_->warn(ORD, 2018, "pin is not ITerm or BTerm"); + logger_->warn( + ORD, 2018, "pin is not ITerm or BTerm or modITerm or ModBTerm"); } } } @@ -2037,17 +2115,6 @@ void dbNetwork::staToDb(const Cell* cell, } } -/* - dbObject* obj = reinterpret_cast(const_cast(cell)); - dbObjectType obj_typ = obj -> getObjectType(); - if (obj_typ == odb::dbModuleObj) - module = reinterpret_cast(const_cast(cell)); - if (obj_typ == odb::dbMasterObj) - master = reinterpret_cast(const_cast(cell)); - } -} -*/ - dbMaster* dbNetwork::staToDb(const LibertyCell* cell) const { const ConcreteCell* ccell = cell; @@ -2162,6 +2229,11 @@ Pin* dbNetwork::dbToSta(dbModITerm* mod_iterm) const return reinterpret_cast(mod_iterm); } +Pin* dbNetwork::dbToStaPin(dbModBTerm* mod_bterm) const +{ + return reinterpret_cast(mod_bterm); +} + Net* dbNetwork::dbToSta(dbNet* net) const { return reinterpret_cast(net); diff --git a/src/dbSta/src/dbReadVerilog.cc b/src/dbSta/src/dbReadVerilog.cc index 99c41a071e9..0eee15f7b81 100644 --- a/src/dbSta/src/dbReadVerilog.cc +++ b/src/dbSta/src/dbReadVerilog.cc @@ -192,6 +192,7 @@ void dbLinkDesign(const char* top_cell_name, bool link_make_black_boxes = true; bool success = verilog_network->linkNetwork( top_cell_name, link_make_black_boxes, verilog_network->report()); + if (success) { Verilog2db v2db(verilog_network, db, logger); v2db.makeBlock(); diff --git a/src/dbSta/test/hier2.v b/src/dbSta/test/hier2.v new file mode 100644 index 00000000000..a690a231a4b --- /dev/null +++ b/src/dbSta/test/hier2.v @@ -0,0 +1,47 @@ +/* + lef: example1.lef + lib: example1_typ.lib + + */ + +module gate1 (a1,a2,zn); + input a1; + input a2; + output zn; + + AND2_X1 _5_ ( + .A1(a1), + .A2(a2), + .ZN(zn) + ); + +endmodule // gatel + +module top (a,b, out); + input a; + input b; + output out; + + + wire a_int; + + INV_X1 _4_ ( + .A(a), + .ZN(a_int) + ); + +// gate1 gate1_inst ( +// .a1(a_int), +// .a2(b), +// .zn(out) +// ); + + gate1 gate2_inst ( + .a1(a_int), + .a2(b), + .zn(out) + ); + + + +endmodule diff --git a/src/dbSta/test/read_verilog2.ok b/src/dbSta/test/read_verilog2.ok index ed136c13315..123bd743333 100644 --- a/src/dbSta/test/read_verilog2.ok +++ b/src/dbSta/test/read_verilog2.ok @@ -10,7 +10,7 @@ Instance b1/r1 Path cells: snl_ffqx1 Input pins: D input u1out - CP input clk + CP input clk1 Output pins: Q output r1q Net b1out diff --git a/src/dft/src/replace/ScanReplace.cpp b/src/dft/src/replace/ScanReplace.cpp index 54c69c35004..42493506183 100644 --- a/src/dft/src/replace/ScanReplace.cpp +++ b/src/dft/src/replace/ScanReplace.cpp @@ -394,8 +394,13 @@ void ScanReplace::scanReplace(odb::dbBlock* block) sta::LibertyCell* scan_cell = scan_candidate->getScanCell(); odb::dbMaster* master_scan_cell = db_network_->staToDb(scan_cell); - odb::dbInst* new_cell = utils::ReplaceCell( - block, inst, master_scan_cell, scan_candidate->getPortMapping()); + odb::dbInst* new_cell + = utils::ReplaceCell(sta_, + db_network_, + block, + inst, + master_scan_cell, + scan_candidate->getPortMapping()); already_replaced.insert(new_cell); addCellForRollback(master, master_scan_cell, scan_candidate); @@ -438,7 +443,9 @@ void ScanReplace::rollbackScanReplace(odb::dbBlock* block) } RollbackCandidate& rollback_candidate = *found->second; - utils::ReplaceCell(block, + utils::ReplaceCell(sta_, + db_network_, + block, inst, rollback_candidate.getMaster(), rollback_candidate.getPortMapping()); diff --git a/src/dft/src/utils/Utils.cpp b/src/dft/src/utils/Utils.cpp index d8bbf237f77..00a17dba308 100644 --- a/src/dft/src/utils/Utils.cpp +++ b/src/dft/src/utils/Utils.cpp @@ -34,9 +34,11 @@ #include #include +#include #include "db_sta/dbNetwork.hh" +//#define DEBUG_UTILS namespace dft::utils { namespace { @@ -51,6 +53,16 @@ void PopulatePortNameToNet( } } +void PopulatePortNameToModNet( + odb::dbInst* instance, + std::vector>& port_name_to_modnet) +{ + for (odb::dbITerm* iterm : instance->getITerms()) { + port_name_to_modnet.emplace_back(iterm->getMTerm()->getName(), + iterm->getModNet()); + } +} + void ConnectPinsToNets( odb::dbInst* instance, const std::vector>& port_name_to_net, @@ -61,10 +73,34 @@ void ConnectPinsToNets( continue; } std::string port_name_new = port_mapping.find(port_name_old)->second; +#ifdef DEBUG_UTILS + printf("Setting up iterm %s with net %s\n", + instance->findITerm(port_name_new.c_str())->getName().c_str(), + net->getName().c_str()); +#endif instance->findITerm(port_name_new.c_str())->connect(net); } } +void ConnectPinsToModNets( + odb::dbInst* instance, + const std::vector>& + port_name_to_net, + const std::unordered_map& port_mapping) +{ + for (const auto& [port_name_old, modnet] : port_name_to_net) { + if (modnet == nullptr) { + continue; + } + std::string port_name_new = port_mapping.find(port_name_old)->second; +#ifdef DEBUG_UTILS + printf("Setting up iterm %s with modnet %s\n", + instance->findITerm(port_name_new.c_str())->getName().c_str(), + modnet->getName()); +#endif + instance->findITerm(port_name_new.c_str())->connect(modnet); + } +} } // namespace bool IsSequentialCell(sta::dbNetwork* db_network, odb::dbInst* instance) @@ -76,16 +112,58 @@ bool IsSequentialCell(sta::dbNetwork* db_network, odb::dbInst* instance) } odb::dbInst* ReplaceCell( + sta::dbSta* sta, + sta::dbNetwork* db_network, odb::dbBlock* top_block, odb::dbInst* old_instance, odb::dbMaster* new_master, const std::unordered_map& port_mapping) { +#ifdef DEBUG_UTILS + static int debug; + debug++; +#endif + std::vector clock_pin = GetClockPin(old_instance); + odb::dbModule* inst_module = old_instance->getModule(); + + // Check have we got a clock pin accessible from the instane + if (clock_pin.size() != 0) { +#ifdef DEBUG_UTILS + printf("Hacking cell with clock %s with clock pin %p %s\n", + old_instance->getName().c_str(), + clock_pin.at(0), + clock_pin.at(0)->getName().c_str()); + printf("Containing module %s\n", inst_module->getName()); +#endif + + // Check is that dbiterm in the clock set for the sta. +#ifdef DEBUG_UTILS + sta::Pin* clock_p = db_network->dbToSta(clock_pin.at(0)); // iterm -> pin + printf("Clock pin %s\n", db_network->name(clock_p)); +#endif + const sta::ClockSet clock_set + = sta->clocks(db_network->dbToSta(clock_pin.at(0))); +#ifdef DEBUG_UTILS + if (clock_set.size() == 0) + printf("Error cannot get clock pin\n"); + else + printf("ok got clock pin\n"); +#endif + } + std::vector> port_name_to_net; PopulatePortNameToNet(old_instance, port_name_to_net); + std::vector> port_name_to_modnet; + PopulatePortNameToModNet(old_instance, port_name_to_modnet); + odb::dbInst* new_instance - = odb::dbInst::create(top_block, new_master, /*name=*/"tmp_scan_flop"); + = odb::dbInst::create(top_block, + new_master, + /*name=*/"tmp_scan_flop", + false, + inst_module /* put in module in hierarchy */ + ); std::string old_cell_name = old_instance->getName(); // Delete the old cell @@ -93,10 +171,21 @@ odb::dbInst* ReplaceCell( // Connect the new cell to the old instance's nets ConnectPinsToNets(new_instance, port_name_to_net, port_mapping); + ConnectPinsToModNets(new_instance, port_name_to_modnet, port_mapping); // Rename as the old cell new_instance->rename(old_cell_name.c_str()); +#ifdef DEBUG_UTILS + std::vector clock_pin_new = GetClockPin(new_instance); + if (clock_pin_new.size() != 0) { + printf("Successfully hacked cell %s with clock\n", + new_instance->getName().c_str()); + printf("Clock dbITerm %p %s\n", + clock_pin_new.at(0), + clock_pin_new.at(0)->getName().c_str()); + } +#endif return new_instance; } @@ -113,16 +202,41 @@ std::vector GetClockPin(odb::dbInst* inst) std::optional GetClock(sta::dbSta* sta, odb::dbITerm* iterm) { +#ifdef DEBUG_UTILS + static int debug; + debug++; + printf("Getting clock for iterm %s %p\n", iterm->getName('/').c_str(), iterm); +#endif const sta::dbNetwork* db_network = sta->getDbNetwork(); + // but note that db network is wrong in the hierarchy. + // we are somewhere deep in the hierarchy. const sta::ClockSet clock_set = sta->clocks(db_network->dbToSta(iterm)); + odb::dbInst* instance = (odb::dbInst*) (iterm->getInst()); + std::vector clock_pin = GetClockPin(instance); +#ifdef DEBUG_UTILS + if (clock_pin.size() != 0) + printf("Success got clock %s for iterm (%p) from instance\n", + clock_pin.at(0)->getName().c_str(), + clock_pin.at(0)); + else + printf("Failure no clock found\n"); +#endif + sta::ClockSet::ConstIterator iter(clock_set); if (!iter.container()->empty()) { // Returns the first clock for the given iterm, TODO can we have more than // one clock driver? +#ifdef DEBUG_UTILS + printf("Success -- found clock\n"); +#endif return *iter.container()->begin(); + } else { +#ifdef DEBUG_UTILS + printf("D %d Failure, no clock for iterm %p in sta\n", debug, iterm); +#endif + ; } - return std::nullopt; } diff --git a/src/dft/src/utils/Utils.hh b/src/dft/src/utils/Utils.hh index 1c7fb4f7116..861591cc614 100644 --- a/src/dft/src/utils/Utils.hh +++ b/src/dft/src/utils/Utils.hh @@ -45,6 +45,8 @@ namespace dft::utils { // . Returns the new instance and deletes the old // one. The name of the new instance is going to be the same as the old one. odb::dbInst* ReplaceCell( + sta::dbSta* sta, + sta::dbNetwork* db_network, odb::dbBlock* top_block, odb::dbInst* old_instance, odb::dbMaster* new_master, diff --git a/src/dft/test/scan_architect_clock_mix_sky130.vok b/src/dft/test/scan_architect_clock_mix_sky130.vok index 25f9a4f7372..39b01c27f72 100644 --- a/src/dft/test/scan_architect_clock_mix_sky130.vok +++ b/src/dft/test/scan_architect_clock_mix_sky130.vok @@ -64,6 +64,12 @@ module scan_architect (clock1, input scan_in_7; + sky130_fd_sc_hd__sdfbbn_1 ff1_clk1_falling (.D(port1), + .Q(output11), + .SCD(scan_in_4), + .SCE(scan_enable_1), + .SET_B(set_b), + .CLK_N(clock1)); sky130_fd_sc_hd__sdfsbp_1 ff1_clk1_rising (.D(port1), .Q(output1), .SCD(scan_in_7), @@ -178,10 +184,4 @@ module scan_architect (clock1, .SCE(scan_enable_1), .SET_B(set_b), .CLK(clock2)); - sky130_fd_sc_hd__sdfbbn_1 ff1_clk1_falling (.D(port1), - .Q(output11), - .SCD(scan_in_4), - .SCE(scan_enable_1), - .SET_B(set_b), - .CLK_N(clock1)); endmodule diff --git a/src/dft/test/scan_architect_no_mix_sky130.vok b/src/dft/test/scan_architect_no_mix_sky130.vok index cba7508fb25..bda337bfb63 100644 --- a/src/dft/test/scan_architect_no_mix_sky130.vok +++ b/src/dft/test/scan_architect_no_mix_sky130.vok @@ -58,6 +58,12 @@ module scan_architect (clock1, input scan_in_4; + sky130_fd_sc_hd__sdfbbn_1 ff1_clk1_falling (.D(port1), + .Q(output11), + .SCD(output13), + .SCE(scan_enable_1), + .SET_B(set_b), + .CLK_N(clock1)); sky130_fd_sc_hd__sdfsbp_1 ff1_clk1_rising (.D(port1), .Q(output1), .SCD(output3), @@ -172,10 +178,4 @@ module scan_architect (clock1, .SCE(scan_enable_1), .SET_B(set_b), .CLK(clock2)); - sky130_fd_sc_hd__sdfbbn_1 ff1_clk1_falling (.D(port1), - .Q(output11), - .SCD(output13), - .SCE(scan_enable_1), - .SET_B(set_b), - .CLK_N(clock1)); endmodule diff --git a/src/dft/test/sub_modules_sky130.vok b/src/dft/test/sub_modules_sky130.vok index b67b4459c5c..684e09403f8 100644 --- a/src/dft/test/sub_modules_sky130.vok +++ b/src/dft/test/sub_modules_sky130.vok @@ -14,19 +14,35 @@ module sub_modules (clock, output scan_out_1; wire \my_shift_register/net1 ; - wire \my_shift_register/set_b ; - sky130_fd_sc_hd__sdfsbp_1 \my_shift_register/ff2 (.D(\my_shift_register/net1 ), - .Q(output1), - .SCD(scan_in_1), + shift_register_2b my_shift_register (.clock(clock), + .set_b(set_b), + .to(output1), + .from(port1)); + assign output1 = output1; + assign scan_out_1 = \my_shift_register/net1 ; +endmodule +module shift_register_2b (clock, + set_b, + to, + from); + input clock; + input set_b; + output to; + input from; + + + sky130_fd_sc_hd__sdfsbp_1 \my_shift_register/ff1 (.D(from), + .Q(net1), + .SCD(output1), .SCE(scan_enable_1), - .SET_B(\my_shift_register/set_b ), + .SET_B(set_b), .CLK(clock)); - sky130_fd_sc_hd__sdfsbp_1 \my_shift_register/ff1 (.D(port1), - .Q(\my_shift_register/net1 ), - .SCD(output1), + sky130_fd_sc_hd__sdfsbp_1 \my_shift_register/ff2 (.D(net1), + .Q(to), + .SCD(scan_in_1), .SCE(scan_enable_1), - .SET_B(\my_shift_register/set_b ), + .SET_B(set_b), .CLK(clock)); - assign scan_out_1 = \my_shift_register/net1 ; + assign to = output1; endmodule diff --git a/src/odb/src/db/dbModule.cpp b/src/odb/src/db/dbModule.cpp index c5d7a572fd6..959fb5fc80d 100644 --- a/src/odb/src/db/dbModule.cpp +++ b/src/odb/src/db/dbModule.cpp @@ -540,9 +540,15 @@ std::vector dbModule::getLeafInsts() dbModBTerm* dbModule::findModBTerm(const char* name) { + std::string bterm_name(name); + size_t last_idx = bterm_name.find_last_of("/"); + if (last_idx != std::string::npos) + bterm_name = bterm_name.substr(last_idx + 1); + for (dbModBTerm* mod_bterm : getModBTerms()) { - if (!strcmp(mod_bterm->getName(), name)) + if (!strcmp(mod_bterm->getName(), bterm_name.c_str())) { return mod_bterm; + } } return nullptr; }