Skip to content
Open
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
2 changes: 2 additions & 0 deletions src/grt/include/grt/GlobalRouter.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ class GlobalRouter
void updateVias();

// Report wire length
void reportNetGlobalRoutingDetour(odb::dbNet* net);
void reportNetWireLength(odb::dbNet* net,
bool global_route,
bool detailed_route,
Expand Down Expand Up @@ -622,3 +623,4 @@ class IncrementalGRoute
};

} // namespace grt

8 changes: 8 additions & 0 deletions src/grt/src/GlobalRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5970,3 +5970,11 @@ std::size_t GSegmentHash::operator()(const GSegment& seg) const
}

} // namespace grt


void GlobalRouter::reportNetGlobalRoutingDetour(odb::dbNet* net)
{
logger_->info(GRT, 301, "Reporting detour metric for net: {}", net->getName());
// TODO: Hook up computeNetSttWirelength and computeNetFinalWirelength
// using the FastRoute netID mapping
}
5 changes: 5 additions & 0 deletions src/grt/src/GlobalRouter.i
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,8 @@ float estimate_path_resistance(odb::dbObject* pin1,
} // namespace

%} // inline

void report_net_global_routing_detour(odb::dbNet* net)
{
getGlobalRouter()->reportNetGlobalRoutingDetour(net);
}
29 changes: 28 additions & 1 deletion src/grt/src/GlobalRouter.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,6 @@ proc repair_antennas { args } {

if { [grt::have_routes] || [grt::have_detailed_routes] } {
if { [llength $args] == 0 } {
# repairAntennas locates diode
set diode_mterm "NULL"
} elseif { [llength $args] == 1 } {
set db [ord::get_db]
Expand Down Expand Up @@ -649,3 +648,31 @@ proc have_detailed_route { block } {

# grt namespace end
}

sta::define_cmd_args "report_net_global_routing_detour" { [-nets net_list] }

proc report_net_global_routing_detour { args } {
sta::parse_key_args "report_net_global_routing_detour" args \
keys {-nets} \
flags {}

set block [ord::get_db_block]
if { $block == "NULL" } {
utl::error GRT 242 "Missing dbBlock."
}

if { [info exists keys(-nets)] } {
foreach net [get_nets $keys(-nets)] {
set db_net [sta::sta_to_db_net $net]
if {
[$db_net getSigType] != "POWER" &&
[$db_net getSigType] != "GROUND" &&
![$db_net isSpecial]
} {
grt::report_net_global_routing_detour $db_net
}
}
} else {
utl::error GRT 243 "-nets is required."
}
}
10 changes: 10 additions & 0 deletions src/grt/src/fastroute/include/FastRoute.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,14 @@ class FastRouteCore
void getPlanarRoute(odb::dbNet* db_net, GRoute& route);
void get3DRoute(odb::dbNet* db_net, GRoute& route);
void setIncrementalGrt(bool is_incremental);
int computeNetSttWirelength(int netID);
int computeNetFinalWirelength(int netID);
const std::unordered_map<int, int>& getSttWirelengths() { return stt_wirelengths_; }
int computeTotalWirelength();

private:
std::vector<int> stt_wirelengths_;
int computeNetSttWirelength(int netID);
int getEdgeCapacity(FrNet* net, int x1, int y1, EdgeDirection direction);
void getNetId(odb::dbNet* db_net, int& net_id, bool& exists);
void clearNetRoute(int netID);
Expand Down Expand Up @@ -721,6 +727,7 @@ class FastRouteCore
horizontal_blocked_intervals_;

std::vector<int> net_ids_;
std::unordered_map<int, int> stt_wirelengths_; // netID -> STT wirelength

// Maze 3D variables
multi_array<Direction, 3> directions_3D_;
Expand All @@ -738,3 +745,6 @@ class FastRouteCore
extern const char* getNetName(odb::dbNet* db_net);

} // namespace grt



70 changes: 34 additions & 36 deletions src/grt/src/fastroute/src/RSMT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ static int ordery(const Pnt* a, const Pnt* b)
return a->y < b->y;
}

// binary search to map the new coordinates to original coordinates
static int mapxy(const int nx,
const std::vector<int>& xs,
const std::vector<int>& nxs,
Expand Down Expand Up @@ -71,16 +70,13 @@ void FastRouteCore::copyStTree(const int ind, const stt::Tree& rsmt)
auto& treenodes = sttrees_[ind].nodes;
auto& treeedges = sttrees_[ind].edges;

// initialize the nbrcnt for treenodes
const int sizeV = 2 * nets_[ind]->getNumPins();
std::vector<int> nbrcnt(sizeV);
for (int i = 0; i < numnodes; i++) {
nbrcnt[i] = 0;
}

int edgecnt = 0;
// original rsmt has 2*d-2 branch (one is a loop for root), in StTree 2*d-3
// edges (no original loop)
for (int i = 0; i < numnodes; i++) {
const int x1 = rsmt.branch[i].x;
const int y1 = rsmt.branch[i].y;
Expand All @@ -94,9 +90,8 @@ void FastRouteCore::copyStTree(const int ind, const stt::Tree& rsmt)
} else {
treenodes[i].status = 0;
}
if (n != i) { // not root
if (n != i) {
treeedges[edgecnt].len = abs(x1 - x2) + abs(y1 - y2);
// make x1 always less than x2
if (x1 < x2) {
treeedges[edgecnt].n1 = i;
treeedges[edgecnt].n2 = n;
Expand All @@ -119,7 +114,6 @@ void FastRouteCore::copyStTree(const int ind, const stt::Tree& rsmt)
}
}

// Map the node indices to the pin indices of the net
std::map<odb::Point, int> pos_count;
for (int i = 0; i < d; i++) {
odb::Point pos{treenodes[i].x, treenodes[i].y};
Expand All @@ -129,7 +123,6 @@ void FastRouteCore::copyStTree(const int ind, const stt::Tree& rsmt)
sttrees_[ind].node_to_pin_idx[i] = pin_idx;
}

// Copy num neighbors
for (int i = 0; i < numnodes; i++) {
treenodes[i].nbr_count = nbrcnt[i];
}
Expand Down Expand Up @@ -257,7 +250,6 @@ void FastRouteCore::fluteNormal(const int netID,
ptp[i]->o = i;
}

// sort y to find s[]
if (d < 1000) {
for (int i = 0; i < d - 1; i++) {
int minval = ptp[i]->y;
Expand Down Expand Up @@ -398,18 +390,17 @@ void FastRouteCore::fluteCongest(const int netID,
s[i] = gs_[netID][i];
}

// get the new coordinates considering congestion
for (int i = 0; i < d - 1; i++) {
x_seg[i] = (xs[i + 1] - xs[i]) * 100;
y_seg[i] = (ys[i + 1] - ys[i]) * 100;
}

const int height = ys[d - 1] - ys[0] + 1; // # vertical grids the net span
const int width = xs[d - 1] - xs[0] + 1; // # horizontal grids the net span
const int height = ys[d - 1] - ys[0] + 1;
const int width = xs[d - 1] - xs[0] + 1;

for (int i = 0; i < d - 1; i++) {
int usageH = 0;
for (int k = ys[0]; k <= ys[d - 1]; k++) // all grids in the column
for (int k = ys[0]; k <= ys[d - 1]; k++)
{
for (int j = xs[i]; j < xs[i + 1]; j++) {
usageH += graph2d_.getEstUsageRedH(j, k);
Expand All @@ -418,20 +409,18 @@ void FastRouteCore::fluteCongest(const int netID,
if (x_seg[i] != 0 && usageH != 0) {
x_seg[i]
*= coeffH * usageH / ((xs[i + 1] - xs[i]) * height * h_capacity_);
x_seg[i] = std::max(1, x_seg[i]); // the segment len is at least 1 if
// original segment len > 0
x_seg[i] = std::max(1, x_seg[i]);
}
int usageV = 0;
for (int j = ys[i]; j < ys[i + 1]; j++) {
for (int k = xs[0]; k <= xs[d - 1]; k++) { // all grids in the row
for (int k = xs[0]; k <= xs[d - 1]; k++) {
usageV += graph2d_.getEstUsageRedV(k, j);
}
}
if (y_seg[i] != 0 && usageV != 0) {
y_seg[i]
*= coeffV * usageV / ((ys[i + 1] - ys[i]) * width * v_capacity_);
y_seg[i] = std::max(1, y_seg[i]); // the segment len is at least 1 if
// original segment len > 0
y_seg[i] = std::max(1, y_seg[i]);
}
}

Expand All @@ -444,7 +433,6 @@ void FastRouteCore::fluteCongest(const int netID,

t = stt_builder_->makeSteinerTree(nxs, nys, s, acc);

// map the new coordinates back to original coordinates
for (auto& branch : t.branch) {
branch.x = mapxy(branch.x, xs, nxs, d);
branch.y = mapxy(branch.y, ys, nys, d);
Expand All @@ -457,7 +445,6 @@ bool FastRouteCore::netCongestion(const int netID)
for (const Segment& seg : seglist_[netID]) {
const auto [ymin, ymax] = std::minmax(seg.y1, seg.y2);

// remove L routing
if (seg.xFirst) {
for (int i = seg.x1; i < seg.x2; i++) {
const int cap = getEdgeCapacity(
Expand Down Expand Up @@ -574,9 +561,6 @@ float FastRouteCore::coeffADJ(const int netID)
Vusage += graph2d_.getEstUsageV(i, j);
}
}
// (Husage * Vcap) resulting in zero is unlikely, but
// this check was added to avoid undefined behavior if
// the expression results in zero
if ((Husage * Vcap) > 0) {
coef = (Hcap * Vusage) / (Husage * Vcap);
} else {
Expand Down Expand Up @@ -614,7 +598,6 @@ void FastRouteCore::gen_brk_RSMT(const bool congestionDriven,
const auto& treeedges = sttrees_[netID].edges;
const auto& treenodes = sttrees_[netID].nodes;
for (int j = 0; j < sttrees_[netID].num_edges(); j++) {
// only route the non-degraded edges (len>0)
if (sttrees_[netID].edges[j].len > 0) {
const TreeEdge* treeedge = &(treeedges[j]);
const int n1 = treeedge->n1;
Expand All @@ -627,15 +610,12 @@ void FastRouteCore::gen_brk_RSMT(const bool congestionDriven,
}
}
} else {
// remove the est_usage due to the segments in this net
for (auto& seg : seglist_[netID]) {
ripupSegL(&seg);
}
}
}

// check net alpha because FastRoute has a special implementation of flute
// TODO: move this flute implementation to SteinerTreeBuilder
const float net_alpha = stt_builder_->getAlpha(net->getDbNet());
if (net_alpha > 0.0) {
rsmt = stt_builder_->makeSteinerTree(
Expand All @@ -644,7 +624,6 @@ void FastRouteCore::gen_brk_RSMT(const bool congestionDriven,
float coeffV = 1.36;

if (congestionDriven) {
// call congestion driven flute to generate RSMT
bool cong;
coeffV = noADJ ? 1.2 : coeffADJ(netID);
cong = netCongestion(netID);
Expand All @@ -667,7 +646,6 @@ void FastRouteCore::gen_brk_RSMT(const bool congestionDriven,
numShift += edgeShiftNew(rsmt, netID);
}
} else {
// call FLUTE to generate RSMT for each net
if (noADJ || HTreeSuite(netID)) {
coeffV = 1.2;
}
Expand Down Expand Up @@ -708,27 +686,27 @@ void FastRouteCore::gen_brk_RSMT(const bool congestionDriven,

wl += abs(x1 - x2) + abs(y1 - y2);

if (x1 != x2 || y1 != y2) { // the branch is not degraded (a point)
// the position of this segment in seglist
if (x1 != x2 || y1 != y2) {
const int8_t cost = nets_[netID]->getEdgeCost();
if (x1 < x2) {
seglist_[netID].emplace_back(netID, x1, y1, x2, y2, cost);
} else {
seglist_[netID].emplace_back(netID, x2, y2, x1, y1, cost);
}
}
} // loop j
}

totalNumSeg += seglist_[netID].size();

if (reRoute) {
// update the est_usage due to the segments in this net
newrouteL(
netID,
RouteType::NoRoute,
true); // route the net with no previous route for each tree edge
true);
}
} // loop i

stt_wirelengths_[netID] = computeNetSttWirelength(netID);
}

debugPrint(logger_,
GRT,
Expand All @@ -742,4 +720,24 @@ void FastRouteCore::gen_brk_RSMT(const bool congestionDriven,
numShift);
}

} // namespace grt
int FastRouteCore::computeNetSttWirelength(int netID)
{
int stt_wl = 0;
const auto& treeedges = sttrees_[netID].edges;
const auto& treenodes = sttrees_[netID].nodes;
for (int j = 0; j < sttrees_[netID].num_edges(); j++) {
const TreeEdge* treeedge = &(treeedges[j]);
if (treeedge->len > 0) {
const int n1 = treeedge->n1;
const int n2 = treeedge->n2;
const int x1 = treenodes[n1].x;
const int y1 = treenodes[n1].y;
const int x2 = treenodes[n2].x;
const int y2 = treenodes[n2].y;
stt_wl += abs(x1 - x2) + abs(y1 - y2);
}
}
return stt_wl;
}

}
Loading