nexus: More global placement infrastructure
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
2df4d212c3
commit
7645354917
@ -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) {}
|
explicit NexusPacker(Context *ctx) : ctx(ctx) {}
|
||||||
|
|
||||||
void operator()()
|
void operator()()
|
||||||
|
Loading…
Reference in New Issue
Block a user