diff options
author | David Shah <davey1576@gmail.com> | 2018-11-16 09:58:34 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-16 09:58:34 +0000 |
commit | fe4f98f26fb295b3b8d09c3303f1172c91698407 (patch) | |
tree | 706e1b76f81861b7cb7917b404b29b8d805ddfb5 /ecp5/globals.cc | |
parent | 9472b6d78f68544d430feeae6d75dbd2dc43019d (diff) | |
parent | f07bd98d59765f2c565815d1a6483db04c57a9d1 (diff) | |
download | nextpnr-fe4f98f26fb295b3b8d09c3303f1172c91698407.tar.gz nextpnr-fe4f98f26fb295b3b8d09c3303f1172c91698407.tar.bz2 nextpnr-fe4f98f26fb295b3b8d09c3303f1172c91698407.zip |
Merge pull request #118 from daveshah1/dcu
Adding ECP5 DCU support
Diffstat (limited to 'ecp5/globals.cc')
-rw-r--r-- | ecp5/globals.cc | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/ecp5/globals.cc b/ecp5/globals.cc index 9b0928a4..66c62024 100644 --- a/ecp5/globals.cc +++ b/ecp5/globals.cc @@ -55,6 +55,9 @@ class Ecp5GlobalRouter { if (user.cell->type == id_TRELLIS_SLICE && (user.port == id_CLK || user.port == id_WCK)) return true; + if (user.cell->type == id_DCUA && (user.port == id_CH0_FF_RXI_CLK || user.port == id_CH1_FF_RXI_CLK || + user.port == id_CH0_FF_TXI_CLK || user.port == id_CH1_FF_TXI_CLK)) + return true; return false; } @@ -65,8 +68,11 @@ class Ecp5GlobalRouter NetInfo *ni = net.second.get(); clockCount[ni->name] = 0; for (const auto &user : ni->users) { - if (is_clock_port(user)) + if (is_clock_port(user)) { clockCount[ni->name]++; + if (user.cell->type == id_DCUA) + clockCount[ni->name] += 100; + } } // log_info("clkcount %s: %d\n", ni->name.c_str(ctx),clockCount[ni->name]); } @@ -290,6 +296,10 @@ class Ecp5GlobalRouter float tns; return get_net_metric(ctx, clki, MetricType::WIRELENGTH, tns); } else { + // Check for dedicated routing + if (has_short_route(ctx->getBelPinWire(drv_bel, drv.port), ctx->getBelPinWire(dcc->bel, id_CLKI))) { + return 0; + } // Driver is locked Loc dcc_loc = ctx->getBelLocation(dcc->bel); Loc drv_loc = ctx->getBelLocation(drv_bel); @@ -297,6 +307,46 @@ class Ecp5GlobalRouter } } + // Return true if a short (<5) route exists between two wires + bool has_short_route(WireId src, WireId dst, int thresh = 5) + { + std::queue<WireId> visit; + std::unordered_map<WireId, PipId> backtrace; + visit.push(src); + WireId cursor; + while (true) { + + if (visit.empty() || visit.size() > 1000) { + // log_info ("dist %s -> %s = inf\n", ctx->getWireName(src).c_str(ctx), + // ctx->getWireName(dst).c_str(ctx)); + return false; + } + cursor = visit.front(); + visit.pop(); + + if (cursor == dst) + break; + for (auto dh : ctx->getPipsDownhill(cursor)) { + WireId pipDst = ctx->getPipDstWire(dh); + if (backtrace.count(pipDst)) + continue; + backtrace[pipDst] = dh; + visit.push(pipDst); + } + } + int length = 0; + while (true) { + auto fnd = backtrace.find(cursor); + if (fnd == backtrace.end()) + break; + cursor = ctx->getPipSrcWire(fnd->second); + length++; + } + // log_info ("dist %s -> %s = %d\n", ctx->getWireName(src).c_str(ctx), ctx->getWireName(dst).c_str(ctx), + // length); + return length < thresh; + } + // Attempt to place a DCC void place_dcc(CellInfo *dcc) { @@ -335,6 +385,8 @@ class Ecp5GlobalRouter for (auto user : net->users) { if (user.port == id_CLKFB) { keep_users.push_back(user); + } else if (net->driver.cell->type == id_EXTREFB && user.cell->type == id_DCUA) { + keep_users.push_back(user); } else { glbnet->users.push_back(user); user.cell->ports.at(user.port).net = glbnet.get(); |