aboutsummaryrefslogtreecommitdiffstats
path: root/common/router2.cc
diff options
context:
space:
mode:
authorKeith Rothman <537074+litghost@users.noreply.github.com>2021-02-25 15:55:29 -0800
committerKeith Rothman <537074+litghost@users.noreply.github.com>2021-02-25 15:55:29 -0800
commitc64a9101512daf645d5244ffd737d2a0f162a9ba (patch)
tree3b7148d5ecf6ab06ea2119df78f02efcd8a3c62a /common/router2.cc
parentde107da5b3c66d329de0a0430a67ca843e27f3bd (diff)
downloadnextpnr-c64a9101512daf645d5244ffd737d2a0f162a9ba.tar.gz
nextpnr-c64a9101512daf645d5244ffd737d2a0f162a9ba.tar.bz2
nextpnr-c64a9101512daf645d5244ffd737d2a0f162a9ba.zip
Allow router2 to use routed but not fixed arcs.
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
Diffstat (limited to 'common/router2.cc')
-rw-r--r--common/router2.cc58
1 files changed, 54 insertions, 4 deletions
diff --git a/common/router2.cc b/common/router2.cc
index f5779356..abe5f302 100644
--- a/common/router2.cc
+++ b/common/router2.cc
@@ -205,7 +205,7 @@ struct Router2
pwd.w = wire;
NetInfo *bound = ctx->getBoundWireNet(wire);
if (bound != nullptr) {
- pwd.bound_nets[bound->udata] = std::make_pair(1, bound->wires.at(wire).pip);
+ pwd.bound_nets[bound->udata] = std::make_pair(0, bound->wires.at(wire).pip);
if (bound->wires.at(wire).strength > STRENGTH_STRONG)
pwd.unavailable = true;
}
@@ -217,6 +217,19 @@ struct Router2
wire_to_idx[wire] = int(flat_wires.size());
flat_wires.push_back(pwd);
}
+
+ for (auto net_pair : sorted(ctx->nets)) {
+ auto *net = net_pair.second;
+ auto &nd = nets.at(net->udata);
+ for (size_t usr = 0; usr < net->users.size(); usr++) {
+ auto &ad = nd.arcs.at(usr);
+ for (size_t phys_pin = 0; phys_pin < ad.size(); phys_pin++) {
+ if (check_arc_routing(net, usr, phys_pin)) {
+ record_prerouted_net(net, usr, phys_pin);
+ }
+ }
+ }
+ }
}
struct QueuedWire
@@ -393,6 +406,22 @@ struct Router2
return (cursor == src_wire);
}
+ void record_prerouted_net(NetInfo *net, size_t usr, size_t phys_pin)
+ {
+ auto &ad = nets.at(net->udata).arcs.at(usr).at(phys_pin);
+ ad.routed = true;
+
+ WireId src = nets.at(net->udata).src_wire;
+ WireId cursor = ad.sink_wire;
+ while (cursor != src) {
+ size_t wire_idx = wire_to_idx.at(cursor);
+ auto &wd = flat_wires.at(wire_idx);
+ PipId pip = wd.bound_nets.at(net->udata).second;
+ bind_pip_internal(net, usr, wire_idx, pip);
+ cursor = ctx->getPipSrcWire(pip);
+ }
+ }
+
// Returns true if a wire contains no source ports or driving pips
bool is_wire_undriveable(WireId wire)
{
@@ -729,8 +758,10 @@ struct Router2
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))
+ if (check_arc_routing(net, i, j)) {
+ ROUTE_LOG_DBG("Arc '%s' (user %zu, arc %zu) already routed skipping.\n", ctx->nameOf(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)
@@ -812,12 +843,22 @@ struct Router2
return true;
WireId dst = ctx->getNetinfoSinkWire(net, usr, phys_pin);
// Skip routes where the destination is already bound
- if (dst == WireId() || ctx->getBoundWireNet(dst) == net)
+ if (dst == WireId())
+ return true;
+ if (ctx->getBoundWireNet(dst) == net) {
+ if (ctx->debug) {
+ log("Net %s already bound (because wire %s is part of net), not binding\n", ctx->nameOf(net),
+ ctx->nameOfWire(dst));
+ }
return true;
+ }
// Skip routes where there is no routing (special cases)
if (!ad.routed) {
if ((src == dst) && ctx->getBoundWireNet(dst) != net)
ctx->bindWire(src, net, STRENGTH_WEAK);
+ if (ctx->debug) {
+ log("Net %s not routed, not binding\n", ctx->nameOf(net));
+ }
return true;
}
@@ -875,11 +916,20 @@ struct Router2
// Ripup wires and pips used by the net in nextpnr's structures
net_wires.clear();
for (auto &w : net->wires) {
- if (w.second.strength <= STRENGTH_STRONG)
+ if (w.second.strength <= STRENGTH_STRONG) {
net_wires.push_back(w.first);
+ } else if (ctx->debug) {
+ log("Net %s didn't rip up wire %s because strength was %d\n", ctx->nameOf(net),
+ ctx->nameOfWire(w.first), w.second.strength);
+ }
}
for (auto w : net_wires)
ctx->unbindWire(w);
+
+ if (ctx->debug) {
+ log("Ripped up %zu wires on net %s\n", net_wires.size(), ctx->nameOf(net));
+ }
+
// Bind the arcs using the routes we have discovered
for (size_t i = 0; i < net->users.size(); i++) {
for (size_t phys_pin = 0; phys_pin < nets.at(net->udata).arcs.at(i).size(); phys_pin++) {