Skip to content

Commit 24c1196

Browse files
committed
rsz: Fixed RepairHold::makeHoldDelay() to resolve ORD-2030 errors in multiple hierarchical designs.
- Fixes #8047 Signed-off-by: Jaehyun Kim <[email protected]>
1 parent e561a14 commit 24c1196

File tree

3 files changed

+67
-122
lines changed

3 files changed

+67
-122
lines changed

src/odb/src/db/dbModNet.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ const char* dbModNet::getName() const
166166
void dbModNet::rename(const char* new_name)
167167
{
168168
_dbModNet* obj = (_dbModNet*) this;
169+
if (strcmp(obj->_name, new_name) == 0) {
170+
return;
171+
}
172+
169173
_dbBlock* block = (_dbBlock*) obj->getOwner();
170174
_dbModule* parent = block->_module_tbl->getPtr(obj->_parent);
171175
parent->_modnet_hash.erase(obj->_name);

src/rsz/src/RepairHold.cc

Lines changed: 54 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -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.

src/rsz/test/repair_hold1_hier_out.vok

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,27 @@ module top (clk,
3434
.Q(out));
3535
BUF_X1 u1 (.A(r2q),
3636
.Z(u1z));
37-
AND2_X1 u2 (.A1(r1q),
37+
AND2_X1 u2 (.A1(net_o),
3838
.A2(u1z),
3939
.ZN(u2z));
40-
hier1 h1 (.in1(in1),
40+
hier1 h1 (.net_o(net_o),
41+
.in1(in1),
4142
.i1z(i1z),
4243
.op(r1q));
4344
endmodule
44-
module hier1 (in1,
45+
module hier1 (net_o,
46+
in1,
4547
i1z,
4648
op);
49+
output net_o;
4750
input in1;
4851
input i1z;
4952
output op;
5053

5154

52-
CLKBUF_X1 hold1 (.A(r1q),
53-
.Z(op));
55+
CLKBUF_X1 hold1 (.A(op),
56+
.Z(net_o));
5457
DFF_X1 r1 (.D(in1),
5558
.CK(i1z),
56-
.Q(r1q));
59+
.Q(op));
5760
endmodule

0 commit comments

Comments
 (0)