nexus: Generate FASM files that can be used standalone
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
901bf2bb1e
commit
c80144b7f0
@ -77,6 +77,14 @@ Arch::Arch(ArchArgs args) : args(args)
|
||||
log_error("Unknown device string '%s' (expected device name like 'LIFCL-40-8SG72C')\n", args.device.c_str());
|
||||
package = args.device.substr(last_sep + 2, (package_end - (last_sep + 2)) + 1);
|
||||
rating = args.device.substr(package_end + 1);
|
||||
|
||||
// Check for 'ES' part
|
||||
if (rating.size() > 1 && rating.substr(1) == "ES") {
|
||||
variant = "ES";
|
||||
} else {
|
||||
variant = "";
|
||||
}
|
||||
|
||||
// Load database
|
||||
std::string chipdb = stringf("nexus/chipdb-%s.bin", family.c_str());
|
||||
auto db_ptr = reinterpret_cast<const RelPtr<DatabasePOD> *>(get_chipdb(chipdb));
|
||||
|
@ -826,7 +826,7 @@ struct ArchArgs
|
||||
struct Arch : BaseCtx
|
||||
{
|
||||
ArchArgs args;
|
||||
std::string family, device, package, speed, rating;
|
||||
std::string family, device, package, speed, rating, variant;
|
||||
Arch(ArchArgs args);
|
||||
|
||||
// -------------------------------------------------
|
||||
|
@ -155,3 +155,11 @@ X(IOPAD)
|
||||
X(PADDO)
|
||||
X(PADDI)
|
||||
X(PADDT)
|
||||
|
||||
X(PREADD9_CORE)
|
||||
X(MULT9_CORE)
|
||||
X(MULT18_CORE)
|
||||
X(REG18_CORE)
|
||||
X(MULT18X36_CORE)
|
||||
X(MULT36_CORE)
|
||||
X(ACC54_CORE)
|
||||
|
102
nexus/fasm.cc
102
nexus/fasm.cc
@ -67,6 +67,13 @@ struct NexusFasmWriter
|
||||
out << name << std::endl;
|
||||
}
|
||||
}
|
||||
// Write a FASM attribute
|
||||
void write_attribute(const std::string &key, const std::string &value, bool str = true)
|
||||
{
|
||||
std::string qu = str ? "\"" : "";
|
||||
out << "{ " << key << "=" << qu << value << qu << " }" << std::endl;
|
||||
last_was_blank = false;
|
||||
}
|
||||
// Write a FASM comment
|
||||
void write_comment(const std::string &cmt) { out << "# " << cmt << std::endl; }
|
||||
// Write a FASM bitvector; optionally inverting the values in the process
|
||||
@ -161,6 +168,12 @@ struct NexusFasmWriter
|
||||
std::string s = stringf("R%dC%d_%s", r, c, ctx->nameOf(ctx->bel_data(bel).name));
|
||||
push(s);
|
||||
}
|
||||
// Push a bel's group and name
|
||||
void push_bel(BelId bel)
|
||||
{
|
||||
push_belgroup(bel);
|
||||
fasm_ctx.back() += stringf(".%s", ctx->nameOf(ctx->bel_data(bel).name));
|
||||
}
|
||||
// Write out a pip in tile.dst.src format
|
||||
void write_pip(PipId pip)
|
||||
{
|
||||
@ -284,12 +297,15 @@ struct NexusFasmWriter
|
||||
write_cell_muxes(cell);
|
||||
pop(2);
|
||||
}
|
||||
|
||||
std::unordered_set<BelId> used_io;
|
||||
|
||||
// Write config for an SEIO33_CORE cell
|
||||
void write_io33(const CellInfo *cell)
|
||||
{
|
||||
BelId bel = cell->bel;
|
||||
push_belgroup(bel);
|
||||
push_belname(bel);
|
||||
used_io.insert(bel);
|
||||
push_bel(bel);
|
||||
const NetInfo *t = get_net_or_empty(cell, id_T);
|
||||
auto tmux = ctx->get_cell_pinmux(cell, id_T);
|
||||
bool is_input = false, is_output = false;
|
||||
@ -302,14 +318,14 @@ struct NexusFasmWriter
|
||||
write_bit(stringf("BASE_TYPE.%s_%s", iodir, str_or_default(cell->attrs, id_IO_TYPE, "LVCMOS33").c_str()));
|
||||
write_ioattr(cell, "PULLMODE", "NONE");
|
||||
write_cell_muxes(cell);
|
||||
pop(2);
|
||||
pop();
|
||||
}
|
||||
// Write config for an SEIO18_CORE cell
|
||||
void write_io18(const CellInfo *cell)
|
||||
{
|
||||
BelId bel = cell->bel;
|
||||
push_belgroup(bel);
|
||||
push_belname(bel);
|
||||
used_io.insert(bel);
|
||||
push_bel(bel);
|
||||
push("SEIO18");
|
||||
const NetInfo *t = get_net_or_empty(cell, id_T);
|
||||
auto tmux = ctx->get_cell_pinmux(cell, id_T);
|
||||
@ -323,7 +339,7 @@ struct NexusFasmWriter
|
||||
write_bit(stringf("BASE_TYPE.%s_%s", iodir, str_or_default(cell->attrs, id_IO_TYPE, "LVCMOS18H").c_str()));
|
||||
write_ioattr(cell, "PULLMODE", "NONE");
|
||||
write_cell_muxes(cell);
|
||||
pop(3);
|
||||
pop(2);
|
||||
}
|
||||
// Write config for an OSC_CORE cell
|
||||
void write_osc(const CellInfo *cell)
|
||||
@ -341,9 +357,79 @@ struct NexusFasmWriter
|
||||
write_cell_muxes(cell);
|
||||
pop(2);
|
||||
}
|
||||
// Write out FASM for unused bels where needed
|
||||
void write_unused()
|
||||
{
|
||||
write_comment("# Unused bels");
|
||||
|
||||
// DSP primitives are configured to a default mode; even if unused
|
||||
static const std::unordered_map<IdString, std::vector<std::string>> dsp_defconf = {
|
||||
{id_MULT9_CORE,
|
||||
{
|
||||
"GSR.ENABLED",
|
||||
"MODE.NONE",
|
||||
"RSTAMUX.RSTA",
|
||||
"RSTPMUX.RSTP",
|
||||
}},
|
||||
{id_PREADD9_CORE,
|
||||
{
|
||||
"GSR.ENABLED",
|
||||
"MODE.NONE",
|
||||
"RSTBMUX.RSTB",
|
||||
"RSTCLMUX.RSTCL",
|
||||
}},
|
||||
{id_REG18_CORE,
|
||||
{
|
||||
"GSR.ENABLED",
|
||||
"MODE.NONE",
|
||||
"RSTPMUX.RSTP",
|
||||
}},
|
||||
{id_ACC54_CORE,
|
||||
{
|
||||
"ACCUBYPS.BYPASS",
|
||||
"MODE.NONE",
|
||||
}},
|
||||
};
|
||||
|
||||
for (BelId bel : ctx->getBels()) {
|
||||
IdString type = ctx->getBelType(bel);
|
||||
if (type == id_SEIO33_CORE && !used_io.count(bel)) {
|
||||
push_bel(bel);
|
||||
write_bit("BASE_TYPE.NONE");
|
||||
pop();
|
||||
blank();
|
||||
} else if (type == id_SEIO18_CORE && !used_io.count(bel)) {
|
||||
push_bel(bel);
|
||||
push("SEIO18");
|
||||
write_bit("BASE_TYPE.NONE");
|
||||
pop(2);
|
||||
blank();
|
||||
} else if (dsp_defconf.count(type) && ctx->getBoundBelCell(bel) == nullptr) {
|
||||
push_bel(bel);
|
||||
for (const auto &cbit : dsp_defconf.at(type))
|
||||
write_bit(cbit);
|
||||
pop();
|
||||
blank();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Write out placeholder bankref config
|
||||
void write_bankcfg()
|
||||
{
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (i >= 3 && i <= 5)
|
||||
continue; // 1.8V banks, skip for now
|
||||
write_bit(stringf("GLOBAL.BANK%d.VCC.3V3", i));
|
||||
}
|
||||
blank();
|
||||
}
|
||||
// Write out FASM for the whole design
|
||||
void operator()()
|
||||
{
|
||||
// Write device config
|
||||
write_attribute("oxide.device", ctx->device);
|
||||
write_attribute("oxide.device_variant", ctx->variant);
|
||||
blank();
|
||||
// Write routing
|
||||
for (auto n : sorted(ctx->nets)) {
|
||||
write_net(n.second);
|
||||
@ -364,6 +450,10 @@ struct NexusFasmWriter
|
||||
write_osc(ci);
|
||||
blank();
|
||||
}
|
||||
// Write config for unused bels
|
||||
write_unused();
|
||||
// Write bank config
|
||||
write_bankcfg();
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
Loading…
Reference in New Issue
Block a user