router2: reduce memory footprint
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
37543ad003
commit
a1c703729c
@ -44,14 +44,16 @@ struct Router2
|
|||||||
|
|
||||||
struct PerArcData
|
struct PerArcData
|
||||||
{
|
{
|
||||||
std::unordered_map<WireId, PipId> wires;
|
WireId sink_wire;
|
||||||
ArcBounds bb;
|
ArcBounds bb;
|
||||||
|
bool routed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// As we allow overlap at first; the nextpnr bind functions can't be used
|
// As we allow overlap at first; the nextpnr bind functions can't be used
|
||||||
// as the primary relation between arcs and wires/pips
|
// as the primary relation between arcs and wires/pips
|
||||||
struct PerNetData
|
struct PerNetData
|
||||||
{
|
{
|
||||||
|
WireId src_wire;
|
||||||
std::vector<PerArcData> arcs;
|
std::vector<PerArcData> arcs;
|
||||||
ArcBounds bb;
|
ArcBounds bb;
|
||||||
// Coordinates of the center of the net, used for the weight-to-average
|
// Coordinates of the center of the net, used for the weight-to-average
|
||||||
@ -123,6 +125,7 @@ struct Router2
|
|||||||
for (size_t j = 0; j < ni->users.size(); j++) {
|
for (size_t j = 0; j < ni->users.size(); j++) {
|
||||||
auto &usr = ni->users.at(j);
|
auto &usr = ni->users.at(j);
|
||||||
WireId src_wire = ctx->getNetinfoSourceWire(ni), dst_wire = ctx->getNetinfoSinkWire(ni, usr);
|
WireId src_wire = ctx->getNetinfoSourceWire(ni), dst_wire = ctx->getNetinfoSinkWire(ni, usr);
|
||||||
|
nets.at(i).src_wire = src_wire;
|
||||||
if (ni->driver.cell == nullptr)
|
if (ni->driver.cell == nullptr)
|
||||||
src_wire = dst_wire;
|
src_wire = dst_wire;
|
||||||
if (src_wire == WireId())
|
if (src_wire == WireId())
|
||||||
@ -131,6 +134,7 @@ struct Router2
|
|||||||
if (dst_wire == WireId())
|
if (dst_wire == WireId())
|
||||||
log_error("No wire found for port %s on destination cell %s.\n", ctx->nameOf(usr.port),
|
log_error("No wire found for port %s on destination cell %s.\n", ctx->nameOf(usr.port),
|
||||||
ctx->nameOf(usr.cell));
|
ctx->nameOf(usr.cell));
|
||||||
|
nets.at(i).arcs.at(j).sink_wire = dst_wire;
|
||||||
// Set bounding box for this arc
|
// Set bounding box for this arc
|
||||||
nets.at(i).arcs.at(j).bb = ctx->getRouteBoundingBox(src_wire, dst_wire);
|
nets.at(i).arcs.at(j).bb = ctx->getRouteBoundingBox(src_wire, dst_wire);
|
||||||
// Expand net bounding box to include this arc
|
// Expand net bounding box to include this arc
|
||||||
@ -259,26 +263,31 @@ struct Router2
|
|||||||
} else {
|
} else {
|
||||||
NPNR_ASSERT(b.second == pip);
|
NPNR_ASSERT(b.second == pip);
|
||||||
}
|
}
|
||||||
nets.at(net->udata).arcs.at(user).wires[wire] = pip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void unbind_pip_internal(NetInfo *net, size_t user, WireId wire, bool dont_touch_arc = false)
|
void unbind_pip_internal(NetInfo *net, size_t user, WireId wire)
|
||||||
{
|
{
|
||||||
auto &b = wires.at(wire).bound_nets[net->udata];
|
auto &b = wires.at(wire).bound_nets.at(net->udata);
|
||||||
--b.first;
|
--b.first;
|
||||||
if (b.first == 0) {
|
if (b.first == 0) {
|
||||||
wires.at(wire).bound_nets.erase(net->udata);
|
wires.at(wire).bound_nets.erase(net->udata);
|
||||||
}
|
}
|
||||||
if (!dont_touch_arc)
|
|
||||||
nets.at(net->udata).arcs.at(user).wires.erase(wire);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ripup_arc(NetInfo *net, size_t user)
|
void ripup_arc(NetInfo *net, size_t user)
|
||||||
{
|
{
|
||||||
auto &ad = nets.at(net->udata).arcs.at(user);
|
auto &ad = nets.at(net->udata).arcs.at(user);
|
||||||
for (auto &wire : ad.wires)
|
if (!ad.routed)
|
||||||
unbind_pip_internal(net, user, wire.first, true);
|
return;
|
||||||
ad.wires.clear();
|
WireId src = nets.at(net->udata).src_wire;
|
||||||
|
WireId cursor = ad.sink_wire;
|
||||||
|
while (cursor != src) {
|
||||||
|
auto &wd = wires.at(cursor);
|
||||||
|
PipId pip = wd.bound_nets.at(net->udata).second;
|
||||||
|
unbind_pip_internal(net, user, cursor);
|
||||||
|
cursor = ctx->getPipSrcWire(pip);
|
||||||
|
}
|
||||||
|
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, WireId wire, PipId pip)
|
||||||
@ -316,14 +325,13 @@ struct Router2
|
|||||||
bool check_arc_routing(NetInfo *net, size_t usr)
|
bool check_arc_routing(NetInfo *net, size_t usr)
|
||||||
{
|
{
|
||||||
auto &ad = nets.at(net->udata).arcs.at(usr);
|
auto &ad = nets.at(net->udata).arcs.at(usr);
|
||||||
WireId src_wire = ctx->getNetinfoSourceWire(net);
|
WireId src_wire = nets.at(net->udata).src_wire;
|
||||||
WireId dst_wire = ctx->getNetinfoSinkWire(net, net->users.at(usr));
|
WireId cursor = ad.sink_wire;
|
||||||
WireId cursor = dst_wire;
|
while (wires.at(cursor).bound_nets.count(net->udata)) {
|
||||||
while (ad.wires.count(cursor)) {
|
|
||||||
auto &wd = wires.at(cursor);
|
auto &wd = wires.at(cursor);
|
||||||
if (wd.bound_nets.size() != 1)
|
if (wd.bound_nets.size() != 1)
|
||||||
return false;
|
return false;
|
||||||
auto &uh = ad.wires.at(cursor);
|
auto &uh = wd.bound_nets.at(net->udata).second;
|
||||||
if (uh == PipId())
|
if (uh == PipId())
|
||||||
break;
|
break;
|
||||||
cursor = ctx->getPipSrcWire(uh);
|
cursor = ctx->getPipSrcWire(uh);
|
||||||
@ -502,6 +510,7 @@ struct Router2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
NPNR_ASSERT(cursor_fwd == dst_wire);
|
NPNR_ASSERT(cursor_fwd == dst_wire);
|
||||||
|
ad.routed = true;
|
||||||
t.processed_sinks.insert(dst_wire);
|
t.processed_sinks.insert(dst_wire);
|
||||||
return ARC_SUCCESS;
|
return ARC_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -602,6 +611,7 @@ struct Router2
|
|||||||
cursor_bwd = ctx->getPipSrcWire(v.pip);
|
cursor_bwd = ctx->getPipSrcWire(v.pip);
|
||||||
}
|
}
|
||||||
t.processed_sinks.insert(dst_wire);
|
t.processed_sinks.insert(dst_wire);
|
||||||
|
ad.routed = true;
|
||||||
return ARC_SUCCESS;
|
return ARC_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
return ARC_RETRY_WITHOUT_BB;
|
return ARC_RETRY_WITHOUT_BB;
|
||||||
@ -709,7 +719,7 @@ struct Router2
|
|||||||
if (dst == WireId() || ctx->getBoundWireNet(dst) == net)
|
if (dst == WireId() || ctx->getBoundWireNet(dst) == net)
|
||||||
return true;
|
return true;
|
||||||
// Skip routes where there is no routing (special cases)
|
// Skip routes where there is no routing (special cases)
|
||||||
if (ad.wires.empty())
|
if (!ad.routed)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
WireId cursor = dst;
|
WireId cursor = dst;
|
||||||
@ -725,16 +735,13 @@ struct Router2
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ad.wires.count(cursor)) {
|
auto &wd = wires.at(cursor);
|
||||||
|
if (!wd.bound_nets.count(net->udata)) {
|
||||||
log("Failure details:\n");
|
log("Failure details:\n");
|
||||||
log(" Cursor: %s\n", ctx->nameOfWire(cursor));
|
log(" Cursor: %s\n", ctx->nameOfWire(cursor));
|
||||||
log(" route backtrace: \n");
|
|
||||||
for (auto w : ad.wires)
|
|
||||||
log(" %s: %s (src: %s)\n", ctx->nameOfWire(w.first), ctx->nameOfPip(w.second),
|
|
||||||
ctx->nameOfWire(ctx->getPipSrcWire(w.second)));
|
|
||||||
log_error("Internal error; incomplete route tree for arc %d of net %s.\n", usr_idx, ctx->nameOf(net));
|
log_error("Internal error; incomplete route tree for arc %d of net %s.\n", usr_idx, ctx->nameOf(net));
|
||||||
}
|
}
|
||||||
auto &p = ad.wires.at(cursor);
|
auto &p = wd.bound_nets.at(net->udata).second;
|
||||||
if (!ctx->checkPipAvail(p)) {
|
if (!ctx->checkPipAvail(p)) {
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user