aboutsummaryrefslogtreecommitdiffstats
path: root/nexus
diff options
context:
space:
mode:
Diffstat (limited to 'nexus')
-rw-r--r--nexus/arch.h29
-rw-r--r--nexus/pack.cc86
2 files changed, 106 insertions, 9 deletions
diff --git a/nexus/arch.h b/nexus/arch.h
index 0b058bd7..47276f42 100644
--- a/nexus/arch.h
+++ b/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
-
- PINSTYLE_INV_PD = 0x17, // invertible, pull down by default
- PINSTYLE_INV_PU = 0x27, // invertible, pull up by default
+ PINGLB_CLK = 0x100, // pin is a 'clock' for global purposes
+
+ 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,
};
// -----------------------------------------------------------------------
diff --git a/nexus/pack.cc b/nexus/pack.cc
index eb740858..f367c3f8 100644
--- a/nexus/pack.cc
+++ b/nexus/pack.cc
@@ -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()()