heap: Allow customising legalisation ordering (#1507)

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
myrtle 2025-07-01 15:32:28 +02:00 committed by GitHub
parent 39f020b033
commit 27635785c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 23 additions and 5 deletions

View File

@ -862,7 +862,7 @@ class HeAPPlacer
// the simple greedy largest-macro-first approach.
std::priority_queue<std::pair<int, IdString>> remaining;
for (auto cell : solve_cells) {
remaining.emplace(chain_size[cell->name], cell->name);
remaining.emplace(chain_size[cell->name] * cfg.get_cell_legalisation_weight(ctx, cell), cell->name);
}
int ripup_radius = 2;
int total_iters = 0;
@ -875,7 +875,8 @@ class HeAPPlacer
// Was now placed, ignore
if (ci->bel != BelId())
continue;
// log_info(" Legalising %s (%s) %d\n", top.second.c_str(ctx), ci->type.c_str(ctx), top.first);
if (ctx->debug)
log_info(" Legalising %s (%s) priority=%d\n", top.second.c_str(ctx), ci->type.c_str(ctx), top.first);
FastBels::FastBelsData *fb;
fast_bels.getBelsForCellType(ci->type, &fb);
int radius = 0;
@ -973,7 +974,8 @@ class HeAPPlacer
CellInfo *bound = ctx->getBoundBelCell(bestBel);
if (bound != nullptr) {
ctx->unbindBel(bound->bel);
remaining.emplace(chain_size[bound->name], bound->name);
remaining.emplace(chain_size[bound->name] * cfg.get_cell_legalisation_weight(ctx, bound),
bound->name);
}
ctx->bindBel(bestBel, ci, STRENGTH_WEAK);
placed = true;
@ -1035,7 +1037,9 @@ class HeAPPlacer
} else {
// It's legal, and we've tried enough. Finish.
if (bound != nullptr)
remaining.emplace(chain_size[bound->name], bound->name);
remaining.emplace(chain_size[bound->name] *
cfg.get_cell_legalisation_weight(ctx, bound),
bound->name);
Loc loc = ctx->getBelLocation(sz);
cell_locs[ci->name].x = loc.x;
cell_locs[ci->name].y = loc.y;
@ -1098,7 +1102,9 @@ class HeAPPlacer
for (auto &swap : swaps_made) {
// Where we have ripped up cells; add them to the queue
if (swap.second != nullptr)
remaining.emplace(chain_size[swap.second->name], swap.second->name);
remaining.emplace(chain_size[swap.second->name] *
cfg.get_cell_legalisation_weight(ctx, swap.second),
swap.second->name);
}
placed = true;

View File

@ -29,6 +29,8 @@
#include "log.h"
#include "nextpnr.h"
#include <functional>
NEXTPNR_NAMESPACE_BEGIN
struct PlacerHeapCfg
@ -53,6 +55,9 @@ struct PlacerHeapCfg
// These cell types are part of the same unit (e.g. slices split into
// components) so will always be spread together
std::vector<pool<BelBucketId>> cellGroups;
// this is an optional callback to prioritise certain cells/clusters for legalisation
std::function<float(Context *, CellInfo *)> get_cell_legalisation_weight = [](Context *, CellInfo *) { return 1; };
};
extern bool placer_heap(Context *ctx, PlacerHeapCfg cfg);

View File

@ -278,6 +278,13 @@ void XilinxImpl::configurePlacerHeap(PlacerHeapCfg &cfg)
cfg.hpwl_scale_y = 1;
cfg.beta = 0.5;
cfg.placeAllAtOnce = true;
cfg.get_cell_legalisation_weight = [this](Context *, CellInfo *ci) {
if (ci->type != id_SLICE_LUTX)
return 1;
auto tags = get_tags(ci);
// Place memory first, because they require entire SLICEMs
return tags->lut.is_memory ? 100 : 1;
};
}
void XilinxImpl::preRoute()