Skip to content

Commit 3144e83

Browse files
authored
Merge pull request #697 from YosysHQ/gatecat/router2-dynamic-bb-expand
router2: Dynamicly expand bounding box based on congestion
2 parents ae8a910 + 65c611d commit 3144e83

File tree

1 file changed

+61
-23
lines changed

1 file changed

+61
-23
lines changed

common/router2.cc

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

Comments
 (0)