Skip to content

Commit

Permalink
router2: Add a cleanup pass between iterations
Browse files Browse the repository at this point in the history
Signed-off-by: gatecat <gatecat@ds0.me>
  • Loading branch information
gatecat committed Sep 30, 2024
1 parent fcdaf3f commit 61cd793
Showing 1 changed file with 122 additions and 4 deletions.
126 changes: 122 additions & 4 deletions common/route/router2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,120 @@ struct Router2
}
}

int trim_routing(NetInfo *net)
{
// Find places where we have a cheaper way of reaching a wire from earlier in the route tree
// and rewrite routing trees to use those cheaper routes.
int cleaned = 0;
#ifdef ARCH_ECP5
if (net->is_global)
return 0;
#endif
// Build a reverse of the wires map going downhill
auto &nd = nets.at(net->udata);
dict<WireId, pool<PipId>> src2pips;
pool<WireId> sources;
for (const auto &wire : nd.wires) {
PipId pip = wire.second.first;
if (pip == PipId()) {
sources.insert(wire.first);
} else {
src2pips[ctx->getPipSrcWire(pip)].insert(pip);
}
}
// Compute depths of wires in the route tree for a net
dict<WireId, int> depth;
auto update_depth = [&](WireId src, int src_depth) {
std::queue<std::pair<WireId, int>> visit;
visit.emplace(src, src_depth);
depth[src] = src_depth;
while (!visit.empty()) {
auto cursor = visit.front();
visit.pop();
if (!src2pips.count(cursor.first))
continue;
for (PipId dh : src2pips.at(cursor.first)) {
WireId dst = ctx->getPipDstWire(dh);
depth[dst] = cursor.second;
visit.emplace(dst, cursor.second + 1);
}
}
};
for (WireId src : sources) {
update_depth(src, 0);
}
for (auto entry : depth) {
// Check it wasn't removed by a previous prune
if (!nd.wires.count(entry.first))
continue;
// Find cheaper route
PipId best;
int score = entry.second;
for (PipId pip : ctx->getPipsUphill(entry.first)) {
WireId src = ctx->getPipSrcWire(pip);
auto fnd_depth = depth.find(src);
if (fnd_depth == depth.end())
continue;
if ((fnd_depth->second + 1) < score) {
if (!nd.wires.count(src))
continue;
if (ctx->debug) {
log_info(" found cheaper route to '%s' (%d) from '%s' (%d) on net '%s'\n",
ctx->nameOfWire(entry.first), entry.second, ctx->nameOfWire(src), fnd_depth->second, ctx->nameOf(net));
}
score = fnd_depth->second + 1;
best = pip;
}
}
if (best != PipId()) {
cleaned++;
WireId new_src = ctx->getPipSrcWire(best);
// Transplant the route tree on top of the cheaper pip
auto &dst_entry = nd.wires.at(entry.first);
// Add before removing to avoid any unnecessary remove-and-re-add
WireId cursor = new_src;
while (true) {
auto &entry = nd.wires.at(cursor);
entry.second += dst_entry.second;
if (entry.first != PipId()) {
cursor = ctx->getPipSrcWire(entry.first);
} else {
break;
}
}
cursor = ctx->getPipSrcWire(dst_entry.first);
src2pips[cursor].erase(dst_entry.first);

while (true) {
auto &entry = nd.wires.at(cursor);
entry.second -= dst_entry.second;
WireId next_cursor;
if (entry.first != PipId()) {
next_cursor = ctx->getPipSrcWire(entry.first);
}

NPNR_ASSERT(entry.second >= 0);

if (entry.second == 0) {
nd.wires.erase(cursor);
}

if (next_cursor != WireId()) {
cursor = next_cursor;
} else {
break;
}
}

dst_entry.first = best;
src2pips[new_src].insert(best);

update_depth(entry.first, score);
}
}
return cleaned;
}

bool bind_and_check(NetInfo *net, store_index<PortRef> usr_idx, int phys_pin)
{
#ifdef ARCH_ECP5
Expand Down Expand Up @@ -1439,6 +1553,10 @@ struct Router2
}

do_route();
int cleaned = 0;
for (auto n : route_queue) {
cleaned += trim_routing(nets_by_udata.at(n));
}
update_route_delays();
route_queue.clear();
update_congestion();
Expand Down Expand Up @@ -1472,12 +1590,12 @@ struct Router2
for (auto cn : failed_nets)
route_queue.push_back(cn);
if (timing_driven_ripup)
log_info(" iter=%d wires=%d overused=%d overuse=%d tmgfail=%d archfail=%s\n", iter, total_wire_use,
overused_wires, total_overuse, tmgfail,
log_info(" iter=%d wires=%d overused=%d overuse=%d tmgfail=%d cleanedup=%d archfail=%s\n", iter, total_wire_use,
overused_wires, total_overuse, tmgfail, cleaned,
(overused_wires > 0 || tmgfail > 0) ? "NA" : std::to_string(arch_fail).c_str());
else
log_info(" iter=%d wires=%d overused=%d overuse=%d archfail=%s\n", iter, total_wire_use,
overused_wires, total_overuse,
log_info(" iter=%d wires=%d overused=%d overuse=%d cleanedup=%d archfail=%s\n", iter, total_wire_use,
overused_wires, total_overuse, cleaned,
(overused_wires > 0 || tmgfail > 0) ? "NA" : std::to_string(arch_fail).c_str());
++iter;
if (curr_cong_weight < 1e9)
Expand Down

0 comments on commit 61cd793

Please sign in to comment.