aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5/globals.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ecp5/globals.cc')
-rw-r--r--ecp5/globals.cc54
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();