Skip to content

grt: add incremental routing support to CUGR#9645

Closed
sparsh-karna wants to merge 0 commit intoThe-OpenROAD-Project:masterfrom
sparsh-karna:master
Closed

grt: add incremental routing support to CUGR#9645
sparsh-karna wants to merge 0 commit intoThe-OpenROAD-Project:masterfrom
sparsh-karna:master

Conversation

@sparsh-karna
Copy link

@sparsh-karna sparsh-karna commented Mar 5, 2026

Summary

Adds incremental global routing support to the CUGR backend,
mirroring the existing FastRoute incremental API.

Changes

  • Added addDirtyNet(), startIncremental(), endIncremental()
    public methods to CUGR
  • Added private rerouteNets() helper to avoid code duplication
  • Incremental mode rips up dirty nets, reroutes them through all
    three routing stages, and propagates overflow to neighboring nets
  • Sort dirty nets by slack (then HPWL) before rip-up phase in
    rerouteNets(), ensuring critical nets reclaim routing resources
    first, mirroring FastRoute's incremental behavior

Testing

  • All existing grt regression tests pass
  • Builds cleanly on Linux (GCC 13) and but on macOS (AppleClang 17)

Copy link
Contributor

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

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 incremental routing capabilities to the CUGR global router, which is a significant feature enhancement. The implementation mirrors the existing FastRoute API by adding addDirtyNet, startIncremental, and endIncremental methods. A new helper function rerouteNets is introduced to avoid code duplication, which is good practice. The logic correctly handles rerouting of dirty nets and also considers secondary overflows by rerouting neighboring affected nets. The code is well-structured. I have one suggestion to improve the implementation by using a standard library algorithm which can make the code more concise and performant.

Note: Security Review did not run due to the size of the PR.

Comment on lines +658 to +663
std::vector<int> secondary_nets;
for (const int net_index : overflow_nets) {
if (dirty_net_indices_.find(net_index) == dirty_net_indices_.end()) {
secondary_nets.push_back(net_index);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This loop to find secondary nets can be implemented more concisely and efficiently using std::set_difference. Since overflow_nets (as populated by updateOverflowNets) and dirty_net_indices_ are both sorted, std::set_difference is a suitable replacement. This change would improve performance from O(N*logM) for the loop with find to O(N+M) for the algorithm, where N and M are the sizes of the two containers.

  std::vector<int> secondary_nets;
  std::set_difference(overflow_nets.begin(),
                      overflow_nets.end(),
                      dirty_net_indices_.begin(),
                      dirty_net_indices_.end(),
                      std::back_inserter(secondary_nets));

@Divinesoumyadip
Copy link

The bot makes a good point regarding the O(N+M) STL optimization for the secondary nets, but looking at the higher-level architecture, I have a concern regarding the grid state synchronization.

I’ve been deep in the grt core recently wrapping up the GridGraph architectural refactor (PR #9642) and detour metric tracking (PR #9641), and I'm very interested in how your incremental API interacts with the underlying grid state during the rip-up phase.

When rerouteNets() rips up the dirty nets, how are you ensuring that the 3D edge capacities and history costs within the GridGraph are synchronously decremented before the CUGR engine triggers the reroute? If the grid state isn't explicitly cleared from the previous routing iteration, we risk hitting "phantom congestion" where the incremental pass avoids tracks that are actually free.

We should probably align your startIncremental() and net invalidation hooks with the new GridGraph coordinate search logic I'm finalizing to ensure accurate capacity tracking during high-frequency timing loops.

@sparsh-karna
Copy link
Author

Code Review

This pull request introduces incremental routing capabilities to the CUGR global router, which is a significant feature enhancement. The implementation mirrors the existing FastRoute API by adding addDirtyNet, startIncremental, and endIncremental methods. A new helper function rerouteNets is introduced to avoid code duplication, which is good practice. The logic correctly handles rerouting of dirty nets and also considers secondary overflows by rerouting neighboring affected nets. The code is well-structured. I have one suggestion to improve the implementation by using a standard library algorithm which can make the code more concise and performant.

Note: Security Review did not run due to the size of the PR.

Good catch — applied in the latest commit.

@eder-matheus
Copy link
Member

@sparsh-karna DCO is failing in the PR. You need to sign-off your commits by adding the -s flag to the git commit call: git commit -s -m "".

Check the DCO link in the checks for advise on how to fix DCO.

I'll review the code in details soon.

@sparsh-karna
Copy link
Author

@sparsh-karna DCO is failing in the PR. You need to sign-off your commits by adding the -s flag to the git commit call: git commit -s -m "".

Check the DCO link in the checks for advise on how to fix DCO.

I'll review the code in details soon.

got it, will keep that in mind for future

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

std::set_difference(overflow_nets.begin(),
overflow_nets.end(),
dirty_net_indices_.begin(),
dirty_net_indices_.end(),
Copy link
Contributor

Choose a reason for hiding this comment

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

warning: use a ranges version of this algorithm [modernize-use-ranges]

Suggested change
dirty_net_indices_.end(),
std::ranges::set_difference(overflow_nets,
,
dirty_net_indices_,
,

@github-actions
Copy link
Contributor

github-actions bot commented Mar 5, 2026

clang-tidy review says "All clean, LGTM! 👍"

1 similar comment
@github-actions
Copy link
Contributor

github-actions bot commented Mar 5, 2026

clang-tidy review says "All clean, LGTM! 👍"

Copy link
Member

@eder-matheus eder-matheus left a comment

Choose a reason for hiding this comment

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

I find this a good start on digging into how to make CUGR incremental, but my suggestions are aiming to make it simpler and use the existing infrastructure for incremental routing.

dirty_net_indices_.insert(it->second->getIndex());
} else {
logger_->warn(
GRT, 600, "Net {} not found in CUGR net map.", net->getConstName());
Copy link
Member

Choose a reason for hiding this comment

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

During incremental routing, new nets can be created by buffer insertion, and they'll not be inside CUGR map yet. We need to ensure that the new nets are created in these cases.

This warning would make sense if the process of adding the new nets to CUGR structures is performed before the addDirtyNet calls.

Comment on lines +629 to +633
void CUGR::startIncremental()
{
incremental_mode_ = true;
dirty_net_indices_.clear();
}
Copy link
Member

Choose a reason for hiding this comment

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

I believe a simpler approach would be to mimic how incremental works for FastRouteCore. Instead of managing the start/end incremental, FastRouteCore looks at the list of nets that will be routed on the run. All the management regarding detecting the dirty nets is performed by the GlobalRouter class.

My suggestions would be:

  • Instead of a dirty nets list inside CUGR, we'd have a list of nets to route (similar to FastRouteCore)
  • Prior to incremental route, all the nets would be routed, so this list would have all the net IDs
  • On incremental calls, GlobalRouter will be responsible to tell CUGR what are the dirty nets

APIs to include new individual nets, and to update the net pins will also be necessary.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants