aboutsummaryrefslogtreecommitdiffstats
path: root/common/router2.cc
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-02-10 14:43:49 +0000
committergatecat <gatecat@ds0.me>2021-02-10 15:14:44 +0000
commit7c7d69e1d2030dc983d0ddbc0e04f6765d51bbbc (patch)
treee01f2194626c7032124fcd2902f4c655b1b13aa6 /common/router2.cc
parent7dafc64f78270ec37e2155c609da7cbf2ae18028 (diff)
downloadnextpnr-7c7d69e1d2030dc983d0ddbc0e04f6765d51bbbc.tar.gz
nextpnr-7c7d69e1d2030dc983d0ddbc0e04f6765d51bbbc.tar.bz2
nextpnr-7c7d69e1d2030dc983d0ddbc0e04f6765d51bbbc.zip
router2: Support for multiple bel pins per cell pin
Signed-off-by: gatecat <gatecat@ds0.me>
Diffstat (limited to 'common/router2.cc')
-rw-r--r--common/router2.cc180
1 files changed, 95 insertions, 85 deletions
diff --git a/common/router2.cc b/common/router2.cc
index d1e4e347..a2023f47 100644
--- a/common/router2.cc
+++ b/common/router2.cc
@@ -58,7 +58,7 @@ struct Router2
struct PerNetData
{
WireId src_wire;
- std::vector<PerArcData> arcs;
+ std::vector<std::vector<PerArcData>> arcs;
ArcBounds bb;
// Coordinates of the center of the net, used for the weight-to-average
int cx, cy, hpwl;
@@ -150,26 +150,30 @@ struct Router2
for (size_t j = 0; j < ni->users.size(); j++) {
auto &usr = ni->users.at(j);
- WireId src_wire = ctx->getNetinfoSourceWire(ni), dst_wire = ctx->getNetinfoSinkWire(ni, usr, 0);
- nets.at(i).src_wire = src_wire;
- if (ni->driver.cell == nullptr)
- src_wire = dst_wire;
- if (ni->driver.cell == nullptr && dst_wire == WireId())
- continue;
- if (src_wire == WireId())
- log_error("No wire found for port %s on source cell %s.\n", ctx->nameOf(ni->driver.port),
- ctx->nameOf(ni->driver.cell));
- if (dst_wire == WireId())
- log_error("No wire found for port %s on destination cell %s.\n", ctx->nameOf(usr.port),
- ctx->nameOf(usr.cell));
- nets.at(i).arcs.at(j).sink_wire = dst_wire;
- // Set bounding box for this arc
- nets.at(i).arcs.at(j).bb = ctx->getRouteBoundingBox(src_wire, dst_wire);
- // Expand net bounding box to include this arc
- nets.at(i).bb.x0 = std::min(nets.at(i).bb.x0, nets.at(i).arcs.at(j).bb.x0);
- nets.at(i).bb.x1 = std::max(nets.at(i).bb.x1, nets.at(i).arcs.at(j).bb.x1);
- nets.at(i).bb.y0 = std::min(nets.at(i).bb.y0, nets.at(i).arcs.at(j).bb.y0);
- nets.at(i).bb.y1 = std::max(nets.at(i).bb.y1, nets.at(i).arcs.at(j).bb.y1);
+ WireId src_wire = ctx->getNetinfoSourceWire(ni);
+ for (auto &dst_wire : ctx->getNetinfoSinkWires(ni, usr)) {
+ nets.at(i).src_wire = src_wire;
+ if (ni->driver.cell == nullptr)
+ src_wire = dst_wire;
+ if (ni->driver.cell == nullptr && dst_wire == WireId())
+ continue;
+ if (src_wire == WireId())
+ log_error("No wire found for port %s on source cell %s.\n", ctx->nameOf(ni->driver.port),
+ ctx->nameOf(ni->driver.cell));
+ if (dst_wire == WireId())
+ log_error("No wire found for port %s on destination cell %s.\n", ctx->nameOf(usr.port),
+ ctx->nameOf(usr.cell));
+ nets.at(i).arcs.at(j).emplace_back();
+ auto &ad = nets.at(i).arcs.at(j).back();
+ ad.sink_wire = dst_wire;
+ // Set bounding box for this arc
+ ad.bb = ctx->getRouteBoundingBox(src_wire, dst_wire);
+ // Expand net bounding box to include this arc
+ nets.at(i).bb.x0 = std::min(nets.at(i).bb.x0, ad.bb.x0);
+ nets.at(i).bb.x1 = std::max(nets.at(i).bb.x1, ad.bb.x1);
+ nets.at(i).bb.y0 = std::min(nets.at(i).bb.y0, ad.bb.y0);
+ nets.at(i).bb.y1 = std::max(nets.at(i).bb.x1, ad.bb.y1);
+ }
// Add location to centroid sum
Loc usr_loc = ctx->getBelLocation(usr.cell->bel);
nets.at(i).cx += usr_loc.x;
@@ -254,7 +258,7 @@ struct Router2
// Nets that failed routing
std::vector<NetInfo *> failed_nets;
- std::vector<int> route_arcs;
+ std::vector<std::pair<size_t, size_t>> route_arcs;
std::priority_queue<QueuedWire, std::vector<QueuedWire>, QueuedWire::Greater> queue;
// Special case where one net has multiple logical arcs to the same physical sink
@@ -317,9 +321,9 @@ struct Router2
}
}
- void ripup_arc(NetInfo *net, size_t user)
+ void ripup_arc(NetInfo *net, size_t user, size_t phys_pin)
{
- auto &ad = nets.at(net->udata).arcs.at(user);
+ auto &ad = nets.at(net->udata).arcs.at(user).at(phys_pin);
if (!ad.routed)
return;
WireId src = nets.at(net->udata).src_wire;
@@ -333,7 +337,7 @@ struct Router2
ad.routed = false;
}
- float score_wire_for_arc(NetInfo *net, size_t user, WireId wire, PipId pip)
+ float score_wire_for_arc(NetInfo *net, size_t user, size_t phys_pin, WireId wire, PipId pip)
{
auto &wd = wire_data(wire);
auto &nd = nets.at(net->udata);
@@ -350,7 +354,7 @@ struct Router2
for (auto &bound : wd.bound_nets)
if (bound.first != net->udata)
max_bound_crit = std::max(max_bound_crit, nets.at(bound.first).max_crit);
- if (max_bound_crit >= 0.8 && nd.arcs.at(user).arc_crit < (max_bound_crit + 0.01)) {
+ if (max_bound_crit >= 0.8 && nd.arcs.at(user).at(phys_pin).arc_crit < (max_bound_crit + 0.01)) {
present_cost *= 1.5;
}
}
@@ -372,9 +376,9 @@ struct Router2
return (ctx->getDelayNS(ctx->estimateDelay(wd.w, sink)) / (1 + source_uses)) + cfg.ipin_cost_adder;
}
- bool check_arc_routing(NetInfo *net, size_t usr)
+ bool check_arc_routing(NetInfo *net, size_t usr, size_t phys_pin)
{
- auto &ad = nets.at(net->udata).arcs.at(usr);
+ auto &ad = nets.at(net->udata).arcs.at(usr).at(phys_pin);
WireId src_wire = nets.at(net->udata).src_wire;
WireId cursor = ad.sink_wire;
while (wire_data(cursor).bound_nets.count(net->udata)) {
@@ -405,35 +409,34 @@ struct Router2
void reserve_wires_for_arc(NetInfo *net, size_t i)
{
WireId src = ctx->getNetinfoSourceWire(net);
- WireId sink = ctx->getNetinfoSinkWire(net, net->users.at(i), 0);
- if (sink == WireId())
- return;
- std::unordered_set<WireId> rsv;
- WireId cursor = sink;
- bool done = false;
- if (ctx->debug)
- log("reserving wires for arc %d of net %s\n", int(i), ctx->nameOf(net));
- while (!done) {
- auto &wd = wire_data(cursor);
+ for (auto sink : ctx->getNetinfoSinkWires(net, net->users.at(i))) {
+ std::unordered_set<WireId> rsv;
+ WireId cursor = sink;
+ bool done = false;
if (ctx->debug)
- log(" %s\n", ctx->nameOfWire(cursor));
- wd.reserved_net = net->udata;
- if (cursor == src)
- break;
- WireId next_cursor;
- for (auto uh : ctx->getPipsUphill(cursor)) {
- WireId w = ctx->getPipSrcWire(uh);
- if (is_wire_undriveable(w))
- continue;
- if (next_cursor != WireId()) {
- done = true;
+ log("reserving wires for arc %d of net %s\n", int(i), ctx->nameOf(net));
+ while (!done) {
+ auto &wd = wire_data(cursor);
+ if (ctx->debug)
+ log(" %s\n", ctx->nameOfWire(cursor));
+ wd.reserved_net = net->udata;
+ if (cursor == src)
break;
+ WireId next_cursor;
+ for (auto uh : ctx->getPipsUphill(cursor)) {
+ WireId w = ctx->getPipSrcWire(uh);
+ if (is_wire_undriveable(w))
+ continue;
+ if (next_cursor != WireId()) {
+ done = true;
+ break;
+ }
+ next_cursor = w;
}
- next_cursor = w;
+ if (next_cursor == WireId())
+ break;
+ cursor = next_cursor;
}
- if (next_cursor == WireId())
- break;
- cursor = next_cursor;
}
}
@@ -471,15 +474,15 @@ struct Router2
}
bool was_visited(int wire) { return flat_wires.at(wire).visit.visited; }
- ArcRouteResult route_arc(ThreadContext &t, NetInfo *net, size_t i, bool is_mt, bool is_bb = true)
+ ArcRouteResult route_arc(ThreadContext &t, NetInfo *net, size_t i, size_t phys_pin, bool is_mt, bool is_bb = true)
{
auto &nd = nets[net->udata];
- auto &ad = nd.arcs[i];
+ auto &ad = nd.arcs.at(i).at(phys_pin);
auto &usr = net->users.at(i);
ROUTE_LOG_DBG("Routing arc %d of net '%s' (%d, %d) -> (%d, %d)\n", int(i), ctx->nameOf(net), ad.bb.x0, ad.bb.y0,
ad.bb.x1, ad.bb.y1);
- WireId src_wire = ctx->getNetinfoSourceWire(net), dst_wire = ctx->getNetinfoSinkWire(net, usr, 0);
+ WireId src_wire = ctx->getNetinfoSourceWire(net), dst_wire = ctx->getNetinfoSinkWire(net, usr, phys_pin);
if (src_wire == WireId())
ARC_LOG_ERR("No wire found for port %s on source cell %s.\n", ctx->nameOf(net->driver.port),
ctx->nameOf(net->driver.cell));
@@ -650,7 +653,7 @@ struct Router2
if (!thread_test_wire(t, nwd))
continue; // thread safety issue
WireScore next_score;
- next_score.cost = curr.score.cost + score_wire_for_arc(net, i, next, dh);
+ next_score.cost = curr.score.cost + score_wire_for_arc(net, i, phys_pin, next, dh);
next_score.delay =
curr.score.delay + ctx->getPipDelay(dh).maxDelay() + ctx->getWireDelay(next).maxDelay();
next_score.togo_cost = cfg.estimate_weight * get_togo_cost(net, i, next_idx, dst_wire);
@@ -720,22 +723,26 @@ struct Router2
bool have_failures = false;
t.processed_sinks.clear();
t.route_arcs.clear();
+ auto &nd = nets.at(net->udata);
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, 0);
- // 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);
+ auto &ad = nd.arcs.at(i);
+ for (size_t j = 0; j < ad.size(); j++) {
+ // Ripup failed arcs to start with
+ // Check if arc is already legally routed
+ if (check_arc_routing(net, i, j))
+ continue;
+ auto &usr = net->users.at(i);
+ WireId dst_wire = ctx->getNetinfoSinkWire(net, usr, j);
+ // 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, j);
+ t.route_arcs.emplace_back(i, j);
+ }
}
- for (auto i : t.route_arcs) {
- auto res1 = route_arc(t, net, i, is_mt, true);
+ for (auto a : t.route_arcs) {
+ auto res1 = route_arc(t, net, a.first, a.second, is_mt, true);
if (res1 == ARC_FATAL)
return false; // Arc failed irrecoverably
else if (res1 == ARC_RETRY_WITHOUT_BB) {
@@ -744,14 +751,14 @@ struct Router2
have_failures = true;
} else {
// Attempt a re-route without the bounding box constraint
- ROUTE_LOG_DBG("Rerouting arc %d of net '%s' without bounding box, possible tricky routing...\n",
- int(i), ctx->nameOf(net));
- auto res2 = route_arc(t, net, i, is_mt, false);
+ ROUTE_LOG_DBG("Rerouting arc %d.%d of net '%s' without bounding box, possible tricky routing...\n",
+ int(a.first), int(a.second), ctx->nameOf(net));
+ auto res2 = route_arc(t, net, a.first, a.second, is_mt, false);
// If this also fails, no choice but to give up
if (res2 != ARC_SUCCESS)
- log_error("Failed to route arc %d of net '%s', from %s to %s.\n", int(i), ctx->nameOf(net),
- ctx->nameOfWire(ctx->getNetinfoSourceWire(net)),
- ctx->nameOfWire(ctx->getNetinfoSinkWire(net, net->users.at(i), 0)));
+ log_error("Failed to route arc %d.%d of net '%s', from %s to %s.\n", int(a.first),
+ int(a.second), ctx->nameOf(net), ctx->nameOfWire(ctx->getNetinfoSourceWire(net)),
+ ctx->nameOfWire(ctx->getNetinfoSinkWire(net, net->users.at(a.first), a.second)));
}
}
}
@@ -789,7 +796,7 @@ struct Router2
}
}
- bool bind_and_check(NetInfo *net, int usr_idx)
+ bool bind_and_check(NetInfo *net, int usr_idx, int phys_pin)
{
#ifdef ARCH_ECP5
if (net->is_global)
@@ -797,13 +804,13 @@ struct Router2
#endif
bool success = true;
auto &nd = nets.at(net->udata);
- auto &ad = nd.arcs.at(usr_idx);
+ auto &ad = nd.arcs.at(usr_idx).at(phys_pin);
auto &usr = net->users.at(usr_idx);
WireId src = ctx->getNetinfoSourceWire(net);
// Skip routes with no source
if (src == WireId())
return true;
- WireId dst = ctx->getNetinfoSinkWire(net, usr, 0);
+ WireId dst = ctx->getNetinfoSinkWire(net, usr, phys_pin);
// Skip routes where the destination is already bound
if (dst == WireId() || ctx->getBoundWireNet(dst) == net)
return true;
@@ -849,7 +856,7 @@ struct Router2
for (auto tb : to_bind)
ctx->bindPip(tb, net, STRENGTH_WEAK);
} else {
- ripup_arc(net, usr_idx);
+ ripup_arc(net, usr_idx, phys_pin);
failed_nets.insert(net->udata);
}
return success;
@@ -875,9 +882,11 @@ struct Router2
ctx->unbindWire(w);
// Bind the arcs using the routes we have discovered
for (size_t i = 0; i < net->users.size(); i++) {
- if (!bind_and_check(net, i)) {
- ++arch_fail;
- success = false;
+ for (size_t phys_pin = 0; phys_pin < nets.at(net->udata).arcs.at(i).size(); phys_pin++) {
+ if (!bind_and_check(net, i, phys_pin)) {
+ ++arch_fail;
+ success = false;
+ }
}
}
}
@@ -1123,7 +1132,8 @@ struct Router2
continue;
for (int i = 0; i < int(fnd->second.criticality.size()); i++) {
float c = fnd->second.criticality.at(i);
- net.arcs.at(i).arc_crit = c;
+ for (auto &a : net.arcs.at(i))
+ a.arc_crit = c;
net.max_crit = std::max(net.max_crit, c);
}
}