Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
e98bf40
grt: add incremental routing support to CUGR
sparsh-karna Mar 5, 2026
11a684a
grt: refactor incremental CUGR reroute logic into helper method
TheUnnamedOne-design Mar 5, 2026
7b57166
grt: use std::set_difference for secondary net filtering
sparsh-karna Mar 5, 2026
a568365
grt: use std::set_difference for secondary net filtering
sparsh-karna Mar 5, 2026
f55110d
grt: use std::ranges::set_difference per clang-tidy
sparsh-karna Mar 5, 2026
d131a35
grt: sort dirty nets by slack before rip-up in incremental CUGR
sparsh-karna Mar 5, 2026
8adda02
grt: add updateNet for incremental topology refresh after buffer inse…
sparsh-karna Mar 5, 2026
ce4f149
grt: fix clang-format
sparsh-karna Mar 6, 2026
833cbf9
grt: extract congestion view after rip-up in rerouteNets for accurate…
sparsh-karna Mar 6, 2026
6318ffe
grt: address review comments on #9671
sparsh-karna Mar 11, 2026
bdd8707
grt: limit commitTree null check to incremental context only
sparsh-karna Mar 11, 2026
f68d05a
fix: correct SWIG block syntax in GlobalRouter.i to fix CI build
sparsh-karna Mar 11, 2026
afc543a
fix: correct SWIG block syntax in GlobalRouter.i to fix CI build
sparsh-karna Mar 11, 2026
c2631d4
fix: remove trailing comment from SWIG closing tag
sparsh-karna Mar 11, 2026
f19bd9e
fix: fixed the swig formatting plus chaged name from db_net_to_design…
sparsh-karna Mar 11, 2026
1d70cca
grt: fix test to use renamed update_cugr_net command
sparsh-karna Mar 11, 2026
96e0631
Merge branch 'master' into grt/incremental-update-net
sparsh-karna Mar 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/grt/include/grt/GlobalRouter.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ class GlobalRouter
// Incremental global routing functions.
// See class IncrementalGRoute.
void addDirtyNet(odb::dbNet* net);
void updateCUGRNet(odb::dbNet* net);
std::set<odb::dbNet*> getDirtyNets() { return dirty_nets_; }
// check_antennas
bool haveRoutes();
Expand Down
7 changes: 7 additions & 0 deletions src/grt/src/GlobalRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5855,6 +5855,13 @@ void GlobalRouter::addDirtyNet(odb::dbNet* net)
dirty_nets_.insert(net);
}

void GlobalRouter::updateCUGRNet(odb::dbNet* net)
{
if (use_cugr_) {
cugr_->updateNet(net);
}
}

std::vector<Net*> GlobalRouter::updateDirtyRoutes(bool save_guides)
{
callback_handler_->triggerOnPinAccessUpdateRequired();
Expand Down
6 changes: 6 additions & 0 deletions src/grt/src/GlobalRouter.i
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ set_infinite_cap(bool infinite_capacity)
{
getGlobalRouter()->setInfiniteCapacity(infinite_capacity);
}
// NOTE: Debug-only. Not part of the public incremental API.
void
update_cugr_net(odb::dbNet* net)
{
getGlobalRouter()->updateCUGRNet(net);
}

void start_incremental()
{
Expand Down
10 changes: 10 additions & 0 deletions src/grt/src/cugr/include/CUGR.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <memory>
#include <set>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -91,6 +92,10 @@ class CUGR
{
critical_nets_percentage_ = percentage;
}
void addDirtyNet(odb::dbNet* net);
void updateNet(odb::dbNet* net);
void startIncremental();
void endIncremental();

private:
float calculatePartialSlack();
Expand All @@ -100,6 +105,7 @@ class CUGR
void patternRoute(std::vector<int>& netIndices);
void patternRouteWithDetours(std::vector<int>& netIndices);
void mazeRoute(std::vector<int>& netIndices);
void rerouteNets(std::vector<int>& net_indices);
void sortNetIndices(std::vector<int>& netIndices) const;
void getGuides(const GRNet* net,
std::vector<std::pair<int, grt::BoxT>>& guides);
Expand All @@ -124,6 +130,10 @@ class CUGR
int area_of_wire_patches_ = 0;

float critical_nets_percentage_ = 0;

std::set<int> dirty_net_indices_;
std::unordered_set<odb::dbNet*> updated_nets_;
bool incremental_mode_ = false;
};

} // namespace grt
112 changes: 111 additions & 1 deletion src/grt/src/cugr/src/CUGR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <fstream>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <memory>
Expand Down Expand Up @@ -36,6 +37,8 @@
#include "utl/CallBackHandler.h"
#include "utl/Logger.h"

