diff --git a/nexus/arch.cc b/nexus/arch.cc index fa81485a..95474800 100644 --- a/nexus/arch.cc +++ b/nexus/arch.cc @@ -1030,7 +1030,7 @@ const std::vector Arch::availablePlacers = {"sa", }; -const std::string Arch::defaultRouter = "router2"; +const std::string Arch::defaultRouter = "router1"; const std::vector Arch::availableRouters = {"router1", "router2"}; NEXTPNR_NAMESPACE_END diff --git a/nexus/arch.h b/nexus/arch.h index deb9b6db..300c3760 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -86,6 +86,7 @@ NPNR_PACKED_STRUCT(struct LocWireInfoPOD { enum PipFlags { PIP_FIXED_CONN = 0x8000, + PIP_LUT_PERM = 0x4000, }; NPNR_PACKED_STRUCT(struct PipInfoPOD { @@ -979,10 +980,38 @@ struct Arch : BaseArch return tileStatus[bel.tile].boundcells[bel.index] == nullptr; } + bool is_pseudo_pip_disabled(PipId pip) const + { + const auto &data = pip_data(pip); + if (data.flags & PIP_LUT_PERM) { + int lut_idx = (data.flags >> 8) & 0xF; + int from_pin = (data.flags >> 4) & 0xF; + int to_pin = (data.flags >> 0) & 0xF; + auto &ts = tileStatus.at(pip.tile); + if (!ts.lts) + return false; + const CellInfo *lut = ts.lts->cells[((lut_idx / 2) << 3) | (BEL_LUT0 + (lut_idx % 2))]; + if (lut) { + if (lut->lutInfo.is_memory) + return true; + if (lut->lutInfo.is_carry && (from_pin == 3 || to_pin == 3)) + return true; // Upper pin is special for carries + } + if (lut_idx == 4 || lut_idx == 5) { + const CellInfo *ramw = ts.lts->cells[((lut_idx / 2) << 3) | BEL_RAMW]; + if (ramw) + return true; // Don't permute RAM write address + } + } + return false; + } + bool checkPipAvail(PipId pip) const override { if (disabled_pips.count(pip)) return false; + if (is_pseudo_pip_disabled(pip)) + return false; return BaseArch::checkPipAvail(pip); } @@ -990,6 +1019,8 @@ struct Arch : BaseArch { if (disabled_pips.count(pip)) return false; + if (is_pseudo_pip_disabled(pip)) + return false; return BaseArch::checkPipAvailForNet(pip, net); } diff --git a/nexus/bba_version.inc b/nexus/bba_version.inc index f599e28b..b4de3947 100644 --- a/nexus/bba_version.inc +++ b/nexus/bba_version.inc @@ -1 +1 @@ -10 +11 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, 4> phys_to_log; + const std::array 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");