machxo2: Add packing logic to handle FFs fed with constant value; UART test core routes.

This commit is contained in:
William D. Jones 2021-02-02 09:55:42 -05:00 committed by gatecat
parent 3ab300a28e
commit 086bca18b8
3 changed files with 39 additions and 5 deletions

View File

@ -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")); 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. // FIXME: This will have to change once we support FFs with reset value of 1.
lc->params[ctx->id("REG0_REGSET")] = std::string("RESET"); lc->params[ctx->id("REG0_REGSET")] = std::string("RESET");
replace_port(dff, ctx->id("CLK"), lc, ctx->id("CLK")); 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("LSR"), lc, ctx->id("LSR"));
replace_port(dff, ctx->id("Q"), lc, ctx->id("Q0")); 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) {} void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, std::unordered_set<IdString> &todelete_cells) {}

View File

@ -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 // 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 // be configured as pass through and D connected to I0, otherwise D will be
// ignored // 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 // 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); void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *sbio, std::unordered_set<IdString> &todelete_cells);

View File

@ -124,10 +124,13 @@ static void pack_remaining_ffs(Context *ctx)
} }
// Merge a net into a constant net // 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; (void)constval;
std::unordered_set<IdString> packed_cells;
std::vector<std::unique_ptr<CellInfo>> new_cells;
orig->driver.cell = nullptr; orig->driver.cell = nullptr;
for (auto user : orig->users) { for (auto user : orig->users) {
if (user.cell != nullptr) { if (user.cell != nullptr) {
@ -135,11 +138,33 @@ static void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constne
if (ctx->verbose) if (ctx->verbose)
log_info("%s user %s\n", orig->name.c_str(ctx), uc->name.c_str(ctx)); 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); constnet->users.push_back(user);
} }
} }
orig->users.clear(); 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). // Pack constants (based on simple implementation in generic).