aboutsummaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2022-09-30 13:27:51 +0200
committergatecat <gatecat@ds0.me>2022-09-30 13:27:51 +0200
commit3826a31ad3667d691d95ae027bd0ce66c5596f73 (patch)
tree4c9bf5a5f1b7312bca77b2e3bc9573e7063d0359 /generic
parent124c0fc8121f0ac1e7d9823f3f1576e5fa2c087b (diff)
downloadnextpnr-3826a31ad3667d691d95ae027bd0ce66c5596f73.tar.gz
nextpnr-3826a31ad3667d691d95ae027bd0ce66c5596f73.tar.bz2
nextpnr-3826a31ad3667d691d95ae027bd0ce66c5596f73.zip
fabulous: Pack, validity check and FASM support for muxes
Signed-off-by: gatecat <gatecat@ds0.me>
Diffstat (limited to 'generic')
-rw-r--r--generic/viaduct/fabulous/fabulous.cc9
-rw-r--r--generic/viaduct/fabulous/fasm.cc11
-rw-r--r--generic/viaduct/fabulous/pack.cc48
-rw-r--r--generic/viaduct/fabulous/validity_check.cc21
4 files changed, 84 insertions, 5 deletions
diff --git a/generic/viaduct/fabulous/fabulous.cc b/generic/viaduct/fabulous/fabulous.cc
index 287d7e51..9cb7e74f 100644
--- a/generic/viaduct/fabulous/fabulous.cc
+++ b/generic/viaduct/fabulous/fabulous.cc
@@ -317,12 +317,13 @@ struct FabulousImpl : ViaductAPI
}
// K select inputs
for (unsigned j = 0; j < k; j++) {
- ctx->addBelInput(mux, ctx->idf("S%d", j), data.pins.at(ctx->idf("S%d",
- (m == 8 && j == 2) ? 3 : ((i / m) * k + j)
- )).wire);
+ ctx->addBelInput(mux, ctx->idf("S%d", j),
+ data.pins.at(ctx->idf("S%d", (m == 8 && j == 2) ? 3 : ((i / m) * k + j))).wire);
}
// Output
- IdString output = (m == 2) ? mux_outs.at(i / m) : (m == 4) ? mux_outs.at((i / m) * k + 1) : mux_outs.at(3);
+ IdString output = (m == 2) ? mux_outs.at(i / m)
+ : (m == 4) ? mux_outs.at((i / m) * k + 1)
+ : mux_outs.at(3);
ctx->addBelOutput(mux, id_O, data.pins.at(output).wire);
}
}
diff --git a/generic/viaduct/fabulous/fasm.cc b/generic/viaduct/fabulous/fasm.cc
index e4725555..e4b95f62 100644
--- a/generic/viaduct/fabulous/fasm.cc
+++ b/generic/viaduct/fabulous/fasm.cc
@@ -123,6 +123,14 @@ struct FabFasmWriter
write_bool(lc, "NEG_SR");
write_bool(lc, "ASYNC_SR");
}
+ if (lc->type.in(id_FABULOUS_MUX4, id_FABULOUS_MUX8)) {
+ // TODO: don't hardcode prefix
+ out << prefix << "I.c0" << std::endl;
+ }
+ if (lc->type == id_FABULOUS_MUX8) {
+ // TODO: don't hardcode prefix
+ out << prefix << "I.c1" << std::endl;
+ }
}
void write_io(const CellInfo *io)
@@ -161,7 +169,8 @@ struct FabFasmWriter
void write_cell(const CellInfo *ci)
{
out << stringf("# config for cell '%s'\n", ctx->nameOf(ci)) << std::endl;
- if (ci->type.in(id_FABULOUS_COMB, id_FABULOUS_FF, id_FABULOUS_LC))
+ if (ci->type.in(id_FABULOUS_COMB, id_FABULOUS_FF, id_FABULOUS_LC, id_FABULOUS_MUX2, id_FABULOUS_MUX4,
+ id_FABULOUS_MUX8))
write_logic(ci);
else if (ci->type == id_IO_1_bidirectional_frame_config_pass)
write_io(ci);
diff --git a/generic/viaduct/fabulous/pack.cc b/generic/viaduct/fabulous/pack.cc
index 0273a28a..56a6f855 100644
--- a/generic/viaduct/fabulous/pack.cc
+++ b/generic/viaduct/fabulous/pack.cc
@@ -132,6 +132,53 @@ struct FabulousPacker
}
}
+ void pack_muxes()
+ {
+ // TODO: don't hardcode z-offset -- we should come up with our own constraint structure
+ int lut_muxes_dz = 9;
+ int lut_lut_dz = 1;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
+ unsigned k = 0;
+ if (ci->type == id_FABULOUS_MUX2)
+ k = 1;
+ else if (ci->type == id_FABULOUS_MUX4)
+ k = 2;
+ else if (ci->type == id_FABULOUS_MUX8)
+ k = 3;
+ else
+ continue;
+ unsigned m = (1U << k);
+ std::vector<CellInfo *> luts;
+ for (unsigned i = 0; i < m; i++) {
+ NetInfo *ii = ci->getPort(ctx->idf("I%d", i));
+ if (!ii || !ii->driver.cell || !ii->driver.cell->type.in(id_FABULOUS_LC, id_FABULOUS_COMB) ||
+ ii->driver.port != id_O)
+ log_error("mux %s input I%d net %s is not driven by a LUT!\n", ctx->nameOf(ci), i, ctx->nameOf(ii));
+ CellInfo *lut = ii->driver.cell;
+ NPNR_ASSERT(lut->cluster == ClusterId());
+ luts.push_back(lut);
+ }
+ luts.at(0)->cluster = luts.at(0)->name;
+ for (unsigned i = 0; i < m; i++) {
+ luts.at(i)->cluster = luts.at(0)->name;
+ luts.at(i)->constr_x = 0;
+ luts.at(i)->constr_y = 0;
+ luts.at(i)->constr_z = i * lut_lut_dz;
+ luts.at(i)->constr_abs_z = false;
+ if (i > 0)
+ luts.at(0)->constr_children.push_back(luts.at(i));
+ }
+ int extra_mux_dz = (m == 8) ? 7 : (m == 4) ? 1 : 0;
+ ci->cluster = luts.at(0)->name;
+ ci->constr_x = 0;
+ ci->constr_y = 0;
+ ci->constr_z = lut_muxes_dz + extra_mux_dz;
+ ci->constr_abs_z = false;
+ luts.at(0)->constr_children.push_back(ci);
+ }
+ }
+
void pack_ffs()
{
pool<IdString> to_delete;
@@ -238,6 +285,7 @@ struct FabulousPacker
handle_constants();
handle_io();
pack_luts();
+ pack_muxes();
prepare_ffs();
pack_ffs();
}
diff --git a/generic/viaduct/fabulous/validity_check.cc b/generic/viaduct/fabulous/validity_check.cc
index 91dba689..30b21f29 100644
--- a/generic/viaduct/fabulous/validity_check.cc
+++ b/generic/viaduct/fabulous/validity_check.cc
@@ -33,6 +33,7 @@ CLBState::CLBState(const LogicConfig &cfg)
if (cfg.split_lc) {
ff = std::make_unique<CellInfo *[]>(cfg.lc_per_clb * cfg.ff_per_lc);
}
+ mux = std::make_unique<CellInfo *[]>(cfg.lc_per_clb);
// TODO: mux
}
@@ -173,6 +174,26 @@ bool CLBState::check_validity(const LogicConfig &cfg, const CellTagger &cell_dat
}
}
}
+ // don't allow mixed MUX types in the classic fabulous arch where ctrl sigs are shared
+ int tile_mux_type = 0;
+ for (unsigned z = 0; z < cfg.lc_per_clb; z++) {
+ const CellInfo *m = mux[z];
+ if (!m)
+ continue;
+ int this_mux = 0;
+ if (m->type == id_FABULOUS_MUX2)
+ this_mux = 2;
+ else if (m->type == id_FABULOUS_MUX4)
+ this_mux = 4;
+ else if (m->type == id_FABULOUS_MUX8)
+ this_mux = 8;
+ else
+ NPNR_ASSERT_FALSE("unknown mux type");
+ if (tile_mux_type == 0)
+ tile_mux_type = this_mux;
+ else if (tile_mux_type != this_mux)
+ return false;
+ }
// TODO: other checks...
return true;
}