diff options
author | David Shah <dave@ds0.me> | 2020-10-22 14:22:00 +0100 |
---|---|---|
committer | David Shah <dave@ds0.me> | 2020-11-30 08:45:27 +0000 |
commit | 27ecaf3e88730f2e295345342cec864801dbd851 (patch) | |
tree | 2e427249cdbf6289cc32d5ad7e415e204261bd98 /nexus | |
parent | 4503608c7c81dc04e837bce326deec0c3fcf7caa (diff) | |
download | nextpnr-27ecaf3e88730f2e295345342cec864801dbd851.tar.gz nextpnr-27ecaf3e88730f2e295345342cec864801dbd851.tar.bz2 nextpnr-27ecaf3e88730f2e295345342cec864801dbd851.zip |
nexus: EBR FASM generation
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'nexus')
-rw-r--r-- | nexus/fasm.cc | 78 | ||||
-rw-r--r-- | nexus/pack.cc | 10 |
2 files changed, 88 insertions, 0 deletions
diff --git a/nexus/fasm.cc b/nexus/fasm.cc index 031cd9b3..60ff1aca 100644 --- a/nexus/fasm.cc +++ b/nexus/fasm.cc @@ -93,6 +93,16 @@ struct NexusFasmWriter bits[i] = (value & (1ULL << i)) != 0; write_vector(name, bits, invert); } + // Write an int vector param + void write_int_vector_param(const CellInfo *cell, const std::string &name, uint64_t defval, int width, + bool invert = false) + { + uint64_t value = int_or_default(cell->params, ctx->id(name), defval); + std::vector<bool> bits(width, false); + for (int i = 0; i < width; i++) + bits[i] = (value & (1ULL << i)) != 0; + write_vector(stringf("%s[%d:0]", name.c_str(), width - 1), bits, invert); + } // Look up an enum value in a cell's parameters and write it to the FASM in name.value format void write_enum(const CellInfo *cell, const std::string &name, const std::string &defval = "") { @@ -368,6 +378,72 @@ struct NexusFasmWriter write_cell_muxes(cell); pop(2); } + // Write config for an OXIDE_EBR cell + void write_bram(const CellInfo *cell) + { + // EBR configuration + BelId bel = cell->bel; + push_bel(bel); + int wid = int_or_default(cell->params, id_WID, 0); + std::string mode = str_or_default(cell->params, id_MODE, ""); + + write_bit(stringf("MODE.%s_MODE", mode.c_str())); + write_enum(cell, "GSR", "DISABLED"); + + write_int_vector("WID[10:0]", wid, 11); + + push(stringf("%s_MODE", mode.c_str())); + + if (mode == "DP16K") { + write_int_vector_param(cell, "CSDECODE_A", 7, 3); + write_int_vector_param(cell, "CSDECODE_B", 7, 3); + write_enum(cell, "ASYNC_RST_RELEASE_A"); + write_enum(cell, "ASYNC_RST_RELEASE_B"); + write_enum(cell, "DATA_WIDTH_A"); + write_enum(cell, "DATA_WIDTH_B"); + write_enum(cell, "OUTREG_A"); + write_enum(cell, "OUTREG_B"); + write_enum(cell, "RESETMODE_A"); + write_enum(cell, "RESETMODE_B"); + } else if (mode == "PDP16K" || mode == "PDPSC16K") { + write_int_vector_param(cell, "CSDECODE_W", 7, 3); + write_int_vector_param(cell, "CSDECODE_R", 7, 3); + write_enum(cell, "ASYNC_RST_RELEASE"); + write_enum(cell, "DATA_WIDTH_W"); + write_enum(cell, "DATA_WIDTH_R"); + write_enum(cell, "OUTREG"); + write_enum(cell, "RESETMODE"); + } + + pop(); + push("DP16K_MODE"); // muxes always use the DP16K perspective + write_cell_muxes(cell); + pop(2); + blank(); + + // EBR initialisation + if (wid > 0) { + push(stringf("IP_EBR_WID%d", wid)); + for (int i = 0; i < 64; i++) { + IdString param = ctx->id(stringf("INITVAL_%02X", i)); + if (!cell->params.count(param)) + continue; + auto &prop = cell->params.at(param); + std::string value; + if (prop.is_string) { + NPNR_ASSERT(prop.str.substr(0, 2) == "0x"); + // Lattice-style hex string + value = prop.str.substr(2); + value = stringf("320'h%s", value.c_str()); + } else { + // True Verilog bitvector + value = stringf("320'b%s", prop.str.c_str()); + } + write_bit(stringf("INITVAL_%02X[319:0] = %s", i, value.c_str())); + } + pop(); + } + } // Write out FASM for unused bels where needed void write_unused() { @@ -461,6 +537,8 @@ struct NexusFasmWriter write_io18(ci); else if (ci->type == id_OSC_CORE) write_osc(ci); + else if (ci->type == id_OXIDE_EBR) + write_bram(ci); blank(); } // Write config for unused bels diff --git a/nexus/pack.cc b/nexus/pack.cc index fa2c78e8..2cef0687 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -1047,6 +1047,16 @@ struct NexusPacker log_info("Packing BRAM...\n"); generic_xform(bram_rules, true); + + int wid = 2; + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + if (ci->type != id_OXIDE_EBR) + continue; + if (ci->params.count(id_WID)) + continue; + ci->params[id_WID] = wid++; + } } explicit NexusPacker(Context *ctx) : ctx(ctx) {} |