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:
parent
b05cb86291
commit
4eeb56c0e0
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user