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