Merge pull request #528 from YosysHQ/dave/nexus-lram

nexus: Add basic LRAM support
This commit is contained in:
David Shah 2020-12-08 09:26:09 +00:00 committed by GitHub
commit ca08add9c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 166 additions and 15 deletions

View File

@ -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);
}
}
}
}

View File

@ -838,18 +838,20 @@ enum CellPinStyle
PINBIT_1 = 0x2000, // pin has an explicit bit that must be set if tied to 1
PINBIT_CIBMUX = 0x4000, // pin's CIBMUX must be floating for pin to be 1
PINSTYLE_NONE = 0x0000, // default
PINSTYLE_CIB = 0x4012, // 'CIB' signal, floats high but explicitly zeroed if not used
PINSTYLE_CLK = 0x0107, // CLK type signal, invertible and defaults to disconnected
PINSTYLE_CE = 0x0027, // CE type signal, invertible and defaults to enabled
PINSTYLE_LSR = 0x0017, // LSR type signal, invertible and defaults to not reset
PINSTYLE_DEDI = 0x0000, // dedicated signals, leave alone
PINSTYLE_PU = 0x4022, // signals that float high and default high
PINSTYLE_T = 0x4027, // PIO 'T' signal
PINSTYLE_NONE = 0x0000, // default
PINSTYLE_CIB = 0x4012, // 'CIB' signal, floats high but explicitly zeroed if not used
PINSTYLE_CLK = 0x0107, // CLK type signal, invertible and defaults to disconnected
PINSTYLE_CE = 0x0027, // CE type signal, invertible and defaults to enabled
PINSTYLE_LSR = 0x0017, // LSR type signal, invertible and defaults to not reset
PINSTYLE_DEDI = 0x0000, // dedicated signals, leave alone
PINSTYLE_PU = 0x4022, // signals that float high and default high
PINSTYLE_PU_NONCIB = 0x0022, // signals that float high and default high
PINSTYLE_T = 0x4027, // PIO 'T' signal
PINSTYLE_ADLSB = 0x4017, // special case of the EBR address MSBs
PINSTYLE_INV_PD = 0x0017, // invertible, pull down by default
PINSTYLE_INV_PU = 0x4027, // invertible, pull up by default
PINSTYLE_ADLSB = 0x4017, // special case of the EBR address MSBs
PINSTYLE_INV_PD = 0x0017, // invertible, pull down by default
PINSTYLE_INV_PD_CIB = 0x4017, // invertible, pull down by default
PINSTYLE_INV_PU = 0x4027, // invertible, pull up by default
PINSTYLE_IOL_CE = 0x2027, // CE type signal, with explicit 'const-1' config bit
PINSTYLE_GATE = 0x1011, // gated signal that defaults to 0
@ -1363,7 +1365,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;
// -------------------------------------------------

View File

@ -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)

View File

@ -596,6 +596,44 @@ 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", "BYTE_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();
blank();
Loc l = ctx->getBelLocation(bel);
push(stringf("IP_LRAM_CORE_R%dC%d", l.y, l.x));
for (int i = 0; i < 128; 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("5120'h%s", value.c_str());
} else {
// True Verilog bitvector
value = stringf("5120'b%s", prop.str.c_str());
}
write_bit(stringf("INITVAL_%02X[5119:0] = %s", i, value.c_str()));
}
pop();
}
// Write out FASM for unused bels where needed
void write_unused()
{
@ -710,6 +748,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

View File

@ -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,60 @@ 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;
if (str_or_default(ci->params, ctx->id("ECC_BYTE_SEL"), "BYTE_EN") == "BYTE_EN")
continue;
for (int i = 0; i < 0x80; i++) {
// FIXME: document ECC and remove this DRC
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 in ECC mode (to disable ECC, set ECC_BYTE_SEL "
"to BYTE_EN).\n");
}
}
}
void pack_widefn()
{
std::vector<CellInfo *> widefns;
@ -1883,6 +1938,7 @@ struct NexusPacker
pack_dsps();
convert_prims();
pack_bram();
pack_lram();
pack_lutram();
pack_carries();
pack_widefn();

View File

@ -168,7 +168,28 @@ 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_PU_NONCIB},
{id_CEB, PINSTYLE_PU_NONCIB},
{id_OCEA, PINSTYLE_PU},
{id_OCEB, PINSTYLE_PU},
{id_CSA, PINSTYLE_PU},
{id_CSB, PINSTYLE_PU},
{id_RSTA, PINSTYLE_LSR},
{id_RSTB, PINSTYLE_LSR},
{id_WEA, PINSTYLE_INV_PD_CIB},
{id_WEB, PINSTYLE_INV_PD_CIB},
{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; }