grt: add incremental routing support to CUGR#9645
grt: add incremental routing support to CUGR#9645sparsh-karna wants to merge 0 commit intoThe-OpenROAD-Project:masterfrom
Conversation
There was a problem hiding this comment.
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.
src/grt/src/cugr/src/CUGR.cpp
Outdated
| 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); | ||
| } | ||
| } |
There was a problem hiding this comment.
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));|
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. |
Good catch — applied in the latest commit. |
|
@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 |
src/grt/src/cugr/src/CUGR.cpp
Outdated
| std::set_difference(overflow_nets.begin(), | ||
| overflow_nets.end(), | ||
| dirty_net_indices_.begin(), | ||
| dirty_net_indices_.end(), |
There was a problem hiding this comment.
warning: use a ranges version of this algorithm [modernize-use-ranges]
| dirty_net_indices_.end(), | |
| std::ranges::set_difference(overflow_nets, | |
| , | |
| dirty_net_indices_, | |
| , |
|
clang-tidy review says "All clean, LGTM! 👍" |
1 similar comment
|
clang-tidy review says "All clean, LGTM! 👍" |
eder-matheus
left a comment
There was a problem hiding this comment.
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.
src/grt/src/cugr/src/CUGR.cpp
Outdated
| dirty_net_indices_.insert(it->second->getIndex()); | ||
| } else { | ||
| logger_->warn( | ||
| GRT, 600, "Net {} not found in CUGR net map.", net->getConstName()); |
There was a problem hiding this comment.
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.
src/grt/src/cugr/src/CUGR.cpp
Outdated
| void CUGR::startIncremental() | ||
| { | ||
| incremental_mode_ = true; | ||
| dirty_net_indices_.clear(); | ||
| } |
There was a problem hiding this comment.
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.
Summary
Adds incremental global routing support to the CUGR backend,
mirroring the existing FastRoute incremental API.
Changes
addDirtyNet(),startIncremental(),endIncremental()public methods to CUGR
rerouteNets()helper to avoid code duplicationthree routing stages, and propagates overflow to neighboring nets
rerouteNets(), ensuring critical nets reclaim routing resources
first, mirroring FastRoute's incremental behavior
Testing