aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-12-01 09:14:34 +0000
committerGitHub <noreply@github.com>2018-12-01 09:14:34 +0000
commitdc549cd56bf1db4342a2bab1fb3fc04ca3a9ceea (patch)
treef1dc4ef417ca8de251c805b149c53728a869cb20 /ecp5
parent58e9c6f32e7ab6a5f83245141f00c3955b91d905 (diff)
parent5ddf99cf5d3e6d012bd0938163dc256ef9e34770 (diff)
downloadnextpnr-dc549cd56bf1db4342a2bab1fb3fc04ca3a9ceea.tar.gz
nextpnr-dc549cd56bf1db4342a2bab1fb3fc04ca3a9ceea.tar.bz2
nextpnr-dc549cd56bf1db4342a2bab1fb3fc04ca3a9ceea.zip
Merge pull request #159 from YosysHQ/ecp5_pllplace
ecp5: Pre-place PLLs and use dedicated routes into globals
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/globals.cc6
-rw-r--r--ecp5/pack.cc55
2 files changed, 59 insertions, 2 deletions
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<WireId> visit;
std::unordered_map<WireId, PipId> 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<BelId> 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<int>::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();