aboutsummaryrefslogtreecommitdiffstats
path: root/common/router2.cc
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2019-11-19 15:41:16 +0000
committerDavid Shah <dave@ds0.me>2020-02-03 11:38:31 +0000
commitffd679cd368225cde6621efd78bea89a034cfc1c (patch)
tree1d012741d7a441980676df0c309eb8febfe78a23 /common/router2.cc
parent3b28ba2f76c519145795b1b330fda5851d8f38ca (diff)
downloadnextpnr-ffd679cd368225cde6621efd78bea89a034cfc1c.tar.gz
nextpnr-ffd679cd368225cde6621efd78bea89a034cfc1c.tar.bz2
nextpnr-ffd679cd368225cde6621efd78bea89a034cfc1c.zip
router2: Attempt to fix some stuck routing cases
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'common/router2.cc')
-rw-r--r--common/router2.cc35
1 files changed, 26 insertions, 9 deletions
diff --git a/common/router2.cc b/common/router2.cc
index 1cb04f9f..0782c403 100644
--- a/common/router2.cc
+++ b/common/router2.cc
@@ -196,7 +196,7 @@ struct Router2
};
};
- int bb_margin_x = 4, bb_margin_y = 4; // number of units outside the bounding box we may go
+ int bb_margin_x = 2, bb_margin_y = 2; // number of units outside the bounding box we may go
bool hit_test_pip(ArcBounds &bb, Loc l)
{
return l.x >= (bb.x0 - bb_margin_x) && l.x <= (bb.x1 + bb_margin_x) && l.y >= (bb.y0 - bb_margin_y) &&
@@ -218,6 +218,8 @@ struct Router2
// Nets that failed routing
std::vector<NetInfo *> failed_nets;
+ std::vector<int> route_arcs;
+
std::priority_queue<QueuedWire, std::vector<QueuedWire>, QueuedWire::Greater> queue;
std::unordered_map<WireId, VisitInfo> visited;
// Special case where one net has multiple logical arcs to the same physical sink
@@ -346,17 +348,9 @@ struct Router2
if (dst_wire == WireId())
ARC_LOG_ERR("No wire found for port %s on destination cell %s.\n", ctx->nameOf(usr.port),
ctx->nameOf(usr.cell));
- // Case of arcs that were pre-routed strongly (e.g. clocks)
- if (net->wires.count(dst_wire) && net->wires.at(dst_wire).strength > STRENGTH_STRONG)
- return ARC_SUCCESS;
- // Check if arc is already legally routed
- if (check_arc_routing(net, i))
- return ARC_SUCCESS;
// Check if arc was already done _in this iteration_
if (t.processed_sinks.count(dst_wire))
return ARC_SUCCESS;
- // Ripup arc to start with
- ripup_arc(net, i);
if (!t.queue.empty()) {
std::priority_queue<QueuedWire, std::vector<QueuedWire>, QueuedWire::Greater> new_queue;
@@ -536,7 +530,22 @@ struct Router2
bool have_failures = false;
t.processed_sinks.clear();
+ t.route_arcs.clear();
for (size_t i = 0; i < net->users.size(); i++) {
+ // Ripup failed arcs to start with
+ // Check if arc is already legally routed
+ if (check_arc_routing(net, i))
+ continue;
+ auto &usr = net->users.at(i);
+ WireId dst_wire = ctx->getNetinfoSinkWire(net, usr);
+ // Case of arcs that were pre-routed strongly (e.g. clocks)
+ if (net->wires.count(dst_wire) && net->wires.at(dst_wire).strength > STRENGTH_STRONG)
+ return ARC_SUCCESS;
+ // Ripup arc to start with
+ ripup_arc(net, i);
+ t.route_arcs.push_back(i);
+ }
+ for (auto i : t.route_arcs) {
auto res1 = route_arc(t, net, i, is_mt, true);
if (res1 == ARC_FATAL)
return false; // Arc failed irrecoverably
@@ -770,6 +779,14 @@ struct Router2
void do_route()
{
+ // Don't multithread if fewer than 200 nets (heuristic)
+ if (route_queue.size() < 200) {
+ ThreadContext st;
+ for (size_t j = 0; j < route_queue.size(); j++) {
+ route_net(st, nets_by_udata[route_queue[j]], false);
+ }
+ return;
+ }
const int N = 4;
std::vector<ThreadContext> tcs(N + 1);
for (auto n : route_queue) {