diff options
author | William D. Jones <thor0505@comcast.net> | 2020-11-26 05:01:14 -0500 |
---|---|---|
committer | gatecat <gatecat@ds0.me> | 2021-02-12 10:36:59 +0000 |
commit | da6204442fb2635ec82621c00cdf4f7e3dfa3499 (patch) | |
tree | e747a5ed98058f2815e7216bb5e4c0bff5e4ef8b | |
parent | f2a240550e14184041d3f0cfd7526386d985f27c (diff) | |
download | nextpnr-da6204442fb2635ec82621c00cdf4f7e3dfa3499.tar.gz nextpnr-da6204442fb2635ec82621c00cdf4f7e3dfa3499.tar.bz2 nextpnr-da6204442fb2635ec82621c00cdf4f7e3dfa3499.zip |
machxo2: Add LUT and FF packing functions.
-rw-r--r-- | machxo2/cells.cc | 19 | ||||
-rw-r--r-- | machxo2/cells.h | 8 | ||||
-rw-r--r-- | machxo2/pack.cc | 60 |
3 files changed, 82 insertions, 5 deletions
diff --git a/machxo2/cells.cc b/machxo2/cells.cc index d56c6d71..9a682a72 100644 --- a/machxo2/cells.cc +++ b/machxo2/cells.cc @@ -143,12 +143,29 @@ std::unique_ptr<CellInfo> create_machxo2_cell(Context *ctx, IdString type, std:: void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff) { + lc->params[ctx->id("LUT0_INITVAL")] = lut->params[ctx->id("INIT")]; + for (std::string i : {"A", "B", "C", "D"}) { + IdString lut_port = ctx->id(i); + IdString lc_port = ctx->id(i + "0"); + replace_port(lut, lut_port, lc, lc_port); + } + + replace_port(lut, ctx->id("Z"), lc, ctx->id("F0")); } void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut) { - + // By this point, we have shown that LUT4 Z is attached to FACADE_FF DI. + // This connection will be preserved by port replacement, but the SD mux + // which selects the actual DFF input needs to be told to use the + // FACADE_SLICE DI input instead of the FACADE_SLICE M input. + lc->params[ctx->id("REG0_SD")] = std::string("0"); + + replace_port(dff, ctx->id("CLK"), lc, ctx->id("CLK")); + replace_port(dff, ctx->id("DI"), lc, ctx->id("DI0")); + replace_port(dff, ctx->id("LSR"), lc, ctx->id("LSR")); + replace_port(dff, ctx->id("Q"), lc, ctx->id("Q0")); } void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, std::unordered_set<IdString> &todelete_cells) diff --git a/machxo2/cells.h b/machxo2/cells.h index b2971bda..f129f762 100644 --- a/machxo2/cells.h +++ b/machxo2/cells.h @@ -24,17 +24,17 @@ NEXTPNR_NAMESPACE_BEGIN -// Create a generic arch cell and return it +// Create a MachXO2 arch cell and return it // Name will be automatically assigned if not specified std::unique_ptr<CellInfo> create_machxo2_cell(Context *ctx, IdString type, std::string name = ""); // Return true if a cell is a LUT -inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell) { return false; } +inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("LUT4"); } // Return true if a cell is a flipflop -inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell) { return false; } +inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("FACADE_FF"); } -inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return false; } +inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("FACADE_SLICE"); } // Convert a LUT primitive to (part of) an GENERIC_SLICE, swapping ports // as needed. Set no_dff if a DFF is not being used, so that the output diff --git a/machxo2/pack.cc b/machxo2/pack.cc index c418ceda..76fd7240 100644 --- a/machxo2/pack.cc +++ b/machxo2/pack.cc @@ -27,6 +27,65 @@ NEXTPNR_NAMESPACE_BEGIN +// Pack LUTs and LUT-FF pairs +static void pack_lut_lutffs(Context *ctx) +{ + log_info("Packing LUT-FFs..\n"); + + std::unordered_set<IdString> packed_cells; + std::vector<std::unique_ptr<CellInfo>> new_cells; + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + if (ctx->verbose) + log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx)); + if (is_lut(ctx, ci)) { + std::unique_ptr<CellInfo> packed = + create_machxo2_cell(ctx, ctx->id("FACADE_SLICE"), ci->name.str(ctx) + "_LC"); + std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); + + packed_cells.insert(ci->name); + if (ctx->verbose) + log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx)); + // See if we can pack into a DFF. Both LUT4 and FF outputs are + // available for a given slice, so we can pack a FF even if the + // LUT4 drives more than one FF. + NetInfo *o = ci->ports.at(ctx->id("Z")).net; + CellInfo *dff = net_only_drives(ctx, o, is_ff, ctx->id("DI"), false); + auto lut_bel = ci->attrs.find(ctx->id("BEL")); + bool packed_dff = false; + + if (dff) { + if (ctx->verbose) + log_info("found attached dff %s\n", dff->name.c_str(ctx)); + auto dff_bel = dff->attrs.find(ctx->id("BEL")); + if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() && lut_bel->second != dff_bel->second) { + // Locations don't match, can't pack + } else { + lut_to_lc(ctx, ci, packed.get(), false); + dff_to_lc(ctx, dff, packed.get(), false); + if (dff_bel != dff->attrs.end()) + packed->attrs[ctx->id("BEL")] = dff_bel->second; + packed_cells.insert(dff->name); + if (ctx->verbose) + log_info("packed cell %s into %s\n", dff->name.c_str(ctx), packed->name.c_str(ctx)); + packed_dff = true; + } + } + if (!packed_dff) { + lut_to_lc(ctx, ci, packed.get(), true); + } + new_cells.push_back(std::move(packed)); + } + } + + for (auto pcell : packed_cells) { + ctx->cells.erase(pcell); + } + for (auto &ncell : new_cells) { + ctx->cells[ncell->name] = std::move(ncell); + } +} + // Merge a net into a constant net static void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constnet, bool constval) { @@ -135,6 +194,7 @@ bool Arch::pack() log_break(); pack_constants(ctx); pack_io(ctx); + pack_lut_lutffs(ctx); ctx->settings[ctx->id("pack")] = 1; ctx->assignArchInfo(); log_info("Checksum: 0x%08x\n", ctx->checksum()); |