xilinx: Support single-port LUTRAM variants
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
7516b8950a
commit
e4dfd4e622
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user