nexus: Promote CE/LSR globals

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2021-05-06 17:21:22 +01:00
parent 01b51fb715
commit 68e4d18339
5 changed files with 34 additions and 6 deletions

View File

@ -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);

View File

@ -786,8 +786,9 @@ enum CellPinStyle
PINDEF_MASK = 0x30,
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<ArchRanges>
dict<IdString, int> id_to_x, id_to_y;
pool<PipId> disabled_pips;
pool<BelId> disabled_bels;
// -------------------------------------------------

View File

@ -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;
}
}

View File

@ -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

View File

@ -852,7 +852,9 @@ struct NexusPacker
void promote_globals()
{
std::vector<std::pair<int, IdString>> clk_fanout;
int available_globals = 16;
std::vector<std::pair<int, IdString>> 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::pair<int, IdString>>());
std::sort(ce_lsr_fanout.begin(), ce_lsr_fanout.end(), std::greater<std::pair<int, IdString>>());
log_info("Promoting globals...\n");
// Promote the N highest fanout clocks
for (size_t i = 0; i < std::min<size_t>(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<int>(available_globals, 1);
for (size_t i = 0; i < std::min<size_t>(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