nexus: Add basic LRAM support (no init)
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
86e6a2225c
commit
270efdca85
@ -619,6 +619,10 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const
|
|||||||
bb.x0 = std::max<int>(0, bb.x0 - 6);
|
bb.x0 = std::max<int>(0, bb.x0 - 6);
|
||||||
bb.x1 = std::min<int>(chip_info->width, bb.x1 + 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;
|
return bb;
|
||||||
}
|
}
|
||||||
@ -669,6 +673,13 @@ void Arch::pre_routing()
|
|||||||
dsp_wires.insert(wire);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1363,7 +1363,7 @@ struct Arch : BaseCtx
|
|||||||
|
|
||||||
// for better DSP bounding boxes
|
// for better DSP bounding boxes
|
||||||
void pre_routing();
|
void pre_routing();
|
||||||
std::unordered_set<WireId> dsp_wires;
|
std::unordered_set<WireId> dsp_wires, lram_wires;
|
||||||
|
|
||||||
// -------------------------------------------------
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
@ -443,3 +443,24 @@ X(DIVF)
|
|||||||
X(REF_MMD_DIG)
|
X(REF_MMD_DIG)
|
||||||
X(FBK_MMD_DIG)
|
X(FBK_MMD_DIG)
|
||||||
X(CLKMUX_FB)
|
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)
|
||||||
|
@ -596,6 +596,22 @@ struct NexusFasmWriter
|
|||||||
}
|
}
|
||||||
pop();
|
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
|
// Write out FASM for unused bels where needed
|
||||||
void write_unused()
|
void write_unused()
|
||||||
{
|
{
|
||||||
@ -710,6 +726,8 @@ struct NexusFasmWriter
|
|||||||
write_dsp(ci);
|
write_dsp(ci);
|
||||||
else if (ci->type == id_PLL_CORE)
|
else if (ci->type == id_PLL_CORE)
|
||||||
write_pll(ci);
|
write_pll(ci);
|
||||||
|
else if (ci->type == id_LRAM_CORE)
|
||||||
|
write_lram(ci);
|
||||||
blank();
|
blank();
|
||||||
}
|
}
|
||||||
// Write config for unused bels
|
// Write config for unused bels
|
||||||
|
@ -1024,8 +1024,9 @@ struct NexusPacker
|
|||||||
{
|
{
|
||||||
// Convert primitives from their non-CORE variant to their CORE variant
|
// Convert primitives from their non-CORE variant to their CORE variant
|
||||||
static const std::unordered_map<IdString, IdString> prim_map = {
|
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_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_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},
|
{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()
|
void pack_widefn()
|
||||||
{
|
{
|
||||||
std::vector<CellInfo *> widefns;
|
std::vector<CellInfo *> widefns;
|
||||||
@ -1883,6 +1935,7 @@ struct NexusPacker
|
|||||||
pack_dsps();
|
pack_dsps();
|
||||||
convert_prims();
|
convert_prims();
|
||||||
pack_bram();
|
pack_bram();
|
||||||
|
pack_lram();
|
||||||
pack_lutram();
|
pack_lutram();
|
||||||
pack_carries();
|
pack_carries();
|
||||||
pack_widefn();
|
pack_widefn();
|
||||||
|
@ -168,7 +168,16 @@ static const std::unordered_map<IdString, Arch::CellPinsData> base_cell_pin_data
|
|||||||
{id_ENEXT, PINSTYLE_DEDI},
|
{id_ENEXT, PINSTYLE_DEDI},
|
||||||
{{}, PINSTYLE_CIB},
|
{{}, 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
|
} // namespace
|
||||||
|
|
||||||
void Arch::init_cell_pin_data() { cell_pins_db = base_cell_pin_data; }
|
void Arch::init_cell_pin_data() { cell_pins_db = base_cell_pin_data; }
|
||||||
|
Loading…
Reference in New Issue
Block a user