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();
|
flush_cells();
|
||||||
|
std::unordered_set<BelId> used_eclksyncb;
|
||||||
for (auto cell : sorted(ctx->cells)) {
|
for (auto cell : sorted(ctx->cells)) {
|
||||||
CellInfo *ci = cell.second;
|
CellInfo *ci = cell.second;
|
||||||
if (ci->type == id_CLKDIVF) {
|
if (ci->type == id_CLKDIVF) {
|
||||||
@ -2687,6 +2688,7 @@ class Ecp5Packer
|
|||||||
Loc loc = ctx->getBelLocation(bel);
|
Loc loc = ctx->getBelLocation(bel);
|
||||||
ci->attrs[ctx->id("BEL")] =
|
ci->attrs[ctx->id("BEL")] =
|
||||||
ctx->getBelName(ctx->getBelByLocation(Loc(loc.x, loc.y, 15))).str(ctx);
|
ctx->getBelName(ctx->getBelByLocation(Loc(loc.x, loc.y, 15))).str(ctx);
|
||||||
|
used_eclksyncb.insert(bel);
|
||||||
goto eclksync_done;
|
goto eclksync_done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2702,6 +2704,7 @@ class Ecp5Packer
|
|||||||
Loc loc = ctx->getBelLocation(bel);
|
Loc loc = ctx->getBelLocation(bel);
|
||||||
if (loc.x == eckbuf_loc.x && loc.y == eckbuf_loc.y && loc.z == eckbuf_loc.z - 2) {
|
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);
|
ci->attrs[ctx->id("BEL")] = ctx->getBelName(bel).str(ctx);
|
||||||
|
used_eclksyncb.insert(bel);
|
||||||
goto eclksync_done;
|
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();
|
flush_cells();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user