Skip to content

Commit 217bf3b

Browse files
committed
rsz: skip ensureWireParasitic in repair_design hot path
Pass a local load_cap computed from BufferedNet wire RC to resizeToTargetSlew as a hint. When supplied, the hint skips the expensive ensureWireParasitic + STA loadCap query that triggers an incremental FastRoute setup per buffer in the repair_design driver loop. For repairNetWire, the hint reflects the wire that the buffer actually drives (buf_dist x wire_cap + ref_cap), not the full Steiner edge. repairNetJunc passes cap_left / cap_right since the buffer is placed at the junction location. Profiling on a large customer design (497k inst) showed ensureWireParasitic accounting for 96% of repair_design wall time (5,860 calls x ~390ms FastRoute setup each). See private issue The-OpenROAD-Project-private/OpenROAD-flow-scripts#1676. Signed-off-by: Minju Kim <mkim@precisioninno.com>
1 parent d088e22 commit 217bf3b

4 files changed

Lines changed: 40 additions & 15 deletions

File tree

src/rsz/include/rsz/Resizer.hh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,8 @@ class Resizer : public sta::dbStaState, public sta::dbNetworkObserver
641641
bool getCin(const sta::LibertyCell* cell, float& cin);
642642
// Resize drvr_pin instance to target slew.
643643
// Return 1 if resized.
644-
int resizeToTargetSlew(const sta::Pin* drvr_pin);
644+
int resizeToTargetSlew(const sta::Pin* drvr_pin,
645+
std::optional<float> load_cap_hint = std::nullopt);
645646

646647
// Resize drvr_pin instance to target cap ratio.
647648
// Return 1 if resized.

src/rsz/src/RepairDesign.cc

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,6 +1592,12 @@ void RepairDesign::repairNetWire(
15921592
double d = (length == 0) ? 0.0 : buf_dist / length;
15931593
int buf_x = to_x + d * dx;
15941594
int buf_y = to_y + d * dy;
1595+
// Buffer is inserted at buf_dist from to_pt, so it drives only the
1596+
// downstream wire (buf_dist long) + ref_cap, not the full Steiner edge.
1597+
// buf_dist may be fractional (length_margin scaling) so divide in
1598+
// double, then narrow at the end to match makeRepeater's optional<float>.
1599+
const float buffer_load_cap
1600+
= static_cast<float>(buf_dist / (dbu_ * 1e+6) * wire_cap + ref_cap);
15951601
float repeater_cap, repeater_fanout;
15961602
if (!makeRepeater("wire",
15971603
odb::Point(buf_x, buf_y),
@@ -1601,7 +1607,8 @@ void RepairDesign::repairNetWire(
16011607
load_pins,
16021608
repeater_cap,
16031609
repeater_fanout,
1604-
max_load_slew)) {
1610+
max_load_slew,
1611+
/* load_cap_hint= */ buffer_load_cap)) {
16051612
debugPrint(logger_,
16061613
RSZ,
16071614
"repair_net",
@@ -1796,7 +1803,8 @@ void RepairDesign::repairNetJunc(
17961803
loads_left,
17971804
cap_left,
17981805
fanout_left,
1799-
max_load_slew_left);
1806+
max_load_slew_left,
1807+
/* load_cap_hint= */ cap_left);
18001808
wire_length_left = 0;
18011809
}
18021810
if (repeater_right) {
@@ -1808,7 +1816,8 @@ void RepairDesign::repairNetJunc(
18081816
loads_right,
18091817
cap_right,
18101818
fanout_right,
1811-
max_load_slew_right);
1819+
max_load_slew_right,
1820+
/* load_cap_hint= */ cap_right);
18121821
wire_length_right = 0;
18131822
}
18141823

@@ -2121,7 +2130,8 @@ bool RepairDesign::makeRepeater(const char* reason,
21212130
sta::PinSeq& load_pins,
21222131
float& repeater_cap,
21232132
float& repeater_fanout,
2124-
float& repeater_max_slew)
2133+
float& repeater_max_slew,
2134+
std::optional<float> load_cap_hint)
21252135
{
21262136
sta::Net* out_net;
21272137
sta::Pin *repeater_in_pin, *repeater_out_pin;
@@ -2137,7 +2147,8 @@ bool RepairDesign::makeRepeater(const char* reason,
21372147
repeater_max_slew,
21382148
out_net,
21392149
repeater_in_pin,
2140-
repeater_out_pin);
2150+
repeater_out_pin,
2151+
load_cap_hint);
21412152
}
21422153

