diff --git a/nexus/arch.cc b/nexus/arch.cc index f343096836..6192a19b87 100644 --- a/nexus/arch.cc +++ b/nexus/arch.cc @@ -178,6 +178,7 @@ Arch::Arch(ArchArgs args) : args(args) // some tweaks to accomodate properly if (getBelType(bel) != id_DCC) continue; + disabled_bels.insert(bel); WireId w = getBelPinWire(bel, id_CLKI); for (auto pip : getPipsUphill(w)) disabled_pips.insert(pip); diff --git a/nexus/arch.h b/nexus/arch.h index 4d2649fd7e..0d24515fba 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 @@ -920,6 +921,7 @@ struct Arch : BaseArch dict id_to_x, id_to_y; pool disabled_pips; + pool disabled_bels; // ------------------------------------------------- diff --git a/nexus/arch_place.cc b/nexus/arch_place.cc index 7b2c08ee4c..cb288175ff 100644 --- a/nexus/arch_place.cc +++ b/nexus/arch_place.cc @@ -105,6 +105,10 @@ bool Arch::isBelLocationValid(BelId bel) const else return nexus_logic_tile_valid(*lts); } else { + if (getBelType(bel) == id_DCC) { + if (getBoundBelCell(bel) != nullptr && disabled_bels.count(bel)) + return false; + } return true; } } diff --git a/nexus/global.cc b/nexus/global.cc index 1c763a3100..dd1a2d5690 100644 --- a/nexus/global.cc +++ b/nexus/global.cc @@ -107,6 +107,10 @@ struct NexusGlobalRouter while (!visit.empty() && (iter++ < iter_limit)) { WireId cursor = visit.front(); visit.pop(); + if (ctx->getBoundWireNet(cursor) == net) { + src = cursor; + break; + } // Search uphill pips for (PipId pip : ctx->getPipsUphill(cursor)) { // Skip pip if unavailable, and not because it's already used for this net diff --git a/nexus/pack.cc b/nexus/pack.cc index 6385121b28..d233bdc7e0 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -852,7 +852,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 : ctx->nets) { NetInfo *ni = net.second.get(); // Skip undriven nets; and nets that are already global @@ -863,19 +865,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++) { @@ -883,6 +891,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 1 LSR/CE to avoid routeability issues + int available_ce_lsr_globals = std::min(available_globals, 1); + for (size_t i = 0; i < std::min(ce_lsr_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