nexus: Packing helper functions
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
46536773f4
commit
2f822a3b79
27
nexus/arch.h
27
nexus/arch.h
@ -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,
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
@ -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()()
|
||||
|
Loading…
Reference in New Issue
Block a user