grt,cts,est: backside-aware fixes (cross-side direction check, NDR creation, parasitic midpoint)#10600
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces changes to handle backside routing layers appropriately across TritonCTS, EstimateParasitics, and GlobalRouter. Specifically, it skips backside routing layers when writing clock NDRs, refines the fallback logic for estimating parasitics to focus on the frontside routing stack, and avoids adjacent layer direction checks across the backside/frontside boundary. The review feedback highlights potential segmentation faults in TritonCTS.cpp and GlobalRouter.cpp due to missing null checks on routing layer pointers returned by findRoutingLayer before calling isBackside().
|
@mguthaus I just reran with this PR and no errors this time. Thanks |
checkAdjacentLayersDirection walks tech->findRoutingLayer(l) and findRoutingLayer(l+1) and errors GRT-126 when the two share a preferred direction. dbTech::findRoutingLayer indexes both frontside and backside layers by routing level, so the level-l / level-l+1 pair can straddle the backside / frontside boundary (e.g. BPR(H) at level k and M0(H) at level k+1 in a BSPDN tech). Those layers are not physical neighbors; they sit on opposite sides of the substrate, and direction agreement across the boundary is not a misconfiguration. Skip the pair when the two layers disagree on isBackside(). Does not trip in flows that set MIN_ROUTING_LAYER above the boundary (as the gt2n ORFS platform does today with M2), but the check would fire as a hard error if MIN_ROUTING_LAYER were lowered to M0 or below. Signed-off-by: Matthew Guthaus <mrg@ucsc.edu>
writeClockNDRsToDb walks tech->findRoutingLayer(1..count) and creates a dbTechLayerRule under the clock NDR for every routing layer in the tech, including backside layers (BPR, BM*, BRDL on a BSPDN tech). Clock trees are routed on the frontside; the backside NDR rules pick up backside-specific widths and pitches that would never be applied to a clock net but still live in the dbTechNonDefaultRule and could leak through downstream lookups by layer name. Guard the loop with isBackside() so the NDR only covers layers that clock routing can actually use. Signed-off-by: Matthew Guthaus <mrg@ucsc.edu>
computeAverageCutResistance falls back to getRoutingLayerCount() / 2 when the block has no explicit max routing layer set. On a BSPDN tech the count includes backside routing layers (BPR, BM*, BRDL) sitting at low routing levels, so the midpoint lands on the backside stack and the loop that averages cut-layer resistance walks an inactive part of the via stack instead of the signal-routing layers it is meant to characterize. Use firstFrontsideRoutingLayer() to anchor the fallback at the first frontside level and halve the frontside-only count from there. Legacy techs without backside layers (first frontside == level 1) keep exactly the previous count / 2 behavior. Signed-off-by: Matthew Guthaus <mrg@ucsc.edu>
3dd35b3 to
778e7e9
Compare
|
Had to rebase/push again since Jenkins randomly failed. |
Summary
Three small backside-aware fixes uncovered while bringing up the
gt2n BSPDN PDK in OpenROAD-flow-scripts. Each is independent and
sits as its own commit. The underlying theme is the same: routines
that walk
dbTech::findRoutingLayer(1..count)without anisBackside()guard misbehave on a tech whose routing-layerenumeration interleaves a backside stack (BPR, BM*, BRDL) with the
familiar frontside stack (M0 .. RDL).
Commits
grt: skip cross-side pairs in checkAdjacentLayersDirection
GRT-126 is a hard error fired when two consecutive routing levels
share a preferred direction. On a BSPDN tech the level-l /
level-l+1 pair can straddle the backside boundary (e.g. BPR(H) and
M0(H)). Those layers are not physical neighbors and direction
agreement across the boundary is not a misconfiguration. Skip the
pair when isBackside() differs.
cts: skip backside layers in writeClockNDRsToDb
The default-NDR creation loop builds a dbTechLayerRule for every
routing layer in the tech. Clock trees route on the frontside.
The backside rules are derived from backside design rules and
would never apply to a clock net, but still live in the
dbTechNonDefaultRule and could leak through by-name lookups.
est: keep cut-resistance fallback midpoint on the frontside stack
computeAverageCutResistance falls back to
getRoutingLayerCount() / 2 when block max routing layer is unset.
With backside layers in the count, that midpoint lands on the
backside via stack instead of the signal-routing via stack the
function is meant to characterize. Anchor the fallback at
firstFrontsideRoutingLayer() and halve the frontside-only count.
Legacy non-backside techs are unchanged.
Why now / impact
The GRT-126 case is not theoretical. Lowering MIN_ROUTING_LAYER to
M0, a perfectly reasonable choice that @gadfort appears to have been
running when he flagged this, is enough to make the check walk the
BPR(H) / M0(H) pair and abort the flow with a hard error on a valid
BSPDN PDK. The default ORFS gt2n config sets MIN_ROUTING_LAYER=M2
today and so happens to skip over the boundary, which masks the bug;
any config that opens the bottom of the stack hits it immediately.
The CTS and EST cases are quieter. The bogus NDR rules on backside
layers never get applied to a clock net in practice, and the EST
fallback only fires when block max routing layer is unset. They are
the same underlying pattern and worth cleaning up at the same time.
Test plan
5_1_grtclean with the seriesapplied (no GRT-126, no behavioral change vs. unpatched for
that config since MIN_ROUTING_LAYER=M2 and block max is set).
which is what the legacy-equivalence arms of each patch preserve.
Related
@gadfort flagged the GRT-126 case on a review comment elsewhere.
Filing the cluster of three together since they all share the same
underlying pattern.