diff options
author | David Shah <davey1576@gmail.com> | 2018-07-29 10:35:05 +0200 |
---|---|---|
committer | David Shah <davey1576@gmail.com> | 2018-09-29 16:06:30 +0100 |
commit | d43138b022c84efc01895f51f15244d8a42a5156 (patch) | |
tree | 3d4e8e2dca4f644640021d149491eee31ae9021f /ecp5/globals.cc | |
parent | 7d48acff52cfa31cf7873d7462a3a4e6395ee520 (diff) | |
download | nextpnr-d43138b022c84efc01895f51f15244d8a42a5156.tar.gz nextpnr-d43138b022c84efc01895f51f15244d8a42a5156.tar.bz2 nextpnr-d43138b022c84efc01895f51f15244d8a42a5156.zip |
ecp5: Global routing algorithm up to TAPs
Signed-off-by: David Shah <davey1576@gmail.com>
Diffstat (limited to 'ecp5/globals.cc')
-rw-r--r-- | ecp5/globals.cc | 85 |
1 files changed, 75 insertions, 10 deletions
diff --git a/ecp5/globals.cc b/ecp5/globals.cc index 770eb7e2..9d51316c 100644 --- a/ecp5/globals.cc +++ b/ecp5/globals.cc @@ -17,8 +17,14 @@ * */ -#include "nextpnr.h" #include <algorithm> +#include <iomanip> +#include <queue> +#include "nextpnr.h" + +#include "log.h" + +#define fmt_str(x) (static_cast<const std::ostringstream &>(std::ostringstream() << x).str()) NEXTPNR_NAMESPACE_BEGIN @@ -26,15 +32,16 @@ class Ecp5GlobalRouter { public: Ecp5GlobalRouter(Context *ctx) : ctx(ctx){}; - private: - bool is_clock_port(const PortRef &user) { + private: + bool is_clock_port(const PortRef &user) + { if (user.cell->type == ctx->id("TRELLIS_LC") && user.port == ctx->id("CLK")) return true; return false; } - std::vector<NetInfo*> get_clocks() + std::vector<NetInfo *> get_clocks() { std::unordered_map<IdString, int> clockCount; for (auto &net : ctx->nets) { @@ -45,13 +52,11 @@ class Ecp5GlobalRouter clockCount[ni->name]++; } } - std::vector<NetInfo*> clocks; + std::vector<NetInfo *> clocks; while (clocks.size() < 16) { - auto max = std::max_element(clockCount.begin(), clockCount.end(), []( - const decltype(clockCount)::value_type &a, const decltype(clockCount)::value_type &b - ) { - return a.second < b.second; - }); + auto max = std::max_element(clockCount.begin(), clockCount.end(), + [](const decltype(clockCount)::value_type &a, + const decltype(clockCount)::value_type &b) { return a.second < b.second; }); if (max == clockCount.end() || max->second < 3) break; clocks.push_back(ctx->nets.at(max->first).get()); @@ -77,6 +82,66 @@ class Ecp5GlobalRouter return *(ctx->getPipsUphill(tap_wire).begin()); } + void route_logic_tile_global(IdString net, int global_index, PortRef user) + { + WireId userWire = ctx->getBelPinWire(user.cell->bel, ctx->portPinFromId(user.port)); + WireId globalWire; + IdString global_name = ctx->id(fmt_str("G_HPBX" << std::setw(2) << std::setfill('0') << global_index << "00")); + std::queue<WireId> upstream; + std::unordered_map<WireId, PipId> backtrace; + upstream.push(userWire); + bool already_routed = false; + // Search back from the pin until we reach the global network + while (true) { + WireId next = upstream.front(); + upstream.pop(); + + if (ctx->getBoundWireNet(next) == net) { + already_routed = true; + globalWire = next; + break; + } + + if (ctx->getWireBasename(next) == global_name) { + globalWire = next; + break; + } + if (ctx->checkWireAvail(next)) { + for (auto pip : ctx->getPipsUphill(next)) { + WireId src = ctx->getPipSrcWire(pip); + backtrace[src] = pip; + upstream.push(src); + } + } + if (upstream.size() > 3000) { + log_error("failed to route HPBX%02d00 to %s.%s\n", global_index, + ctx->getBelName(user.cell->bel).c_str(ctx), user.port.c_str(ctx)); + } + } + // Set all the pips we found along the way + WireId cursor = userWire; + while (true) { + auto fnd = backtrace.find(cursor); + if (fnd == backtrace.end()) + break; + ctx->bindPip(fnd->second, net, STRENGTH_LOCKED); + cursor = ctx->getPipSrcWire(fnd->second); + } + // If the global network inside the tile isn't already set up, + // we also need to bind the buffers along the way + if (!already_routed) { + ctx->bindWire(cursor, net, STRENGTH_LOCKED); + PipId tap_pip = find_tap_pip(cursor); + IdString tap_net = ctx->getBoundPipNet(tap_pip); + if (tap_net == IdString()) { + ctx->bindPip(tap_pip, net, STRENGTH_LOCKED); + // TODO: SPINE + } else { + NPNR_ASSERT(tap_net == net); + } + } + } + Context *ctx; }; |