@@ -434,20 +434,35 @@ struct Router2
434434 }
435435
436436 // Returns true if a wire contains no source ports or driving pips
437- bool is_wire_undriveable (WireId wire)
437+ bool is_wire_undriveable (WireId wire, const NetInfo *net, int iter_count = 0 )
438438 {
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
439450 for (auto bp : ctx->getWireBelPins (wire))
440- 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)
441453 return false ;
442454 for (auto p : ctx->getPipsUphill (wire))
443- if (ctx->checkPipAvail (p))
444- return false ;
455+ if (ctx->checkPipAvail (p)) {
456+ if (!is_wire_undriveable (ctx->getPipSrcWire (p), net, iter_count + 1 ))
457+ return false ;
458+ }
445459 return true ;
446460 }
447461
448462 // Find all the wires that must be used to route a given arc
449- void reserve_wires_for_arc (NetInfo *net, size_t i)
463+ bool reserve_wires_for_arc (NetInfo *net, size_t i)
450464 {
465+ bool did_something = false ;
451466 WireId src = ctx->getNetinfoSourceWire (net);
452467 for (auto sink : ctx->getNetinfoSinkWires (net, net->users .at (i))) {
453468 std::unordered_set<WireId> rsv;
@@ -459,13 +474,14 @@ struct Router2
459474 auto &wd = wire_data (cursor);
460475 if (ctx->debug )
461476 log (" %s\n " , ctx->nameOfWire (cursor));
477+ did_something |= (wd.reserved_net != net->udata );
462478 wd.reserved_net = net->udata ;
463479 if (cursor == src)
464480 break ;
465481 WireId next_cursor;
466482 for (auto uh : ctx->getPipsUphill (cursor)) {
467483 WireId w = ctx->getPipSrcWire (uh);
468- if (is_wire_undriveable (w))
484+ if (is_wire_undriveable (w, net ))
469485 continue ;
470486 if (next_cursor != WireId ()) {
471487 done = true ;
@@ -478,17 +494,23 @@ struct Router2
478494 cursor = next_cursor;
479495 }
480496 }
497+ return did_something;
481498 }
482499
483500 void find_all_reserved_wires ()
484501 {
485- for (auto net : nets_by_udata) {
486- WireId src = ctx->getNetinfoSourceWire (net);
487- if (src == WireId ())
488- continue ;
489- for (size_t i = 0 ; i < net->users .size (); i++)
490- reserve_wires_for_arc (net, i);
491- }
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);
492514 }
493515
494516 void reset_wires (ThreadContext &t)
@@ -720,6 +742,7 @@ struct Router2
720742 next_score.delay =
721743 curr.score .delay + ctx->getPipDelay (dh).maxDelay () + ctx->getWireDelay (next).maxDelay ();
722744 next_score.togo_cost = cfg.estimate_weight * get_togo_cost (net, i, next_idx, dst_wire, &forward);
745+ #if 0
723746 ROUTE_LOG_DBG(
724747 "src_wire = %s -> next %s -> dst_wire = %s (backward: %s, forward: %s, sum: %s, cost = %f, "
725748 "togo_cost = %f, total = %f), dt = %02fs\n",
@@ -728,6 +751,7 @@ struct Router2
728751 std::to_string(next_score.delay + forward).c_str(), next_score.cost, next_score.togo_cost,
729752 next_score.cost + next_score.togo_cost,
730753 std::chrono::duration<float>(std::chrono::high_resolution_clock::now() - arc_start).count());
754+ #endif
731755 const auto &v = nwd.visit ;
732756 if (!v.visited || (v.score .total () > next_score.total ())) {
733757 ++explored;
@@ -809,7 +833,9 @@ struct Router2
809833 // Ripup failed arcs to start with
810834 // Check if arc is already legally routed
811835 if (check_arc_routing (net, i, j)) {
836+ #if 0
812837 ROUTE_LOG_DBG("Arc '%s' (user %zu, arc %zu) already routed skipping.\n", ctx->nameOf(net), i, j);
838+ #endif
813839 continue ;
814840 }
815841
0 commit comments