From da1e3c8612e9b63c91340142a9bf4529ac5f056a Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 13 Oct 2020 14:15:29 +0100 Subject: nexus: Add constant/inversion packing Signed-off-by: David Shah --- nexus/arch.h | 12 +++++++----- nexus/fasm.cc | 47 ++++++++++++++++++++++++++++++++++++++++++----- nexus/pack.cc | 28 +++++++++++++++++++++++++--- nexus/pins.cc | 8 ++++---- 4 files changed, 78 insertions(+), 17 deletions(-) (limited to 'nexus') diff --git a/nexus/arch.h b/nexus/arch.h index 4da60706..d5481bac 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -783,19 +783,21 @@ enum CellPinStyle PINGLB_MASK = 0x100, - PINBIT_GATED = 0x1000, // pin must be enabled in bitstream if used - PINBIT_1 = 0x2000, // pin has an explicit bit that must be set if tied to 1 + PINBIT_GATED = 0x1000, // pin must be enabled in bitstream if used + PINBIT_1 = 0x2000, // pin has an explicit bit that must be set if tied to 1 + PINBIT_CIBMUX = 0x4000, // pin's CIBMUX must be floating for pin to be 1 PINSTYLE_NONE = 0x0000, // default - PINSTYLE_CIB = 0x0012, // 'CIB' signal, floats high but explicitly zeroed if not used + PINSTYLE_CIB = 0x4012, // 'CIB' signal, floats high but explicitly zeroed if not used PINSTYLE_CLK = 0x0107, // CLK type signal, invertible and defaults to disconnected PINSTYLE_CE = 0x0027, // CE type signal, invertible and defaults to enabled PINSTYLE_LSR = 0x0017, // LSR type signal, invertible and defaults to not reset PINSTYLE_DEDI = 0x0000, // dedicated signals, leave alone - PINSTYLE_PU = 0x0022, // signals that float high and default high + PINSTYLE_PU = 0x4022, // signals that float high and default high + PINSTYLE_T = 0x4027, // PIO 'T' signal PINSTYLE_INV_PD = 0x0017, // invertible, pull down by default - PINSTYLE_INV_PU = 0x0027, // invertible, pull up by default + PINSTYLE_INV_PU = 0x4027, // invertible, pull up by default PINSTYLE_IOL_CE = 0x2027, // CE type signal, with explicit 'const-1' config bit PINSTYLE_GATE = 0x1011, // gated signal that defaults to 0 diff --git a/nexus/fasm.cc b/nexus/fasm.cc index 50b41e06..3029f4dc 100644 --- a/nexus/fasm.cc +++ b/nexus/fasm.cc @@ -170,7 +170,7 @@ struct NexusFasmWriter std::string tile = tile_name(pip.tile, tile_by_type_and_loc(pip.tile, pd.tile_type)); std::string source_wire = escape_name(ctx->pip_src_wire_name(pip).str(ctx)); std::string dest_wire = escape_name(ctx->pip_dst_wire_name(pip).str(ctx)); - write_bit(stringf("%s.PIP.%s.%s", tile.c_str(), dest_wire.c_str(), source_wire.c_str())); + out << stringf("%s.PIP.%s.%s", tile.c_str(), dest_wire.c_str(), source_wire.c_str()) << std::endl; } // Write out all the pips corresponding to a net void write_net(const NetInfo *net) @@ -184,6 +184,25 @@ struct NexusFasmWriter write_pip(p); blank(); } + // Find the CIBMUX output for a signal + WireId find_cibmux(const CellInfo *cell, IdString pin) + { + WireId cursor = ctx->getBelPinWire(cell->bel, pin); + if (cursor == WireId()) + return WireId(); + for (int i = 0; i < 10; i++) { + std::string cursor_name = IdString(ctx->wire_data(cursor).name).str(ctx); + if (cursor_name.find("JCIBMUXOUT") == 0) { + return cursor; + } + for (PipId pip : ctx->getPipsUphill(cursor)) + if (ctx->checkPipAvail(pip)) { + cursor = ctx->getPipSrcWire(pip); + break; + } + } + return WireId(); + } // Write out the mux config for a cell void write_cell_muxes(const CellInfo *cell) { @@ -206,8 +225,26 @@ struct NexusFasmWriter // Pins that must be explictly set to 1 rather than just left floating if ((pin_style & PINBIT_1) && (pin_mux == PINMUX_1)) write_bit(stringf("%sMUX.1", ctx->nameOf(port.first))); + // Handle CIB muxes - these must be set such that floating pins really are floating to VCC and not connected + // to another CIB signal + if ((pin_style & PINBIT_CIBMUX) && port.second.net == nullptr) { + WireId cibmuxout = find_cibmux(cell, port.first); + if (cibmuxout != WireId()) { + write_comment(stringf("CIBMUX for unused pin %s", ctx->nameOf(port.first))); + bool found = false; + for (PipId pip : ctx->getPipsUphill(cibmuxout)) { + if (ctx->checkPipAvail(pip) && ctx->checkWireAvail(ctx->getPipSrcWire(pip))) { + write_pip(pip); + found = true; + break; + } + } + NPNR_ASSERT(found); + } + } } } + // Write config for an OXIDE_COMB cell void write_comb(const CellInfo *cell) { @@ -244,10 +281,7 @@ struct NexusFasmWriter pop(); write_enum(cell, "REGDDR"); write_enum(cell, "SRMODE"); - write_enum(cell, "CLKMUX"); - write_enum(cell, "CEMUX"); - write_enum(cell, "LSRMUX"); - write_enum(cell, "GSR"); + write_cell_muxes(cell); pop(2); } // Write config for an SEIO33_CORE cell @@ -267,6 +301,7 @@ struct NexusFasmWriter const char *iodir = is_input ? "INPUT" : (is_output ? "OUTPUT" : "BIDIR"); write_bit(stringf("BASE_TYPE.%s_%s", iodir, str_or_default(cell->attrs, id_IO_TYPE, "LVCMOS33").c_str())); write_ioattr(cell, "PULLMODE", "NONE"); + write_cell_muxes(cell); pop(2); } // Write config for an SEIO18_CORE cell @@ -287,6 +322,7 @@ struct NexusFasmWriter const char *iodir = is_input ? "INPUT" : (is_output ? "OUTPUT" : "BIDIR"); write_bit(stringf("BASE_TYPE.%s_%s", iodir, str_or_default(cell->attrs, id_IO_TYPE, "LVCMOS18H").c_str())); write_ioattr(cell, "PULLMODE", "NONE"); + write_cell_muxes(cell); pop(3); } // Write config for an OSC_CORE cell @@ -302,6 +338,7 @@ struct NexusFasmWriter write_enum(cell, "LF_OUTPUT_EN"); write_enum(cell, "DEBUG_N", "DISABLED"); write_int_vector(stringf("HF_CLK_DIV[7:0]"), ctx->parse_lattice_param(cell, id_HF_CLK_DIV, 8, 0).intval, 8); + write_cell_muxes(cell); pop(2); } // Write out FASM for the whole design diff --git a/nexus/pack.cc b/nexus/pack.cc index b9472ed1..e9b4336d 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -321,7 +321,12 @@ struct NexusPacker { NetInfo *net = get_net_or_empty(cell, port); if (net == nullptr || net->driver.cell == nullptr) { - // Pin is disconnected, return its default value + // Pin is disconnected + // If a mux value exists already, honour it + CellPinMux exist_mux = ctx->get_cell_pinmux(cell, port); + if (exist_mux != PINMUX_SIG) + return exist_mux; + // Otherwise, look up the default value and use that CellPinStyle pin_style = ctx->get_cell_pin_style(cell, port); if ((pin_style & PINDEF_MASK) == PINDEF_0) return PINMUX_0; @@ -434,7 +439,7 @@ struct NexusPacker if (req_mux == PINMUX_INV) { // Pin is inverted. If there is a hard inverter; then use it - if ((pin_style & PINOPT_MASK) == PINOPT_INV) { + if (pin_style & PINOPT_INV) { uninvert_port(cell, port_name); ctx->set_cell_pinmux(cell, port_name, PINMUX_INV); } @@ -624,13 +629,30 @@ struct NexusPacker } } + void pack_constants() + { + // Make sure we have high and low nets available + get_const_net(id_VHI); + get_const_net(id_VLO); + // Iterate through cells + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + // Skip certain cells at this point + if (ci->type != id_LUT4 && ci->type != id_INV && ci->type != id_VHI && ci->type != id_VLO) + process_inv_constants(cell.second); + } + // Remove superfluous inverters and constant drivers + trim_design(); + } + explicit NexusPacker(Context *ctx) : ctx(ctx) {} void operator()() { + pack_io(); pack_ffs(); + pack_constants(); pack_luts(); - pack_io(); } }; diff --git a/nexus/pins.cc b/nexus/pins.cc index 33015add..f9ddd5f5 100644 --- a/nexus/pins.cc +++ b/nexus/pins.cc @@ -48,15 +48,15 @@ static const std::unordered_map base_cell_pin_data }}, {id_SEIO18_CORE, { - {id_T, PINSTYLE_CE}, + {id_T, PINSTYLE_T}, {id_B, PINSTYLE_DEDI}, - {{}, PINSTYLE_INV_PU}, + {{}, PINSTYLE_PU}, }}, {id_SEIO33_CORE, { - {id_T, PINSTYLE_CE}, + {id_T, PINSTYLE_T}, {id_B, PINSTYLE_DEDI}, - {{}, PINSTYLE_INV_PU}, + {{}, PINSTYLE_PU}, }}, {id_OXIDE_EBR, {{id_CLKA, PINSTYLE_CLK}, {id_CLKB, PINSTYLE_CLK}, {id_CEA, PINSTYLE_CE}, {id_CEB, PINSTYLE_CE}, {id_CSA0, PINSTYLE_PU}, {id_CSA1, PINSTYLE_PU}, -- cgit v1.2.3