From 885fae8236c0bdb73c99b0605e1d7bdf14000dd4 Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 1 Oct 2018 16:43:22 +0100 Subject: ecp5: Handling of DRAM initialisation and wiring Signed-off-by: David Shah --- ecp5/cells.cc | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/ecp5/cells.cc b/ecp5/cells.cc index 048db1d7..ba2d511f 100644 --- a/ecp5/cells.cc +++ b/ecp5/cells.cc @@ -252,13 +252,49 @@ void dram_to_ramw(Context *ctx, CellInfo *ram, CellInfo *lc) replace_port(ram, ctx->id("DI[3]"), lc, ctx->id("B1")); } +static unsigned get_dram_init(const Context *ctx, const CellInfo *ram, int bit) +{ + const std::string &idata = str_or_default(ram->params, ctx->id("INITVAL"), + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + NPNR_ASSERT(idata.length() == 64); + unsigned value = 0; + for (int i = 0; i < 16; i++) { + char c = idata.at(63 - (4 * i + bit)); + if (c == '1') + value |= (i << i); + else + NPNR_ASSERT(c == '0' || c == 'x'); + } + return value; +} + void dram_to_ram_slice(Context *ctx, CellInfo *ram, CellInfo *lc, CellInfo *ramw, int index) { lc->params[ctx->id("MODE")] = "DPRAM"; lc->params[ctx->id("WREMUX")] = str_or_default(ram->params, ctx->id("WREMUX"), "WRE"); lc->params[ctx->id("WCKMUX")] = str_or_default(ram->params, ctx->id("WCKMUX"), "WCK"); - // TODO: INIT + unsigned permuted_init0 = 0, permuted_init1 = 0; + unsigned init0 = get_dram_init(ctx, ramw, index * 2), init1 = get_dram_init(ctx, ramw, index * 2 + 1); + + for (int i = 0; i < 16; i++) { + int permuted_addr = 0; + if (i & 1) + permuted_addr |= 8; + if (i & 2) + permuted_addr |= 2; + if (i & 4) + permuted_addr |= 4; + if (i & 8) + permuted_addr |= 1; + if (init0 & (1 << permuted_addr)) + permuted_init0 |= (1 << i); + if (init1 & (1 << permuted_addr)) + permuted_init1 |= (1 << i); + } + + lc->params[ctx->id("LUT0_INITVAL")] = std::to_string(permuted_init0); + lc->params[ctx->id("LUT1_INITVAL")] = std::to_string(permuted_init1); if (ram->ports.count(ctx->id("RAD[0]"))) { connect_port(ctx, ram->ports.at(ctx->id("RAD[0]")).net, lc, ctx->id("D0")); @@ -281,6 +317,28 @@ void dram_to_ram_slice(Context *ctx, CellInfo *ram, CellInfo *lc, CellInfo *ramw connect_port(ctx, ram->ports.at(ctx->id("WRE")).net, lc, ctx->id("WRE")); if (ram->ports.count(ctx->id("WCK"))) connect_port(ctx, ram->ports.at(ctx->id("WCK")).net, lc, ctx->id("WCK")); + + connect_ports(ctx, ramw, id_WADO0, lc, id_WAD0); + connect_ports(ctx, ramw, id_WADO1, lc, id_WAD1); + connect_ports(ctx, ramw, id_WADO2, lc, id_WAD2); + connect_ports(ctx, ramw, id_WADO3, lc, id_WAD3); + + if (index == 0) { + connect_ports(ctx, ramw, id_WDO0, lc, id_WD0); + connect_ports(ctx, ramw, id_WDO1, lc, id_WD1); + + replace_port(ram, ctx->id("DO[0]"), lc, id_F0); + replace_port(ram, ctx->id("DO[1]"), lc, id_F1); + + } else if (index == 1) { + connect_ports(ctx, ramw, id_WDO2, lc, id_WD0); + connect_ports(ctx, ramw, id_WDO3, lc, id_WD1); + + replace_port(ram, ctx->id("DO[2]"), lc, id_F0); + replace_port(ram, ctx->id("DO[3]"), lc, id_F1); + } else { + NPNR_ASSERT_FALSE("bad DPRAM index"); + } } NEXTPNR_NAMESPACE_END -- cgit v1.2.3