aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylvain Munaut <tnt@246tNt.com>2019-04-17 06:51:11 +0200
committerSylvain Munaut <tnt@246tNt.com>2019-04-17 14:06:23 +0200
commit6387a3d33e51db9ececc630b3d0a1f947dd43bd8 (patch)
treeee692b665a79db5c9890bdda4cb51822ff79ddc1
parent9dd68aa0e2054fef723b3a183d04768cc8d80e77 (diff)
downloadnextpnr-6387a3d33e51db9ececc630b3d0a1f947dd43bd8.tar.gz
nextpnr-6387a3d33e51db9ececc630b3d0a1f947dd43bd8.tar.bz2
nextpnr-6387a3d33e51db9ececc630b3d0a1f947dd43bd8.zip
ice40: Only create padin gbuf for PLLs if global output actually used
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
-rw-r--r--ice40/pack.cc49
1 files changed, 38 insertions, 11 deletions
diff --git a/ice40/pack.cc b/ice40/pack.cc
index 6f528cd6..2ba0bb5a 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -868,16 +868,26 @@ static void place_plls(Context *ctx)
BelId gb_bel = ctx->getBelByName(ctx->id(gb_ci->attrs[ctx->id("BEL")]));
for (auto placed_pll : pll_used_bels) {
+ CellInfo *ci = placed_pll.second;
+
+ // Used global connections
+ bool gb_a_used = ci->ports.count(id_PLLOUT_A_GLOBAL) && (ci->ports[id_PLLOUT_A_GLOBAL].net != nullptr) &&
+ (ci->ports[id_PLLOUT_A_GLOBAL].net->users.size() > 0);
+ bool gb_b_used = is_sb_pll40_dual(ctx, ci) && ci->ports.count(id_PLLOUT_B_GLOBAL) &&
+ (ci->ports[id_PLLOUT_B_GLOBAL].net != nullptr) &&
+ (ci->ports[id_PLLOUT_B_GLOBAL].net->users.size() > 0);
+
+ // Check for conflict
BelPin pll_io_a, pll_io_b;
BelId gb_a, gb_b;
std::tie(pll_io_a, gb_a, pll_io_b, gb_b) = pll_all_bels[placed_pll.first];
- if (gb_bel == gb_a) {
+ if (gb_a_used && (gb_bel == gb_a)) {
log_error("PLL '%s' A output conflict with SB_GB '%s'\n", placed_pll.second->name.c_str(ctx),
gb_cell.second->name.c_str(ctx));
- } else if (gb_bel == gb_b) {
- if (is_sb_pll40_dual(ctx, placed_pll.second))
- log_error("PLL '%s' B output conflicts with SB_GB '%s'\n", placed_pll.second->name.c_str(ctx),
- gb_cell.second->name.c_str(ctx));
+ }
+ if (gb_b_used && (gb_bel == gb_b)) {
+ log_error("PLL '%s' B output conflicts with SB_GB '%s'\n", placed_pll.second->name.c_str(ctx),
+ gb_cell.second->name.c_str(ctx));
}
}
@@ -903,6 +913,13 @@ static void place_plls(Context *ctx)
log_error("PLL '%s' is of CORE type but doesn't have a valid REFERENCECLK connection\n",
ci->name.c_str(ctx));
+ // Used global connections
+ bool gb_a_used = ci->ports.count(id_PLLOUT_A_GLOBAL) && (ci->ports[id_PLLOUT_A_GLOBAL].net != nullptr) &&
+ (ci->ports[id_PLLOUT_A_GLOBAL].net->users.size() > 0);
+ bool gb_b_used = is_sb_pll40_dual(ctx, ci) && ci->ports.count(id_PLLOUT_B_GLOBAL) &&
+ (ci->ports[id_PLLOUT_B_GLOBAL].net != nullptr) &&
+ (ci->ports[id_PLLOUT_B_GLOBAL].net->users.size() > 0);
+
// Could this be a PAD PLL ?
bool could_be_pad = false;
BelId pad_bel;
@@ -924,9 +941,9 @@ static void place_plls(Context *ctx)
}
if (bel2io.count(pll_io_b.bel) && is_sb_pll40_dual(ctx, ci))
continue;
- if (bel2gb.count(gb_a))
+ if (gb_a_used && bel2gb.count(gb_a))
continue;
- if (bel2gb.count(gb_b) && is_sb_pll40_dual(ctx, ci))
+ if (gb_b_used && bel2gb.count(gb_b))
continue;
found_bel = bel_pll.first;
break;
@@ -1337,10 +1354,20 @@ static void pack_special(Context *ctx)
else
continue;
- std::unique_ptr<CellInfo> gb =
- create_padin_gbuf(ctx, packed.get(), pi.name,
- "$gbuf_" + ci->name.str(ctx) + "_pllout_" + (is_b_port ? "b" : "a"));
- new_cells.push_back(std::move(gb));
+ // Only if there is actually a net ...
+ if (pi.net != nullptr) {
+ // ... and it's used
+ if (pi.net->users.size() > 0) {
+ std::unique_ptr<CellInfo> gb =
+ create_padin_gbuf(ctx, packed.get(), pi.name,
+ "$gbuf_" + ci->name.str(ctx) + "_pllout_" + (is_b_port ? "b" : "a"));
+ new_cells.push_back(std::move(gb));
+ } else {
+ // If not, remove it to avoid routing issues
+ ctx->nets.erase(pi.net->name);
+ packed->ports[pi.name].net = nullptr;
+ }
+ }
}
new_cells.push_back(std::move(packed));