Merge pull request #785 from YosysHQ/gatecat/nexus2glb2fabric

nexus: Fix routeing of global clocks that also drive fabric
This commit is contained in:
gatecat 2021-07-29 09:17:37 +01:00 committed by GitHub
commit 0991003de9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 2 deletions

View File

@ -444,6 +444,8 @@ struct Router2
// and LUT // and LUT
if (iter_count > 7) if (iter_count > 7)
return false; // heuristic to assume we've hit general routing 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) if (wire_data(wire).reserved_net != -1 && wire_data(wire).reserved_net != net->udata)
return true; // reserved for another net return true; // reserved for another net
for (auto bp : ctx->getWireBelPins(wire)) for (auto bp : ctx->getWireBelPins(wire))

View File

@ -26,6 +26,18 @@
NEXTPNR_NAMESPACE_BEGIN 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 struct NexusGlobalRouter
{ {
Context *ctx; Context *ctx;
@ -42,6 +54,22 @@ struct NexusGlobalRouter
return true; 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 // Dedicated backwards BFS routing for global networks
template <typename Tfilt> template <typename Tfilt>
bool backwards_bfs_route(NetInfo *net, size_t user_idx, int iter_limit, bool strict, Tfilt pip_filter) 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 // 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) if (sink.cell->type == id_DPHY_CORE && sink.port == id_URXCKINE)
return true; 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; return false;
} }
void route_clk_net(NetInfo *net) void route_clk_net(NetInfo *net)
{ {
for (size_t i = 0; i < net->users.size(); i++) for (size_t i = 0; i < net->users.size(); i++)
backwards_bfs_route(net, i, 1000000, true, backwards_bfs_route(net, i, 1000000, true, [&](PipId pip) {
[&](PipId pip) { return is_relaxed_sink(net->users.at(i)) || global_pip_filter(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)); log_info(" routed net '%s' using global resources\n", ctx->nameOf(net));
} }