Merge pull request #620 from litghost/handle_partial_routed
Add support for partially routed nets from the placer in router2.
This commit is contained in:
commit
035b797ec2
@ -370,6 +370,8 @@ struct ArcBounds
|
|||||||
dist += loc.y - y1;
|
dist += loc.y - y1;
|
||||||
return dist;
|
return dist;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool contains(int x, int y) const { return x >= x0 && y >= y0 && x <= x1 && y <= y1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
@ -426,9 +428,10 @@ enum PlaceStrength
|
|||||||
STRENGTH_NONE = 0,
|
STRENGTH_NONE = 0,
|
||||||
STRENGTH_WEAK = 1,
|
STRENGTH_WEAK = 1,
|
||||||
STRENGTH_STRONG = 2,
|
STRENGTH_STRONG = 2,
|
||||||
STRENGTH_FIXED = 3,
|
STRENGTH_PLACER = 3,
|
||||||
STRENGTH_LOCKED = 4,
|
STRENGTH_FIXED = 4,
|
||||||
STRENGTH_USER = 5
|
STRENGTH_LOCKED = 5,
|
||||||
|
STRENGTH_USER = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PortRef
|
struct PortRef
|
||||||
|
@ -211,9 +211,15 @@ struct Router2
|
|||||||
pwd.w = wire;
|
pwd.w = wire;
|
||||||
NetInfo *bound = ctx->getBoundWireNet(wire);
|
NetInfo *bound = ctx->getBoundWireNet(wire);
|
||||||
if (bound != nullptr) {
|
if (bound != nullptr) {
|
||||||
pwd.bound_nets[bound->udata] = std::make_pair(0, bound->wires.at(wire).pip);
|
auto iter = bound->wires.find(wire);
|
||||||
if (bound->wires.at(wire).strength > STRENGTH_STRONG)
|
if (iter != bound->wires.end()) {
|
||||||
pwd.unavailable = true;
|
pwd.bound_nets[bound->udata] = std::make_pair(0, bound->wires.at(wire).pip);
|
||||||
|
if (bound->wires.at(wire).strength == STRENGTH_PLACER) {
|
||||||
|
pwd.reserved_net = bound->udata;
|
||||||
|
} else if (bound->wires.at(wire).strength > STRENGTH_PLACER) {
|
||||||
|
pwd.unavailable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArcBounds wire_loc = ctx->getRouteBoundingBox(wire, wire);
|
ArcBounds wire_loc = ctx->getRouteBoundingBox(wire, wire);
|
||||||
@ -335,6 +341,7 @@ struct Router2
|
|||||||
{
|
{
|
||||||
auto &b = wire_data(wire).bound_nets.at(net->udata);
|
auto &b = wire_data(wire).bound_nets.at(net->udata);
|
||||||
--b.first;
|
--b.first;
|
||||||
|
NPNR_ASSERT(b.first >= 0);
|
||||||
if (b.first == 0) {
|
if (b.first == 0) {
|
||||||
wire_data(wire).bound_nets.erase(net->udata);
|
wire_data(wire).bound_nets.erase(net->udata);
|
||||||
}
|
}
|
||||||
@ -657,7 +664,7 @@ struct Router2
|
|||||||
t.queue.pop();
|
t.queue.pop();
|
||||||
++iter;
|
++iter;
|
||||||
#if 0
|
#if 0
|
||||||
ROUTE_LOG_DBG("current wire %s\n", ctx->nameOfWire(curr.wire));
|
ROUTE_LOG_DBG("current wire %s\n", ctx->nameOfWire(d.w));
|
||||||
#endif
|
#endif
|
||||||
// Explore all pips downhill of cursor
|
// Explore all pips downhill of cursor
|
||||||
for (auto dh : ctx->getPipsDownhill(d.w)) {
|
for (auto dh : ctx->getPipsDownhill(d.w)) {
|
||||||
@ -672,14 +679,27 @@ struct Router2
|
|||||||
#else
|
#else
|
||||||
if (is_bb && !hit_test_pip(ad.bb, ctx->getPipLocation(dh)))
|
if (is_bb && !hit_test_pip(ad.bb, ctx->getPipLocation(dh)))
|
||||||
continue;
|
continue;
|
||||||
if (!ctx->checkPipAvail(dh) && ctx->getBoundPipNet(dh) != net)
|
if (!ctx->checkPipAvail(dh)) {
|
||||||
continue;
|
NetInfo *bound_net = ctx->getBoundPipNet(dh);
|
||||||
|
if (bound_net != net) {
|
||||||
|
if (bound_net != nullptr) {
|
||||||
|
ROUTE_LOG_DBG("Skipping pip %s because it is bound to net '%s' not net '%s'\n",
|
||||||
|
ctx->nameOfPip(dh), bound_net->name.c_str(ctx), net->name.c_str(ctx));
|
||||||
|
} else {
|
||||||
|
ROUTE_LOG_DBG("Skipping pip %s because it is reported not available\n", ctx->nameOfPip(dh));
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
// Evaluate score of next wire
|
// Evaluate score of next wire
|
||||||
WireId next = ctx->getPipDstWire(dh);
|
WireId next = ctx->getPipDstWire(dh);
|
||||||
int next_idx = wire_to_idx.at(next);
|
int next_idx = wire_to_idx.at(next);
|
||||||
if (was_visited(next_idx))
|
if (was_visited(next_idx)) {
|
||||||
|
// Don't expand the same node twice.
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
#if 1
|
#if 1
|
||||||
if (debug_arc)
|
if (debug_arc)
|
||||||
ROUTE_LOG_DBG(" src wire %s\n", ctx->nameOfWire(next));
|
ROUTE_LOG_DBG(" src wire %s\n", ctx->nameOfWire(next));
|
||||||
@ -789,11 +809,7 @@ struct Router2
|
|||||||
ROUTE_LOG_DBG("Arc '%s' (user %zu, arc %zu) already routed skipping.\n", ctx->nameOf(net), i, j);
|
ROUTE_LOG_DBG("Arc '%s' (user %zu, arc %zu) already routed skipping.\n", ctx->nameOf(net), i, j);
|
||||||
continue;
|
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 to start with
|
||||||
ripup_arc(net, i, j);
|
ripup_arc(net, i, j);
|
||||||
t.route_arcs.emplace_back(i, j);
|
t.route_arcs.emplace_back(i, j);
|
||||||
@ -869,16 +885,9 @@ struct Router2
|
|||||||
if (src == WireId())
|
if (src == WireId())
|
||||||
return true;
|
return true;
|
||||||
WireId dst = ctx->getNetinfoSinkWire(net, usr, phys_pin);
|
WireId dst = ctx->getNetinfoSinkWire(net, usr, phys_pin);
|
||||||
// Skip routes where the destination is already bound
|
|
||||||
if (dst == WireId())
|
if (dst == WireId())
|
||||||
return true;
|
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)
|
// Skip routes where there is no routing (special cases)
|
||||||
if (!ad.routed) {
|
if (!ad.routed) {
|
||||||
if ((src == dst) && ctx->getBoundWireNet(dst) != net)
|
if ((src == dst) && ctx->getBoundWireNet(dst) != net)
|
||||||
@ -895,9 +904,17 @@ struct Router2
|
|||||||
|
|
||||||
while (cursor != src) {
|
while (cursor != src) {
|
||||||
if (!ctx->checkWireAvail(cursor)) {
|
if (!ctx->checkWireAvail(cursor)) {
|
||||||
if (ctx->getBoundWireNet(cursor) == net)
|
NetInfo *bound_net = ctx->getBoundWireNet(cursor);
|
||||||
break; // hit the part of the net that is already bound
|
if (bound_net != net) {
|
||||||
else {
|
if (ctx->verbose) {
|
||||||
|
if (bound_net != nullptr) {
|
||||||
|
log_info("Failed to bind wire %s to net %s, bound to net %s\n", ctx->nameOfWire(cursor),
|
||||||
|
net->name.c_str(ctx), bound_net->name.c_str(ctx));
|
||||||
|
} else {
|
||||||
|
log_info("Failed to bind wire %s to net %s, bound net nullptr\n", ctx->nameOfWire(cursor),
|
||||||
|
net->name.c_str(ctx));
|
||||||
|
}
|
||||||
|
}
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -910,8 +927,14 @@ struct Router2
|
|||||||
}
|
}
|
||||||
auto &p = wd.bound_nets.at(net->udata).second;
|
auto &p = wd.bound_nets.at(net->udata).second;
|
||||||
if (!ctx->checkPipAvail(p)) {
|
if (!ctx->checkPipAvail(p)) {
|
||||||
success = false;
|
NetInfo *bound_net = ctx->getBoundPipNet(p);
|
||||||
break;
|
if (bound_net != net) {
|
||||||
|
if (ctx->verbose) {
|
||||||
|
log_info("Failed to bind pip %s to net %s\n", ctx->nameOfPip(p), net->name.c_str(ctx));
|
||||||
|
}
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
to_bind.push_back(p);
|
to_bind.push_back(p);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user