From efe551ef8fef3bb50e8a0d0432f4b759b0ff6bd1 Mon Sep 17 00:00:00 2001 From: Suhrid Marwah Date: Fri, 10 Apr 2026 12:23:40 +0530 Subject: [PATCH] rsz: fix load cap computation in hold buffer insertion guard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In repairEndHold(), the buffer delay guard used loadCap() on the wrong pin (end_vertex, a sink) to estimate the inserted buffer's load capacitance. This returned near-zero cap, making the guard trivially permissive and relying entirely on the post-insertion journal rollback. Replacing it with loadCap() on the driver pin (path_vertex) is semantically more correct but overestimates the buffer load: it includes the full pre-split net parasitics, which are absent on the shorter post-split net. This causes buffer_delays to be overestimated, valid hold buffer insertions to be rejected by the guard, and consequently worse slew and capacitance slack. Fix: compute load_cap directly as the sum of pin capacitances of load_pins — the exact set of pins the inserted buffer will drive. This avoids counting parasitics from net segments that will not exist after splitting, giving an accurate and non-pessimistic guard estimate. Signed-off-by: Suhrid Marwah --- src/rsz/src/RepairHold.cc | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/rsz/src/RepairHold.cc b/src/rsz/src/RepairHold.cc index ae08c67939..84707bfc0d 100644 --- a/src/rsz/src/RepairHold.cc +++ b/src/rsz/src/RepairHold.cc @@ -572,7 +572,6 @@ void RepairHold::repairEndHold(sta::Vertex* end_vertex, sta::PinSeq load_pins; Slacks slacks; mergeInit(slacks); - float excluded_cap = 0.0; bool loads_have_out_port = false; sta::VertexOutEdgeIterator edge_iter(path_vertex, graph_); while (edge_iter.hasNext()) { @@ -590,11 +589,6 @@ void RepairHold::repairEndHold(sta::Vertex* end_vertex, && network_->isTopLevelPort(load_pin)) { loads_have_out_port = true; } - } else { - sta::LibertyPort* load_port = network_->libertyPort(load_pin); - if (load_port) { - excluded_cap += load_port->capacitance(); - } } } } @@ -611,9 +605,18 @@ void RepairHold::repairEndHold(sta::Vertex* end_vertex, delayAsString(slacks[fall_index_][max_index_], sta_), load_pins.size()); sta::Scene* corner = sta_->cmdScene(); - float load_cap - = graph_delay_calc_->loadCap(end_vertex->pin(), corner, max_) - - excluded_cap; + // Compute load cap as the sum of the pin capacitances that the + // inserted hold buffer will drive. Using loadCap on the driver pin + // would include the full original-net parasitics which are absent + // on the post-split net, causing the guard below to over-reject + // valid insertions. + float load_cap = 0.0; + for (const sta::Pin* load_pin : load_pins) { + sta::LibertyPort* load_port = network_->libertyPort(load_pin); + if (load_port) { + load_cap += load_port->capacitance(); + } + } sta::ArcDelay buffer_delays[sta::RiseFall::index_count]; sta::Slew buffer_slews[sta::RiseFall::index_count]; resizer_->bufferDelays(buffer_cell,