Skip to content

grt: enhance FastRoute NDR handling - #11963

Open
jfgava wants to merge 16 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:grt-update-fr-ndr-handling
Open

jfgava wants to merge 16 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:grt-update-fr-ndr-handling

Conversation

@jfgava

@jfgava jfgava commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Problem

During the 2D stages, FastRoute checks that each NDR net fits in a single layer of every edge it uses. When no layer could host the net, Graph2D::getCostNDRAware added 100 × the net's edge cost to the shared edge usage. Every later NDR net on that edge was charged the same, even when it fit.

For example, an edge with three layers of 2 tracks each cannot host an NDR net of cost 3. That edge looked about 300 tracks over capacity, although it still had room for three regular nets. As a result:

  • Regular nets were pushed off edges they fit in.
  • The overflow iterations chased overflow that did not exist.
  • The inflated usage could exceed the 2D usage limit, triggering the GRT-0228.

Implementation

  • True usage. The shared usage always gets the net's real edge cost. The tracks an NDR net misses on its best layer are recorded as its NDR deficit on the edge (NDRUsage::deficit, Edge::ndr_deficit, plus a running total).
  • Pricing for NDR nets only. FastRouteCore::getUsageNDRAware makes an edge with a deficit look overflowed by kNdrDeficitCost (100) tracks per missing track, but only to NDR nets. Regular nets see the true usage. It feeds the maze cost and the L, Z, spiral and monotonic pattern routes. The NDR nets on an edge share its deficit (getNDRDeficitIfRouted), so a net that fits also sees the nets it leaves without room.
  • Rip-up. NDR nets are rerouted off edges with a deficit, even when the edge is below capacity.
  • Overflow. The 2D overflow includes the total deficit, in both the incremental count and its full-scan reference. The iteration loop, best-solution tracking and soft-NDR demotion therefore still react to it. The NDR fallback after layer assignment also triggers whenever a deficit is left.
  • Net order. StNetOrder adds 100 × an NDR net's own deficit to the net's congestion key. The key is now capped at the int16_t maximum instead of wrapping.
  • Stale records. initNDRnets clears the per-edge NDR records of the previous run. Without this, a new net allocated at the address of a deleted one was taken for a net already using the edge.
  • Cleanup. The multiplier, hasNDRCapacity, and the unused net name copy in getCostNDRAware are removed.

Tests

  • New: NDR deficits. Two tests in the NDRDeficitTest fixture of TestOverflow:
    • the 3 layers × 2 tracks example with an NDR net of cost 3: usage 3, deficit 1, three regular nets still fit, 2D overflow 1;
    • two NDR nets sharing one edge's deficit.
  • New: re-init. A TestGraph2D test checks that a same-size re-init drops the previous run's NDR records. It fails without the fix.
  • Updated. AccountsForNDRDeficitsAndCancellation (previously AccountsForNDRPenaltiesAndCancellation), and few goldens.

Results

The initial global_route was replayed on 21 ORFS checkpoints and compared with the code before this change:

design wirelength vias
nangate45/mempool_group −0.61% ≈0
sky130hd/gcd −0.29% 0
sky130hd/chameleon −0.20% −0.09%
sky130hd/microwatt −0.11% +0.05%
nangate45/tinyRocket −0.08% +0.08%
sky130hd/aes +0.08% +0.15%
  • The other 15 designs, including nangate45/ariane133, are bit-identical.
  • None of the 21 designs ends with 3D overflow.

Type of Change

  • New feature

Impact

Better handling of routing resources when dealing with NDR nets during FastRoute 2D phases.

Verification

  • I have verified that the local build succeeds (./etc/Build.sh).
  • I have run the relevant tests and they pass.
  • My code follows the repository's formatting guidelines.
  • I have included tests to prevent regressions.
  • I have signed my commits (DCO).

When no layer of an edge could host an NDR net, getCostNDRAware added
100 times the net's edge cost to the shared 2D usage, and every later
NDR net on that edge was charged the same, even when it fit. All nets
then saw the edge as overflowed although it still had room for regular
nets, the overflow iterations chased overflow that did not exist, and
the inflated usage could exceed the usage limit (GRT-0228 on
nangate45/mempool_group).

The shared usage now gets the true edge cost. The tracks an NDR net
misses on its best layer are recorded as its NDR deficit on the edge,
and only the NDR nets see it:
- NDR nets price an edge with a deficit, in the maze and pattern
  routing costs, as overflowed by kNdrDeficitCost (100) tracks per
  missing track. The NDR nets on an edge share its deficit, so the one
  that fits can also move away.
- NDR nets are ripped up from edges with a deficit.
- The 2D overflow counts the deficits, and the NDR fallback after layer
  assignment also triggers when one is left.
