grt: Implement timing-driven net sorting for incremental CUGR#9828
grt: Implement timing-driven net sorting for incremental CUGR#9828Divinesoumyadip wants to merge 3 commits intoThe-OpenROAD-Project:masterfrom
Conversation
This PR ensures that critical paths are prioritized during incremental routing by querying slacks from OpenSTA before sorting the reroute queue. This significantly improves timing QoR during ECO passes. Signed-off-by: Divinesoumyadip <soumyacode7@gmail.com>
There was a problem hiding this comment.
Code Review
This pull request introduces timing-driven net sorting for incremental routing in CUGR. The changes in rerouteNets correctly query slack data from OpenSTA and prioritize critical nets. A new helper function, removeRouteUsage, is also added for ripping up individual nets. The implementation is sound and aligns with the goal of improving timing QoR during ECOs. I have one suggestion to merge two loops in rerouteNets for better performance, aligning with principles of optimizing loop structures.
| for (const int idx : net_indices) { | ||
| if (gr_nets_[idx]->getRoutingTree()) { | ||
| grid_graph_->removeTreeUsage(gr_nets_[idx]->getRoutingTree()); | ||
| } | ||
| } | ||
|
|
||
| // 2. Query STA for fresh slacks if timing is available | ||
| if (sta_ != nullptr) { | ||
| for (const int idx : net_indices) { | ||
| odb::dbNet* db_net = gr_nets_[idx]->getDbNet(); | ||
| float slack = getNetSlack(db_net); | ||
| gr_nets_[idx]->setSlack(slack); | ||
| } | ||
| // 3. Sort: Most negative slack (critical) nets go FIRST | ||
| sortNetIndices(net_indices); | ||
| } |
There was a problem hiding this comment.
For better performance, the loop for ripping up nets and the loop for querying slacks can be merged into a single loop. This avoids iterating over net_indices twice, which can be a significant saving if the number of nets to reroute is large. This aligns with the principle of optimizing loop structures to reduce redundant iterations, similar to how a single-pass approach can be more efficient than a two-pass approach.
for (const int idx : net_indices) {
GRNet* gr_net = gr_nets_[idx];
if (gr_net->getRoutingTree()) {
grid_graph_->removeTreeUsage(gr_net->getRoutingTree());
}
if (sta_ != nullptr) {
odb::dbNet* db_net = gr_net->getDbNet();
float slack = getNetSlack(db_net);
gr_net->setSlack(slack);
}
}
// 3. Sort if timing is available
if (sta_ != nullptr) {
// Sort: Most negative slack (critical) nets go FIRST
sortNetIndices(net_indices);
}References
- When analyzing code within a loop, consider the entire loop structure. Operations at the beginning of the loop can affect the logic within the loop body, potentially making similar calls inside the loop redundant. Also, a single-pass method can be more efficient than a two-pass approach by avoiding processing all items multiple times.
| updated_nets_.insert(db_net); | ||
| } | ||
|
|
||
| void CUGR::removeRouteUsage(odb::dbNet* db_net) |
There was a problem hiding this comment.
warning: out-of-line definition of 'removeRouteUsage' does not match any declaration in 'grt::CUGR' [clang-diagnostic-error]
void CUGR::removeRouteUsage(odb::dbNet* db_net)
^
src/grt/src/cugr/src/CUGR.cpp
Outdated
| for (const int idx : net_indices) { | ||
| if (gr_nets_[idx]->getRoutingTree()) { | ||
| grid_graph_->removeTreeUsage(gr_nets_[idx]->getRoutingTree()); | ||
| GRNet* gr_net = gr_nets_[idx]; |
There was a problem hiding this comment.
warning: no viable conversion from 'value_type' (aka 'std::unique_ptrgrt::GRNet') to 'GRNet *' [clang-diagnostic-error]
GRNet* gr_net = gr_nets_[idx];
^Signed-off-by: Divinesoumyadip <soumyacode7@gmail.com>
dc51033 to
5758666
Compare
eder-matheus
left a comment
There was a problem hiding this comment.
The idea of the PR is good, but if you look at the patternRoute, patternRouteWithDetours and mazeRoute functions, you'll see that they already call the sortNetIndices internally. So the new process introduced in this PR is redundant.
| updated_nets_.insert(db_net); | ||
| } | ||
|
|
||
| void CUGR::removeRouteUsage(odb::dbNet* db_net) |
There was a problem hiding this comment.
Where's this function used? I believe the first lines of the rerouteNets function already covers this process.
| grid_graph_->removeTreeUsage(gr_net->getRoutingTree()); | ||
| } | ||
|
|
||
| if (sta_ != nullptr) { |
There was a problem hiding this comment.
You don't need this sta_ check (here and below).
| } | ||
| } | ||
|
|
||
| // 3. Sort: Most negative slack (critical) nets go FIRST |
There was a problem hiding this comment.
This comment seems a bit out of place - where are steps 1. and 2.? Please remove it (and the comment below), the functions are self documented.
This PR prioritizes timing-critical nets during the incremental rerouting process. By querying fresh slack data from OpenSTA before rerouting, the tool ensures that nets with the worst negative slack (WNS) get the first choice of routing resources.
In the previous incremental flow, nets were rerouted in an arbitrary order. This often led to non-critical nets occupying the most direct tracks, forcing critical timing paths into long detours. This PR ensures that "VIP" nets (those with negative slack) are handled first to protect chip performance during ECO passes.
I modified
CUGR::rerouteNetsto refresh timing data before routing.Integrated a loop to querysta_(OpenSTA) for each net's current slack.UtilizessortNetIndicesto re-order the reroute queue so that nets with the most negative slack are at the front.Reduces timing degradation during ECO passes and improves the overall Timing Quality of Results (QoR) by prioritizing paths that define the chip's maximum clock frequency.