diff --git a/common/router2.cc b/common/router2.cc index eb889e12..2994038c 100644 --- a/common/router2.cc +++ b/common/router2.cc @@ -444,6 +444,8 @@ struct Router2 // and LUT if (iter_count > 7) return false; // heuristic to assume we've hit general routing + if (wire_data(wire).unavailable) + return true; if (wire_data(wire).reserved_net != -1 && wire_data(wire).reserved_net != net->udata) return true; // reserved for another net for (auto bp : ctx->getWireBelPins(wire)) diff --git a/nexus/global.cc b/nexus/global.cc index 8b204152..1c763a31 100644 --- a/nexus/global.cc +++ b/nexus/global.cc @@ -26,6 +26,18 @@ NEXTPNR_NAMESPACE_BEGIN +namespace { +bool str_match(const std::string &s, const std::string &pattern) +{ + if (s.size() != pattern.size()) + return false; + for (size_t i = 0; i < s.size(); i++) + if (pattern.at(i) != '?' && s.at(i) != pattern.at(i)) + return false; + return true; +} +} // namespace + struct NexusGlobalRouter { Context *ctx; @@ -42,6 +54,22 @@ struct NexusGlobalRouter return true; } + // These rules make sure global->fabric connections are always routeable, as they won't be ripup-able by the general + // router + bool routeability_pip_filter(PipId pip) const + { + IdString dest_basename(ctx->wire_data(ctx->getPipDstWire(pip)).name); + const std::string &s = dest_basename.str(ctx); + if (str_match(s, "JDI?_DIMUX")) { + IdString src_basename(ctx->wire_data(ctx->getPipSrcWire(pip)).name); + return str_match(src_basename.str(ctx), "JM?_DIMUX"); + } else if (str_match(s, "JDL?_DRMUX")) { + IdString src_basename(ctx->wire_data(ctx->getPipSrcWire(pip)).name); + return str_match(src_basename.str(ctx), "JD?_DRMUX"); + } + return true; + } + // Dedicated backwards BFS routing for global networks template bool backwards_bfs_route(NetInfo *net, size_t user_idx, int iter_limit, bool strict, Tfilt pip_filter) @@ -141,14 +169,19 @@ struct NexusGlobalRouter // This DPHY clock port can't be routed without going through some general routing if (sink.cell->type == id_DPHY_CORE && sink.port == id_URXCKINE) return true; + // Cases where global clocks are driving fabric + if ((sink.cell->type == id_OXIDE_COMB && sink.port != id_WCK) || + (sink.cell->type == id_OXIDE_FF && sink.port != id_CLK)) + return true; return false; } void route_clk_net(NetInfo *net) { for (size_t i = 0; i < net->users.size(); i++) - backwards_bfs_route(net, i, 1000000, true, - [&](PipId pip) { return is_relaxed_sink(net->users.at(i)) || global_pip_filter(pip); }); + backwards_bfs_route(net, i, 1000000, true, [&](PipId pip) { + return (is_relaxed_sink(net->users.at(i)) || global_pip_filter(pip)) && routeability_pip_filter(pip); + }); log_info(" routed net '%s' using global resources\n", ctx->nameOf(net)); }