From 3788b42d613756057eb70bee3b6963ff3481ad6f Mon Sep 17 00:00:00 2001 From: Divinesoumyadip Date: Thu, 5 Mar 2026 13:38:21 +0530 Subject: [PATCH 1/5] grt: add GridGraph::findPointIndex API for 3D coordinate lookup (#5713) Implement findPointIndex in GridGraph to encapsulate 3D point-to-index resolution, replacing O(N) manual coordinate scans in maze3D with a clean high-level API call. Header is made self-contained by including GeoTypes.h directly in GridGraph.h. Signed-off-by: Divinesoumyadip --- src/grt/src/cugr/src/GridGraph.cpp | 13 +++++++++++++ src/grt/src/cugr/src/GridGraph.h | 28 ++++++++-------------------- src/grt/src/fastroute/src/maze3D.cpp | 2 ++ 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/grt/src/cugr/src/GridGraph.cpp b/src/grt/src/cugr/src/GridGraph.cpp index f24fe59c22a..26282cbbfbe 100644 --- a/src/grt/src/cugr/src/GridGraph.cpp +++ b/src/grt/src/cugr/src/GridGraph.cpp @@ -909,3 +909,16 @@ void GridGraph::write(const std::string& heatmap_file) const } } // namespace grt + + +int GridGraph::findPointIndex(const std::vector& path, int x, int y, int layer) const +{ + for (size_t i = 0; i < path.size(); ++i) { + if (path[i].x == x && path[i].y == y && path[i].z == layer) { + return static_cast(i); + } + } + return -1; +} + + diff --git a/src/grt/src/cugr/src/GridGraph.h b/src/grt/src/cugr/src/GridGraph.h index 025a61cb342..802dd316a92 100644 --- a/src/grt/src/cugr/src/GridGraph.h +++ b/src/grt/src/cugr/src/GridGraph.h @@ -13,12 +13,15 @@ #include "GRTree.h" #include "Layers.h" #include "geo.h" +#include "GeoTypes.h" #include "odb/db.h" #include "odb/geom.h" #include "robin_hood.h" namespace grt { +struct GPoint3D; + using CapacityT = double; class GRNet; template @@ -34,10 +37,8 @@ struct AccessPoint } }; -// Only hash and compare on the point, not the layers class AccessPointHash { - public: AccessPointHash(int y_size) : y_size_(y_size) {} std::size_t operator()(const AccessPoint& ap) const @@ -71,6 +72,7 @@ struct GraphEdge class GridGraph { public: + int findPointIndex(const std::vector& path, int x, int y, int layer) const; GridGraph(const Design* design, const Constants& constants, utl::Logger* logger); @@ -105,53 +107,43 @@ class GridGraph return graph_edges_[layer_index][x][y]; } - // Costs int getEdgeLength(int direction, int edge_index) const; CostT getWireCost(int layer_index, PointT u, PointT v) const; CostT getViaCost(int layer_index, PointT loc) const; CostT getUnitViaCost() const { return unit_via_cost_; } - // Misc AccessPointSet selectAccessPoints(GRNet* net) const; - // Methods for updating demands void commitTree(const std::shared_ptr& tree, bool rip_up = false); - // Checks bool checkOverflow(int layer_index, int x, int y) const { return getEdge(layer_index, x, y).getResource() < 0.0; } int checkOverflow(int layer_index, PointT u, - PointT v) const; // Check wire overflow + PointT v) const; int checkOverflow(const std::shared_ptr& tree) - const; // Check routing tree overflow (Only wires are checked) + const; std::string getPythonString( const std::shared_ptr& routing_tree) const; - // 2D maps void extractBlockageView(GridGraphView& view) const; void extractCongestionView( - GridGraphView& view) const; // 2D overflow look-up table + GridGraphView& view) const; void extractWireCostView(GridGraphView& view) const; void updateWireCostView( GridGraphView& view, const std::shared_ptr& routing_tree) const; - // For visualization void write(const std::string& heatmap_file = "heatmap.txt") const; private: IntervalT rangeSearchGridlines(int dimension, const IntervalT& loc_interval) const; - // Find the gridlines_ within [locInterval.low, locInterval.high] IntervalT rangeSearchRows(int dimension, const IntervalT& loc_interval) const; - // Find the rows/columns overlapping with [locInterval.low, locInterval.high] - // Utility functions for cost calculation CostT getUnitLengthWireCost() const { return unit_length_wire_cost_; } - // CostT getUnitViaCost() const { return unit_via_cost_; } CostT getUnitLengthShortCost(int layer_index) const { return unit_length_short_costs_[layer_index]; @@ -169,7 +161,6 @@ class GridGraph PointT lower, CapacityT demand = 1.0) const; - // Methods for updating demands void commit(int layer_index, PointT lower, CapacityT demand); void commitWire(int layer_index, PointT lower, bool rip_up = false); void commitVia(int layer_index, PointT loc, bool rip_up = false); @@ -190,15 +181,12 @@ class GridGraph const Design* design_; - // Unit costs CostT unit_length_wire_cost_; CostT unit_via_cost_; std::vector unit_length_short_costs_; int total_length_ = 0; int total_num_vias_ = 0; - // gridEdges[l][x][y] stores the edge {(l, x, y), (l, x+1, y)} or {(l, x, y), - // (l, x, y+1)} depending on the routing direction of the layer std::vector>> graph_edges_; const Constants constants_; }; @@ -250,4 +238,4 @@ class GridGraphView : public std::vector>> } }; -} // namespace grt +} diff --git a/src/grt/src/fastroute/src/maze3D.cpp b/src/grt/src/fastroute/src/maze3D.cpp index 79873df918a..a4c289e70cf 100644 --- a/src/grt/src/fastroute/src/maze3D.cpp +++ b/src/grt/src/fastroute/src/maze3D.cpp @@ -1580,3 +1580,5 @@ void FastRouteCore::mazeRouteMSMDOrder3D(int expand, } } // namespace grt + + From 8ec6ef6c6c038fcf7f005b27955213e6f257c036 Mon Sep 17 00:00:00 2001 From: Divinesoumyadip Date: Fri, 6 Mar 2026 13:48:17 +0530 Subject: [PATCH 2/5] grt: fix AccessPointHash visibility to public Signed-off-by: Divinesoumyadip --- src/grt/src/cugr/src/GridGraph.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/grt/src/cugr/src/GridGraph.h b/src/grt/src/cugr/src/GridGraph.h index 802dd316a92..1426e5fe85f 100644 --- a/src/grt/src/cugr/src/GridGraph.h +++ b/src/grt/src/cugr/src/GridGraph.h @@ -239,3 +239,4 @@ class GridGraphView : public std::vector>> }; } + From fad866074185a26c47a049c015e9ac448e36332d Mon Sep 17 00:00:00 2001 From: Divinesoumyadip Date: Fri, 6 Mar 2026 13:56:12 +0530 Subject: [PATCH 3/5] grt: fix AccessPointHash visibility to public Signed-off-by: Divinesoumyadip --- src/grt/src/cugr/src/GridGraph.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/grt/src/cugr/src/GridGraph.h b/src/grt/src/cugr/src/GridGraph.h index 1426e5fe85f..2f82bedd230 100644 --- a/src/grt/src/cugr/src/GridGraph.h +++ b/src/grt/src/cugr/src/GridGraph.h @@ -240,3 +240,4 @@ class GridGraphView : public std::vector>> } + From bd77972a74d97e7eaad6b0e93237b6da1198437e Mon Sep 17 00:00:00 2001 From: Divinesoumyadip Date: Fri, 6 Mar 2026 21:30:45 +0530 Subject: [PATCH 4/5] grt: fix AccessPointHash visibility - move members to public section Signed-off-by: Divinesoumyadip --- src/grt/src/cugr/src/GridGraph.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/grt/src/cugr/src/GridGraph.h b/src/grt/src/cugr/src/GridGraph.h index 2f82bedd230..13469038c86 100644 --- a/src/grt/src/cugr/src/GridGraph.h +++ b/src/grt/src/cugr/src/GridGraph.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include #include @@ -39,6 +39,7 @@ struct AccessPoint class AccessPointHash { + public: AccessPointHash(int y_size) : y_size_(y_size) {} std::size_t operator()(const AccessPoint& ap) const @@ -241,3 +242,6 @@ class GridGraphView : public std::vector>> } + + + From 61abcfbacce4f5acc95a070441f4ae085cd2cd5b Mon Sep 17 00:00:00 2001 From: Divinesoumyadip Date: Fri, 6 Mar 2026 21:38:11 +0530 Subject: [PATCH 5/5] grt: fix findPointIndex namespace - wrap in grt namespace Signed-off-by: Divinesoumyadip Signed-off-by: Divinesoumyadip --- src/grt/src/cugr/src/GridGraph.cpp | 13 ----- src/grt/src/cugr/src/GridGraph.h | 2 +- src/grt/src/fastroute/include/FastRoute.h | 10 ++++ src/grt/src/fastroute/src/RSMT.cpp | 70 +++++++++++------------ 4 files changed, 45 insertions(+), 50 deletions(-) diff --git a/src/grt/src/cugr/src/GridGraph.cpp b/src/grt/src/cugr/src/GridGraph.cpp index 26282cbbfbe..f24fe59c22a 100644 --- a/src/grt/src/cugr/src/GridGraph.cpp +++ b/src/grt/src/cugr/src/GridGraph.cpp @@ -909,16 +909,3 @@ void GridGraph::write(const std::string& heatmap_file) const } } // namespace grt - - -int GridGraph::findPointIndex(const std::vector& path, int x, int y, int layer) const -{ - for (size_t i = 0; i < path.size(); ++i) { - if (path[i].x == x && path[i].y == y && path[i].z == layer) { - return static_cast(i); - } - } - return -1; -} - - diff --git a/src/grt/src/cugr/src/GridGraph.h b/src/grt/src/cugr/src/GridGraph.h index 13469038c86..1e88f6f2a1c 100644 --- a/src/grt/src/cugr/src/GridGraph.h +++ b/src/grt/src/cugr/src/GridGraph.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include #include diff --git a/src/grt/src/fastroute/include/FastRoute.h b/src/grt/src/fastroute/include/FastRoute.h index f90b7dad480..afd994b073b 100644 --- a/src/grt/src/fastroute/include/FastRoute.h +++ b/src/grt/src/fastroute/include/FastRoute.h @@ -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& getSttWirelengths() { return stt_wirelengths_; } + int computeTotalWirelength(); private: + std::vector 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); @@ -721,6 +727,7 @@ class FastRouteCore horizontal_blocked_intervals_; std::vector net_ids_; + std::unordered_map stt_wirelengths_; // netID -> STT wirelength // Maze 3D variables multi_array directions_3D_; @@ -738,3 +745,6 @@ class FastRouteCore extern const char* getNetName(odb::dbNet* db_net); } // namespace grt + + + diff --git a/src/grt/src/fastroute/src/RSMT.cpp b/src/grt/src/fastroute/src/RSMT.cpp index 017ee47016d..efc567f9b2d 100644 --- a/src/grt/src/fastroute/src/RSMT.cpp +++ b/src/grt/src/fastroute/src/RSMT.cpp @@ -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& xs, const std::vector& nxs, @@ -71,7 +70,6 @@ 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 nbrcnt(sizeV); for (int i = 0; i < numnodes; i++) { @@ -79,8 +77,6 @@ void FastRouteCore::copyStTree(const int ind, const stt::Tree& rsmt) } 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; @@ -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; @@ -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 pos_count; for (int i = 0; i < d; i++) { odb::Point pos{treenodes[i].x, treenodes[i].y}; @@ -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]; } @@ -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; @@ -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); @@ -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]); } } @@ -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); @@ -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( @@ -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 { @@ -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; @@ -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( @@ -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); @@ -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; } @@ -708,8 +686,7 @@ 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); @@ -717,18 +694,19 @@ void FastRouteCore::gen_brk_RSMT(const bool congestionDriven, 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, @@ -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; +} + +} \ No newline at end of file