Skip to content

Commit a2b21b7

Browse files
authored
Merge pull request #10544 from eder-matheus/est_fix_vias
est: fix parasitic nodes for vias
2 parents 3a29dc8 + 0a1b087 commit a2b21b7

12 files changed

Lines changed: 6084 additions & 4939 deletions

src/dbSta/test/escape_slash.spefok

Lines changed: 886 additions & 886 deletions
Large diffs are not rendered by default.

src/dbSta/test/escape_slash_hier.spefok

Lines changed: 883 additions & 883 deletions
Large diffs are not rendered by default.

src/est/src/EstimateParasitics.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,31 +1017,49 @@ void EstimateParasitics::insertViaResistances(odb::dbTechLayer* pin_layer,
10171017
if (cut_layer->getType() != odb::dbTechLayerType::CUT) {
10181018
continue;
10191019
}
1020-
sta::ParasiticNode* mid_node = parasitics->ensureParasiticNode(
1021-
parasitic, net, ++max_node_index, network_);
1022-
10231020
const double cut_res
10241021
= std::max(layer_res_[layer_idx][corner->index()], 1.0e-3);
10251022

1023+
// Resolve from/to endpoints first, so we only allocate a new mid_node
1024+
// when this iteration actually needs one. On the terminal iteration the
1025+
// resistor connects directly to the pin or tree anchor; if we had
1026+
// pre-allocated a mid_node here it would never be wired up and would
1027+
// become a floating ParasiticNode (singular row in the conductance
1028+
// matrix for Prima/CCS).
10261029
sta::ParasiticNode* from_node = prev_node;
1027-
sta::ParasiticNode* to_node = mid_node;
1030+
sta::ParasiticNode* to_node = nullptr;
1031+
bool need_new_mid = true;
10281032
if (pin_is_below) {
10291033
if (layer_idx - 1 == pin_layer_idx) {
10301034
from_node = pin_node;
1031-
} else if (layer_idx + 1 == tree_layer_idx) {
1035+
}
1036+
if (layer_idx + 1 == tree_layer_idx) {
10321037
to_node = node;
1038+
need_new_mid = false;
10331039
}
10341040
} else {
10351041
if (layer_idx - 1 == tree_layer_idx) {
10361042
from_node = node;
1037-
} else if (layer_idx + 1 == pin_layer_idx) {
1043+
}
1044+
if (layer_idx + 1 == pin_layer_idx) {
10381045
to_node = pin_node;
1046+
need_new_mid = false;
10391047
}
10401048
}
10411049

1050+
sta::ParasiticNode* mid_node = nullptr;
1051+
if (need_new_mid) {
1052+
mid_node = parasitics->ensureParasiticNode(
1053+
parasitic, net, ++max_node_index, network_);
1054+
to_node = mid_node;
1055+
}
1056+
10421057
parasitics->makeResistor(
10431058
parasitic, resistor_id++, cut_res, from_node, to_node);
10441059

1060+
// On the terminal iteration mid_node is nullptr and prev_node is unused
1061+
// by the next iteration (there is none); on every other iteration we
1062+
// chain through the freshly allocated mid_node.
10451063
prev_node = mid_node;
10461064
}
10471065
}

src/est/src/MakeWireParasitics.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33

44
#include "MakeWireParasitics.h"
55

6+
#include <algorithm>
67
#include <cmath>
78
#include <cstddef>
9+
#include <iterator>
10+
#include <map>
811
#include <string>
12+
#include <utility>
913
#include <vector>
1014

1115
#include "db_sta/SpefWriter.hh"
@@ -242,6 +246,67 @@ void MakeWireParasitics::makeRouteParasitics(sta::Parasitics* parasitics,
242246
parasitics->makeResistor(parasitic, resistor_id_++, res, n1, n2);
243247
parasitics->incrCap(n2, cap / 2.0);
244248
}
249+
250+
// Workaround: implicit-via post-pass.
251+
//
252+
// GRT does not always emit an explicit isVia=true segment at every
253+
// layer transition along a route; coincident endpoints on adjacent
254+
// routing levels are treated as implicitly connected. EST has historically
255+
// taken GRoute literally, so any layer transition without an explicit via
256+
// segment ends up as two distinct ParasiticNodes at the same (x, y) with
257+
// no resistor between them -- a disconnected island in the parasitic
258+
// network. That goes unnoticed by pi-Elmore-based delay calculators but
259+
// produces a singular conductance matrix in Prima/CCS.
260+
//
261+
// Close the contract gap here: scan node_map for coincident endpoints on
262+
// adjacent routing levels and, when no resistor already bridges them,
263+
// insert one with the appropriate cut-layer resistance.
264+
std::vector<std::pair<sta::ParasiticNode*, sta::ParasiticNode*>>
265+
connected_pairs;
266+
for (sta::ParasiticResistor* r : parasitics->resistors(parasitic)) {
267+
sta::ParasiticNode* a = parasitics->node1(r);
268+
sta::ParasiticNode* b = parasitics->node2(r);
269+
connected_pairs.emplace_back(std::minmax(a, b));
270+
}
271+
std::ranges::sort(connected_pairs);
272+
273+
if (!node_map.empty()) {
274+
auto prev_it = node_map.begin();
275+
for (auto it = std::next(prev_it); it != node_map.end();
276+
prev_it = it, ++it) {
277+
const auto& prev_pt = prev_it->first;
278+
const auto& curr_pt = it->first;
279+
if (prev_pt.x() != curr_pt.x() || prev_pt.y() != curr_pt.y()) {
280+
continue;
281+
}
282+
if (curr_pt.layer() != prev_pt.layer() + 1) {
283+
// Not adjacent routing levels -- skipping signals that an
284+
// intermediate routing-level node is missing entirely, which is a
285+
// different bug worth surfacing rather than silently bridging.
286+
continue;
287+
}
288+
sta::ParasiticNode* lo_node = prev_it->second;
289+
sta::ParasiticNode* hi_node = it->second;
290+
const std::pair<sta::ParasiticNode*, sta::ParasiticNode*> pair
291+
= std::minmax(lo_node, hi_node);
292+
auto bound_it = std::ranges::lower_bound(connected_pairs, pair);
293+
if (bound_it != connected_pairs.end() && *bound_it == pair) {
294+
continue;
295+
}
296+
odb::dbTechLayer* lower_routing
297+
= tech_->findRoutingLayer(prev_pt.layer());
298+
odb::dbTechLayer* cut_layer
299+
= lower_routing ? lower_routing->getUpperLayer() : nullptr;
300+
if (cut_layer == nullptr) {
301+
// Top of stack or unresolved -- do not silently invent a resistor.
302+
continue;
303+
}
304+
const float via_R = getCutLayerRes(cut_layer, corner);
305+
parasitics->makeResistor(
306+
parasitic, resistor_id_++, via_R, lo_node, hi_node);
307+
connected_pairs.insert(bound_it, pair);
308+
}
309+
}
245310
}
246311

247312
void MakeWireParasitics::makeParasiticsToPins(

0 commit comments

Comments
 (0)