From 349be76d2693f0c9527c6373d31fae7e711f9270 Mon Sep 17 00:00:00 2001 From: David Shah Date: Sat, 7 Dec 2019 12:14:34 +0000 Subject: ecp5: Add support for flipflops with preload Signed-off-by: David Shah --- ecp5/bitstream.cc | 4 ++++ ecp5/cells.cc | 18 +++++++++++++++--- ecp5/pack.cc | 8 ++++++-- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index 9b1a65ab..66bd639a 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -759,6 +759,10 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex str_or_default(ci->params, ctx->id("REG0_REGSET"), "RESET")); cc.tiles[tname].add_enum(slice + ".REG1.REGSET", str_or_default(ci->params, ctx->id("REG1_REGSET"), "RESET")); + cc.tiles[tname].add_enum(slice + ".REG0.LSRMODE", + str_or_default(ci->params, ctx->id("REG0_LSRMODE"), "LSR")); + cc.tiles[tname].add_enum(slice + ".REG1.LSRMODE", + str_or_default(ci->params, ctx->id("REG1_LSRMODE"), "LSR")); cc.tiles[tname].add_enum(slice + ".CEMUX", str_or_default(ci->params, ctx->id("CEMUX"), "1")); if (ci->sliceInfo.using_dff) { diff --git a/ecp5/cells.cc b/ecp5/cells.cc index 9accdd55..b06350c7 100644 --- a/ecp5/cells.cc +++ b/ecp5/cells.cc @@ -243,6 +243,7 @@ void ff_to_slice(Context *ctx, CellInfo *ff, CellInfo *lc, int index, bool drive lc->params[ctx->id(reg + "_SD")] = std::string(driven_by_lut ? "1" : "0"); lc->params[ctx->id(reg + "_REGSET")] = str_or_default(ff->params, ctx->id("REGSET"), "RESET"); + lc->params[ctx->id(reg + "_LSRMODE")] = str_or_default(ff->params, ctx->id("LSRMODE"), "LSR"); replace_port_safe(has_ff, ff, ctx->id("CLK"), lc, ctx->id("CLK")); if (ff->ports.find(ctx->id("LSR")) != ff->ports.end()) replace_port_safe(has_ff, ff, ctx->id("LSR"), lc, ctx->id("LSR")); @@ -250,10 +251,21 @@ void ff_to_slice(Context *ctx, CellInfo *ff, CellInfo *lc, int index, bool drive replace_port_safe(has_ff, ff, ctx->id("CE"), lc, ctx->id("CE")); replace_port(ff, ctx->id("Q"), lc, ctx->id("Q" + std::to_string(index))); - if (driven_by_lut) { - replace_port(ff, ctx->id("DI"), lc, ctx->id("DI" + std::to_string(index))); + if (get_net_or_empty(ff, ctx->id("M")) != nullptr) { + // PRLD FFs that use both M and DI + NPNR_ASSERT(!driven_by_lut); + // As M is used; must route DI through a new LUT + lc->params[ctx->id(reg + "_SD")] = std::string("1"); + lc->params[ctx->id("LUT" + std::to_string(index) + "_INITVAL")] = Property(0xFF00, 16); + replace_port(ff, ctx->id("DI"), lc, ctx->id("D" + std::to_string(index))); + replace_port(ff, ctx->id("M"), lc, ctx->id("M" + std::to_string(index))); + connect_ports(ctx, lc, ctx->id("F" + std::to_string(index)), lc, ctx->id("DI" + std::to_string(index))); } else { - replace_port(ff, ctx->id("DI"), lc, ctx->id("M" + std::to_string(index))); + if (driven_by_lut) { + replace_port(ff, ctx->id("DI"), lc, ctx->id("DI" + std::to_string(index))); + } else { + replace_port(ff, ctx->id("DI"), lc, ctx->id("M" + std::to_string(index))); + } } } diff --git a/ecp5/pack.cc b/ecp5/pack.cc index 09947d88..3867ab3d 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -112,7 +112,8 @@ class Ecp5Packer NetInfo *znet = ci->ports.at(ctx->id("Z")).net; if (znet != nullptr) { CellInfo *ff = net_only_drives(ctx, znet, is_ff, ctx->id("DI"), false); - if (ff != nullptr) { + // Can't combine preload FF with LUT due to conflict on M + if (ff != nullptr && get_net_or_empty(ff, ctx->id("M")) == nullptr) { lutffPairs[ci->name] = ff->name; fflutPairs[ff->name] = ci->name; } @@ -232,6 +233,8 @@ class Ecp5Packer // Return true if a FF can be added to a DPRAM slice bool can_pack_ff_dram(CellInfo *dpram, CellInfo *ff) { + if (get_net_or_empty(ff, ctx->id("M")) != nullptr) + return false; // skip PRLD FFs due to M/DI conflict std::string wckmux = str_or_default(dpram->params, ctx->id("WCKMUX"), "WCK"); std::string clkmux = str_or_default(ff->params, ctx->id("CLKMUX"), "CLK"); if (wckmux != clkmux && !(wckmux == "WCK" && clkmux == "CLK")) @@ -1178,7 +1181,8 @@ class Ecp5Packer CellInfo *ci = cell.second; if (is_ff(ctx, ci)) { bool pack_dense = used_slices > (dense_pack_mode_thresh * available_slices); - if (pack_dense) { + bool requires_m = get_net_or_empty(ci, ctx->id("M")) != nullptr; + if (pack_dense && !requires_m) { // If dense packing threshold exceeded; always try and pack the FF into an existing slice // Find a SLICE with space "near" the flipflop in the netlist std::vector ltile; -- cgit v1.2.3