machxo2: Add packing logic to handle FFs fed with constant value; UART test core routes.
This commit is contained in:
parent
3ab300a28e
commit
086bca18b8
@ -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) {}
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
||||
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).
|
||||
|
Loading…
Reference in New Issue
Block a user