mirror of https://github.com/YosysHQ/nextpnr.git
himbaechel/xilinx: fix LUTRAM initialisation (INIT_A..INIT_D)
Distributed RAM primitives (RAM32M/RAM64M etc.) carry their per-port initialisation in parameters named INIT_A..INIT_D, but pack_dram looked up INITA..INITD. The lookup never matched, so all LUTRAM was configured with INIT=0 regardless of the design's initial contents. Fixing the name exposed a second, previously unreachable bug in the wide (dbits>1) path: the 64-bit INIT slice was converted with as_bits(), which yields raw bool values rather than the '0'/'1' characters a Property string requires, producing a corrupt property. De-interleave the canonical bit string directly (bit k*2+j of the 64-bit INIT is bit j of entry k) and rebuild the Property with update_intval(). Repro: a RAM32M with a nonzero INIT_A..D readback (WE held low / driven by a live net); before this change the read data is all-zero. Hardware-verified on xc7a100t (QMTech Wukong): LUTRAM-based tables in a MEGA65 core port now read back their initial contents correctly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
68c1acd80a
commit
4fd89bca9a
|
|
@ -495,8 +495,8 @@ void XilinxPacker::pack_dram()
|
|||
dout, zoffset + i);
|
||||
if (base == nullptr)
|
||||
base = dram;
|
||||
if (ci->params.count(ctx->idf("INIT%c", 'A' + i)))
|
||||
dram->params[id_INIT] = ci->params[ctx->idf("INIT%c", 'A' + i)];
|
||||
if (ci->params.count(ctx->idf("INIT_%c", 'A' + i)))
|
||||
dram->params[id_INIT] = ci->params[ctx->idf("INIT_%c", 'A' + i)];
|
||||
} else {
|
||||
for (int j = 0; j < dbits; j++) {
|
||||
NetInfo *di = ci->getPort(ctx->idf("DI%c[%d]", 'A' + i, j));
|
||||
|
|
@ -507,13 +507,19 @@ void XilinxPacker::pack_dram()
|
|||
address, di, dout, (j == 0), zoffset + i);
|
||||
if (base == nullptr)
|
||||
base = dram;
|
||||
if (ci->params.count(ctx->idf("INIT%c", 'A' + i))) {
|
||||
auto orig_init = ci->params.at(ctx->idf("INIT%c", 'A' + i)).extract(0, 64).as_bits();
|
||||
std::string init;
|
||||
for (int k = 0; k < 32; k++) {
|
||||
init.push_back(orig_init.at(k * 2 + j));
|
||||
}
|
||||
dram->params[id_INIT] = Property::from_string(init);
|
||||
if (ci->params.count(ctx->idf("INIT_%c", 'A' + i))) {
|
||||
// De-interleave the 64-bit INIT (bit k*2+j is bit j
|
||||
// of entry k) into this RAMD32's 32 bits. Slice the
|
||||
// canonical bit string ('0'/'1' chars, LSB first) -
|
||||
// as_bits() gives raw bools, which are not valid
|
||||
// Property string characters.
|
||||
Property orig_init = ci->params.at(ctx->idf("INIT_%c", 'A' + i)).extract(0, 64);
|
||||
Property init;
|
||||
init.is_string = false;
|
||||
for (int k = 0; k < 32; k++)
|
||||
init.str.push_back(orig_init.str.at(k * 2 + j));
|
||||
init.update_intval();
|
||||
dram->params[id_INIT] = init;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue