aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-07-28 15:34:54 +0100
committergatecat <gatecat@ds0.me>2021-07-28 15:35:19 +0100
commit504199e70e07b85da36d14ba546285fffb19cc99 (patch)
tree0d10e943f0eda3794d06d8c6a2fcd8b89a3dd17f
parent39a7381928359934788aefd670c835dedbbf2cd7 (diff)
downloadnextpnr-504199e70e07b85da36d14ba546285fffb19cc99.tar.gz
nextpnr-504199e70e07b85da36d14ba546285fffb19cc99.tar.bz2
nextpnr-504199e70e07b85da36d14ba546285fffb19cc99.zip
nexus: Fix routeing of global clocks that also drive fabric
Signed-off-by: gatecat <gatecat@ds0.me>
-rw-r--r--common/router2.cc2
-rw-r--r--nexus/global.cc37
2 files changed, 37 insertions, 2 deletions
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 <typename Tfilt>
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));
}