ecp5: Adding ancillary DCU bels
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
37cbabecfb
commit
e9fe444dc7
@ -651,7 +651,7 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in
|
||||
return TMG_IGNORE; // FIXME
|
||||
} else if (cell->type == id_EHXPLLL) {
|
||||
return TMG_IGNORE;
|
||||
} else if (cell->type == id_DCUA) {
|
||||
} else if (cell->type == id_DCUA || cell->type == id_EXTREFB || cell->type == id_PCSCLKDIV) {
|
||||
return TMG_IGNORE; // FIXME
|
||||
} else {
|
||||
NPNR_ASSERT_FALSE_STR("no timing data for cell type '" + cell->type.str(this) + "'");
|
||||
|
@ -514,6 +514,12 @@ static std::vector<bool> parse_config_str(std::string str, int length)
|
||||
for (int i = 0; i < length; i++)
|
||||
if (value & (1 << i))
|
||||
word.at(i) = true;
|
||||
} else {
|
||||
NPNR_ASSERT(length < 64);
|
||||
unsigned long long value = std::stoull(str);
|
||||
for (int i = 0; i < length; i++)
|
||||
if (value & (1 << i))
|
||||
word.at(i) = true;
|
||||
}
|
||||
return word;
|
||||
}
|
||||
@ -1078,6 +1084,17 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
#include "dcu_bitstream.h"
|
||||
cc.tilegroups.push_back(tg);
|
||||
tieoff_dcu_ports(ctx, cc, ci);
|
||||
} else if (ci->type == id_EXTREFB) {
|
||||
TileGroup tg;
|
||||
tg.tiles = get_dcu_tiles(ctx, ci->bel);
|
||||
tg.config.add_word("EXTREF.REFCK_DCBIAS_EN", parse_config_str(str_or_default(ci->params, ctx->id("REFCK_DCBIAS_EN"), "0"), 1));
|
||||
tg.config.add_word("EXTREF.REFCK_RTERM", parse_config_str(str_or_default(ci->params, ctx->id("REFCK_RTERM"), "0"), 1));
|
||||
tg.config.add_word("EXTREF.REFCK_PWDNB", parse_config_str(str_or_default(ci->params, ctx->id("REFCK_PWDNB"), "0"), 1));
|
||||
cc.tilegroups.push_back(tg);
|
||||
} else if (ci->type == id_PCSCLKDIV) {
|
||||
Loc loc = ctx->getBelLocation(ci->bel);
|
||||
std::string tname = ctx->getTileByTypeAndLocation(loc.y+1, loc.x, "BMID_0H");
|
||||
cc.tiles[tname].add_enum("PCSCLKDIV" + std::to_string(loc.z), str_or_default(ci->params, ctx->id("GSR"), "ENABLED"));
|
||||
} else {
|
||||
NPNR_ASSERT_FALSE("unsupported cell type");
|
||||
}
|
||||
|
@ -1110,3 +1110,10 @@ X(D_COUT18)
|
||||
X(D_COUT19)
|
||||
X(D_REFCLKI)
|
||||
X(D_FFS_PLOL)
|
||||
|
||||
X(PCSCLKDIV)
|
||||
X(SEL2)
|
||||
X(SEL1)
|
||||
X(SEL0)
|
||||
X(CDIV1)
|
||||
X(CDIVX)
|
32
ecp5/pack.cc
32
ecp5/pack.cc
@ -1039,6 +1039,8 @@ class Ecp5Packer
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
if (ci->type == id_DCUA) {
|
||||
if (!ci->attrs.count(ctx->id("BEL")))
|
||||
log_error("DCU must be constrained to a Bel!\n");
|
||||
// Empty port auto-creation to generate correct tie-downs
|
||||
BelId exemplar_bel;
|
||||
for (auto bel : ctx->getBels()) {
|
||||
@ -1051,6 +1053,36 @@ class Ecp5Packer
|
||||
for (auto pin : ctx->getBelPins(exemplar_bel))
|
||||
if (ctx->getBelPinType(exemplar_bel, pin) == PORT_IN)
|
||||
autocreate_empty_port(ci, pin);
|
||||
} else if (ci->type == id_EXTREFB) {
|
||||
const NetInfo *refo = net_or_nullptr(ci, id_REFCLKO);
|
||||
CellInfo *dcu = nullptr;
|
||||
if (refo == nullptr)
|
||||
log_error("EXTREFB REFCLKO must not be unconnected\n");
|
||||
for (auto user : refo->users) {
|
||||
if (user.cell->type != id_DCUA || (dcu != nullptr && dcu != user.cell))
|
||||
log_error("EXTREFB REFCLKO must only drive a single DCUA\n");
|
||||
dcu = user.cell;
|
||||
}
|
||||
if (!dcu->attrs.count(ctx->id("BEL")))
|
||||
log_error("DCU must be constrained to a Bel!\n");
|
||||
std::string bel = dcu->attrs.at(ctx->id("BEL"));
|
||||
NPNR_ASSERT(bel.substr(bel.length() - 3) == "DCU");
|
||||
bel.replace(bel.length() - 3, 3, "EXTREF");
|
||||
ci->attrs[ctx->id("BEL")] = bel;
|
||||
} else if (ci->type == id_PCSCLKDIV) {
|
||||
const NetInfo *clki = net_or_nullptr(ci, id_CLKI);
|
||||
if (clki != nullptr && clki->driver.cell != nullptr && clki->driver.cell->type == id_DCUA) {
|
||||
CellInfo *dcu = clki->driver.cell;
|
||||
if (!dcu->attrs.count(ctx->id("BEL")))
|
||||
log_error("DCU must be constrained to a Bel!\n");
|
||||
BelId bel = ctx->getBelByName(ctx->id(dcu->attrs.at(ctx->id("BEL"))));
|
||||
if (bel == BelId())
|
||||
log_error("Invalid DCU bel '%s'\n", dcu->attrs.at(ctx->id("BEL")).c_str());
|
||||
Loc loc = ctx->getBelLocation(bel);
|
||||
// DCU0 -> CLKDIV z=0; DCU1 -> CLKDIV z=1
|
||||
ci->constr_abs_z = true;
|
||||
ci->constr_z = (loc.x >= 69) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user