@@ -680,140 +680,78 @@ void RepairHold::makeHoldDelay(Vertex* drvr,
680680 const Point& loc)
681681{
682682 Pin* drvr_pin = drvr->pin ();
683- odb::dbModNet* mod_drvr_net = nullptr ; // hierarchical driver, default none
684- dbNet* db_drvr_net = nullptr ; // regular flat driver
685-
686- Instance* parent = nullptr ;
687- if (db_network_->hasHierarchy ()) {
688- // get the nets on the driver pin (possibly both flat and hierarchical)
689- db_network_->net (drvr_pin, db_drvr_net, mod_drvr_net);
690- // Get the parent instance (owning the instance of the driver pin)
691- // we will put the new buffer in that parent
692- parent = db_network_->getOwningInstanceParent (drvr_pin);
693- // exception case: drvr pin is a top level, fix the db_drvr_net to be
694- // the lower level net. Explictly get the "flat" net.
695- if (network_->isTopLevelPort (drvr_pin)) {
696- db_drvr_net = db_network_->flatNet (db_network_->term (drvr_pin));
697- }
698- } else {
699- // original flat code (which handles exception case at top level &
700- // defaults to top level instance as parent).
701- db_drvr_net = db_network_->staToDb (
702- network_->isTopLevelPort (drvr_pin)
703- ? db_network_->net (db_network_->term (drvr_pin))
704- : db_network_->net (drvr_pin));
705- parent = db_network_->topInstance ();
706- }
707- Net *in_net = nullptr , *out_net = nullptr ;
708-
709- if (loads_have_out_port) {
710- // Verilog uses nets as ports, so the net connected to an output port has
711- // to be preserved.
712- // Move the driver pin over to gensym'd net.
683+ dbNet* db_drvr_net = db_network_->findFlatDbNet (drvr_pin);
684+ odb::dbModNet* mod_drvr_net = db_network_->hierNet (drvr_pin);
685+ Instance* parent = db_network_->getOwningInstanceParent (drvr_pin);
686+
687+ // If output port is in load pins, do "Driver pin buffering".
688+ // - Verilog uses nets as ports, so the net connected to an output port has
689+ // - to be preserved.
690+ // - Move the driver pin over to gensym'd net.
691+ // Otherwise, do "Load pin buffering".
692+ bool driver_pin_buffering = loads_have_out_port;
693+ Net* buf_input_net = nullptr ;
694+ Net* buf_output_net = nullptr ;
695+ if (driver_pin_buffering) {
696+ // Do "Driver pin buffering": Buffer drives the existing net.
713697 //
714- in_net = db_network_->makeNet ();
698+ // driver --- (new_net) --- new_buffer ---- (existing_net) ---- loads
699+ //
700+ buf_input_net = db_network_->makeNet (parent); // New net
715701 Port* drvr_port = network_->port (drvr_pin);
716702 Instance* drvr_inst = network_->instance (drvr_pin);
717703 sta_->disconnectPin (drvr_pin);
718- sta_->connectPin (drvr_inst, drvr_port, in_net );
719- out_net = db_network_->dbToSta (db_drvr_net);
704+ sta_->connectPin (drvr_inst, drvr_port, buf_input_net );
705+ buf_output_net = db_network_->dbToSta (db_drvr_net);
720706 } else {
721- in_net = db_network_->dbToSta (db_drvr_net);
722- // make the output net, put in same module as buffer
723- out_net = db_network_->makeNet (parent);
724- }
725-
726- dbNet* in_net_db = db_network_->staToDb (in_net);
727-
728- // Disconnect the original drvr pin from everything (hierarchical nets
729- // and flat nets).
730- odb::dbITerm* drvr_pin_iterm;
731- odb::dbBTerm* drvr_pin_bterm;
732- odb::dbModITerm* drvr_pin_moditerm;
733- db_network_->staToDb (
734- drvr_pin, drvr_pin_iterm, drvr_pin_bterm, drvr_pin_moditerm);
735- if (drvr_pin_iterm) {
736- // disconnect the iterm from both the modnet and the dbnet
737- // note we will rewire the drvr_pin to connect to the new buffer later.
738- drvr_pin_iterm->disconnect ();
739- drvr_pin_iterm->connect (in_net_db);
740- }
741- if (drvr_pin_moditerm) {
742- drvr_pin_moditerm->disconnect ();
707+ // Do "Load pin buffering": The existing net drives the new buffer.
708+ //
709+ // driver --- (existing_net) --- new_buffer ---- (new_net) ---- loads
710+ //
711+ buf_input_net = db_network_->dbToSta (db_drvr_net);
712+ buf_output_net = db_network_->makeNet (parent); // New net
743713 }
744714
745- LibertyPort *input, *output;
746- buffer_cell->bufferPorts (input, output);
747-
748- // drvr_pin->drvr_net->hold_buffer->net2->load_pins
749-
750- // make the buffer in the driver pin's parent
715+ // Make the buffer in the driver pin's parent hierarchy
751716 Instance* buffer = resizer_->makeBuffer (buffer_cell, " hold" , parent, loc);
752717 inserted_buffer_count_++;
753718 debugPrint (
754719 logger_, RSZ, " repair_hold" , 3 , " insert {}" , network_->name (buffer));
755720
756- // wire in the buffer
757- sta_->connectPin (buffer, input, in_net);
758- sta_->connectPin (buffer, output, out_net);
759-
760- // Now patch in the output of the new buffer to the original hierarchical
761- // net,if any, from the original driver
762- if (mod_drvr_net != nullptr ) {
763- Pin* ip_pin = nullptr ;
764- Pin* op_pin = nullptr ;
765- resizer_->getBufferPins (buffer, ip_pin, op_pin);
766- (void ) ip_pin;
767- if (op_pin) {
768- // get the iterm of the op_pin of the buffer (a dbInst)
769- // and connect to the hierarchical net.
770- odb::dbITerm* iterm;
771- odb::dbBTerm* bterm;
772- odb::dbModITerm* moditerm;
773- db_network_->staToDb (op_pin, iterm, bterm, moditerm);
774- // we only need to look at the iterm, the buffer is a dbInst
775- if (iterm) {
776- // hook up the hierarchical net
777- iterm->connect (mod_drvr_net);
778- }
779- }
721+ LibertyPort *input, *output;
722+ buffer_cell->bufferPorts (input, output);
723+ Pin* buffer_in_pin = network_->findPin (buffer, input);
724+ Pin* buffer_out_pin = network_->findPin (buffer, output);
725+
726+ // Connect input and output of the new buffer
727+ sta_->connectPin (buffer, input, buf_input_net);
728+ sta_->connectPin (buffer, output, buf_output_net);
729+
730+ // TODO: Revisit this. Looks not good.
731+ if (mod_drvr_net) {
732+ // The input of the buffer is a new load on the original hierarchical net.
733+ db_network_->connectPin (buffer_in_pin, (Net*) mod_drvr_net);
780734 }
781735
782- // hook up loads to buffer
783- for (const Pin* load_pin : load_pins) {
784- if (resizer_->dontTouch (load_pin)) {
785- continue ;
786- }
787- dbNet* db_load_net = network_->isTopLevelPort (load_pin)
788- ? db_network_->flatNet (network_->term (load_pin))
789- : db_network_->flatNet (load_pin);
790- Net* load_net = db_network_->dbToSta (db_load_net);
791-
792- if (load_net != out_net) {
793- Instance* load = db_network_->instance (load_pin);
794- Port* load_port = db_network_->port (load_pin);
795- // record the original connections
796- odb::dbModNet* original_mod_net = nullptr ;
797- odb::dbNet* original_flat_net = nullptr ;
798- db_network_->net (load_pin, original_flat_net, original_mod_net);
799- (void ) original_flat_net;
800- // Remove all the connections on load_pin
801- sta_->disconnectPin (const_cast <Pin*>(load_pin));
802- // Connect it to the correct output driver net
803- sta_->connectPin (load, load_port, out_net);
804- // connect the original load modnet (hierarchical net), if any,
805- // on the iterm of the buffer created.
806- odb::dbITerm* iterm;
807- odb::dbBTerm* bterm;
808- odb::dbModITerm* moditerm;
809- db_network_->staToDb (load_pin, iterm, bterm, moditerm);
810- if (iterm && original_mod_net) {
811- iterm->connect (original_mod_net);
736+ // Buffering target load pins.
737+ // - No need in driver pin buffering case
738+ if (driver_pin_buffering == false ) {
739+ // Do load pins buffering
740+ for (const Pin* load_pin : load_pins) {
741+ if (resizer_->dontTouch (load_pin)) {
742+ continue ;
812743 }
744+
745+ // Disconnect the load pin
746+ db_network_->disconnectPin (const_cast <Pin*>(load_pin));
747+
748+ // Connect with the buffer output
749+ db_network_->hierarchicalConnect (db_network_->flatPin (buffer_out_pin),
750+ db_network_->flatPin (load_pin));
813751 }
814752 }
815753
816- Pin* buffer_out_pin = network_-> findPin (buffer, output);
754+ // Update RC and delay. Resize if necessary
817755 Vertex* buffer_out_vertex = graph_->pinDrvrVertex (buffer_out_pin);
818756 estimate_parasitics_->updateParasitics ();
819757 // Sta::checkMaxSlewCap does not force dcalc update so do it explicitly.
0 commit comments