From 3826a31ad3667d691d95ae027bd0ce66c5596f73 Mon Sep 17 00:00:00 2001 From: gatecat Date: Fri, 30 Sep 2022 13:27:51 +0200 Subject: fabulous: Pack, validity check and FASM support for muxes Signed-off-by: gatecat --- generic/viaduct/fabulous/fabulous.cc | 9 +++--- generic/viaduct/fabulous/fasm.cc | 11 ++++++- generic/viaduct/fabulous/pack.cc | 48 ++++++++++++++++++++++++++++++ generic/viaduct/fabulous/validity_check.cc | 21 +++++++++++++ 4 files changed, 84 insertions(+), 5 deletions(-) (limited to 'generic') 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 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 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(cfg.lc_per_clb * cfg.ff_per_lc); } + mux = std::make_unique(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; } -- cgit v1.2.3