gowin: Himbaechel. Improve global router.

* Don't stop at the first bad "arc", but use the global network to the
  maximum.
* Report partial/full use of global wires for the network.
* In case of complete routing failure, releasing the source - this is
  actually a BUGFIX.

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
YRabbit 2024-01-31 16:04:31 +10:00 committed by myrtle
parent b05cb86291
commit 4eeb56c0e0

View File

@ -71,7 +71,7 @@ struct GowinGlobalRouter
template <typename Tfilt> template <typename Tfilt>
bool backwards_bfs_route(NetInfo *net, WireId src, WireId dst, int iter_limit, bool strict, Tfilt pip_filter) bool backwards_bfs_route(NetInfo *net, WireId src, WireId dst, int iter_limit, bool strict, Tfilt pip_filter)
{ {
// log_info("%s:%s->%s\n", net->name.c_str(ctx), ctx->nameOfWire(src), ctx->nameOfWire(dst)); // log_info("route arc %s:%s->%s\n", net->name.c_str(ctx), ctx->nameOfWire(src), ctx->nameOfWire(dst));
// Queue of wires to visit // Queue of wires to visit
std::queue<WireId> visit; std::queue<WireId> visit;
// Wire -> upstream pip // Wire -> upstream pip
@ -141,7 +141,7 @@ struct GowinGlobalRouter
// Bind pips until we hit already-bound routing // Bind pips until we hit already-bound routing
for (PipId pip : pips) { for (PipId pip : pips) {
WireId dst = ctx->getPipDstWire(pip); WireId dst = ctx->getPipDstWire(pip);
// log_info("%s:%s\n", ctx->getPipName(pip).str(ctx).c_str(), ctx->nameOfWire(dst)); // log_info("bind pip %s:%s\n", ctx->getPipName(pip).str(ctx).c_str(), ctx->nameOfWire(dst));
if (ctx->getBoundWireNet(dst) == net) { if (ctx->getBoundWireNet(dst) == net) {
break; break;
} }
@ -160,7 +160,14 @@ struct GowinGlobalRouter
} }
} }
bool route_direct_net(NetInfo *net) enum RouteResult
{
NOT_ROUTED = 0,
ROUTED_PARTIALLY,
ROUTED_ALL
};
RouteResult route_direct_net(NetInfo *net)
{ {
// Lookup source and destination wires // Lookup source and destination wires
WireId src = ctx->getNetinfoSourceWire(net); WireId src = ctx->getNetinfoSourceWire(net);
@ -172,20 +179,24 @@ struct GowinGlobalRouter
ctx->bindWire(src, net, STRENGTH_LOCKED); ctx->bindWire(src, net, STRENGTH_LOCKED);
} }
bool routed = false; RouteResult routed = NOT_ROUTED;
for (auto usr : net->users.enumerate()) { for (auto usr : net->users.enumerate()) {
WireId dst = ctx->getNetinfoSinkWire(net, net->users.at(usr.index), 0); WireId dst = ctx->getNetinfoSinkWire(net, net->users.at(usr.index), 0);
if (dst == WireId()) { if (dst == WireId()) {
log_error("Net '%s' has an invalid sink port %s.%s\n", ctx->nameOf(net), log_error("Net '%s' has an invalid sink port %s.%s\n", ctx->nameOf(net),
ctx->nameOf(net->users.at(usr.index).cell), ctx->nameOf(net->users.at(usr.index).port)); ctx->nameOf(net->users.at(usr.index).cell), ctx->nameOf(net->users.at(usr.index).port));
} }
routed = backwards_bfs_route(net, src, dst, 1000000, false, [&](PipId pip) { if (backwards_bfs_route(net, src, dst, 1000000, false, [&](PipId pip) {
return (is_relaxed_sink(usr.value) || global_pip_filter(pip)); return (is_relaxed_sink(usr.value) || global_pip_filter(pip));
}); })) {
if (!routed) { routed = routed == ROUTED_PARTIALLY ? routed : ROUTED_ALL;
break; } else {
routed = routed == NOT_ROUTED ? routed : ROUTED_PARTIALLY;
} }
} }
if (routed == NOT_ROUTED) {
ctx->unbindWire(src);
}
return routed; return routed;
} }
@ -229,8 +240,10 @@ struct GowinGlobalRouter
void route_clk_net(NetInfo *net) void route_clk_net(NetInfo *net)
{ {
if (route_direct_net(net)) { RouteResult res = route_direct_net(net);
log_info(" routed net '%s' using global resources\n", ctx->nameOf(net)); if (res) {
log_info(" routed net '%s' using global resources %s\n", ctx->nameOf(net),
res == ROUTED_ALL ? "completely" : "partially");
} }
} }
@ -301,6 +314,9 @@ struct GowinGlobalRouter
continue; continue;
} }
if (driver_is_clksrc(ni->driver)) { if (driver_is_clksrc(ni->driver)) {
if (ctx->verbose) {
log_info("route clock net '%s'\n", ctx->nameOf(ni));
}
route_clk_net(ni); route_clk_net(ni);
continue; continue;
} }