From 5ddf99cf5d3e6d012bd0938163dc256ef9e34770 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 30 Nov 2018 16:09:56 +0000 Subject: ecp5: Pre-place PLLs and use dedicated routes into globals Signed-off-by: David Shah --- ecp5/globals.cc | 6 ++++-- ecp5/pack.cc | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) (limited to 'ecp5') diff --git a/ecp5/globals.cc b/ecp5/globals.cc index 66c62024..ddaae5e5 100644 --- a/ecp5/globals.cc +++ b/ecp5/globals.cc @@ -298,6 +298,8 @@ class Ecp5GlobalRouter } else { // Check for dedicated routing if (has_short_route(ctx->getBelPinWire(drv_bel, drv.port), ctx->getBelPinWire(dcc->bel, id_CLKI))) { + // log_info("dedicated route %s -> %s\n", ctx->getWireName(ctx->getBelPinWire(drv_bel, + // drv.port)).c_str(ctx), ctx->getBelName(dcc->bel).c_str(ctx)); return 0; } // Driver is locked @@ -308,7 +310,7 @@ class Ecp5GlobalRouter } // Return true if a short (<5) route exists between two wires - bool has_short_route(WireId src, WireId dst, int thresh = 5) + bool has_short_route(WireId src, WireId dst, int thresh = 7) { std::queue visit; std::unordered_map backtrace; @@ -316,7 +318,7 @@ class Ecp5GlobalRouter WireId cursor; while (true) { - if (visit.empty() || visit.size() > 1000) { + if (visit.empty() || visit.size() > 10000) { // log_info ("dist %s -> %s = inf\n", ctx->getWireName(src).c_str(ctx), // ctx->getWireName(dst).c_str(ctx)); return false; diff --git a/ecp5/pack.cc b/ecp5/pack.cc index 78bf7a87..ca329530 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -1323,6 +1323,60 @@ class Ecp5Packer } } + // Preplace PLL + void preplace_plls() + { + std::set available_plls; + for (auto bel : ctx->getBels()) { + if (ctx->getBelType(bel) == id_EHXPLLL && ctx->checkBelAvail(bel)) + available_plls.insert(bel); + } + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + if (ci->type == id_EHXPLLL && ci->attrs.count(ctx->id("BEL"))) + available_plls.erase(ctx->getBelByName(ctx->id(ci->attrs.at(ctx->id("BEL"))))); + } + // Place PLL connected to fixed drivers such as IO close to their source + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + if (ci->type == id_EHXPLLL && !ci->attrs.count(ctx->id("BEL"))) { + const NetInfo *drivernet = net_or_nullptr(ci, id_CLKI); + if (drivernet == nullptr || drivernet->driver.cell == nullptr) + continue; + const CellInfo *drivercell = drivernet->driver.cell; + if (!drivercell->attrs.count(ctx->id("BEL"))) + continue; + BelId drvbel = ctx->getBelByName(ctx->id(drivercell->attrs.at(ctx->id("BEL")))); + Loc drvloc = ctx->getBelLocation(drvbel); + BelId closest_pll; + int closest_distance = std::numeric_limits::max(); + for (auto bel : available_plls) { + Loc pllloc = ctx->getBelLocation(bel); + int distance = std::abs(drvloc.x - pllloc.x) + std::abs(drvloc.y - pllloc.y); + if (distance < closest_distance) { + closest_pll = bel; + closest_distance = distance; + } + } + if (closest_pll == BelId()) + log_error("failed to place PLL '%s'\n", ci->name.c_str(ctx)); + available_plls.erase(closest_pll); + ci->attrs[ctx->id("BEL")] = ctx->getBelName(closest_pll).str(ctx); + } + } + // Place PLLs driven by logic, etc, randomly + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + if (ci->type == id_EHXPLLL && !ci->attrs.count(ctx->id("BEL"))) { + if (available_plls.empty()) + log_error("failed to place PLL '%s'\n", ci->name.c_str(ctx)); + BelId next_pll = *(available_plls.begin()); + available_plls.erase(next_pll); + ci->attrs[ctx->id("BEL")] = ctx->getBelName(next_pll).str(ctx); + } + } + } + public: void pack() { @@ -1330,6 +1384,7 @@ class Ecp5Packer pack_ebr(); pack_dsps(); pack_dcus(); + preplace_plls(); pack_constants(); pack_dram(); pack_carries(); -- cgit v1.2.3