@@ -68,6 +68,7 @@ struct Router2
6868 int cx, cy, hpwl;
6969 int total_route_us = 0 ;
7070 float max_crit = 0 ;
71+ int fail_count = 0 ;
7172 };
7273
7374 struct WireScore
@@ -189,6 +190,10 @@ struct Router2
189190 log_info (" %s: bb=(%d, %d)->(%d, %d) c=(%d, %d) hpwl=%d\n " , ctx->nameOf (ni), nets.at (i).bb .x0 ,
190191 nets.at (i).bb .y0 , nets.at (i).bb .x1 , nets.at (i).bb .y1 , nets.at (i).cx , nets.at (i).cy ,
191192 nets.at (i).hpwl );
193+ nets.at (i).bb .x0 = std::max (nets.at (i).bb .x0 - cfg.bb_margin_x , 0 );
194+ nets.at (i).bb .y0 = std::max (nets.at (i).bb .y0 - cfg.bb_margin_y , 0 );
195+ nets.at (i).bb .x1 = std::min (nets.at (i).bb .x1 + cfg.bb_margin_x , ctx->getGridDimX ());
196+ nets.at (i).bb .y1 = std::min (nets.at (i).bb .y1 + cfg.bb_margin_y , ctx->getGridDimY ());
192197 i++;
193198 }
194199 }
@@ -264,11 +269,7 @@ struct Router2
264269 };
265270 };
266271
267- bool hit_test_pip (ArcBounds &bb, Loc l)
268- {
269- return l.x >= (bb.x0 - cfg.bb_margin_x ) && l.x <= (bb.x1 + cfg.bb_margin_x ) &&
270- l.y >= (bb.y0 - cfg.bb_margin_y ) && l.y <= (bb.y1 + cfg.bb_margin_y );
271- }
272+ bool hit_test_pip (ArcBounds &bb, Loc l) { return l.x >= bb.x0 && l.x <= bb.x1 && l.y >= bb.y0 && l.y <= bb.y1 ; }
272273
273274 double curr_cong_weight, hist_cong_weight, estimate_weight;
274275
@@ -433,20 +434,35 @@ struct Router2
433434 }
434435
435436 // Returns true if a wire contains no source ports or driving pips
436- bool is_wire_undriveable (WireId wire)
437+ bool is_wire_undriveable (WireId wire, const NetInfo *net, int iter_count = 0 )
437438 {
439+ // This is specifically designed to handle a particularly icky case that the current router struggles with in
440+ // the nexus device,
441+ // C -> C lut input only
442+ // C; D; or F from another lut -> D lut input
443+ // D or M -> M ff input
444+ // without careful reservation of C for C lut input and D for D lut input, there is fighting for D between FF
445+ // and LUT
446+ if (iter_count > 7 )
447+ return false ; // heuristic to assume we've hit general routing
448+ if (wire_data (wire).reserved_net != -1 && wire_data (wire).reserved_net != net->udata )
449+ return true ; // reserved for another net
438450 for (auto bp : ctx->getWireBelPins (wire))
439- if (ctx->getBelPinType (bp.bel , bp.pin ) != PORT_IN)
451+ if ((net->driver .cell == nullptr || bp.bel == net->driver .cell ->bel ) &&
452+ ctx->getBelPinType (bp.bel , bp.pin ) != PORT_IN)
440453 return false ;
441454 for (auto p : ctx->getPipsUphill (wire))
442- if (ctx->checkPipAvail (p))
443- return false ;
455+ if (ctx->checkPipAvail (p)) {
456+ if (!is_wire_undriveable (ctx->getPipSrcWire (p), net, iter_count + 1 ))
457+ return false ;
458+ }
444459 return true ;
445460 }
446461
447462 // Find all the wires that must be used to route a given arc
448- void reserve_wires_for_arc (NetInfo *net, size_t i)
463+ bool reserve_wires_for_arc (NetInfo *net, size_t i)
449464 {
465+ bool did_something = false ;
450466 WireId src = ctx->getNetinfoSourceWire (net);
451467 for (auto sink : ctx->getNetinfoSinkWires (net, net->users .at (i))) {
452468 std::unordered_set<WireId> rsv;
@@ -458,13 +474,14 @@ struct Router2
458474 auto &wd = wire_data (cursor);
459475 if (ctx->debug )
460476 log (" %s\n " , ctx->nameOfWire (cursor));
477+ did_something |= (wd.reserved_net != net->udata );
461478 wd.reserved_net = net->udata ;
462479 if (cursor == src)
463480 break ;
464481 WireId next_cursor;
465482 for (auto uh : ctx->getPipsUphill (cursor)) {
466483 WireId w = ctx->getPipSrcWire (uh);
467- if (is_wire_undriveable (w))
484+ if (is_wire_undriveable (w, net ))
468485 continue ;
469486 if (next_cursor != WireId ()) {
470487 done = true ;
@@ -477,17 +494,23 @@ struct Router2
477494 cursor = next_cursor;
478495 }
479496 }
497+ return did_something;
480498 }
481499
482500 void find_all_reserved_wires ()
483501 {
484- for (auto net : nets_by_udata) {
485- WireId src = ctx->getNetinfoSourceWire (net);
486- if (src == WireId ())
487- continue ;
488- for (size_t i = 0 ; i < net->users .size (); i++)
489- reserve_wires_for_arc (net, i);
490- }
502+ // Run iteratively, as reserving wires for one net might limit choices for another
503+ bool did_something = false ;
504+ do {
505+ did_something = false ;
506+ for (auto net : nets_by_udata) {
507+ WireId src = ctx->getNetinfoSourceWire (net);
508+ if (src == WireId ())
509+ continue ;
510+ for (size_t i = 0 ; i < net->users .size (); i++)
511+ did_something |= reserve_wires_for_arc (net, i);
512+ }
513+ } while (did_something);
491514 }
492515
493516 void reset_wires (ThreadContext &t)
@@ -684,7 +707,7 @@ struct Router2
684707 if (is_bb && !hit_test_pip(ad.bb, ctx->getPipLocation(dh)) && wire_intent != ID_PSEUDO_GND && wire_intent != ID_PSEUDO_VCC)
685708 continue;
686709#else
687- if (is_bb && !hit_test_pip (ad .bb , ctx->getPipLocation (dh)))
710+ if (is_bb && !hit_test_pip (nd .bb , ctx->getPipLocation (dh)))
688711 continue ;
689712 if (!ctx->checkPipAvailForNet (dh, net)) {
690713 ROUTE_LOG_DBG (" Skipping pip %s because it is bound to net '%s' not net '%s'\n " , ctx->nameOfPip (dh),
@@ -719,6 +742,7 @@ struct Router2
719742 next_score.delay =
720743 curr.score .delay + ctx->getPipDelay (dh).maxDelay () + ctx->getWireDelay (next).maxDelay ();
721744 next_score.togo_cost = cfg.estimate_weight * get_togo_cost (net, i, next_idx, dst_wire, &forward);
745+ #if 0
722746 ROUTE_LOG_DBG(
723747 "src_wire = %s -> next %s -> dst_wire = %s (backward: %s, forward: %s, sum: %s, cost = %f, "
724748 "togo_cost = %f, total = %f), dt = %02fs\n",
@@ -727,6 +751,7 @@ struct Router2
727751 std::to_string(next_score.delay + forward).c_str(), next_score.cost, next_score.togo_cost,
728752 next_score.cost + next_score.togo_cost,
729753 std::chrono::duration<float>(std::chrono::high_resolution_clock::now() - arc_start).count());
754+ #endif
730755 const auto &v = nwd.visit ;
731756 if (!v.visited || (v.score .total () > next_score.total ())) {
732757 ++explored;
@@ -808,7 +833,9 @@ struct Router2
808833 // Ripup failed arcs to start with
809834 // Check if arc is already legally routed
810835 if (check_arc_routing (net, i, j)) {
836+ #if 0
811837 ROUTE_LOG_DBG("Arc '%s' (user %zu, arc %zu) already routed skipping.\n", ctx->nameOf(net), i, j);
838+ #endif
812839 continue ;
813840 }
814841
@@ -870,6 +897,17 @@ struct Router2
870897 failed_nets.insert (bound.first );
871898 }
872899 }
900+ for (int n : failed_nets) {
901+ auto &net_data = nets.at (n);
902+ ++net_data.fail_count ;
903+ if ((net_data.fail_count % 3 ) == 0 ) {
904+ // Every three times a net fails to route, expand the bounding box to increase the search space
905+ net_data.bb .x0 = std::max (net_data.bb .x0 - 1 , 0 );
906+ net_data.bb .y0 = std::max (net_data.bb .y0 - 1 , 0 );
907+ net_data.bb .x1 = std::min (net_data.bb .x1 + 1 , ctx->getGridDimX ());
908+ net_data.bb .y1 = std::min (net_data.bb .y1 + 1 , ctx->getGridDimY ());
909+ }
910+ }
873911 }
874912
875913 bool bind_and_check (NetInfo *net, int usr_idx, int phys_pin)
@@ -1113,10 +1151,10 @@ struct Router2
11131151 for (auto &th : tcs) {
11141152 th.rng .rngseed (ctx->rng64 ());
11151153 }
1116- int le_x = mid_x - cfg. bb_margin_x ;
1117- int rs_x = mid_x + cfg. bb_margin_x ;
1118- int le_y = mid_y - cfg. bb_margin_y ;
1119- int rs_y = mid_y + cfg. bb_margin_y ;
1154+ int le_x = mid_x;
1155+ int rs_x = mid_x;
1156+ int le_y = mid_y;
1157+ int rs_y = mid_y;
11201158 // Set up thread bounding boxes
11211159 tcs.at (0 ).bb = ArcBounds (0 , 0 , mid_x, mid_y);
11221160 tcs.at (1 ).bb = ArcBounds (mid_x + 1 , 0 , std::numeric_limits<int >::max (), le_y);
0 commit comments