From 9715a1d56580d0652b4a90d58eb4096ba537e3ce Mon Sep 17 00:00:00 2001 From: myrtle Date: Fri, 5 Sep 2025 09:02:19 +0200 Subject: [PATCH] heap: Allow chains to ripup other chains (opt-in only) (#1552) Signed-off-by: gatecat --- common/place/placer_heap.cc | 50 ++++++++++++++++++--------- common/place/placer_heap.h | 1 + himbaechel/uarch/gatemate/gatemate.cc | 5 ++- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/common/place/placer_heap.cc b/common/place/placer_heap.cc index be8a670d..a6e70c8f 100644 --- a/common/place/placer_heap.cc +++ b/common/place/placer_heap.cc @@ -865,6 +865,7 @@ class HeAPPlacer remaining.emplace(chain_size[cell->name] * cfg.get_cell_legalisation_weight(ctx, cell), cell->name); } int ripup_radius = 2; + int chain_ripup_radius = std::max(max_x, max_y); // only ripup chains as last resort int total_iters = 0; int total_iters_noreset = 0; while (!remaining.empty()) { @@ -1054,7 +1055,7 @@ class HeAPPlacer // List of cells and their destination std::vector> targets; // List of bels we placed things at; and the cell that was there before if applicable - std::vector> swaps_made; + dict moves_made; if (!ctx->getClusterPlacement(ci->cluster, sz, targets)) continue; @@ -1065,31 +1066,45 @@ class HeAPPlacer goto fail; CellInfo *bound = ctx->getBoundBelCell(target.second); // Chains cannot overlap; so if we have to ripup a cell make sure it isn't part of a chain - if (bound != nullptr) - if (bound->cluster != ClusterId() || bound->belStrength > STRENGTH_WEAK) + if (bound != nullptr) { + if (bound->belStrength > (cfg.chainRipup ? STRENGTH_STRONG : STRENGTH_WEAK)) goto fail; + if (bound->cluster != ClusterId() && (!cfg.chainRipup || radius < chain_ripup_radius)) + goto fail; + } } // Actually perform the move; keeping track of the moves we make so we can revert them if needed for (auto &target : targets) { CellInfo *bound = ctx->getBoundBelCell(target.second); - if (bound != nullptr) - ctx->unbindBel(target.second); + if (bound != nullptr) { + if (bound->cluster != ClusterId()) { + for (auto cell : cluster2cells[bound->cluster]) { + if (cell->bel != BelId()) { + moves_made[cell->bel] = cell; + ctx->unbindBel(cell->bel); + } + } + } else { + ctx->unbindBel(target.second); + } + } ctx->bindBel(target.second, target.first, STRENGTH_STRONG); - swaps_made.emplace_back(target.second, bound); + moves_made[target.second] = bound; } // Check that the move we have made is legal - for (auto &sm : swaps_made) { - if (!ctx->isBelLocationValid(sm.first)) + for (auto &move : moves_made) { + if (!ctx->isBelLocationValid(move.first)) goto fail; } if (false) { fail: // If the move turned out to be illegal; revert all the moves we made - for (auto &swap : swaps_made) { - ctx->unbindBel(swap.first); - if (swap.second != nullptr) - ctx->bindBel(swap.first, swap.second, STRENGTH_WEAK); + for (auto &move : moves_made) { + if (ctx->getBoundBelCell(move.first)) + ctx->unbindBel(move.first); + if (move.second != nullptr) + ctx->bindBel(move.first, move.second, STRENGTH_WEAK); } continue; } @@ -1099,12 +1114,12 @@ class HeAPPlacer cell_locs[target.first->name].y = loc.y; // log_info("%s %d %d %d\n", target.first->name.c_str(ctx), loc.x, loc.y, loc.z); } - for (auto &swap : swaps_made) { + for (auto &move : moves_made) { // Where we have ripped up cells; add them to the queue - if (swap.second != nullptr) - remaining.emplace(chain_size[swap.second->name] * - cfg.get_cell_legalisation_weight(ctx, swap.second), - swap.second->name); + if (move.second != nullptr && (move.second->cluster == ClusterId() || ctx->getClusterRootCell(move.second->cluster) == move.second)) + remaining.emplace(chain_size[move.second->name] * + cfg.get_cell_legalisation_weight(ctx, move.second), + move.second->name); } placed = true; @@ -1841,6 +1856,7 @@ PlacerHeapCfg::PlacerHeapCfg(Context *ctx) timing_driven = ctx->setting("timing_driven"); solverTolerance = 1e-5; placeAllAtOnce = false; + chainRipup = false; int timeout_divisor = ctx->setting("placerHeap/cellPlacementTimeout", 8); if (timeout_divisor > 0) { diff --git a/common/place/placer_heap.h b/common/place/placer_heap.h index 704eb157..d91120eb 100644 --- a/common/place/placer_heap.h +++ b/common/place/placer_heap.h @@ -45,6 +45,7 @@ struct PlacerHeapCfg bool placeAllAtOnce; float netShareWeight; bool parallelRefine; + bool chainRipup; int cell_placement_timeout; int hpwl_scale_x, hpwl_scale_y; diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index f7d8c787..e724886b 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -456,7 +456,10 @@ void GateMateImpl::expandBoundingBox(BoundingBox &bb) const bb.y1 = std::min((bb.y1 & 0xfffe) + 5, ctx->getGridDimY()); } -void GateMateImpl::configurePlacerHeap(PlacerHeapCfg &cfg) { cfg.placeAllAtOnce = true; } +void GateMateImpl::configurePlacerHeap(PlacerHeapCfg &cfg) { + cfg.chainRipup = true; + cfg.placeAllAtOnce = true; +} int GateMateImpl::get_dff_config(CellInfo *dff) const {