@@ -155,7 +155,9 @@ void GlobalRouter::clear()
155155 routing_tracks_.clear ();
156156 routing_layers_.clear ();
157157 grid_->clear ();
158- fastroute_->clear ();
158+ if (!use_cugr_) {
159+ fastroute_->clear ();
160+ }
159161 vertical_capacities_.clear ();
160162 horizontal_capacities_.clear ();
161163 initialized_ = false ;
@@ -180,7 +182,6 @@ std::vector<Net*> GlobalRouter::initNets(bool check_pin_placement)
180182 if (check_pin_placement) {
181183 checkPinPlacement ();
182184 }
183- initNetlist (nets);
184185 return nets;
185186}
186187
@@ -190,18 +191,21 @@ void GlobalRouter::initRoutingGrid(int min_routing_layer, int max_routing_layer)
190191 reportLayerSettings (min_routing_layer, max_routing_layer);
191192 initRoutingTracks (max_routing_layer);
192193 initCoreGrid (max_routing_layer);
193- computeObstructionsAdjustments ();
194- computeUserGlobalAdjustments (min_routing_layer, max_routing_layer);
195194}
196195
197196std::vector<Net*> GlobalRouter::initCUGR (int min_routing_layer,
198197 int max_routing_layer)
199198{
200199 initRoutingGrid (min_routing_layer, max_routing_layer);
200+ // Propagate the global adjustment to per-layer values that CUGR reads from
201+ // the tech layers; this is engine-agnostic, unlike the FastRoute edge passes.
202+ computeUserGlobalAdjustments (min_routing_layer, max_routing_layer);
203+ reportMacrosAndBlockages ();
201204 std::vector<Net*> nets = initNets (true );
202205 initialized_ = true ;
203206 odb::PtrSet<odb::dbNet> clock_nets;
204207 findClockNets (nets, clock_nets);
208+ reportNetDegree (nets);
205209
206210 cugr_->setCongestionIterations (congestion_iterations_);
207211 cugr_->init (min_routing_layer, max_routing_layer, clock_nets);
@@ -222,6 +226,7 @@ std::vector<Net*> GlobalRouter::initFastRoute(int min_routing_layer,
222226 reportLayerSettings (min_routing_layer, max_routing_layer);
223227 initRoutingTracks (max_routing_layer);
224228 initCoreGrid (max_routing_layer);
229+ mirrorGridToFastRoute (max_routing_layer);
225230 setCapacities (min_routing_layer, max_routing_layer);
226231
227232 applyAdjustments (min_routing_layer, max_routing_layer);
@@ -231,6 +236,7 @@ std::vector<Net*> GlobalRouter::initFastRoute(int min_routing_layer,
231236 fastroute_->initEdgesCapacityPerLayer ();
232237
233238 std::vector<Net*> nets = initNets (check_pin_placement);
239+ initNetlist (nets);
234240
235241 initialized_ = true ;
236242 return nets;
@@ -240,6 +246,7 @@ void GlobalRouter::applyAdjustments(int min_routing_layer,
240246 int max_routing_layer)
241247{
242248 computeObstructionsAdjustments ();
249+ reportMacrosAndBlockages ();
243250 std::vector<int > track_space = grid_->getTrackPitches ();
244251 fastroute_->initBlockedIntervals (track_space);
245252 // Save global resources before add adjustment by layer
@@ -291,12 +298,25 @@ NetRouteMap GlobalRouter::getPartialRoutes()
291298 NetRouteMap net_routes;
292299 // TODO: still need to fix this during incremental grt
293300 if (is_incremental_) {
301+ // Source partial routes from the active engine; CUGR has no FastRoute
302+ // trees.
303+ NetRouteMap cugr_routes;
304+ if (use_cugr_) {
305+ cugr_routes = cugr_->getRoutes ();
306+ }
294307 for (const auto & [db_net, net] : db_net_map_) {
295308 // Do not add local nets, as they are not routed in incremental grt.
296309 if (routes_[db_net].empty () && !net->isLocal ()) {
297- GRoute route;
298- net_routes.insert ({db_net, route});
299- fastroute_->getPlanarRoute (db_net, net_routes[db_net]);
310+ if (use_cugr_) {
311+ auto it = cugr_routes.find (db_net);
312+ if (it != cugr_routes.end () && !it->second .empty ()) {
313+ net_routes[db_net] = it->second ;
314+ }
315+ } else {
316+ GRoute route;
317+ net_routes.insert ({db_net, route});
318+ fastroute_->getPlanarRoute (db_net, net_routes[db_net]);
319+ }
300320 }
301321 }
302322 } else {
@@ -409,7 +429,6 @@ void GlobalRouter::startIncremental()
409429void GlobalRouter::endIncremental (bool save_guides)
410430{
411431 is_incremental_ = true ;
412- fastroute_->setResistanceAware (resistance_aware_);
413432 updateDirtyRoutes (save_guides);
414433 grouter_cbk_->removeOwner ();
415434 delete grouter_cbk_;
@@ -499,8 +518,10 @@ void GlobalRouter::finishGlobalRouting(bool save_guides)
499518 }
500519
501520 if (is_congested_) {
502- // Suggest adjustment value
503- suggestAdjustment ();
521+ // suggestAdjustment relies on FastRoute congestion data.
522+ if (!use_cugr_) {
523+ suggestAdjustment ();
524+ }
504525 // CUGR overflow is downgraded to a warning even without -allow_congestion,
505526 // since it produces good results on detailed routing.
506527 if (allow_congestion_ || use_cugr_) {
@@ -769,7 +790,14 @@ void GlobalRouter::initCoreGrid(int max_routing_layer)
769790{
770791 initGrid (max_routing_layer);
771792 findTrackPitches (max_routing_layer);
793+ }
772794
795+ // Mirror the engine-agnostic grid into FastRoute's structures. Only the
796+ // FastRoute path needs this; CUGR maintains its own grid.
797+ void GlobalRouter::mirrorGridToFastRoute (int max_routing_layer)
798+ {
799+ fastroute_->setRegularX (grid_->isPerfectRegularX ());
800+ fastroute_->setRegularY (grid_->isPerfectRegularY ());
773801 fastroute_->setLowerLeft (grid_->getXMin (), grid_->getYMin ());
774802 fastroute_->setTileSize (grid_->getTileSize ());
775803 fastroute_->setGridsAndLayers (
@@ -1413,8 +1441,9 @@ std::vector<RoutePt> GlobalRouter::findOnGridPositions(
14131441 pos_on_grid = grid_->getPositionOnGrid (rect_middle);
14141442 // if a macro/pad pin is unreachable due to not having enough resources
14151443 // at its on grid position, get the position closest to the macro/pad
1416- // boundary to ensure routability
1417- if (pin.isConnectedToPadOrMacro ()
1444+ // boundary to ensure routability. CUGR has no FastRoute edge capacities
1445+ // to query, so it skips this heuristic and routes from the center.
1446+ if (!use_cugr_ && pin.isConnectedToPadOrMacro ()
14181447 && !isPinReachable (pin, pos_on_grid)) {
14191448 pos_on_grid = grid_->getPositionOnGrid (
14201449 pin.getPositionNearInstEdge (pin_box, rect_middle));
@@ -1560,17 +1589,85 @@ float GlobalRouter::getNetSlack(Net* net)
15601589 return sta_->slack (net->getDbNet (), sta::MinMax::max ());
15611590}
15621591
1592+ // Net degree (pin count) statistics over the nets that get routed; engine
1593+ // agnostic, so both FastRoute and CUGR report the same numbers.
1594+ void GlobalRouter::computeNetDegree (const std::vector<Net*>& nets,
1595+ int & min_degree,
1596+ int & max_degree)
1597+ {
1598+ min_degree = std::numeric_limits<int >::max ();
1599+ // Do NOT use numeric_limits<int>::min() to init this because if there are
1600+ // no FR nets the max degree will be big negative and cannot be used to init
1601+ // the vectors in FR.
1602+ max_degree = 1 ;
1603+ for (Net* net : nets) {
1604+ int pin_count = net->getNumPins ();
1605+ int min_layer, max_layer;
1606+ getNetLayerRange (net->getDbNet (), min_layer, max_layer);
1607+ odb::dbTechLayer* max_routing_layer
1608+ = db_->getTech ()->findRoutingLayer (max_layer);
1609+ if (pin_count > 1
1610+ && (!net->hasWires () || net->hasStackedVias (max_routing_layer))) {
1611+ min_degree = std::min (pin_count, min_degree);
1612+ max_degree = std::max (pin_count, max_degree);
1613+ }
1614+ }
1615+ }
1616+
1617+ void GlobalRouter::reportNetDegree (const std::vector<Net*>& nets)
1618+ {
1619+ if (!verbose_) {
1620+ return ;
1621+ }
1622+ int min_degree, max_degree;
1623+ computeNetDegree (nets, min_degree, max_degree);
1624+ // No routable net passed the degree filter; report zeros instead of the
1625+ // sentinel min_degree.
1626+ if (nets.empty () || min_degree == std::numeric_limits<int >::max ()) {
1627+ min_degree = 0 ;
1628+ max_degree = 0 ;
1629+ }
1630+ logger_->info (GRT , 1 , " Minimum degree: {}" , min_degree);
1631+ logger_->info (GRT , 2 , " Maximum degree: {}" , max_degree);
1632+ }
1633+
1634+ // Macro and blockage counts read straight from the db; engine agnostic.
1635+ void GlobalRouter::reportMacrosAndBlockages ()
1636+ {
1637+ if (!verbose_) {
1638+ return ;
1639+ }
1640+ const int min_layer = getMinRoutingLayer ();
1641+ const int max_layer = getMaxRoutingLayer ();
1642+ int macros_cnt = 0 ;
1643+ int blockages_cnt = 0 ;
1644+
1645+ for (odb::dbObstruction* obstruction : block_->getObstructions ()) {
1646+ const int layer = obstruction->getBBox ()->getTechLayer ()->getRoutingLevel ();
1647+ if (min_layer <= layer && layer <= max_layer) {
1648+ blockages_cnt++;
1649+ }
1650+ }
1651+ for (odb::dbInst* inst : block_->getInsts ()) {
1652+ odb::dbMaster* master = inst->getMaster ();
1653+ if (master->isBlock ()) {
1654+ macros_cnt++;
1655+ }
1656+ for (odb::dbBox* box : master->getObstructions ()) {
1657+ const int layer = box->getTechLayer ()->getRoutingLevel ();
1658+ if (min_layer <= layer && layer <= max_layer) {
1659+ blockages_cnt++;
1660+ }
1661+ }
1662+ }
1663+ logger_->info (GRT , 3 , " Macros: {}" , macros_cnt);
1664+ logger_->info (GRT , 4 , " Blockages: {}" , blockages_cnt);
1665+ }
1666+
15631667void GlobalRouter::initNetlist (std::vector<Net*>& nets, bool incremental)
15641668{
15651669 pad_pins_connections_.clear ();
15661670
1567- int min_degree = std::numeric_limits<int >::max ();
1568- // Do NOT use numeric_limits<int>::min() to init
1569- // this because if there are no FR nets the max
1570- // degree will be big negative and cannot be used
1571- // to init the vectors in FR.
1572- int max_degree = 1 ;
1573-
15741671 if (nets.size () > 1 && seed_ != 0 ) {
15751672 std::mt19937 g;
15761673 g.seed (seed_);
@@ -1585,20 +1682,13 @@ void GlobalRouter::initNetlist(std::vector<Net*>& nets, bool incremental)
15851682 = db_->getTech ()->findRoutingLayer (max_layer);
15861683 if (pin_count > 1
15871684 && (!net->hasWires () || net->hasStackedVias (max_routing_layer))) {
1588- min_degree = std::min (pin_count, min_degree);
1589-
1590- max_degree = std::max (pin_count, max_degree);
15911685 makeFastrouteNet (net);
15921686 }
15931687 }
1688+ int min_degree, max_degree;
1689+ computeNetDegree (nets, min_degree, max_degree);
15941690 fastroute_->setMaxNetDegree (max_degree);
1595-
1596- if (verbose_) {
1597- min_degree = nets.empty () ? 0 : min_degree;
1598- max_degree = nets.empty () ? 0 : max_degree;
1599- logger_->info (GRT , 1 , " Minimum degree: {}" , min_degree);
1600- logger_->info (GRT , 2 , " Maximum degree: {}" , max_degree);
1601- }
1691+ reportNetDegree (nets);
16021692
16031693 // Add resources for pin access in macro/pad pins after defining their on grid
16041694 // position. It must be done only in the initialization of the tool, not
@@ -2522,6 +2612,7 @@ void GlobalRouter::initGridAndNets()
25222612 initRoutingLayers (min_layer, max_layer);
25232613 initRoutingTracks (max_layer);
25242614 initCoreGrid (max_layer);
2615+ mirrorGridToFastRoute (max_layer);
25252616 setCapacities (min_layer, max_layer);
25262617 applyAdjustments (min_layer, max_layer);
25272618 }
@@ -4350,9 +4441,6 @@ void GlobalRouter::initGrid(int max_layer)
43504441 bool perfect_regular_x = (x_grids * tile_size) == dx;
43514442 bool perfect_regular_y = (y_grids * tile_size) == dy;
43524443
4353- fastroute_->setRegularX (perfect_regular_x);
4354- fastroute_->setRegularY (perfect_regular_y);
4355-
43564444 int num_layers = routing_layers_.size ();
43574445 if (max_layer > -1 ) {
43584446 num_layers = max_layer;
@@ -4990,17 +5078,12 @@ void GlobalRouter::computeObstructionsAdjustments()
49905078 std::map<int , std::vector<odb::Rect>> layer_obs_map;
49915079
49925080 findLayerExtensions (layer_extensions);
4993- int obstructions_cnt = findObstructions (die_area);
4994- obstructions_cnt
4995- += findInstancesObstructions (die_area, layer_extensions, layer_obs_map);
5081+ findObstructions (die_area);
5082+ findInstancesObstructions (die_area, layer_extensions, layer_obs_map);
49965083 findNetsObstructions (die_area);
49975084
49985085 std::vector<LayerId> transition_layers = findTransitionLayers ();
49995086 adjustTransitionLayers (transition_layers, layer_obs_map);
5000-
5001- if (verbose_) {
5002- logger_->info (GRT , 4 , " Blockages: {}" , obstructions_cnt);
5003- }
50045087}
50055088
50065089void GlobalRouter::findLayerExtensions (std::vector<int >& layer_extensions)
@@ -5151,7 +5234,6 @@ int GlobalRouter::findInstancesObstructions(
51515234 const std::vector<int >& layer_extensions,
51525235 std::map<int , std::vector<odb::Rect>>& layer_obs_map)
51535236{
5154- int macros_cnt = 0 ;
51555237 int obstructions_cnt = 0 ;
51565238 int pin_out_of_die_count = 0 ;
51575239 odb::dbTech* tech = db_->getTech ();
@@ -5162,7 +5244,6 @@ int GlobalRouter::findInstancesObstructions(
51625244
51635245 bool is_macro = false ;
51645246 if (master->isBlock ()) {
5165- macros_cnt++;
51665247 is_macro = true ;
51675248 has_macros_or_pads_ = true ;
51685249 }
@@ -5283,9 +5364,6 @@ int GlobalRouter::findInstancesObstructions(
52835364 }
52845365 }
52855366
5286- if (verbose_) {
5287- logger_->info (GRT , 3 , " Macros: {}" , macros_cnt);
5288- }
52895367 return obstructions_cnt;
52905368}
52915369
@@ -6263,6 +6341,8 @@ std::vector<Net*> GlobalRouter::updateDirtyRoutes(bool save_guides)
62636341
62646342 std::vector<Net*> dirty_nets;
62656343
6344+ fastroute_->setResistanceAware (resistance_aware_);
6345+
62666346 if (!initialized_) {
62676347 int min_layer, max_layer;
62686348 getMinMaxLayer (min_layer, max_layer);
0 commit comments