Allow router2 to use routed but not fixed arcs.

Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
Keith Rothman 2021-02-25 15:55:29 -08:00
parent de107da5b3
commit c64a910151

View File

@ -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++) {