Skip to content

Commit 65c611d

Browse files
committed
router2: Reserve wires in more complex cases
Signed-off-by: gatecat <[email protected]>
1 parent 62613cb commit 65c611d

File tree

1 file changed

+39
-13
lines changed

1 file changed

+39
-13
lines changed

common/router2.cc

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)