diff options
Diffstat (limited to 'machxo2')
-rw-r--r-- | machxo2/cells.cc | 13 | ||||
-rw-r--r-- | machxo2/cells.h | 2 | ||||
-rw-r--r-- | machxo2/pack.cc | 29 |
3 files changed, 39 insertions, 5 deletions
diff --git a/machxo2/cells.cc b/machxo2/cells.cc index 20e68ab5..7d15b1af 100644 --- a/machxo2/cells.cc +++ b/machxo2/cells.cc @@ -154,15 +154,24 @@ 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(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut) +void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut) { // FIXME: This will have to change once we support FFs with reset value of 1. lc->params[ctx->id("REG0_REGSET")] = std::string("RESET"); 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")); + + // 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) { + lc->params[ctx->id("LUT0_INITVAL")] = 0xAAAA; + replace_port(dff, ctx->id("DI"), lc, ctx->id("A0")); + connect_ports(ctx, lc, ctx->id("F0"), lc, ctx->id("DI0")); + } else { + replace_port(dff, ctx->id("DI"), lc, ctx->id("DI0")); + } } 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 351780ec..a6de219e 100644 --- a/machxo2/cells.h +++ b/machxo2/cells.h @@ -46,7 +46,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(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut = false); +void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut = false); // Convert a nextpnr IO buffer to a GENERIC_IOB void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, std::unordered_set<IdString> &todelete_cells); diff --git a/machxo2/pack.cc b/machxo2/pack.cc index 47f8c907..786a84d6 100644 --- a/machxo2/pack.cc +++ b/machxo2/pack.cc @@ -124,10 +124,13 @@ static void pack_remaining_ffs(Context *ctx) } // Merge a net into a constant net -static void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constnet, bool constval) +static void set_net_constant(Context *ctx, NetInfo *orig, NetInfo *constnet, bool constval) { (void)constval; + std::unordered_set<IdString> packed_cells; + std::vector<std::unique_ptr<CellInfo>> new_cells; + orig->driver.cell = nullptr; for (auto user : orig->users) { if (user.cell != nullptr) { @@ -135,11 +138,33 @@ static void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constne if (ctx->verbose) log_info("%s user %s\n", orig->name.c_str(ctx), uc->name.c_str(ctx)); - uc->ports[user.port].net = constnet; + if(uc->type == id_FACADE_FF && user.port == id_DI) { + log_info("FACADE_FF %s is driven by a constant\n", uc->name.c_str(ctx)); + + std::unique_ptr<CellInfo> lc = create_machxo2_cell(ctx, id_FACADE_SLICE, uc->name.str(ctx) + "_CONST"); + dff_to_lc(ctx, uc, lc.get(), true); + packed_cells.insert(uc->name); + + lc->ports[id_A0].net = constnet; + user.cell = lc.get(); + user.port = id_A0; + + new_cells.push_back(std::move(lc)); + } else { + uc->ports[user.port].net = constnet; + } + constnet->users.push_back(user); } } orig->users.clear(); + + for (auto pcell : packed_cells) { + ctx->cells.erase(pcell); + } + for (auto &ncell : new_cells) { + ctx->cells[ncell->name] = std::move(ncell); + } } // Pack constants (based on simple implementation in generic). |