aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2020-10-15 09:44:21 +0100
committerDavid Shah <dave@ds0.me>2020-11-30 08:45:27 +0000
commit7645354917b93417ebeef974f5ca8961c9a1a3c8 (patch)
tree291c2285982fb0687cb28b7447500628cdd45ff6
parent2df4d212c34abe8b6329817c530f2c7bfbac9f80 (diff)
downloadnextpnr-7645354917b93417ebeef974f5ca8961c9a1a3c8.tar.gz
nextpnr-7645354917b93417ebeef974f5ca8961c9a1a3c8.tar.bz2
nextpnr-7645354917b93417ebeef974f5ca8961c9a1a3c8.zip
nexus: More global placement infrastructure
Signed-off-by: David Shah <dave@ds0.me>
-rw-r--r--nexus/pack.cc77
1 files changed, 77 insertions, 0 deletions
diff --git a/nexus/pack.cc b/nexus/pack.cc
index 96b48da9..7ba1ef7f 100644
--- a/nexus/pack.cc
+++ b/nexus/pack.cc
@@ -699,6 +699,83 @@ struct NexusPacker
}
}
+ // Find the nearest bel of a given type; matching a closure predicate
+ template <typename Tpred> BelId find_nearest_bel(const CellInfo *cell, IdString dest_type, Tpred predicate)
+ {
+ BelId origin = get_bel_attr(cell);
+ if (origin == BelId())
+ return BelId();
+ Loc origin_loc = ctx->getBelLocation(origin);
+ int best_distance = std::numeric_limits<int>::max();
+ BelId best_bel = BelId();
+
+ for (BelId bel : ctx->getBels()) {
+ if (ctx->getBelType(bel) != dest_type)
+ continue;
+ if (!predicate(bel))
+ continue;
+ Loc bel_loc = ctx->getBelLocation(bel);
+ int dist = std::abs(origin_loc.x - bel_loc.x) + std::abs(origin_loc.y - bel_loc.y);
+ if (dist < best_distance) {
+ best_distance = dist;
+ best_bel = bel;
+ }
+ }
+ return best_bel;
+ }
+
+ std::unordered_set<BelId> used_bels;
+
+ // Pre-place a primitive based on routeability first and distance second
+ BelId preplace_prim(CellInfo *cell, IdString pin, bool strict_routing)
+ {
+ std::vector<BelId> routeability_candidates;
+
+ NetInfo *pin_net = get_net_or_empty(cell, pin);
+ if (pin_net == nullptr)
+ return BelId();
+
+ CellInfo *pin_drv = pin_net->driver.cell;
+ if (pin_drv == nullptr)
+ return BelId();
+
+ // Check based on routeability
+ find_connected_bels(pin_drv, pin_net->driver.port, cell->type, pin, 25000, routeability_candidates);
+
+ for (BelId cand : routeability_candidates) {
+ if (used_bels.count(cand))
+ continue;
+ cell->attrs[id_BEL] = ctx->getBelName(cand).str(ctx);
+ used_bels.insert(cand);
+ return cand;
+ }
+
+ // Unless in strict mode; check based on simple distance too
+ BelId nearest = find_nearest_bel(pin_drv, cell->type, [&](BelId bel) { return !used_bels.count(bel); });
+
+ if (nearest != BelId()) {
+ cell->attrs[id_BEL] = ctx->getBelName(nearest).str(ctx);
+ used_bels.insert(nearest);
+ return nearest;
+ }
+
+ return BelId();
+ }
+
+ // Pre-place a singleton primitive; so decisions can be made on routeability downstream of it
+ void preplace_singleton(CellInfo *cell)
+ {
+ if (cell->attrs.count(id_BEL))
+ return;
+ for (BelId bel : ctx->getBels()) {
+ if (ctx->getBelType(bel) != cell->type)
+ continue;
+ // Check that the bel really is a singleton...
+ NPNR_ASSERT(!cell->attrs.count(id_BEL));
+ cell->attrs[id_BEL] = ctx->getBelName(bel).str(ctx);
+ }
+ }
+
explicit NexusPacker(Context *ctx) : ctx(ctx) {}
void operator()()