aboutsummaryrefslogtreecommitdiffstats
path: root/nexus/fasm.cc
diff options
context:
space:
mode:
Diffstat (limited to 'nexus/fasm.cc')
-rw-r--r--nexus/fasm.cc41
1 files changed, 39 insertions, 2 deletions
diff --git a/nexus/fasm.cc b/nexus/fasm.cc
index 964828cb..bb0a7941 100644
--- a/nexus/fasm.cc
+++ b/nexus/fasm.cc
@@ -207,7 +207,7 @@ struct NexusFasmWriter
void write_pip(PipId pip)
{
auto &pd = ctx->pip_data(pip);
- if (pd.flags & PIP_FIXED_CONN)
+ if ((pd.flags & PIP_FIXED_CONN) || (pd.flags & PIP_LUT_PERM))
return;
std::string tile = tile_name(pip.tile, tile_by_type_and_loc(pip.tile, IdString(pd.tile_type)));
std::string source_wire = escape_name(ctx->pip_src_wire_name(pip).str(ctx));
@@ -317,6 +317,43 @@ struct NexusFasmWriter
}
}
+ unsigned permute_init(const CellInfo *cell)
+ {
+ unsigned orig_init = int_or_default(cell->params, id_INIT, 0);
+ std::array<std::vector<unsigned>, 4> phys_to_log;
+ const std::array<IdString, 4> ports{id_A, id_B, id_C, id_D};
+ for (unsigned i = 0; i < 4; i++) {
+ WireId pin_wire = ctx->getBelPinWire(cell->bel, ports[i]);
+ for (PipId pip : ctx->getPipsUphill(pin_wire)) {
+ if (!ctx->getBoundPipNet(pip))
+ continue;
+ const auto &data = ctx->pip_data(pip);
+ if (data.flags & PIP_FIXED_CONN) { // non-permuting
+ phys_to_log[i].push_back(i);
+ } else { // permuting
+ NPNR_ASSERT(data.flags & PIP_LUT_PERM);
+ unsigned from_pin = (data.flags >> 4) & 0xF;
+ unsigned to_pin = (data.flags >> 0) & 0xF;
+ NPNR_ASSERT(to_pin == i);
+ phys_to_log[from_pin].push_back(i);
+ }
+ }
+ }
+ unsigned permuted_init = 0;
+ for (unsigned i = 0; i < 16; i++) {
+ unsigned log_idx = 0;
+ for (unsigned j = 0; j < 4; j++) {
+ if ((i >> j) & 0x1) {
+ for (auto log_pin : phys_to_log[j])
+ log_idx |= (1 << log_pin);
+ }
+ }
+ if ((orig_init >> log_idx) & 0x1)
+ permuted_init |= (1 << i);
+ }
+ return permuted_init;
+ }
+
// Write config for an OXIDE_COMB cell
void write_comb(const CellInfo *cell)
{
@@ -327,7 +364,7 @@ struct NexusFasmWriter
push_tile(bel.tile, id_PLC);
push(stringf("SLICE%c", slice));
if (cell->params.count(id_INIT))
- write_int_vector(stringf("K%d.INIT[15:0]", k), int_or_default(cell->params, id_INIT, 0), 16);
+ write_int_vector(stringf("K%d.INIT[15:0]", k), permute_init(cell), 16);
if (cell->lutInfo.is_carry) {
write_bit("MODE.CCU2");
write_enum(cell, "CCU2.INJECT", "NO");