aboutsummaryrefslogtreecommitdiffstats
path: root/machxo2
diff options
context:
space:
mode:
authorWilliam D. Jones <thor0505@comcast.net>2021-06-30 15:23:09 -0400
committerWilliam D. Jones <thor0505@comcast.net>2021-07-01 09:59:53 -0400
commit41d09f71871184aabbd7495a485e257fc0450d40 (patch)
treea57e46a0fcbcd4bb90551100fe32bbdbcecec0c0 /machxo2
parente625876949795ea3c0bc9b3071cbb45451cc1a16 (diff)
downloadnextpnr-41d09f71871184aabbd7495a485e257fc0450d40.tar.gz
nextpnr-41d09f71871184aabbd7495a485e257fc0450d40.tar.bz2
nextpnr-41d09f71871184aabbd7495a485e257fc0450d40.zip
machxo2: Fix packing for directly-connected DFFs.
Diffstat (limited to 'machxo2')
-rw-r--r--machxo2/cells.cc17
-rw-r--r--machxo2/cells.h12
-rw-r--r--machxo2/pack.cc8
3 files changed, 28 insertions, 9 deletions
diff --git a/machxo2/cells.cc b/machxo2/cells.cc
index 9b463147..7334234d 100644
--- a/machxo2/cells.cc
+++ b/machxo2/cells.cc
@@ -154,7 +154,7 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
replace_port(lut, ctx->id("Z"), lc, ctx->id("F0"));
}
-void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut)
+void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, LutType lut_type)
{
// FIXME: This will have to change once we support FFs with reset value of 1.
lc->params[ctx->id("REG0_REGSET")] = std::string("RESET");
@@ -163,14 +163,21 @@ void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut)
replace_port(dff, ctx->id("LSR"), lc, ctx->id("LSR"));
replace_port(dff, ctx->id("Q"), lc, ctx->id("Q0"));
- // If a register's DI port is fed by a constant, options for placing are
- // limited. Use the LUT to get around this.
- if (pass_thru_lut) {
+ if (lut_type == LutType::PassThru) {
+ // If a register's DI port is fed by a constant, options for placing are
+ // limited. Use the LUT to get around this.
+ // LUT output will go to F0, which will feed back to DI0 input.
lc->params[ctx->id("LUT0_INITVAL")] = Property(0xAAAA, 16);
- ;
replace_port(dff, ctx->id("DI"), lc, ctx->id("A0"));
connect_ports(ctx, lc, ctx->id("F0"), lc, ctx->id("DI0"));
+ } else if (lut_type == LutType::None) {
+ // If there is no LUT, use the M0 input because DI0 requires
+ // going through the LUTs.
+ lc->params[ctx->id("REG0_SD")] = std::string("0");
+ replace_port(dff, ctx->id("DI"), lc, ctx->id("M0"));
} else {
+ // Otherwise, there's a LUT being used in the slice and mapping DI to
+ // DI0 input is fine.
replace_port(dff, ctx->id("DI"), lc, ctx->id("DI0"));
}
}
diff --git a/machxo2/cells.h b/machxo2/cells.h
index d26fdfa0..409b68b1 100644
--- a/machxo2/cells.h
+++ b/machxo2/cells.h
@@ -25,6 +25,16 @@
NEXTPNR_NAMESPACE_BEGIN
+// When packing DFFs, we need context of how it's connected to a LUT to
+// properly map DFF ports to FACADE_SLICEs; DI0 input muxes F0 and OFX0,
+// and a DFF inside a slice can use either DI0 or M0 as an input.
+enum class LutType
+{
+ None,
+ Normal,
+ PassThru,
+};
+
// 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 = "");
@@ -46,7 +56,7 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff = tr
// and reconnecting signals as necessary. If pass_thru_lut is True, the LUT will
// be configured as pass through and D connected to I0, otherwise D will be
// ignored
-void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut = false);
+void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, LutType lut_type = LutType::Normal);
// Convert a nextpnr IO buffer to a GENERIC_IOB
void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &todelete_cells);
diff --git a/machxo2/pack.cc b/machxo2/pack.cc
index a8a2a671..66d2d411 100644
--- a/machxo2/pack.cc
+++ b/machxo2/pack.cc
@@ -62,7 +62,7 @@ static void pack_lut_lutffs(Context *ctx)
// Locations don't match, can't pack
} else {
lut_to_lc(ctx, ci, packed.get(), false);
- dff_to_lc(ctx, dff, packed.get(), false);
+ dff_to_lc(ctx, dff, packed.get(), LutType::Normal);
if (dff_bel != dff->attrs.end())
packed->attrs[ctx->id("BEL")] = dff_bel->second;
packed_cells.insert(dff->name);
@@ -105,7 +105,9 @@ static void pack_remaining_ffs(Context *ctx)
packed->attrs[attr.first] = attr.second;
auto dff_bel = ci->attrs.find(ctx->id("BEL"));
- dff_to_lc(ctx, ci, packed.get(), false);
+
+ dff_to_lc(ctx, ci, packed.get(), LutType::None);
+
if (dff_bel != ci->attrs.end())
packed->attrs[ctx->id("BEL")] = dff_bel->second;
packed_cells.insert(ci->name);
@@ -146,7 +148,7 @@ static void set_net_constant(Context *ctx, NetInfo *orig, NetInfo *constnet, boo
for (auto &attr : uc->attrs)
lc->attrs[attr.first] = attr.second;
- dff_to_lc(ctx, uc, lc.get(), true);
+ dff_to_lc(ctx, uc, lc.get(), LutType::PassThru);
packed_cells.insert(uc->name);
lc->ports[id_A0].net = constnet;