using utl::GRT;

namespace grt {

CUGR::CUGR(odb::dbDatabase* db,
Expand Down Expand Up @@ -130,7 +133,8 @@ void CUGR::updateOverflowNets(std::vector<int>& netIndices)
{
netIndices.clear();
for (const auto& net : gr_nets_) {
if (grid_graph_->checkOverflow(net->getRoutingTree()) > 0) {
if (net->getRoutingTree()
&& grid_graph_->checkOverflow(net->getRoutingTree()) > 0) {
netIndices.push_back(net->getIndex());
}
}
Expand All @@ -148,6 +152,9 @@ void CUGR::patternRoute(std::vector<int>& netIndices)

sortNetIndices(netIndices);
for (const int netIndex : netIndices) {
if (gr_nets_[netIndex]->getNumPins() < 2) {
continue;
}
PatternRoute patternRoute(gr_nets_[netIndex].get(),
grid_graph_.get(),
stt_builder_,
Expand Down Expand Up @@ -179,6 +186,9 @@ void CUGR::patternRouteWithDetours(std::vector<int>& netIndices)
sortNetIndices(netIndices);
for (const int netIndex : netIndices) {
GRNet* net = gr_nets_[netIndex].get();
if (net->getNumPins() < 2) {
continue;
}
grid_graph_->commitTree(net->getRoutingTree(), /*ripup*/ true);
PatternRoute patternRoute(
net, grid_graph_.get(), stt_builder_, constants_, logger_);
Expand Down Expand Up @@ -214,6 +224,9 @@ void CUGR::mazeRoute(std::vector<int>& netIndices)
SparseGrid grid(10, 10, 0, 0);
for (const int netIndex : netIndices) {
GRNet* net = gr_nets_[netIndex].get();
if (net->getNumPins() < 2) {
continue;
}
MazeRoute mazeRoute(net, grid_graph_.get(), logger_);
mazeRoute.constructSparsifiedGraph(wireCostView, grid);
mazeRoute.run();
Expand Down Expand Up @@ -611,4 +624,101 @@ void CUGR::getBTermsAccessPoints(
}
}

void CUGR::addDirtyNet(odb::dbNet* net)
{
auto it = db_net_map_.find(net);
if (it != db_net_map_.end()) {
dirty_net_indices_.insert(it->second->getIndex());
} else {
logger_->warn(
GRT, 600, "Net {} not found in CUGR net map.", net->getConstName());
}
}

void CUGR::updateNet(odb::dbNet* db_net)
{
auto it = db_net_map_.find(db_net);
if (it != db_net_map_.end()) {
GRNet* gr_net = it->second;
if (gr_net->getRoutingTree()) {
grid_graph_->commitTree(gr_net->getRoutingTree(), /*rip_up=*/true);
}
design_->updateNet(db_net);
const int idx = gr_net->getIndex();
const CUGRNet& base_net = design_->getAllNets()[idx];
gr_nets_[idx] = std::make_unique<GRNet>(base_net, grid_graph_.get());
db_net_map_[db_net] = gr_nets_[idx].get();
if (incremental_mode_ && gr_nets_[idx]->getNumPins() >= 2) {
dirty_net_indices_.insert(idx);
}
} else {
design_->updateNet(db_net);
const CUGRNet& base_net = design_->getAllNets().back();
if (base_net.getNumPins() < 2) {
return;
}
const int new_index = static_cast<int>(gr_nets_.size());
gr_nets_.push_back(std::make_unique<GRNet>(base_net, grid_graph_.get()));
net_indices_.push_back(new_index);
db_net_map_[db_net] = gr_nets_.back().get();
if (incremental_mode_) {
dirty_net_indices_.insert(new_index);
}
}
updated_nets_.insert(db_net);
}

void CUGR::startIncremental()
{
incremental_mode_ = true;
dirty_net_indices_.clear();
}

void CUGR::rerouteNets(std::vector<int>& net_indices)
{
for (const int idx : net_indices) {
if (gr_nets_[idx]->getRoutingTree()) {
grid_graph_->commitTree(gr_nets_[idx]->getRoutingTree(), /*rip_up=*/true);
}
}
patternRoute(net_indices);
patternRouteWithDetours(net_indices);
mazeRoute(net_indices);
}

void CUGR::endIncremental()
{
if (!incremental_mode_ || dirty_net_indices_.empty()) {
return;
}

std::vector<int> nets_to_route(dirty_net_indices_.begin(),
dirty_net_indices_.end());

for (const int idx : dirty_net_indices_) {
odb::dbNet* db_net = gr_nets_[idx]->getDbNet();
if (updated_nets_.find(db_net) == updated_nets_.end()) {
updateNet(db_net);
}
}
Comment thread
sparsh-karna marked this conversation as resolved.
updated_nets_.clear();

rerouteNets(nets_to_route);

// Check for secondary overflow caused by rerouting
std::vector<int> overflow_nets;
updateOverflowNets(overflow_nets);
std::vector<int> secondary_nets;
std::ranges::set_difference(
overflow_nets, dirty_net_indices_, std::back_inserter(secondary_nets));
if (!secondary_nets.empty()) {
rerouteNets(secondary_nets);
}

incremental_mode_ = false;
dirty_net_indices_.clear();

printStatistics();
}

} // namespace grt
123 changes: 80 additions & 43 deletions src/grt/src/cugr/src/Design.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <cstdint>
#include <iostream>
#include <set>
#include <utility>
#include <vector>

#include "CUGR.h"
Expand Down Expand Up @@ -87,49 +88,7 @@ void Design::readNetlist()
continue;
}

std::vector<CUGRPin> pins;
int pin_count = 0;
for (odb::dbBTerm* db_bterm : db_net->getBTerms()) {
int x, y;
std::vector<BoxOnLayer> pin_shapes;
if (db_bterm->getFirstPinLocation(x, y)) {
odb::Point position(x, y);
for (odb::dbBPin* bpin : db_bterm->getBPins()) {
for (odb::dbBox* bpin_box : bpin->getBoxes()) {
// adjust layer idx to start with zero
int layer_idx = bpin_box->getTechLayer()->getRoutingLevel() - 1;
pin_shapes.emplace_back(layer_idx,
getBoxFromRect(bpin_box->getBox()));
}
}
}

pins.emplace_back(pin_count, db_bterm, pin_shapes);
pin_count++;
}

for (odb::dbITerm* db_iterm : db_net->getITerms()) {
std::vector<BoxOnLayer> pin_shapes;
odb::dbTransform xform = db_iterm->getInst()->getTransform();
for (odb::dbMPin* mpin : db_iterm->getMTerm()->getMPins()) {
for (odb::dbBox* box : mpin->getGeometry()) {
odb::dbTechLayer* tech_layer = box->getTechLayer();
if (tech_layer->getType() != odb::dbTechLayerType::ROUTING) {
continue;
}

odb::Rect rect = box->getBox();
xform.apply(rect);

int layerIndex = tech_layer->getRoutingLevel() - 1;
pin_shapes.emplace_back(
layerIndex, rect.xMin(), rect.yMin(), rect.xMax(), rect.yMax());
}
}

pins.emplace_back(pin_count, db_iterm, pin_shapes);
pin_count++;
}
auto pins = makeNetPins(db_net);

LayerRange layer_range
= {.min_layer = min_routing_layer_, .max_layer = max_routing_layer_};
Expand All @@ -139,10 +98,88 @@ void Design::readNetlist()
}

nets_.emplace_back(net_index, db_net, pins, layer_range);
Comment thread
eder-matheus marked this conversation as resolved.
db_net_to_id_[db_net] = net_index;
net_index++;
}
}

std::vector<CUGRPin> Design::makeNetPins(odb::dbNet* db_net)
{
std::vector<CUGRPin> pins;
int pin_count = 0;
for (odb::dbBTerm* db_bterm : db_net->getBTerms()) {
int x, y;
std::vector<BoxOnLayer> pin_shapes;
if (db_bterm->getFirstPinLocation(x, y)) {
odb::Point position(x, y);
for (odb::dbBPin* bpin : db_bterm->getBPins()) {
for (odb::dbBox* bpin_box : bpin->getBoxes()) {
// adjust layer idx to start with zero
int layer_idx = bpin_box->getTechLayer()->getRoutingLevel() - 1;
pin_shapes.emplace_back(layer_idx,
getBoxFromRect(bpin_box->getBox()));
}
}
}

pins.emplace_back(pin_count, db_bterm, pin_shapes);
pin_count++;
}

for (odb::dbITerm* db_iterm : db_net->getITerms()) {
std::vector<BoxOnLayer> pin_shapes;
odb::dbTransform xform = db_iterm->getInst()->getTransform();
for (odb::dbMPin* mpin : db_iterm->getMTerm()->getMPins()) {
for (odb::dbBox* box : mpin->getGeometry()) {
odb::dbTechLayer* tech_layer = box->getTechLayer();
if (tech_layer->getType() != odb::dbTechLayerType::ROUTING) {
continue;
}

odb::Rect rect = box->getBox();
xform.apply(rect);

int layerIndex = tech_layer->getRoutingLevel() - 1;
pin_shapes.emplace_back(
layerIndex, rect.xMin(), rect.yMin(), rect.xMax(), rect.yMax());
}
}

pins.emplace_back(pin_count, db_iterm, pin_shapes);
pin_count++;
}

return pins;
}

void Design::updateNet(odb::dbNet* db_net)
{
if (db_net->isSpecial() || db_net->getSigType().isSupply()
|| !db_net->getSWires().empty() || db_net->isConnectedByAbutment()) {
return;
}

auto pins = makeNetPins(db_net);

LayerRange layer_range
= {.min_layer = min_routing_layer_, .max_layer = max_routing_layer_};
if (clock_nets_.find(db_net) != clock_nets_.end()) {
layer_range.min_layer = block_->getMinLayerForClock() - 1;
layer_range.max_layer = block_->getMaxLayerForClock() - 1;
}

Comment thread
eder-matheus marked this conversation as resolved.
auto it = db_net_to_id_.find(db_net);
if (it != db_net_to_id_.end()) {
nets_[it->second].setPins(std::move(pins));
Comment thread
eder-matheus marked this conversation as resolved.
nets_[it->second].setLayerRange(layer_range);
} else {
// Net is new — add it
const int net_index = static_cast<int>(nets_.size());
Comment thread
eder-matheus marked this conversation as resolved.
db_net_to_id_[db_net] = net_index;
nets_.emplace_back(net_index, db_net, std::move(pins), layer_range);
}
}

void Design::readInstanceObstructions()
{
for (odb::dbInst* db_inst : block_->getInsts()) {
Expand Down
Loading
Loading