xilinx: Support single-port LUTRAM variants

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2024-09-26 18:11:01 +02:00
parent 7516b8950a
commit e4dfd4e622
2 changed files with 53 additions and 7 deletions

View File

@ -237,7 +237,7 @@ void XilinxPacker::pack_dram()
auto &dt = dt_iter->second; auto &dt = dt_iter->second;
DRAMControlSet dcs; DRAMControlSet dcs;
for (int i = 0; i < dt.abits; i++) for (int i = 0; i < dt.abits; i++)
dcs.wa.push_back(ci->getPort(ctx->idf(dt.abits <= 6 ? "A%d" : "A[%d]", i))); dcs.wa.push_back(ci->getPort(ctx->idf((dt.abits <= 6 || ci->type == id_RAM128X1S) ? "A%d" : "A[%d]", i)));
dcs.wclk = ci->getPort(id_WCLK); dcs.wclk = ci->getPort(id_WCLK);
dcs.we = ci->getPort(id_WE); dcs.we = ci->getPort(id_WE);
dcs.wclk_inv = bool_or_default(ci->params, id_IS_WCLK_INVERTED); dcs.wclk_inv = bool_or_default(ci->params, id_IS_WCLK_INVERTED);
@ -302,6 +302,26 @@ void XilinxPacker::pack_dram()
z--; z--;
} }
packed_cells.insert(cell->name);
}
} else if (cs.memtype == id_RAM64X1S) {
int z = height - 1;
CellInfo *base = nullptr;
for (auto cell : group.second) {
NPNR_ASSERT(cell->type == id_RAM64X1S); // FIXME
if (z == (height - 1) || (z - 1) < 0) {
z = (height - 1);
base = nullptr;
}
std::vector<NetInfo *> address(cs.wa.begin(), cs.wa.begin() + std::min<size_t>(cs.wa.size(), 6));
CellInfo *ram = create_dram_lut(cell->name.str(ctx) + "/ADDR", base, cs, address, cell->getPort(id_D), cell->getPort(id_O), z);
if (cell->params.count(id_INIT))
ram->params[id_INIT] = cell->params[id_INIT];
if (base == nullptr)
base = ram;
z--;
packed_cells.insert(cell->name); packed_cells.insert(cell->name);
} }
} else if (cs.memtype == id_RAM32X1D) { } else if (cs.memtype == id_RAM32X1D) {
@ -411,6 +431,36 @@ void XilinxPacker::pack_dram()
// Decode mux tree using MUXF[78] // Decode mux tree using MUXF[78]
create_muxf_tree(base, "DPO", dpo_pre, addressr_high, dpo, 0); create_muxf_tree(base, "DPO", dpo_pre, addressr_high, dpo, 0);
packed_cells.insert(ci->name);
}
} else if (cs.memtype.in(id_RAM128X1S, id_RAM256X1S)) {
bool m256 = cs.memtype == id_RAM256X1S;
for (CellInfo *ci : group.second) {
auto init = get_or_default(ci->params, id_INIT, Property(0, m256 ? 256 : 128));
std::vector<NetInfo *> o_pre;
int z = (height - 1);
NetInfo *o = ci->getPort(id_O);
ci->disconnectPort(id_O);
// Low 6 bits of address - connect directly to RAM cells
std::vector<NetInfo *> addressw_64(cs.wa.begin(), cs.wa.begin() + std::min<size_t>(cs.wa.size(), 6));
// Upper bits of address - feed decode muxes
std::vector<NetInfo *> addressw_high(cs.wa.begin() + std::min<size_t>(cs.wa.size(), 6), cs.wa.end());
CellInfo *base = nullptr;
// Combined write address/SPO read cells
for (int i = 0; i < (m256 ? 4 : 2); i++) {
NetInfo *spo_i = create_internal_net(ci->name, stringf("O_%d", i), false);
CellInfo *spr = create_dram_lut(ci->name.str(ctx) + "/ADDR" + std::to_string(i), base, cs,
addressw_64, ci->getPort(id_D), spo_i, z);
if (base == nullptr)
base = spr;
o_pre.push_back(spo_i);
spr->params[id_INIT] = init.extract(i * 64, 64);
z--;
}
// Decode mux tree using MUXF[78]
create_muxf_tree(base, "O", o_pre, addressw_high, o, m256 ? 4 : 2);
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
} }
} }

View File

@ -141,11 +141,11 @@ bool XilinxImpl::xc7_logic_tile_valid(IdString tile_type, const LogicTileStatus
mux_cell = lts.cells[(i - 1) << 4 | BEL_F8MUX]; mux_cell = lts.cells[(i - 1) << 4 | BEL_F8MUX];
auto mux = get_tags(mux_cell); auto mux = get_tags(mux_cell);
if (mux) { if (mux) {
if (x_net) if (!x_net)
x_net = mux->mux.sel; x_net = mux->mux.sel;
else if (x_net != mux->mux.sel) { else if (x_net != mux->mux.sel) {
DBG(); DBG();
return false; // Memory and SRLs only valid in SLICEMs return false; // conflict between existing X use and mux select
} }
} }
@ -197,10 +197,6 @@ bool XilinxImpl::xc7_logic_tile_valid(IdString tile_type, const LogicTileStatus
if (x_net == nullptr) if (x_net == nullptr)
x_net = ff2->ff.d; x_net = ff2->ff.d;
else if (x_net != ff2->ff.d) { else if (x_net != ff2->ff.d) {
#ifdef DEBUG_VALIDITY
log_info("%s %s %s %s %s\n", nameOf(lut6), nameOf(ff1), nameOf(lut5), nameOf(ff2),
nameOf(drv.cell));
#endif
DBG(); DBG();
return false; return false;
} }