ecp5: Fix some tricky ECLKSYNCB/CLKDIVF packing cases
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
b5054f0d77
commit
576baa994f
64
ecp5/pack.cc
64
ecp5/pack.cc
@ -2653,6 +2653,7 @@ class Ecp5Packer
|
||||
}
|
||||
}
|
||||
flush_cells();
|
||||
std::unordered_set<BelId> used_eclksyncb;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
if (ci->type == id_CLKDIVF) {
|
||||
@ -2687,6 +2688,7 @@ class Ecp5Packer
|
||||
Loc loc = ctx->getBelLocation(bel);
|
||||
ci->attrs[ctx->id("BEL")] =
|
||||
ctx->getBelName(ctx->getBelByLocation(Loc(loc.x, loc.y, 15))).str(ctx);
|
||||
used_eclksyncb.insert(bel);
|
||||
goto eclksync_done;
|
||||
}
|
||||
}
|
||||
@ -2702,6 +2704,7 @@ class Ecp5Packer
|
||||
Loc loc = ctx->getBelLocation(bel);
|
||||
if (loc.x == eckbuf_loc.x && loc.y == eckbuf_loc.y && loc.z == eckbuf_loc.z - 2) {
|
||||
ci->attrs[ctx->id("BEL")] = ctx->getBelName(bel).str(ctx);
|
||||
used_eclksyncb.insert(bel);
|
||||
goto eclksync_done;
|
||||
}
|
||||
}
|
||||
@ -2768,6 +2771,67 @@ class Ecp5Packer
|
||||
}
|
||||
}
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
if (ci->type == id_ECLKSYNCB) {
|
||||
// **All** ECLKSYNCBs must be constrained
|
||||
// Most will be dealt with above, but there might be some rogue cases
|
||||
if (ci->attrs.count(ctx->id("BEL")))
|
||||
continue;
|
||||
for (BelId bel : ctx->getBels()) {
|
||||
if (ctx->getBelType(bel) != id_ECLKSYNCB)
|
||||
continue;
|
||||
// Might there be a better way to pick??
|
||||
if (used_eclksyncb.count(bel))
|
||||
continue;
|
||||
log_info("Constraining ECLKSYNCB '%s' to bel '%s'\n", ctx->nameOf(ci), ctx->nameOfBel(bel));
|
||||
ci->attrs[ctx->id("BEL")] = ctx->getBelName(bel).str(ctx);
|
||||
goto eclksync_ii_done;
|
||||
}
|
||||
if (0) {
|
||||
eclksync_ii_done:
|
||||
continue;
|
||||
}
|
||||
log_error("Failed to constrain ECLKSYNCB '%s'\n", ctx->nameOf(ci));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
if (ci->type == id_CLKDIVF) {
|
||||
if (ci->attrs.count(ctx->id("BEL")))
|
||||
continue;
|
||||
// Case of a CLKDIVF driven by an ECLKSYNC constrained above; without the input being used elsewhere as
|
||||
// an edge clock
|
||||
const NetInfo *clki = net_or_nullptr(ci, id_CLKI);
|
||||
if (clki == nullptr || clki->driver.cell == nullptr)
|
||||
continue;
|
||||
CellInfo *drv = clki->driver.cell;
|
||||
if (drv->type != id_ECLKSYNCB || !drv->attrs.count(ctx->id("BEL")))
|
||||
continue;
|
||||
BelId bel = ctx->getBelByName(ctx->id(drv->attrs.at(ctx->id("BEL")).as_string()));
|
||||
// Find a CLKDIVF that is routeable from the ECLKSYNC
|
||||
std::queue<WireId> visit;
|
||||
visit.push(ctx->getBelPinWire(bel, id_ECLKO));
|
||||
while (!visit.empty()) {
|
||||
WireId cursor = visit.front();
|
||||
visit.pop();
|
||||
for (BelPin bp : ctx->getWireBelPins(cursor)) {
|
||||
if (ctx->getBelType(bp.bel) != id_CLKDIVF || bp.pin != id_CLKI)
|
||||
continue;
|
||||
ci->attrs[ctx->id("BEL")] = ctx->getBelName(bp.bel).str(ctx);
|
||||
log_info("Constraining CLKDIVF '%s' to bel '%s' based on ECLKSYNCB.\n", ctx->nameOf(ci),
|
||||
ctx->nameOfBel(bp.bel));
|
||||
goto clkdiv_ii_done;
|
||||
}
|
||||
for (PipId pip : ctx->getPipsDownhill(cursor))
|
||||
visit.push(ctx->getPipDstWire(pip));
|
||||
}
|
||||
clkdiv_ii_done:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
flush_cells();
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user