aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2019-11-01 16:02:23 +0000
committerDavid Shah <dave@ds0.me>2019-11-01 16:07:51 +0000
commit58b7cb920ff80f85a0e28df59d84977804f8d67d (patch)
tree7c456ea6a6db88e6f66d094f1d35a52abbebb627 /ecp5
parent5cf0ed5edead8aa4060978f7b22e598ab03ef1b9 (diff)
downloadnextpnr-58b7cb920ff80f85a0e28df59d84977804f8d67d.tar.gz
nextpnr-58b7cb920ff80f85a0e28df59d84977804f8d67d.tar.bz2
nextpnr-58b7cb920ff80f85a0e28df59d84977804f8d67d.zip
ecp5: Fix placement of ECLKBRIDGECS
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/pack.cc52
1 files changed, 41 insertions, 11 deletions
diff --git a/ecp5/pack.cc b/ecp5/pack.cc
index 244a79d5..8ba3d651 100644
--- a/ecp5/pack.cc
+++ b/ecp5/pack.cc
@@ -2353,6 +2353,7 @@ class Ecp5Packer
for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (ci->type == id_ECLKBRIDGECS) {
+ Loc loc;
NetInfo *i0 = get_net_or_empty(ci, id_CLK0), *i1 = get_net_or_empty(ci, id_CLK1),
*o = get_net_or_empty(ci, id_ECSOUT);
for (NetInfo *input : {i0, i1}) {
@@ -2366,24 +2367,53 @@ class Ecp5Packer
for (auto bel : ctx->getBels()) {
if (ctx->getBelType(bel) != id_ECLKBRIDGECS)
continue;
- Loc loc = ctx->getBelLocation(bel);
+ loc = ctx->getBelLocation(bel);
if (loc.x == user_loc.x) {
ci->attrs[ctx->id("BEL")] = ctx->getBelName(bel).str(ctx);
- if (o != nullptr)
- for (auto user2 : o->users) {
- // Set side hint to ensure edge clock choice is routeable
- if (user2.cell->type == id_ECLKSYNCB && user2.port == id_ECLKI) {
- NetInfo *synco = get_net_or_empty(user2.cell, id_ECLKO);
- if (synco != nullptr)
- bridge_side_hint[synco] = (loc.x > 1) ? 0 : 1;
- }
- }
goto eclkbridge_done;
}
}
}
+ if (input->driver.cell != nullptr) {
+ CellInfo *drv = input->driver.cell;
+ if (!drv->attrs.count(ctx->id("BEL")))
+ continue;
+ Loc drv_loc = ctx->getBelLocation(
+ ctx->getBelByName(ctx->id(drv->attrs.at(ctx->id("BEL")).as_string())));
+ BelId closest;
+ int closest_x = -1; // aim for same side of chip
+ for (auto bel : ctx->getBels()) {
+ if (ctx->getBelType(bel) != id_ECLKBRIDGECS)
+ continue;
+ loc = ctx->getBelLocation(bel);
+ if (closest_x == -1 || std::abs(loc.x - drv_loc.x) < std::abs(closest_x - drv_loc.x)) {
+ closest_x = loc.x;
+ closest = bel;
+ }
+ }
+ NPNR_ASSERT(closest != BelId());
+ loc = ctx->getBelLocation(closest);
+ ci->attrs[ctx->id("BEL")] = ctx->getBelName(closest).str(ctx);
+ goto eclkbridge_done;
+ }
+ }
+ // If all else fails, place randomly
+ for (auto bel : ctx->getBels()) {
+ if (ctx->getBelType(bel) != id_ECLKBRIDGECS)
+ continue;
+ loc = ctx->getBelLocation(bel);
+ ci->attrs[ctx->id("BEL")] = ctx->getBelName(bel).str(ctx);
}
eclkbridge_done:
+ if (o != nullptr)
+ for (auto user2 : o->users) {
+ // Set side hint to ensure edge clock choice is routeable
+ if (user2.cell->type == id_ECLKSYNCB && user2.port == id_ECLKI) {
+ NetInfo *synco = get_net_or_empty(user2.cell, id_ECLKO);
+ if (synco != nullptr)
+ bridge_side_hint[synco] = (loc.x > 1) ? 0 : 1;
+ }
+ }
continue;
}
}
@@ -2659,12 +2689,12 @@ class Ecp5Packer
prepack_checks();
pack_io();
pack_dqsbuf();
+ preplace_plls();
pack_iologic();
pack_ebr();
pack_dsps();
pack_dcus();
pack_misc();
- preplace_plls();
pack_constants();
pack_dram();
pack_carries();