@@ -865,6 +865,7 @@ class HeAPPlacer
865865 remaining.emplace (chain_size[cell->name ] * cfg.get_cell_legalisation_weight (ctx, cell), cell->name );
866866 }
867867 int ripup_radius = 2 ;
868+ int chain_ripup_radius = std::max (max_x, max_y); // only ripup chains as last resort
868869 int total_iters = 0 ;
869870 int total_iters_noreset = 0 ;
870871 while (!remaining.empty ()) {
@@ -1054,7 +1055,7 @@ class HeAPPlacer
10541055 // List of cells and their destination
10551056 std::vector<std::pair<CellInfo *, BelId>> targets;
10561057 // List of bels we placed things at; and the cell that was there before if applicable
1057- std::vector<std::pair< BelId, CellInfo *>> swaps_made ;
1058+ dict< BelId, CellInfo *> moves_made ;
10581059
10591060 if (!ctx->getClusterPlacement (ci->cluster , sz, targets))
10601061 continue ;
@@ -1065,31 +1066,45 @@ class HeAPPlacer
10651066 goto fail;
10661067 CellInfo *bound = ctx->getBoundBelCell (target.second );
10671068 // Chains cannot overlap; so if we have to ripup a cell make sure it isn't part of a chain
1068- if (bound != nullptr )
1069- if (bound->cluster != ClusterId () || bound-> belStrength > STRENGTH_WEAK)
1069+ if (bound != nullptr ) {
1070+ if (bound->belStrength > (cfg. chainRipup ? STRENGTH_STRONG : STRENGTH_WEAK) )
10701071 goto fail;
1072+ if (bound->cluster != ClusterId () && (!cfg.chainRipup || radius < chain_ripup_radius))
1073+ goto fail;
1074+ }
10711075 }
10721076 // Actually perform the move; keeping track of the moves we make so we can revert them if needed
10731077 for (auto &target : targets) {
10741078 CellInfo *bound = ctx->getBoundBelCell (target.second );
1075- if (bound != nullptr )
1076- ctx->unbindBel (target.second );
1079+ if (bound != nullptr ) {
1080+ if (bound->cluster != ClusterId ()) {
1081+ for (auto cell : cluster2cells[bound->cluster ]) {
1082+ if (cell->bel != BelId ()) {
1083+ moves_made[cell->bel ] = cell;
1084+ ctx->unbindBel (cell->bel );
1085+ }
1086+ }
1087+ } else {
1088+ ctx->unbindBel (target.second );
1089+ }
1090+ }
10771091 ctx->bindBel (target.second , target.first , STRENGTH_STRONG);
1078- swaps_made. emplace_back ( target.second , bound) ;
1092+ moves_made[ target.second ] = bound;
10791093 }
10801094 // Check that the move we have made is legal
1081- for (auto &sm : swaps_made ) {
1082- if (!ctx->isBelLocationValid (sm .first ))
1095+ for (auto &move : moves_made ) {
1096+ if (!ctx->isBelLocationValid (move .first ))
10831097 goto fail;
10841098 }
10851099
10861100 if (false ) {
10871101 fail:
10881102 // If the move turned out to be illegal; revert all the moves we made
1089- for (auto &swap : swaps_made) {
1090- ctx->unbindBel (swap.first );
1091- if (swap.second != nullptr )
1092- ctx->bindBel (swap.first , swap.second , STRENGTH_WEAK);
1103+ for (auto &move : moves_made) {
1104+ if (ctx->getBoundBelCell (move.first ))
1105+ ctx->unbindBel (move.first );
1106+ if (move.second != nullptr )
1107+ ctx->bindBel (move.first , move.second , STRENGTH_WEAK);
10931108 }
10941109 continue ;
10951110 }
@@ -1099,12 +1114,12 @@ class HeAPPlacer
10991114 cell_locs[target.first ->name ].y = loc.y ;
11001115 // log_info("%s %d %d %d\n", target.first->name.c_str(ctx), loc.x, loc.y, loc.z);
11011116 }
1102- for (auto &swap : swaps_made ) {
1117+ for (auto &move : moves_made ) {
11031118 // Where we have ripped up cells; add them to the queue
1104- if (swap .second != nullptr )
1105- remaining.emplace (chain_size[swap .second ->name ] *
1106- cfg.get_cell_legalisation_weight (ctx, swap .second ),
1107- swap .second ->name );
1119+ if (move .second != nullptr && (move. second -> cluster == ClusterId () || ctx-> getClusterRootCell (move. second -> cluster ) == move. second ) )
1120+ remaining.emplace (chain_size[move .second ->name ] *
1121+ cfg.get_cell_legalisation_weight (ctx, move .second ),
1122+ move .second ->name );
11081123 }
11091124
11101125 placed = true ;
@@ -1841,6 +1856,7 @@ PlacerHeapCfg::PlacerHeapCfg(Context *ctx)
18411856 timing_driven = ctx->setting <bool >(" timing_driven" );
18421857 solverTolerance = 1e-5 ;
18431858 placeAllAtOnce = false ;
1859+ chainRipup = false ;
18441860
18451861 int timeout_divisor = ctx->setting <int >(" placerHeap/cellPlacementTimeout" , 8 );
18461862 if (timeout_divisor > 0 ) {
0 commit comments