diff --git a/nexus/arch.h b/nexus/arch.h index 55e9becd55c..14dfd63e5c5 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -785,9 +785,10 @@ enum CellPinStyle PINDEF_MASK = 0x30, - PINGLB_CLK = 0x100, // pin is a 'clock' for global purposes + PINGLB_CLK = 0x100, // pin is a 'clock' for global purposes + PINGLB_CE_LSR = 0x200, // pin is CE/LSR for global purposes - PINGLB_MASK = 0x100, + PINGLB_MASK = 0x300, 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 @@ -796,8 +797,8 @@ enum CellPinStyle PINSTYLE_NONE = 0x0000, // default 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_CE = 0x0227, // CE type signal, invertible and defaults to enabled + PINSTYLE_LSR = 0x0217, // LSR type signal, invertible and defaults to not reset PINSTYLE_DEDI = 0x0000, // dedicated signals, leave alone PINSTYLE_PU = 0x4022, // signals that float high and default high PINSTYLE_PU_NONCIB = 0x0022, // signals that float high and default high diff --git a/nexus/pack.cc b/nexus/pack.cc index 66ab4b095ba..93a06443d90 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -853,7 +853,9 @@ struct NexusPacker void promote_globals() { std::vector> clk_fanout; - int available_globals = 16; + std::vector> ce_lsr_fanout; + // TODO: if we are more cunning about placement, the real limits are 16 per device half and 8 per row segment + int available_globals = 8; for (auto net : sorted(ctx->nets)) { NetInfo *ni = net.second; // Skip undriven nets; and nets that are already global @@ -864,19 +866,25 @@ struct NexusPacker continue; } // Count the number of clock ports - int clk_count = 0; + int clk_count = 0, ce_lsr_count = 0; for (const auto &usr : ni->users) { auto port_style = ctx->get_cell_pin_style(usr.cell, usr.port); if (port_style & PINGLB_CLK) ++clk_count; + if (port_style & PINGLB_CE_LSR) + ++ce_lsr_count; } if (clk_count > 0) clk_fanout.emplace_back(clk_count, ni->name); + if (ce_lsr_count > 150) + ce_lsr_fanout.emplace_back(ce_lsr_count, ni->name); } if (available_globals <= 0) return; // Sort clocks by max fanout std::sort(clk_fanout.begin(), clk_fanout.end(), std::greater>()); + std::sort(ce_lsr_fanout.begin(), ce_lsr_fanout.end(), std::greater>()); + log_info("Promoting globals...\n"); // Promote the N highest fanout clocks for (size_t i = 0; i < std::min(clk_fanout.size(), available_globals); i++) { @@ -884,6 +892,15 @@ struct NexusPacker log_info(" promoting clock net '%s'\n", ctx->nameOf(net)); insert_buffer(net, id_DCC, "glb_clk", id_CLKI, id_CLKO, [](const PortRef &port) { return true; }); } + // Limit to 6 LSR/CE to avoid routeability issues + int available_ce_lsr_globals = std::min(available_globals, 6); + for (size_t i = 0; i < std::min(clk_fanout.size(), available_ce_lsr_globals); i++) { + NetInfo *net = ctx->nets.at(ce_lsr_fanout.at(i).second).get(); + log_info(" promoting CE/LSR net '%s'\n", ctx->nameOf(net)); + insert_buffer(net, id_DCC, "glb_ce_lsr", id_CLKI, id_CLKO, [this](const PortRef &port) { + return ctx->get_cell_pin_style(port.cell, port.port) & PINGLB_CE_LSR; + }); + } } // Place certain global cells