diff options
-rw-r--r-- | nexus/arch.cc | 11 | ||||
-rw-r--r-- | nexus/arch.h | 2 | ||||
-rw-r--r-- | nexus/constids.inc | 21 | ||||
-rw-r--r-- | nexus/fasm.cc | 18 | ||||
-rw-r--r-- | nexus/pack.cc | 57 | ||||
-rw-r--r-- | nexus/pins.cc | 11 |
6 files changed, 116 insertions, 4 deletions
diff --git a/nexus/arch.cc b/nexus/arch.cc index f222a5ad..dbc12c13 100644 --- a/nexus/arch.cc +++ b/nexus/arch.cc @@ -619,6 +619,10 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const bb.x0 = std::max<int>(0, bb.x0 - 6); bb.x1 = std::min<int>(chip_info->width, bb.x1 + 6); } + if (lram_wires.count(src) || lram_wires.count(dst)) { + bb.y0 = std::max<int>(0, bb.y0 - 7); + bb.y1 = std::min<int>(chip_info->width, bb.y1 + 7); + } return bb; } @@ -669,6 +673,13 @@ void Arch::pre_routing() dsp_wires.insert(wire); } } + if (ci->type == id_LRAM_CORE) { + for (auto port : sorted_ref(ci->ports)) { + WireId wire = getBelPinWire(ci->bel, port.first); + if (wire != WireId()) + lram_wires.insert(wire); + } + } } } diff --git a/nexus/arch.h b/nexus/arch.h index d4d4799e..c1a5fcde 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -1363,7 +1363,7 @@ struct Arch : BaseCtx // for better DSP bounding boxes void pre_routing(); - std::unordered_set<WireId> dsp_wires; + std::unordered_set<WireId> dsp_wires, lram_wires; // ------------------------------------------------- diff --git a/nexus/constids.inc b/nexus/constids.inc index f8939263..e4901692 100644 --- a/nexus/constids.inc +++ b/nexus/constids.inc @@ -443,3 +443,24 @@ X(DIVF) X(REF_MMD_DIG) X(FBK_MMD_DIG) X(CLKMUX_FB) + +X(LRAM_CORE) + +X(EBR_SP_EN) +X(ECC_BYTE_SEL) +X(CS) +X(CSA) +X(CSB) +X(CSR) +X(CSW) +X(OCEA) +X(OCEB) +X(RSTR) +X(DPS) +X(IGN) +X(INITN) +X(STDBYN) +X(TBISTN) +X(WE) +X(CEOUTA) +X(CEOUTB) diff --git a/nexus/fasm.cc b/nexus/fasm.cc index fcbe0b8c..0c53e836 100644 --- a/nexus/fasm.cc +++ b/nexus/fasm.cc @@ -596,6 +596,22 @@ struct NexusFasmWriter } pop(); } + // Write out config for an LRAM_CORE cell + void write_lram(const CellInfo *cell) + { + BelId bel = cell->bel; + push_bel(bel); + write_enum(cell, "ASYNC_RST_RELEASE", "SYNC"); + write_enum(cell, "EBR_SP_EN", "DISABLE"); + write_enum(cell, "ECC_BYTE_SEL", "ECC_EN"); + write_enum(cell, "GSR", "DISABLED"); + write_enum(cell, "OUT_REGMODE_A", "NO_REG"); + write_enum(cell, "OUT_REGMODE_B", "NO_REG"); + write_enum(cell, "RESETMODE", "SYNC"); + write_enum(cell, "UNALIGNED_READ", "DISABLE"); + write_cell_muxes(cell); + pop(); + } // Write out FASM for unused bels where needed void write_unused() { @@ -710,6 +726,8 @@ struct NexusFasmWriter write_dsp(ci); else if (ci->type == id_PLL_CORE) write_pll(ci); + else if (ci->type == id_LRAM_CORE) + write_lram(ci); blank(); } // Write config for unused bels diff --git a/nexus/pack.cc b/nexus/pack.cc index eb1ac560..b1642153 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -1024,8 +1024,9 @@ struct NexusPacker { // Convert primitives from their non-CORE variant to their CORE variant static const std::unordered_map<IdString, IdString> prim_map = { - {id_OSCA, id_OSC_CORE}, {id_DP16K, id_DP16K_MODE}, {id_PDP16K, id_PDP16K_MODE}, - {id_PDPSC16K, id_PDPSC16K_MODE}, {id_SP16K, id_SP16K_MODE}, {id_FIFO16K, id_FIFO16K_MODE}, + {id_OSCA, id_OSC_CORE}, {id_DP16K, id_DP16K_MODE}, {id_PDP16K, id_PDP16K_MODE}, + {id_PDPSC16K, id_PDPSC16K_MODE}, {id_SP16K, id_SP16K_MODE}, {id_FIFO16K, id_FIFO16K_MODE}, + {id_SP512K, id_SP512K_MODE}, {id_DPSC512K, id_DPSC512K_MODE}, {id_PDPSC512K, id_PDPSC512K_MODE}, {id_PLL, id_PLL_CORE}, }; @@ -1092,6 +1093,57 @@ struct NexusPacker } } + void pack_lram() + { + std::unordered_map<IdString, XFormRule> lram_rules; + lram_rules[id_SP512K_MODE].new_type = id_LRAM_CORE; + lram_rules[id_SP512K_MODE].set_params.emplace_back(id_EBR_SP_EN, std::string("ENABLE")); + lram_rules[id_SP512K_MODE].port_xform[id_CE] = id_CEA; + lram_rules[id_SP512K_MODE].port_xform[id_CS] = id_CSA; + lram_rules[id_SP512K_MODE].port_xform[id_WE] = id_WEA; + lram_rules[id_SP512K_MODE].port_xform[id_RSTOUT] = id_RSTA; + lram_rules[id_SP512K_MODE].port_xform[id_CEOUT] = id_OCEA; + add_bus_xform(lram_rules[id_SP512K_MODE], "DI", "DIA", 32); + add_bus_xform(lram_rules[id_SP512K_MODE], "DO", "DOA", 32); + add_bus_xform(lram_rules[id_SP512K_MODE], "AD", "ADA", 14); + add_bus_xform(lram_rules[id_SP512K_MODE], "BYTEEN_N", "BENA_N", 4); + + lram_rules[id_PDPSC512K_MODE].new_type = id_LRAM_CORE; + lram_rules[id_PDPSC512K_MODE].port_xform[id_CEW] = id_CEA; + lram_rules[id_PDPSC512K_MODE].port_xform[id_CSW] = id_CSA; + lram_rules[id_PDPSC512K_MODE].port_xform[id_CER] = id_CEB; + lram_rules[id_PDPSC512K_MODE].port_xform[id_CSR] = id_CSB; + lram_rules[id_PDPSC512K_MODE].port_xform[id_WE] = id_WEA; + lram_rules[id_PDPSC512K_MODE].port_xform[id_RSTR] = id_RSTB; + add_bus_xform(lram_rules[id_PDPSC512K_MODE], "DI", "DIA", 32); + add_bus_xform(lram_rules[id_PDPSC512K_MODE], "DO", "DOB", 32); + add_bus_xform(lram_rules[id_PDPSC512K_MODE], "ADW", "ADA", 14); + add_bus_xform(lram_rules[id_PDPSC512K_MODE], "ADR", "ADB", 14); + add_bus_xform(lram_rules[id_PDPSC512K_MODE], "BYTEEN_N", "BENA_N", 4); + + lram_rules[id_DPSC512K_MODE].new_type = id_LRAM_CORE; + lram_rules[id_DPSC512K_MODE].port_xform[id_CEOUTA] = id_OCEA; + lram_rules[id_DPSC512K_MODE].port_xform[id_CEOUTB] = id_OCEB; + + log_info("Packing LRAM...\n"); + generic_xform(lram_rules, true); + + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + if (ci->type != id_LRAM_CORE) + continue; + for (int i = 0; i < 0x80; i++) { + // FIXME: support on the prjoxide side + std::string name = stringf("INITVAL_%02X", i); + if (!ci->params.count(ctx->id(name))) + continue; + if (ci->params.at(ctx->id(name)).str.find_last_not_of("0x") == std::string::npos) + continue; + log_error("LRAM initialisation is currently unsupported (prjoxide limitation).\n"); + } + } + } + void pack_widefn() { std::vector<CellInfo *> widefns; @@ -1883,6 +1935,7 @@ struct NexusPacker pack_dsps(); convert_prims(); pack_bram(); + pack_lram(); pack_lutram(); pack_carries(); pack_widefn(); diff --git a/nexus/pins.cc b/nexus/pins.cc index 05bffb1e..5586aeea 100644 --- a/nexus/pins.cc +++ b/nexus/pins.cc @@ -168,7 +168,16 @@ static const std::unordered_map<IdString, Arch::CellPinsData> base_cell_pin_data {id_ENEXT, PINSTYLE_DEDI}, {{}, PINSTYLE_CIB}, }}, -}; + {id_LRAM_CORE, + { + {id_CLK, PINSTYLE_CLK}, {id_CEA, PINSTYLE_CE}, {id_CEB, PINSTYLE_CE}, + {id_OCEA, PINSTYLE_PU}, {id_OCEB, PINSTYLE_PU}, {id_CSA, PINSTYLE_CE}, + {id_CSB, PINSTYLE_CE}, {id_RSTA, PINSTYLE_LSR}, {id_RSTB, PINSTYLE_LSR}, + {id_WEA, PINSTYLE_LSR}, {id_WEB, PINSTYLE_LSR}, {id_IGN, PINSTYLE_PU}, + {id_INITN, PINSTYLE_PU}, {id_STDBYN, PINSTYLE_PU}, {id_TBISTN, PINSTYLE_PU}, + {id_SCANCLK, PINSTYLE_DEDI}, {id_SCANRST, PINSTYLE_DEDI}, {id_OPCGLDCK, PINSTYLE_DEDI}, + {{}, PINSTYLE_CIB}, + }}}; } // namespace void Arch::init_cell_pin_data() { cell_pins_db = base_cell_pin_data; } |