21432154
////////////////////////////////////////////////////////////////
@@ -2172,7 +2183,8 @@ bool RepairDesign::makeRepeater(
21722183
float& repeater_max_slew,
21732184
sta::Net*& out_net,
21742185
sta::Pin*& repeater_in_pin,
2175-
sta::Pin*& repeater_out_pin)
2186+
sta::Pin*& repeater_out_pin,
2187+
std::optional<float> load_cap_hint)
21762188
{
21772189
debugPrint(logger_,
21782190
RSZ,
@@ -2212,7 +2224,7 @@ bool RepairDesign::makeRepeater(
22122224
// Resize repeater as we back up by levels.
22132225
if (resize) {
22142226
sta::Pin* buffer_out_pin = network_->findPin(buffer, buffer_output_port);
2215-
resizer_->resizeToTargetSlew(buffer_out_pin);
2227+
resizer_->resizeToTargetSlew(buffer_out_pin, load_cap_hint);
22162228
buffer_cell = network_->libertyCell(buffer);
22172229
buffer_cell->bufferPorts(buffer_input_port, buffer_output_port);
22182230
}

src/rsz/src/RepairDesign.hh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,8 @@ class RepairDesign : sta::dbStaState
216216
sta::PinSeq& load_pins,
217217
float& repeater_cap,
218218
float& repeater_fanout,
219-
float& repeater_max_slew);
219+
float& repeater_max_slew,
220+
std::optional<float> load_cap_hint = std::nullopt);
220221
bool makeRepeater(const char* reason,
221222
int x,
222223
int y,
@@ -230,7 +231,8 @@ class RepairDesign : sta::dbStaState
230231
float& repeater_max_slew,
231232
sta::Net*& out_net,
232233
sta::Pin*& repeater_in_pin,
233-
sta::Pin*& repeater_out_pin);
234+
sta::Pin*& repeater_out_pin,
235+
std::optional<float> load_cap_hint = std::nullopt);
234236
sta::LibertyCell* findBufferUnderSlew(float max_slew, float load_cap);
235237
bool hasInputPort(const sta::Net* net);
236238
double dbuToMeters(int dist) const;

src/rsz/src/Resizer.cc

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2533,7 +2533,8 @@ VTCategory Resizer::cellVTType(dbMaster* master)
25332533
return new_it->second;
25342534
}
25352535

2536-
int Resizer::resizeToTargetSlew(const sta::Pin* drvr_pin)
2536+
int Resizer::resizeToTargetSlew(const sta::Pin* drvr_pin,
2537+
std::optional<float> load_cap_hint)
25372538
{
25382539
sta::Instance* inst = network_->instance(drvr_pin);
25392540
sta::LibertyCell* cell = network_->libertyCell(inst);
@@ -2550,10 +2551,19 @@ int Resizer::resizeToTargetSlew(const sta::Pin* drvr_pin)
25502551
revisiting_inst ? " - revisit" : "");
25512552
resized_multi_output_insts_.insert(inst);
25522553
}
2553-
estimate_parasitics_->ensureWireParasitic(drvr_pin);
2554-
// Includes net parasitic capacitance.
2555-
float load_cap
2556-
= graph_delay_calc_->loadCap(drvr_pin, tgt_slew_corner_, max_);
2554+
// Hint skips ensureWireParasitic, which triggers an incremental
2555+
// FastRoute per buffer in the repair_design.
2556+
// Only applies under global-routing parasitics;
2557+
// placement-based estimation is already cheap.
2558+
float load_cap;
2559+
if (load_cap_hint.has_value()
2560+
&& estimate_parasitics_->getParasiticsSrc()
2561+
== est::ParasiticsSrc::kGlobalRouting) {
2562+
load_cap = *load_cap_hint;
2563+
} else {
2564+
estimate_parasitics_->ensureWireParasitic(drvr_pin);
2565+
load_cap = graph_delay_calc_->loadCap(drvr_pin, tgt_slew_corner_, max_);
2566+
}
25572567
if (load_cap > 0.0) {
25582568
sta::LibertyCell* target_cell
25592569
= findTargetCell(cell, load_cap, revisiting_inst);

0 commit comments

Comments
 (0)