From 584e8c58a61748b88639336ad5defb41d5389c3a Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Mon, 26 Nov 2018 11:05:18 +0100 Subject: ice40: During global promotion, only promote if this will actually fit ! We need to take into account the global networks that are already used and possibly locked to know what we can promote since all networks can't drive resets / clock-enables Signed-off-by: Sylvain Munaut --- ice40/pack.cc | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'ice40') diff --git a/ice40/pack.cc b/ice40/pack.cc index 682baadd..fc28121e 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -587,10 +587,36 @@ static void promote_globals(Context *ctx) } } int prom_globals = 0, prom_resets = 0, prom_cens = 0, prom_logics = 0; - int gbs_available = 8; + int gbs_available = 8, resets_available = 4, cens_available = 4; for (auto &cell : ctx->cells) - if (is_gbuf(ctx, cell.second.get())) + if (is_gbuf(ctx, cell.second.get())) { + /* One less buffer available */ --gbs_available; + + /* And possibly limits what we can promote */ + if (cell.second->attrs.find(ctx->id("BEL")) != cell.second->attrs.end()) { + /* If the SB_GB is locked, doesn't matter what it drives */ + BelId bel = ctx->getBelByName(ctx->id(cell.second->attrs[ctx->id("BEL")])); + int glb_id = ctx->getDrivenGlobalNetwork(bel); + if ((glb_id % 2) == 0) + resets_available--; + else if ((glb_id % 2) == 1) + cens_available--; + } else { + /* If it's free to move around, then look at what it drives */ + NetInfo *ni = cell.second->ports[id_GLOBAL_BUFFER_OUTPUT].net; + + for (auto user : ni->users) { + if (is_reset_port(ctx, user)) { + resets_available--; + break; + } else if (is_enable_port(ctx, user)) { + cens_available--; + break; + } + } + } + } while (prom_globals < gbs_available) { auto global_clock = std::max_element(clock_count.begin(), clock_count.end(), [](const std::pair &a, const std::pair &b) { @@ -610,8 +636,8 @@ static void promote_globals(Context *ctx) return a.second < b.second; }); if (global_clock->second == 0 && prom_logics < 4 && global_logic->second > logic_fanout_thresh && - (global_logic->second > global_cen->second || prom_cens >= 4) && - (global_logic->second > global_reset->second || prom_resets >= 4)) { + (global_logic->second > global_cen->second || prom_cens >= cens_available) && + (global_logic->second > global_reset->second || prom_resets >= resets_available)) { NetInfo *logicnet = ctx->nets[global_logic->first].get(); insert_global(ctx, logicnet, false, false, true); ++prom_globals; @@ -620,7 +646,7 @@ static void promote_globals(Context *ctx) reset_count.erase(logicnet->name); cen_count.erase(logicnet->name); logic_count.erase(logicnet->name); - } else if (global_reset->second > global_clock->second && prom_resets < 4) { + } else if (global_reset->second > global_clock->second && prom_resets < resets_available) { NetInfo *rstnet = ctx->nets[global_reset->first].get(); insert_global(ctx, rstnet, true, false, false); ++prom_globals; @@ -629,7 +655,7 @@ static void promote_globals(Context *ctx) reset_count.erase(rstnet->name); cen_count.erase(rstnet->name); logic_count.erase(rstnet->name); - } else if (global_cen->second > global_clock->second && prom_cens < 4 && + } else if (global_cen->second > global_clock->second && prom_cens < cens_available && global_cen->second > enable_fanout_thresh) { NetInfo *cennet = ctx->nets[global_cen->first].get(); insert_global(ctx, cennet, false, true, false); -- cgit v1.2.3