From 14050f991bc2e4ce2c6e7f431fe2acd4f0cf2a70 Mon Sep 17 00:00:00 2001 From: gatecat Date: Wed, 22 Feb 2023 14:51:51 +0100 Subject: fabulous: Global constant wires scheme Signed-off-by: gatecat --- generic/viaduct/fabulous/constids.inc | 10 ++++ generic/viaduct/fabulous/fabulous.cc | 94 +++++++++++++++++++++++++++++-- generic/viaduct/fabulous/fasm.cc | 25 ++++++-- generic/viaduct/fabulous/fasm.h | 4 +- generic/viaduct/fabulous/pack.cc | 9 ++- generic/viaduct/fabulous/validity_check.h | 13 +++++ 6 files changed, 140 insertions(+), 15 deletions(-) diff --git a/generic/viaduct/fabulous/constids.inc b/generic/viaduct/fabulous/constids.inc index 21c47463..4299f483 100644 --- a/generic/viaduct/fabulous/constids.inc +++ b/generic/viaduct/fabulous/constids.inc @@ -99,3 +99,13 @@ X(M_EF) X(M_AH) X(I0MUX) + +X(GND0) +X(GND) +X(VCC0) +X(VCC) +X(VDD0) +X(VDD) + +X(_CONST0_DRV) +X(_CONST1_DRV) diff --git a/generic/viaduct/fabulous/fabulous.cc b/generic/viaduct/fabulous/fabulous.cc index e58cf792..529d9ad0 100644 --- a/generic/viaduct/fabulous/fabulous.cc +++ b/generic/viaduct/fabulous/fabulous.cc @@ -69,6 +69,7 @@ struct FabulousImpl : ViaductAPI blk_trk = std::make_unique(ctx, cfg); is_new_fab ? init_bels_v2() : init_bels_v1(); init_pips(); + init_pseudo_constant_wires(); ctx->setDelayScaling(3.0, 3.0); ctx->delay_epsilon = 0.25; ctx->ripup_penalty = 0.5; @@ -105,7 +106,7 @@ struct FabulousImpl : ViaductAPI void postRoute() override { if (!fasm_file.empty()) - fabulous_write_fasm(ctx, cfg, fasm_file); + fabulous_write_fasm(ctx, cfg, pp_tags, fasm_file); } void prePlace() override @@ -150,11 +151,18 @@ struct FabulousImpl : ViaductAPI pool warned_beltypes; - void add_pseudo_pip(WireId src, WireId dst, IdString pip_type) + std::vector pp_tags; + + void add_pseudo_pip(WireId src, WireId dst, IdString pip_type, float delay = 1.0, + PseudoPipTags tags = PseudoPipTags()) { const auto &src_data = ctx->wire_info(src); IdStringList pip_name = IdStringList::concat(ctx->getWireName(src), ctx->getWireName(dst)); - ctx->addPip(pip_name, pip_type, src, dst, ctx->getDelayFromNS(1.0), Loc(src_data.x, src_data.y, 0)); + PipId idx = + ctx->addPip(pip_name, pip_type, src, dst, ctx->getDelayFromNS(delay), Loc(src_data.x, src_data.y, 0)); + if (idx.index >= int(pp_tags.size())) + pp_tags.resize(idx.index + 1); + pp_tags.at(idx.index) = tags; } void handle_bel_ports(BelId bel, IdString tile, IdString bel_type, const std::vector &ports) @@ -405,6 +413,7 @@ struct FabulousImpl : ViaductAPI } } + int max_x = 0, max_y = 0; void init_pips() { std::ifstream in = open_data_rel(is_new_fab ? "/.FABulous/pips.txt" : "/npnroutput/pips.txt"); @@ -418,8 +427,11 @@ struct FabulousImpl : ViaductAPI IdString pip_name = csv.next_field().to_id(ctx); WireId src_wire = get_wire(src_tile, src_port, src_port); WireId dst_wire = get_wire(dst_tile, dst_port, dst_port); + Loc loc = tile_loc(src_tile); + max_x = std::max(loc.x, max_x); + max_y = std::max(loc.y, max_y); ctx->addPip(IdStringList::concat(src_tile, pip_name), pip_name, src_wire, dst_wire, - ctx->getDelayFromNS(0.05 * delay), tile_loc(src_tile)); + ctx->getDelayFromNS(0.05 * delay), loc); } } @@ -455,6 +467,67 @@ struct FabulousImpl : ViaductAPI return ctx->addWire(wire_name, type, loc.x, loc.y); } + void init_pseudo_constant_wires() + { + for (int y = 0; y <= max_y; y++) { + for (int x = 0; x <= max_x; x++) { + for (int c = 0; c <= 1; c++) { + IdString name = ctx->idf("$CONST%d", c); + IdString tile = ctx->idf("X%dY%d", x, y); + WireId const_wire = get_wire(tile, name, name); + // Driver bel; always at 0;0 + if (x == 0 && y == 0) { + int z = 0; + while (ctx->bel_by_loc.count(Loc(x, y, z))) + z++; + BelId const_driver = ctx->addBel(IdStringList::concat(tile, ctx->idf("_CONST%d_DRV", c)), + ctx->idf("_CONST%d_DRV", c), Loc(x, y, z), true, true); + ctx->addBelInput(const_driver, id_O, const_wire); + } + if (x > 0) { + // 'right' pip + WireId prev_wire = get_wire(ctx->idf("X%dY%d", 0, y), name, name); + add_pseudo_pip(prev_wire, const_wire, name, 0.1); + } + if (y > 0) { + // 'down' pip + WireId prev_wire = get_wire(ctx->idf("X%dY%d", x, 0), name, name); + add_pseudo_pip(prev_wire, const_wire, name, 0.1); + } + } + } + } + // LUTs can act as constant drivers if they aren't used. + // To avoid an exorbitant number of pips, only do this for the first LUT in a tile + // This pip will only be enabled if the LUT isn't used + for (BelId bel : ctx->getBels()) { + if (!ctx->getBelType(bel).in(id_FABULOUS_LC, id_FABULOUS_COMB)) + continue; + Loc loc = ctx->getBelLocation(bel); + WireId o = ctx->getBelPinWire(bel, id_O); + for (int c = 0; c <= 1; c++) { + IdString const_name = ctx->idf("$CONST%d", c); + WireId const_wire = get_wire(ctx->idf("X%dY%d", loc.x, loc.y), const_name, const_name); + add_pseudo_pip(const_wire, o, const_name, 0.1, PseudoPipTags(PseudoPipTags::LUT_CONST, bel, c)); + } + } + // We can also have dedicated constant wires in the fabric + for (WireId wire : ctx->getWires()) { + auto &wire_data = ctx->wire_info(wire); + IdString name_suffix = wire_data.name[1]; + int const_val = -1; + if (name_suffix.in(id_GND, id_GND0)) + const_val = 0; + else if (name_suffix.in(id_VCC, id_VCC0, id_VDD, id_VDD0)) + const_val = 1; + else + continue; + IdString const_name = ctx->idf("$CONST%d", const_val); + WireId const_wire = get_wire(ctx->idf("X%dY%d", wire_data.x, wire_data.y), const_name, const_name); + add_pseudo_pip(const_wire, wire, const_name, 0.1); + } + } + CellTagger cell_tags; void assign_cell_info() { @@ -467,6 +540,19 @@ struct FabulousImpl : ViaductAPI CellInfo *old = ctx->getBoundBelCell(bel); blk_trk->update_bel(bel, old, cell); } + + bool checkPipAvail(PipId pip) const override + { + if (pip.index >= int(pp_tags.size())) + return true; + const auto &tags = pp_tags.at(pip.index); + if (tags.type == PseudoPipTags::LUT_CONST) { + return ctx->checkBelAvail(tags.bel); + } else { + // TODO: LUT permuation pseudopips + return true; + } + } }; struct FabulousArch : ViaductArch diff --git a/generic/viaduct/fabulous/fasm.cc b/generic/viaduct/fabulous/fasm.cc index 047ffcbd..4d09d537 100644 --- a/generic/viaduct/fabulous/fasm.cc +++ b/generic/viaduct/fabulous/fasm.cc @@ -34,8 +34,9 @@ NEXTPNR_NAMESPACE_BEGIN namespace { struct FabFasmWriter { - FabFasmWriter(const Context *ctx, const FabricConfig &cfg, const std::string &filename) - : ctx(ctx), cfg(cfg), out(filename) + FabFasmWriter(const Context *ctx, const FabricConfig &cfg, const std::vector &pip_tags, + const std::string &filename) + : ctx(ctx), cfg(cfg), pip_tags(pip_tags), out(filename) { if (!out) log_error("failed to open fasm file '%s' for writing\n", filename.c_str()); @@ -53,7 +54,19 @@ struct FabFasmWriter void write_pip(PipId pip) { auto &data = ctx->pip_info(pip); - if (data.type.in(id_global_clock, id_O2Q)) + if (pip.index < int(pip_tags.size()) && pip_tags.at(pip.index).type != PseudoPipTags::NONE) { + // pseudo PIP + const auto &tag = pip_tags.at(pip.index); + if (tag.type == PseudoPipTags::LUT_CONST) { + NPNR_ASSERT(ctx->checkBelAvail(tag.bel)); + prefix = format_name(ctx->getBelName(tag.bel)) + "."; + write_int_vector(stringf("INIT[%d:0]", (1U << cfg.clb.lut_k) - 1), 0, 1U << cfg.clb.lut_k, + (tag.data & 0x1)); + prefix = ""; + } + return; + } + if (data.type.in(id_global_clock, id_O2Q) || data.type.c_str(ctx)[0] == '$') return; // pseudo-pips with no underlying bitstream bits // write pip name but with '.' instead of '/' for separator out << format_name(data.name) << std::endl; @@ -194,13 +207,15 @@ struct FabFasmWriter const Context *ctx; const FabricConfig &cfg; + const std::vector &pip_tags; std::ofstream out; }; } // namespace -void fabulous_write_fasm(const Context *ctx, const FabricConfig &cfg, const std::string &filename) +void fabulous_write_fasm(const Context *ctx, const FabricConfig &cfg, const std::vector &pip_tags, + const std::string &filename) { - FabFasmWriter wr(ctx, cfg, filename); + FabFasmWriter wr(ctx, cfg, pip_tags, filename); wr.write_fasm(); } diff --git a/generic/viaduct/fabulous/fasm.h b/generic/viaduct/fabulous/fasm.h index 0f152c64..90b10f2a 100644 --- a/generic/viaduct/fabulous/fasm.h +++ b/generic/viaduct/fabulous/fasm.h @@ -22,10 +22,12 @@ #include "fab_cfg.h" #include "nextpnr.h" +#include "validity_check.h" NEXTPNR_NAMESPACE_BEGIN -void fabulous_write_fasm(const Context *ctx, const FabricConfig &cfg, const std::string &filename); +void fabulous_write_fasm(const Context *ctx, const FabricConfig &cfg, const std::vector &pip_tags, + const std::string &filename); NEXTPNR_NAMESPACE_END diff --git a/generic/viaduct/fabulous/pack.cc b/generic/viaduct/fabulous/pack.cc index 10402016..629b000e 100644 --- a/generic/viaduct/fabulous/pack.cc +++ b/generic/viaduct/fabulous/pack.cc @@ -194,7 +194,8 @@ struct FabulousPacker } } - bool check_cluster_legality(CellInfo *lc) { + bool check_cluster_legality(CellInfo *lc) + { if (lc->cluster == ClusterId()) return true; CLBState test_clb(cfg.clb); @@ -204,7 +205,7 @@ struct FabulousPacker if (ci->type == id_FABULOUS_LC) { NPNR_ASSERT(ci->constr_z >= 0 && ci->constr_z < int(cfg.clb.lc_per_clb)); test_clb.lc_comb[ci->constr_z] = ci; - } else if (ci->type.in(id_FABULOUS_MUX2, id_FABULOUS_MUX4, id_FABULOUS_MUX8)) { + } else if (ci->type.in(id_FABULOUS_MUX2, id_FABULOUS_MUX4, id_FABULOUS_MUX8)) { int mux_z = (ci->constr_z - cfg.clb.lc_per_clb - 1); NPNR_ASSERT(mux_z >= 0 && mux_z < int(cfg.clb.lc_per_clb)); test_clb.mux[mux_z] = ci; @@ -317,9 +318,7 @@ struct FabulousPacker void handle_constants() { - const dict vcc_params = {{id_INIT, Property(0x3, 2)}}; - const dict gnd_params = {{id_INIT, Property(0x0, 2)}}; - h.replace_constants(CellTypePort(id_LUT1, id_O), CellTypePort(id_LUT1, id_O), vcc_params, gnd_params); + h.replace_constants(CellTypePort(id__CONST1_DRV, id_O), CellTypePort(id__CONST0_DRV, id_O), {}, {}); } void handle_io() diff --git a/generic/viaduct/fabulous/validity_check.h b/generic/viaduct/fabulous/validity_check.h index 43291f6e..1f21e07b 100644 --- a/generic/viaduct/fabulous/validity_check.h +++ b/generic/viaduct/fabulous/validity_check.h @@ -122,6 +122,19 @@ struct BlockTracker bool check_validity(BelId bel, const FabricConfig &cfg, const CellTagger &cell_data); }; +struct PseudoPipTags +{ + BelId bel; + enum PPType : uint16_t + { + NONE, + LUT_CONST, + LUT_PERM, + } type; + uint16_t data; + PseudoPipTags(PPType type = NONE, BelId bel = BelId(), uint16_t data = 0x0) : bel(bel), type(type), data(data) {} +}; + NEXTPNR_NAMESPACE_END #endif -- cgit v1.2.3