Skip to content

Implement GridGraph capacity clearing for incremental routing state management#9647

Open
Divinesoumyadip wants to merge 1 commit intoThe-OpenROAD-Project:masterfrom
Divinesoumyadip:feat/incremental-grid-capacity
Open

Implement GridGraph capacity clearing for incremental routing state management#9647
Divinesoumyadip wants to merge 1 commit intoThe-OpenROAD-Project:masterfrom
Divinesoumyadip:feat/incremental-grid-capacity

Conversation

@Divinesoumyadip
Copy link

@Divinesoumyadip Divinesoumyadip commented Mar 5, 2026

Summary

This PR introduces clearNetCapacity(const int net_id) to the GridGraph core, providing a memory-safe method to explicitly clear routing state during net rip-up phases.

Architectural Context

As we move towards supporting incremental routing in CUGR (referencing the API wrapper drafted in PR #9645 by @shypark98 ), it is critical that the underlying grid state is mathematically synchronized. If a dirty net is ripped up without restoring the 3D edge capacities and decaying the history costs, the subsequent FastRoute iterations will encounter "phantom congestion" and fail to converge on tight designs.

This implementation traverses the routing tree segments, determines spatial orientation, and explicitly restores the track usage on the exact 3D grid edges before unsetting the net's routed status.

Integration Path

This serves as a required structural prerequisite for the incremental API in #9645. The CUGR engine should call grid_graph_->clearNetCapacity(net_id) before attempting to reroute the dirty nets to ensure the grid space is actually freed.

cc: @eder-matheus .I'd appreciate your architectural review on this grid state synchronization approach!

@Divinesoumyadip Divinesoumyadip force-pushed the feat/incremental-grid-capacity branch from 9f1521e to 3e063c1 Compare March 5, 2026 12:39
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 PR introduces clearNetCapacity to GridGraph for incremental routing, with the goal of clearing net-specific routing state. No security vulnerabilities were found. However, there are critical issues with the placement of the new code: the function declaration for clearNetCapacity has been incorrectly added to AccessPointHash and GridGraphView classes in GridGraph.h, and its implementation in GridGraph.cpp is outside the grt namespace, which will lead to a linker error. These issues need to be addressed.

Comment on lines +911 to +945
} // namespace grt

void GridGraph::clearNetCapacity(const int net_id) {
Tree& tree = getRoutingTree(net_id);
for (const Segment& segment : tree.getSegments()) {
int x1 = segment.x1;
int y1 = segment.y1;
int x2 = segment.x2;
int y2 = segment.y2;
int layer = segment.layer;
bool isHorizontal = (y1 == y2);
if (isHorizontal) {
int min_x = std::min(x1, x2);
int max_x = std::max(x1, x2);
for (int x = min_x; x < max_x; ++x) {
GridEdge* edge = getEdge(x, y1, layer, Direction::Horizontal);
if (edge->getUsage() > 0) {
edge->decrementUsage(1);
}
edge->decayHistoryCost();
}
} else {
int min_y = std::min(y1, y2);
int max_y = std::max(y1, y2);
for (int y = min_y; y < max_y; ++y) {
GridEdge* edge = getEdge(x1, y, layer, Direction::Vertical);
if (edge->getUsage() > 0) {
edge->decrementUsage(1);
}
edge->decayHistoryCost();
}
}
}
setNetRoutedStatus(net_id, false);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

The implementation of GridGraph::clearNetCapacity is defined outside the grt namespace. The GridGraph class is declared within the grt namespace, so its methods must also be defined within this namespace. This will cause a linker error.

void GridGraph::clearNetCapacity(const int net_id) {
    Tree& tree = getRoutingTree(net_id); 
    for (const Segment& segment : tree.getSegments()) {
        int x1 = segment.x1;
        int y1 = segment.y1;
        int x2 = segment.x2;
        int y2 = segment.y2;
        int layer = segment.layer;
        bool isHorizontal = (y1 == y2);
        if (isHorizontal) {
            int min_x = std::min(x1, x2);
            int max_x = std::max(x1, x2);
            for (int x = min_x; x < max_x; ++x) {
                GridEdge* edge = getEdge(x, y1, layer, Direction::Horizontal);
                if (edge->getUsage() > 0) {
                    edge->decrementUsage(1);
                }
                edge->decayHistoryCost(); 
            }
        } else {
            int min_y = std::min(y1, y2);
            int max_y = std::max(y1, y2);
            for (int y = min_y; y < max_y; ++y) {
                GridEdge* edge = getEdge(x1, y, layer, Direction::Vertical);
                if (edge->getUsage() > 0) {
                    edge->decrementUsage(1);
                }
                edge->decayHistoryCost();
            }
        }
    }
    setNetRoutedStatus(net_id, false);
}

}  // namespace grt

class AccessPointHash
{
public:
void clearNetCapacity(const int net_id);
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The clearNetCapacity method declaration seems to be misplaced within the AccessPointHash class. AccessPointHash is a functor for hashing and should not contain logic related to grid capacity management. This method belongs in GridGraph and this declaration is likely a copy-paste error that should be removed.

class GridGraphView : public std::vector<std::vector<std::vector<Type>>>
{
public:
void clearNetCapacity(const int net_id);
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The clearNetCapacity method declaration is misplaced in the GridGraphView template class. GridGraphView is a view over grid data and does not own the grid or have the context to modify net capacities. This logic should be encapsulated within the GridGraph class. This declaration should be removed.

…ate management

Signed-off-by: Divinesoumyadip <soumyadipdasmahapatra343@gmail.com>
@Divinesoumyadip Divinesoumyadip force-pushed the feat/incremental-grid-capacity branch from 3e063c1 to e1f0f36 Compare March 5, 2026 12:57
@Divinesoumyadip
Copy link
Author

Good catch. The previous automated refactor script misplaced the declarations during the header injection. I've just force-pushed a clean update that encapsulates the logic properly within the grt namespace and the GridGraph class. Ready for human review now.
cc: @eder-matheus

@eder-matheus eder-matheus self-requested a review March 5, 2026 16:29
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.

The build in jenkins fails due to the multiple errors in the code. Please, make sure to build it locally and run GRT unit tests before creating the PR and asking for review.

{
public:
void clearNetCapacity(const int net_id);
void clearNetCapacity(const int net_id);
Copy link
Member

Choose a reason for hiding this comment

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

Why is it declared twice?

class GridGraphView : public std::vector<std::vector<std::vector<Type>>>
{
public:
void clearNetCapacity(const int net_id);
Copy link
Member

Choose a reason for hiding this comment

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

Reinforcing the gemini suggestion, remove this declaration from here.

};

} // namespace grt

Copy link
Member

Choose a reason for hiding this comment

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

Remove extra lines.

Comment on lines +947 to +949



Copy link
Member

Choose a reason for hiding this comment

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

Remove extra lines.

int x2 = segment.x2;
int y2 = segment.y2;
int layer = segment.layer;
bool isHorizontal = (y1 == y2);
Copy link
Member

Choose a reason for hiding this comment

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

Use snake_case for variable names.

int min_x = std::min(x1, x2);
int max_x = std::max(x1, x2);
for (int x = min_x; x < max_x; ++x) {
GridEdge* edge = getEdge(x, y1, layer, Direction::Horizontal);
Copy link
Member

Choose a reason for hiding this comment

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

GridEdge is not an existing structure inside CUGR codebase.

Comment on lines +926 to +929
if (edge->getUsage() > 0) {
edge->decrementUsage(1);
}
edge->decayHistoryCost();
Copy link
Member

Choose a reason for hiding this comment

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

These functions don't exist in CUGR code base.

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.

2 participants