From 27635785c8f3d730fd3e954521aed90b3c0665b7 Mon Sep 17 00:00:00 2001 From: myrtle Date: Tue, 1 Jul 2025 15:32:28 +0200 Subject: [PATCH] heap: Allow customising legalisation ordering (#1507) Signed-off-by: gatecat --- common/place/placer_heap.cc | 16 +++++++++++----- common/place/placer_heap.h | 5 +++++ himbaechel/uarch/xilinx/xilinx.cc | 7 +++++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/common/place/placer_heap.cc b/common/place/placer_heap.cc index 940d1d71..be8a670d 100644 --- a/common/place/placer_heap.cc +++ b/common/place/placer_heap.cc @@ -862,7 +862,7 @@ class HeAPPlacer // the simple greedy largest-macro-first approach. std::priority_queue> 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; diff --git a/common/place/placer_heap.h b/common/place/placer_heap.h index c79e3dfc..704eb157 100644 --- a/common/place/placer_heap.h +++ b/common/place/placer_heap.h @@ -29,6 +29,8 @@ #include "log.h" #include "nextpnr.h" +#include + 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> cellGroups; + + // this is an optional callback to prioritise certain cells/clusters for legalisation + std::function get_cell_legalisation_weight = [](Context *, CellInfo *) { return 1; }; }; extern bool placer_heap(Context *ctx, PlacerHeapCfg cfg); diff --git a/himbaechel/uarch/xilinx/xilinx.cc b/himbaechel/uarch/xilinx/xilinx.cc index a1aa3575..ef059f01 100644 --- a/himbaechel/uarch/xilinx/xilinx.cc +++ b/himbaechel/uarch/xilinx/xilinx.cc @@ -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()