nexus: Packing helper functions

Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
David Shah 2020-10-07 12:10:52 +01:00
parent 46536773f4
commit 2f822a3b79
2 changed files with 105 additions and 8 deletions

View File

@ -771,15 +771,26 @@ enum CellPinStyle
PINDEF_0 = 0x10, // connect to 0 if not used
PINDEF_1 = 0x20, // connect to 1 if not used
PINSTYLE_CIB = 0x11, // 'CIB' signal, floats high but explicitly zeroed if not used
PINSTYLE_CLK = 0x07, // CLK type signal, invertible and defaults to disconnected
PINSTYLE_CE = 0x27, // CE type signal, invertible and defaults to enabled
PINSTYLE_LSR = 0x17, // LSR type signal, invertible and defaults to not reset
PINSTYLE_DEDI = 0x00, // dedicated signals, leave alone
PINSTYLE_PU = 0x21, // signals that float high and default high
PINGLB_CLK = 0x100, // pin is a 'clock' for global purposes
PINSTYLE_INV_PD = 0x17, // invertible, pull down by default
PINSTYLE_INV_PU = 0x27, // invertible, pull up by default
PINSTYLE_CIB = 0x011, // 'CIB' signal, floats high but explicitly zeroed if not used
PINSTYLE_CLK = 0x107, // CLK type signal, invertible and defaults to disconnected
PINSTYLE_CE = 0x027, // CE type signal, invertible and defaults to enabled
PINSTYLE_LSR = 0x017, // LSR type signal, invertible and defaults to not reset
PINSTYLE_DEDI = 0x000, // dedicated signals, leave alone
PINSTYLE_PU = 0x021, // signals that float high and default high
PINSTYLE_INV_PD = 0x017, // invertible, pull down by default
PINSTYLE_INV_PU = 0x027, // invertible, pull up by default
};
// This represents the mux options for a pin
enum CellPinMux
{
PINMUX_SIG = 0,
PINMUX_0 = 1,
PINMUX_1 = 2,
PINMUX_INV = 3,
};
// -----------------------------------------------------------------------

View File

@ -261,6 +261,92 @@ struct NexusPacker
generic_xform(ff_rules, true);
}
std::unordered_map<IdString, BelId> reference_bels;
void autocreate_ports(CellInfo *cell)
{
// Automatically create ports for all inputs of a cell; even if they were left off the instantiation
// so we can tie them to constants as appropriate
// This also checks for any cells that don't have corresponding bels
if (!reference_bels.count(cell->type)) {
// We need to look up a corresponding bel to get the list of input ports
BelId ref_bel;
for (BelId bel : ctx->getBels()) {
if (ctx->getBelType(bel) != cell->type)
continue;
ref_bel = bel;
break;
}
if (ref_bel == BelId())
log_error("Cell type '%s' instantiated as '%s' is not supported by this device.\n",
ctx->nameOf(cell->type), ctx->nameOf(cell));
reference_bels[cell->type] = ref_bel;
}
BelId bel = reference_bels.at(cell->type);
for (IdString pin : ctx->getBelPins(bel)) {
PortType dir = ctx->getBelPinType(bel, pin);
if (dir != PORT_IN)
continue;
if (cell->ports.count(pin))
continue;
cell->ports[pin].name = pin;
cell->ports[pin].type = dir;
}
}
bool is_port_inverted(CellInfo *cell, IdString port)
{
NetInfo *net = get_net_or_empty(cell, port);
if (net == nullptr || net->driver.cell == nullptr)
return false;
return (net->driver.cell->type == id_INV);
}
void uninvert_port(CellInfo *cell, IdString port)
{
// Rewire a port so it is driven by the input to an inverter
NetInfo *net = get_net_or_empty(cell, port);
NPNR_ASSERT(net != nullptr && net->driver.cell != nullptr && net->driver.cell->type == id_INV);
CellInfo *inv = net->driver.cell;
disconnect_port(ctx, cell, port);
NetInfo *inv_a = get_net_or_empty(inv, id_A);
if (inv_a != nullptr) {
connect_port(ctx, inv_a, cell, port);
}
}
void trim_design()
{
// Remove unused inverters and high/low drivers
std::vector<IdString> trim_cells;
std::vector<IdString> trim_nets;
for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (ci->type != id_INV && ci->type != id_VLO && ci->type != id_VHI)
continue;
NetInfo *z = get_net_or_empty(ci, id_Z);
if (z == nullptr) {
trim_cells.push_back(ci->name);
continue;
}
if (!z->users.empty())
continue;
disconnect_port(ctx, ci, id_A);
trim_cells.push_back(ci->name);
trim_nets.push_back(z->name);
}
for (IdString rem_net : trim_nets)
ctx->nets.erase(rem_net);
for (IdString rem_cell : trim_cells)
ctx->cells.erase(rem_cell);
}
explicit NexusPacker(Context *ctx) : ctx(ctx) {}
void operator()()