Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions src/grt/include/grt/GlobalRouter.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ class GlobalRouter
std::vector<int> routeLayerLengths(odb::dbNet* db_net);
void startIncremental();
void endIncremental(bool save_guides = false);
// Warn once, at the end of an incremental session, if CUGR left congestion.
void reportIncrementalCongestion();
void globalRoute(bool save_guides = false);
void saveCongestion();
NetRouteMap& getRoutes();
Expand Down Expand Up @@ -429,6 +431,7 @@ class GlobalRouter
odb::Point& pos_on_grid,
bool has_access_points);
void updatePinAccessPoints();
void updatePinAccessPoints(Net* net, odb::dbNet* db_net);
void suggestAdjustment();
void findFastRoutePins(Net* net,
std::vector<RoutePt>& pins_on_grid,
Expand Down
95 changes: 71 additions & 24 deletions src/grt/src/GlobalRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,12 +441,29 @@ void GlobalRouter::endIncremental(bool save_guides)
{
is_incremental_ = true;
updateDirtyRoutes(save_guides);
reportIncrementalCongestion();
grouter_cbk_->removeOwner();
delete grouter_cbk_;
grouter_cbk_ = nullptr;
finishGlobalRouting(save_guides);
}

void GlobalRouter::reportIncrementalCongestion()
{
// CUGR incremental reroutes only dirty nets and does not recover congestion
// it induces on neighboring nets, so surface any residual overflow once.
if (!use_cugr_ || cugr_ == nullptr) {
return;
}
if (cugr_->totalOverflow() > 0) {
is_congested_ = true;
logger_->warn(GRT,
128,
"Incremental global routing finished with congestion. Check "
"the congestion regions in the DRC Viewer.");
}
}

void GlobalRouter::globalRoute(bool save_guides)
{
utl::Timer timer;
Expand Down Expand Up @@ -1523,30 +1540,35 @@ void GlobalRouter::computePinPositionOnGrid(
pin.setConnectionLayer(pin_position.layer());
}

void GlobalRouter::updatePinAccessPoints()
void GlobalRouter::updatePinAccessPoints(Net* net, odb::dbNet* db_net)
{
for (const auto& [db_net, net] : db_net_map_) {
odb::PtrMap<odb::dbITerm, odb::Point3D> iterm_to_aps;
odb::PtrMap<odb::dbBTerm, odb::Point3D> bterm_to_aps;
cugr_->getITermsAccessPoints(db_net, iterm_to_aps);
cugr_->getBTermsAccessPoints(db_net, bterm_to_aps);

auto updatePinPos = [&](Pin& pin, auto* term, const auto& ap_map) {
if (auto it = ap_map.find(term); it != ap_map.end()) {
const auto& ap = it->second;
pin.setConnectionLayer(ap.z());
pin.setOnGridPosition(
grid_->getPositionOnGrid(odb::Point(ap.x(), ap.y())));
}
};
odb::PtrMap<odb::dbITerm, odb::Point3D> iterm_to_aps;
odb::PtrMap<odb::dbBTerm, odb::Point3D> bterm_to_aps;
cugr_->getITermsAccessPoints(db_net, iterm_to_aps);
cugr_->getBTermsAccessPoints(db_net, bterm_to_aps);

for (Pin& pin : net->getPins()) {
if (pin.isPort()) {
updatePinPos(pin, pin.getBTerm(), bterm_to_aps);
} else {
updatePinPos(pin, pin.getITerm(), iterm_to_aps);
}
auto updatePinPos = [&](Pin& pin, auto* term, const auto& ap_map) {
if (auto it = ap_map.find(term); it != ap_map.end()) {
const auto& ap = it->second;
pin.setConnectionLayer(ap.z());
pin.setOnGridPosition(
grid_->getPositionOnGrid(odb::Point(ap.x(), ap.y())));
}
};

for (Pin& pin : net->getPins()) {
if (pin.isPort()) {
updatePinPos(pin, pin.getBTerm(), bterm_to_aps);
} else {
updatePinPos(pin, pin.getITerm(), iterm_to_aps);
}
}
}

void GlobalRouter::updatePinAccessPoints()
{
for (const auto& [db_net, net] : db_net_map_) {
updatePinAccessPoints(net, db_net);
}
}

Expand Down Expand Up @@ -4785,6 +4807,13 @@ void GlobalRouter::removeNet(odb::dbNet* db_net)

if (use_cugr_) {
cugr_->removeNet(db_net);
auto it = db_net_map_.find(db_net);
if (it != db_net_map_.end()) {
delete it->second;
db_net_map_.erase(it);
}
dirty_nets_.erase(db_net);
routes_.erase(db_net);
} else {
auto it = db_net_map_.find(db_net);
if (it == db_net_map_.end() || it->second == nullptr) {
Expand Down Expand Up @@ -6311,6 +6340,7 @@ std::vector<Net*> IncrementalGRoute::updateRoutes(bool save_guides)

IncrementalGRoute::~IncrementalGRoute()
{
groute_->reportIncrementalCongestion();
db_cbk_.removeOwner();
}

Expand Down Expand Up @@ -6344,12 +6374,29 @@ std::vector<Net*> GlobalRouter::updateDirtyRoutes(bool save_guides)

if (use_cugr_) {
cugr_->setVerbose(false);
for (odb::dbNet* net : dirty_nets_) {
cugr_->updateNet(net);
const std::vector<odb::dbNet*> dirty_nets(dirty_nets_.begin(),
dirty_nets_.end());
for (odb::dbNet* db_net : dirty_nets) {
// Rebuild the pin set from the netlist; positions are synced below.
Net* net = getNet(db_net);
updateNetPins(net);
net->setDirtyNet(false);
net->clearLastPinPositions();
cugr_->updateNet(db_net);
}
dirty_nets_.clear();
cugr_->routeIncremental();
routes_ = cugr_->getRoutes();
// Patch only the rerouted nets into routes_ instead of rebuilding the whole
// map, and sync pin access points for the same nets (full route does all).
for (odb::dbNet* db_net : dirty_nets) {
GRoute route = cugr_->getNetRoute(db_net);
if (route.empty()) {
routes_.erase(db_net);
} else {
routes_[db_net] = std::move(route);
}
updatePinAccessPoints(getNet(db_net), db_net);
}
return {};
}

Expand Down
18 changes: 13 additions & 5 deletions src/grt/src/cugr/include/CUGR.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,12 @@ class CUGR
void init(int min_routing_layer,
int max_routing_layer,
const odb::PtrSet<odb::dbNet>& clock_nets);
void route();
void route(bool incremental = false);
void write(const std::string& guide_file);
NetRouteMap getRoutes();
// Route for a single net, so incremental updates patch only the dirty nets
// instead of rebuilding the whole map.
GRoute getNetRoute(odb::dbNet* db_net);
void updateDbCongestion();
void getITermsAccessPoints(
odb::dbNet* net,
Expand Down Expand Up @@ -137,16 +140,16 @@ class CUGR
private:
// Refresh net slacks, re-mark the res-aware/critical set, and demote
// non-critical nets so the next stage routes critical nets first.
void updateCriticalNets();
void updateCriticalNets(const std::vector<int>& net_indices);
// Re-extract parasitics and refresh every net's slack from the routing.
void updateNetSlacks();
void updateNetSlacks(const std::vector<int>& net_indices);
// Slack value at the critical_nets_percentage_ percentile of the nets.
float criticalSlackThreshold() const;
// Push nets with slack above the threshold to the back of the default
// ordering by maxing their slack; res-aware nets are exempt.
void demoteNonCriticalNets(float slack_th);
float getNetSlack(odb::dbNet* net);
void setInitialNetSlacks();
void setInitialNetSlacks(const std::vector<int>& net_indices);

/**
* @brief Computes per-layer NDR demand / cost multipliers for a net.
Expand Down Expand Up @@ -218,6 +221,8 @@ class CUGR
bool res_aware_order) const;
void getGuides(const GRNet* net,
std::vector<std::pair<int, grt::BoxT>>& guides);
// Append net's routing tree to route as GRoute segments.
void buildNetRoute(const GRNet* net, GRoute& route) const;
void printStatistics() const;

/**
Expand Down Expand Up @@ -263,6 +268,9 @@ class CUGR
int congestion_iterations_ = 5;
bool verbose_ = true;

// Suppresses the global parasitics re-estimate during incremental routing.
bool incremental_routing_ = false;

bool resistance_aware_ = false;
// Per-run normalisers for getResAwareScore (default 1 => well-defined).
float worst_slack_ = 1.0f;
Expand All @@ -276,7 +284,7 @@ class CUGR

// Select the res-aware net set (like FastRoute updateSlacks) and refresh the
// worst_* normalisers; no-op unless resistance_aware_.
void markResAwareNets();
void markResAwareNets(const std::vector<int>& net_indices);

// FR-style ordering score (lower routes first): slack/resistance/fanout/
// length blend, each normalised by the per-run worst.
Expand Down
Loading
Loading