- StNetOrder counts the deficit of an NDR net in its overflow, and
  saturates the int16 key instead of wrapping.

initNDRnets now clears the NDR records of the previous run: resize keeps
them on a same-sized grid, and a new net allocated at the address of a
deleted one was taken for a net already using the edge.

The unused net name copy is removed from getCostNDRAware.

Golden updates:
- ndr_1w_3s: wirelength 1684 -> 1663 um, vias 206 -> 211
- soft_ndr_4w_6s: wirelength 1850 -> 1756 um, vias 198 -> 195
- soft_ndr_escalation: wirelength 1814 -> 1872 um, vias 202 -> 199. The
  NDR nets are demoted at the iteration limit instead of on stagnation,
  since the overflow keeps improving.

Signed-off-by: Jonas Gava <jfgava@precisioninno.com>
Replacing the NDR overflow multiplier with NDR deficits changes the
global routes of jpeg_sky130hd and jpeg_sky130hs, and the antenna repair
after detailed routing leaves one more violation in each: 0 -> 1 and
1 -> 2. The violations are on regular signal nets (met1 side area
ratio), not on NDR nets. Timing otherwise holds (DRT WNS -0.481 ->
-0.423 ns and -0.371 -> -0.363 ns), and every other limit is still met,
so only the DRT::ANT::errors limits are raised.

Signed-off-by: Jonas Gava <jfgava@precisioninno.com>
Limits from the flow_metrics.tcl formulas on this branch's results: clock skew 0.392 -> limit 0.470, antenna errors 1.

Signed-off-by: Jonas Gava <jfgava@precisioninno.com>
@jfgava jfgava self-assigned this Oct 23, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the concept of NDR deficits to track and price Non-Default Routing (NDR) nets that cannot fit on any single layer of an edge, separating deficits from edge usage and integrating them into routing costs, rip-up checks, and net ordering. Feedback on these changes highlights two key improvements: first, in Graph2D::initNDRnets(), the multi-arrays should be resized before calling clearNDRnets() to prevent potential out-of-bounds accesses when grid dimensions change; second, in getUsageNDRAware(), using edge-specific capacities via getEdgeCapacity() instead of nominal global capacities would more accurately represent congestion on edges with reduced capacity.

Comment thread src/grt/src/fastroute/src/graph2d.cpp
Comment thread src/grt/src/fastroute/src/FastRoute.cpp Outdated
Signed-off-by: Jonas Gava <jfgava@precisioninno.com>
Signed-off-by: Jonas Gava <jfgava@precisioninno.com>
@github-actions github-actions Bot added size/XL and removed size/L labels Oct 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This PR exceeds the recommended size of 1000 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size.

@jfgava jfgava changed the title grt: update FastRoute NDR handling grt: enhance FastRoute NDR handling Oct 27, 2026
Regenerate the soft_ndr_4w_6s and soft_ndr_escalation goldens for the per-edge capacity in getUsageNDRAware, and add a unit test that pins the price of a reduced edge.

Signed-off-by: Jonas Gava <jfgava@precisioninno.com>
@jfgava
jfgava marked this pull request as ready for review October 27, 2026 20:46
@jfgava
jfgava requested review from a team as code owners October 27, 2026 20:46
@jfgava
jfgava requested a review from eder-matheus October 27, 2026 20:46
When a net leaves an edge, re-reserve the layers of the NDR nets that
miss tracks there, in net id order, so their deficit does not outlive
the net that caused it.

Gate the 3D maze routing on the 2D usage overflow only: the NDR deficit
comes from first-fit 2D layer reservations, which layer assignment can
improve on.

Sum the edge deficits in the full-scan overflow references, so that the
overflow checks catch a drifting running total.

ndr_1w_3s now converges after one extra iteration instead of three,
with the same routes.

Signed-off-by: Jonas Gava <jfgava@precisioninno.com>
…ROAD into grt-update-fr-ndr-handling

Signed-off-by: Jonas Gava <jfgava@precisioninno.com>
Regenerate the metrics and limits of ibex_sky130hd, ibex_sky130hs and
jpeg_sky130hd from the Bazel run after merging master. This branch's
global routing demotes fewer NDR clock nets, which changes post-route
slew, capacitance and antenna results on these designs.

Signed-off-by: Jonas Gava <jfgava@precisioninno.com>
@jfgava
jfgava requested a review from luis201420 October 28, 2026 16:00
@luis201420

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@jfgava

jfgava commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-28T21:18:59.375496Z
We couldn’t complete this review. Comment @codex review to try again.
9752406 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

An unknown error occurred
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@jfgava

jfgava commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

An unknown error occurred
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants