aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2023-02-23 15:19:00 +0100
committermyrtle <gatecat@ds0.me>2023-02-27 08:42:56 +0100
commit26fcf349ad9ef65e4f0758c7bb4a24d5a8b45bf7 (patch)
tree4ac837daf78b42861cbb429e878ca75f1550256d
parent14050f991bc2e4ce2c6e7f431fe2acd4f0cf2a70 (diff)
downloadnextpnr-26fcf349ad9ef65e4f0758c7bb4a24d5a8b45bf7.tar.gz
nextpnr-26fcf349ad9ef65e4f0758c7bb4a24d5a8b45bf7.tar.bz2
nextpnr-26fcf349ad9ef65e4f0758c7bb4a24d5a8b45bf7.zip
fabulous: LUT permutation support
Signed-off-by: gatecat <gatecat@ds0.me>
-rw-r--r--generic/viaduct/fabulous/constids.inc3
-rw-r--r--generic/viaduct/fabulous/fabulous.cc57
-rw-r--r--generic/viaduct/fabulous/fasm.cc42
-rw-r--r--generic/viaduct/fabulous/validity_check.cc2
4 files changed, 102 insertions, 2 deletions
diff --git a/generic/viaduct/fabulous/constids.inc b/generic/viaduct/fabulous/constids.inc
index 4299f483..7c8c3400 100644
--- a/generic/viaduct/fabulous/constids.inc
+++ b/generic/viaduct/fabulous/constids.inc
@@ -109,3 +109,6 @@ X(VDD)
X(_CONST0_DRV)
X(_CONST1_DRV)
+
+X(_LUT_PERM)
+X(_LUT_PERM_IN)
diff --git a/generic/viaduct/fabulous/fabulous.cc b/generic/viaduct/fabulous/fabulous.cc
index 529d9ad0..3400be9a 100644
--- a/generic/viaduct/fabulous/fabulous.cc
+++ b/generic/viaduct/fabulous/fabulous.cc
@@ -70,6 +70,7 @@ struct FabulousImpl : ViaductAPI
is_new_fab ? init_bels_v2() : init_bels_v1();
init_pips();
init_pseudo_constant_wires();
+ setup_lut_permutation();
ctx->setDelayScaling(3.0, 3.0);
ctx->delay_epsilon = 0.25;
ctx->ripup_penalty = 0.5;
@@ -435,6 +436,46 @@ struct FabulousImpl : ViaductAPI
}
}
+ void remove_bel_pin(BelId bel, IdString pin)
+ {
+ auto &bel_data = ctx->bel_info(bel);
+ auto &wire_data = ctx->wire_info(ctx->getBelPinWire(bel, pin));
+ std::vector<BelPin> new_wire_pins;
+ for (const auto &wire_pin : wire_data.bel_pins) {
+ if (wire_pin.bel == bel && wire_pin.pin == pin)
+ continue;
+ new_wire_pins.push_back(wire_pin);
+ }
+ wire_data.bel_pins = new_wire_pins;
+ bel_data.pins.erase(pin);
+ }
+
+ void setup_lut_permutation()
+ {
+ for (auto bel : ctx->getBels()) {
+ auto &bel_data = ctx->bel_info(bel);
+ if (!bel_data.type.in(id_FABULOUS_LC, id_FABULOUS_COMB))
+ continue;
+ std::vector<WireId> orig_inputs, new_inputs;
+ for (unsigned i = 0; i < cfg.clb.lut_k; i++) {
+ // Rewire the LUT input to a permutation pseudo-wire
+ IdString pin = ctx->idf("I%d", i);
+ orig_inputs.push_back(ctx->getBelPinWire(bel, pin));
+ remove_bel_pin(bel, pin);
+ WireId in_wire = get_wire(bel_data.name[0], ctx->idf("%s_PERM_I%d", bel_data.name[1].c_str(ctx), i),
+ id__LUT_PERM_IN);
+ ctx->addBelInput(bel, pin, in_wire);
+ new_inputs.push_back(in_wire);
+ }
+ for (unsigned i = 0; i < cfg.clb.lut_k; i++) {
+ for (unsigned j = 0; j < cfg.clb.lut_k; j++) {
+ add_pseudo_pip(orig_inputs.at(i), new_inputs.at(j), id__LUT_PERM, 0.1,
+ PseudoPipTags(PseudoPipTags::LUT_PERM, bel, ((i << 4) | j)));
+ }
+ }
+ }
+ }
+
// Fast lookup of tile names to XY pairs
dict<IdString, Loc> tile2loc;
Loc tile_loc(IdString tile)
@@ -548,6 +589,22 @@ struct FabulousImpl : ViaductAPI
const auto &tags = pp_tags.at(pip.index);
if (tags.type == PseudoPipTags::LUT_CONST) {
return ctx->checkBelAvail(tags.bel);
+ } else if (tags.type == PseudoPipTags::LUT_PERM) {
+ uint8_t from = (tags.data >> 4) & 0xF, to = (tags.data & 0xF);
+ if (from == to)
+ return true;
+ const CellInfo *lut = ctx->getBoundBelCell(tags.bel);
+ if (!lut)
+ return true;
+ bool is_carry = cell_tags.get(lut).comb.carry_used;
+ if (is_carry) {
+ // Because you have to make sure you route _something_ to each HA input in this mode (undefined I1/I2 inputs aren't OK)
+ // and you also can't swap I0 because it's fixed internally
+ // LUT permutation in carry mode is just more trouble than it's worth.
+ return false;
+ } else {
+ return true; // TODO: other cases where perm illegal; e.g. LUTRAM
+ }
} else {
// TODO: LUT permuation pseudopips
return true;
diff --git a/generic/viaduct/fabulous/fasm.cc b/generic/viaduct/fabulous/fasm.cc
index 4d09d537..159bb8ff 100644
--- a/generic/viaduct/fabulous/fasm.cc
+++ b/generic/viaduct/fabulous/fasm.cc
@@ -122,11 +122,51 @@ struct FabFasmWriter
void add_feature(const std::string &name) { out << prefix << name << std::endl; }
+ uint64_t depermute_lut(const CellInfo *lut)
+ {
+ uint64_t orig_init = int_or_default(lut->params, id_INIT, 0);
+ std::vector<std::vector<unsigned>> phys_to_log;
+ phys_to_log.resize(cfg.clb.lut_k);
+ for (unsigned i = 0; i < cfg.clb.lut_k; i++) {
+ WireId pin_wire = ctx->getBelPinWire(lut->bel, ctx->idf("I%d", i));
+ for (PipId pip : ctx->getPipsUphill(pin_wire)) {
+ if (!ctx->getBoundPipNet(pip))
+ continue;
+ unsigned pip_data = pip_tags.at(pip.index).data;
+ unsigned from_pin = (pip_data >> 4) & 0xF;
+ unsigned to_pin = (pip_data)&0xF;
+ NPNR_ASSERT(to_pin == i);
+ phys_to_log[from_pin].push_back(i);
+ }
+ }
+ if (bool_or_default(lut->params, id_I0MUX, false)) // internal, hardcoded
+ phys_to_log[0].push_back(0);
+ for (unsigned i = 0; i < cfg.clb.lut_k; i++) {
+ for (auto j : phys_to_log.at(i))
+ out << stringf(" # permute phys %d log %d\n", i, j);
+ }
+ uint64_t permuted_init = 0;
+ for (unsigned i = 0; i < (1U << cfg.clb.lut_k); i++) {
+ unsigned log_idx = 0;
+ for (unsigned j = 0; j < cfg.clb.lut_k; 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 |= (uint64_t(1U) << i);
+ }
+ return permuted_init;
+ }
+
void write_logic(const CellInfo *lc)
{
prefix = format_name(ctx->getBelName(lc->bel)) + ".";
if (lc->type.in(id_FABULOUS_LC, id_FABULOUS_COMB)) {
- write_int_vector_param(lc, "INIT", 0U, 1U << cfg.clb.lut_k); // todo lut depermute and thru
+ uint64_t init = depermute_lut(lc);
+ unsigned width = 1U << cfg.clb.lut_k;
+ write_int_vector(stringf("INIT[%d:0]", width - 1), init, width); // todo lut depermute and thru
if (bool_or_default(lc->params, id_I0MUX, false))
add_feature("IOmux"); // typo in FABulous?
}
diff --git a/generic/viaduct/fabulous/validity_check.cc b/generic/viaduct/fabulous/validity_check.cc
index 30b21f29..81f057c8 100644
--- a/generic/viaduct/fabulous/validity_check.cc
+++ b/generic/viaduct/fabulous/validity_check.cc
@@ -53,7 +53,7 @@ void CellTagger::assign_for(const Context *ctx, const FabricConfig &cfg, const C
const NetInfo *sig = ci->getPort(ctx->idf("I%d", i));
t.comb.lut_inputs[i] = sig ? sig->name : IdString();
}
- t.comb.carry_used = false; // TODO
+ t.comb.carry_used = ci->getPort(id_Ci) || ci->getPort(id_Co); // TODO
t.comb.lut_out = ci->getPort(id_O);
}
if (ci->type.in(id_FABULOUS_FF, id_FABULOUS_LC)) {