diff --git a/himbaechel/uarch/xilinx/pack_dram.cc b/himbaechel/uarch/xilinx/pack_dram.cc index 00f9d408..34ed70f9 100644 --- a/himbaechel/uarch/xilinx/pack_dram.cc +++ b/himbaechel/uarch/xilinx/pack_dram.cc @@ -237,7 +237,7 @@ void XilinxPacker::pack_dram() auto &dt = dt_iter->second; DRAMControlSet dcs; 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.we = ci->getPort(id_WE); dcs.wclk_inv = bool_or_default(ci->params, id_IS_WCLK_INVERTED); @@ -302,6 +302,26 @@ void XilinxPacker::pack_dram() 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 address(cs.wa.begin(), cs.wa.begin() + std::min(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); } } else if (cs.memtype == id_RAM32X1D) { @@ -411,6 +431,36 @@ void XilinxPacker::pack_dram() // Decode mux tree using MUXF[78] 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 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 addressw_64(cs.wa.begin(), cs.wa.begin() + std::min(cs.wa.size(), 6)); + // Upper bits of address - feed decode muxes + std::vector addressw_high(cs.wa.begin() + std::min(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); } } diff --git a/himbaechel/uarch/xilinx/xilinx_place.cc b/himbaechel/uarch/xilinx/xilinx_place.cc index d39b94d0..cea618d2 100644 --- a/himbaechel/uarch/xilinx/xilinx_place.cc +++ b/himbaechel/uarch/xilinx/xilinx_place.cc @@ -141,11 +141,11 @@ bool XilinxImpl::xc7_logic_tile_valid(IdString tile_type, const LogicTileStatus mux_cell = lts.cells[(i - 1) << 4 | BEL_F8MUX]; auto mux = get_tags(mux_cell); if (mux) { - if (x_net) + if (!x_net) x_net = mux->mux.sel; else if (x_net != mux->mux.sel) { 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) 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(); return false; }