aboutsummaryrefslogtreecommitdiffstats
path: root/nexus/fasm.cc
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2020-01-10 21:35:21 +0000
committerDavid Shah <dave@ds0.me>2020-11-30 08:45:27 +0000
commit689922bc21ec151ebf495813b639aed4758f9587 (patch)
tree718a6cacd3549b8d2bb04049db68fd0c0e9575a8 /nexus/fasm.cc
parent2c49f812d9c2bb3df423b8e6b510be8e73948e38 (diff)
downloadnextpnr-689922bc21ec151ebf495813b639aed4758f9587.tar.gz
nextpnr-689922bc21ec151ebf495813b639aed4758f9587.tar.bz2
nextpnr-689922bc21ec151ebf495813b639aed4758f9587.zip
nexus: Add FASM export for comb logic and FFs
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'nexus/fasm.cc')
-rw-r--r--nexus/fasm.cc60
1 files changed, 60 insertions, 0 deletions
diff --git a/nexus/fasm.cc b/nexus/fasm.cc
index 36656ec4..2441df4a 100644
--- a/nexus/fasm.cc
+++ b/nexus/fasm.cc
@@ -80,6 +80,17 @@ struct NexusFasmWriter
write_vector(name, bits, invert);
}
+ void write_enum(const CellInfo *cell, const std::string &name, const std::string &defval = "")
+ {
+ auto fnd = cell->params.find(ctx->id(name));
+ if (fnd == cell->params.end()) {
+ if (!defval.empty())
+ write_bit(stringf("%s.%s", name.c_str(), defval.c_str()));
+ } else {
+ write_bit(stringf("%s.%s", name.c_str(), fnd->second.c_str()));
+ }
+ }
+
NexusFasmWriter(const Context *ctx, std::ostream &out) : ctx(ctx), out(out) {}
std::string tile_name(int loc, const PhysicalTileInfoPOD &tile)
{
@@ -108,6 +119,7 @@ struct NexusFasmWriter
}
return escaped;
}
+ void push_tile(int loc, IdString tile_type) { push(tile_name(loc, tile_by_type_and_loc(loc, tile_type))); }
void write_pip(PipId pip)
{
auto &pd = ctx->pip_data(pip);
@@ -128,12 +140,60 @@ struct NexusFasmWriter
write_pip(p);
blank();
}
+ void write_comb(const CellInfo *cell)
+ {
+ BelId bel = cell->bel;
+ int z = ctx->bel_data(bel).z;
+ int k = z & 0x1;
+ char slice = 'A' + (z >> 8);
+ push_tile(bel.tile, id_PLC);
+ push(stringf("SLICE%c", slice));
+ if (cell->params.count(id_INIT))
+ write_int_vector(stringf("K%d.INIT", k), int_or_default(cell->params, id_INIT, 0), 16);
+ if (cell->lutInfo.is_carry) {
+ write_bit("MODE.CCU2");
+ write_enum(cell, "INJECT", "NO");
+ }
+ pop(2);
+ }
+ void write_ff(const CellInfo *cell)
+ {
+ BelId bel = cell->bel;
+ int z = ctx->bel_data(bel).z;
+ int k = z & 0x1;
+ char slice = 'A' + (z >> 8);
+ push_tile(bel.tile, id_PLC);
+ push(stringf("SLICE%c", slice));
+ push(stringf("FF%d", k));
+ write_bit("USED.YES");
+ write_enum(cell, "REGSET", "RESET");
+ write_enum(cell, "LSRMODE", "LSR");
+ write_enum(cell, "SEL", "DF");
+ pop();
+ write_enum(cell, "REGDDR");
+ write_enum(cell, "SRMODE");
+ write_enum(cell, "CLKMUX");
+ write_enum(cell, "CEMUX");
+ write_enum(cell, "LSRMUX");
+ write_enum(cell, "GSR");
+ pop(2);
+ }
void operator()()
{
// Write routing
for (auto n : sorted(ctx->nets)) {
write_net(n.second);
}
+ // Write cell config
+ for (auto c : sorted(ctx->cells)) {
+ const CellInfo *ci = c.second;
+ write_comment(stringf("# Cell %s", ctx->nameOf(ci)));
+ if (ci->type == id_OXIDE_COMB)
+ write_comb(ci);
+ else if (ci->type == id_OXIDE_FF)
+ write_ff(ci);
+ blank();
+ }
}
};
} // namespace