55#include " placer_globals.h"
66#include " move_utils.h"
77
8- static bool get_bb_incrementally (ClusterNetId net_id, t_bb& bb_coord_new, int xold, int yold, int xnew, int ynew);
8+ static bool get_bb_incrementally (ClusterNetId net_id,
9+ t_bb& bb_coord_new,
10+ int xold,
11+ int yold,
12+ int layer_old,
13+ int xnew,
14+ int ynew,
15+ int layer_new);
916
1017static void get_bb_from_scratch_excluding_block (ClusterNetId net_id, t_bb& bb_coord_new, ClusterBlockId block_id, bool & skip_net);
1118
@@ -29,7 +36,7 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_
2936 auto & place_move_ctx = g_placer_ctx.mutable_move ();
3037
3138 const int num_layers = device_ctx.grid .get_num_layers ();
32- bool is_multi_layer = (num_layers > 1 );
39+
3340
3441 t_pl_loc from = place_ctx.block_locs [b_from].loc ;
3542 int from_layer = from.layer ;
@@ -43,12 +50,13 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_
4350 t_bb coords (OPEN, OPEN, OPEN, OPEN, OPEN, OPEN);
4451 t_bb limit_coords;
4552 ClusterBlockId bnum;
46- int pnum, xnew, xold, ynew, yold;
53+ int pnum, xnew, xold, ynew, yold, layer_new, layer_old ;
4754
4855 // clear the vectors that saves X & Y coords
4956 // reused to save allocation time
5057 place_move_ctx.X_coord .clear ();
5158 place_move_ctx.Y_coord .clear ();
59+ place_move_ctx.layer_coord .clear ();
5260 std::vector<int > layer_blk_cnt (num_layers, 0 );
5361
5462 // true if the net is a feedback from the block to itself
@@ -84,8 +92,11 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_
8492 VTR_ASSERT (pnum >= 0 );
8593 xold = place_ctx.block_locs [bnum].loc .x + physical_tile_type (bnum)->pin_width_offset [pnum];
8694 yold = place_ctx.block_locs [bnum].loc .y + physical_tile_type (bnum)->pin_height_offset [pnum];
95+ layer_old = place_ctx.block_locs [bnum].loc .layer ;
96+
8797 xold = std::max (std::min (xold, (int )device_ctx.grid .width () - 2 ), 1 ); // -2 for no perim channels
8898 yold = std::max (std::min (yold, (int )device_ctx.grid .height () - 2 ), 1 ); // -2 for no perim channels
99+ layer_old = std::max (std::min (layer_old, (int )device_ctx.grid .get_num_layers () - 1 ), 0 );
89100
90101 // To calulate the bb incrementally while excluding the moving block
91102 // assume that the moving block is moved to a non-critical coord of the bb
@@ -101,7 +112,23 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_
101112 ynew = net_bb_coords.ymin ;
102113 }
103114
104- if (!get_bb_incrementally (net_id, coords, xold, yold, xnew, ynew)) {
115+ if (net_bb_coords.layer_min == layer_old) {
116+ layer_new = net_bb_coords.layer_max ;
117+ } else {
118+ layer_new = net_bb_coords.layer_min ;
119+ }
120+
121+ // If the mvoing block is on the border of the bounding box, we cannot get
122+ // the bounding box incrementatlly. In that case, bounding box should be calculated
123+ // from scratch.
124+ if (!get_bb_incrementally (net_id,
125+ coords,
126+ xold,
127+ yold,
128+ layer_old,
129+ xnew,
130+ ynew,
131+ layer_new)) {
105132 get_bb_from_scratch_excluding_block (net_id, coords, b_from, skip_net);
106133 if (skip_net)
107134 continue ;
@@ -112,34 +139,29 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_
112139 place_move_ctx.X_coord .push_back (coords.xmax );
113140 place_move_ctx.Y_coord .push_back (coords.ymin );
114141 place_move_ctx.Y_coord .push_back (coords.ymax );
115- if (is_multi_layer) {
116- for (int layer_num = 0 ; layer_num < num_layers; layer_num++) {
117- layer_blk_cnt[layer_num] += place_move_ctx.num_sink_pin_layer [size_t (net_id)][layer_num];
118- }
119- // If the pin under consideration is of type sink, it shouldn't be added to layer_blk_cnt since the block
120- // is moving
121- if (cluster_ctx.clb_nlist .pin_type (pin_id) == PinType::SINK) {
122- VTR_ASSERT_SAFE (layer_blk_cnt[from_layer] > 0 );
123- layer_blk_cnt[from_layer]--;
124- }
125- }
142+ place_move_ctx.layer_coord .push_back (coords.layer_min );
143+ place_move_ctx.layer_coord .push_back (coords.layer_max );
126144 }
127145
128- if ((place_move_ctx.X_coord .empty ()) || (place_move_ctx.Y_coord .empty ())) {
129- VTR_LOGV_DEBUG (g_vpr_ctx.placement ().f_placer_debug , " \t Move aborted - X_coord and y_coord are empty\n " );
146+ if ((place_move_ctx.X_coord .empty ()) || (place_move_ctx.Y_coord .empty ()) || (place_move_ctx. layer_coord . empty ()) ) {
147+ VTR_LOGV_DEBUG (g_vpr_ctx.placement ().f_placer_debug , " \t Move aborted - X_coord or y_coord or layer_coord are empty\n " );
130148 return e_create_move::ABORT;
131149 }
132150
133151 // calculate the median region
134152 std::stable_sort (place_move_ctx.X_coord .begin (), place_move_ctx.X_coord .end ());
135153 std::stable_sort (place_move_ctx.Y_coord .begin (), place_move_ctx.Y_coord .end ());
154+ std::stable_sort (place_move_ctx.layer_coord .begin (), place_move_ctx.layer_coord .end ());
136155
137156 limit_coords.xmin = place_move_ctx.X_coord [floor ((place_move_ctx.X_coord .size () - 1 ) / 2 )];
138157 limit_coords.xmax = place_move_ctx.X_coord [floor ((place_move_ctx.X_coord .size () - 1 ) / 2 ) + 1 ];
139158
140159 limit_coords.ymin = place_move_ctx.Y_coord [floor ((place_move_ctx.Y_coord .size () - 1 ) / 2 )];
141160 limit_coords.ymax = place_move_ctx.Y_coord [floor ((place_move_ctx.Y_coord .size () - 1 ) / 2 ) + 1 ];
142161
162+ limit_coords.layer_min = place_move_ctx.layer_coord [floor ((place_move_ctx.layer_coord .size () - 1 ) / 2 )];
163+ limit_coords.layer_max = place_move_ctx.layer_coord [floor ((place_move_ctx.layer_coord .size () - 1 ) / 2 ) + 1 ];
164+
143165 // arrange the different range limiters
144166 t_range_limiters range_limiters{rlim,
145167 place_move_ctx.first_rlim ,
@@ -149,17 +171,8 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_
149171 t_pl_loc median_point;
150172 median_point.x = (limit_coords.xmin + limit_coords.xmax ) / 2 ;
151173 median_point.y = (limit_coords.ymin + limit_coords.ymax ) / 2 ;
174+ median_point.layer = (limit_coords.layer_min + limit_coords.layer_max ) / 2 ;
152175
153- // Before calling find_to_loc_centroid a valid layer should be assigned to "to" location. If there are multiple layers, the layer
154- // with highest number of sinks will be used. Otherwise, the same layer as "from" loc is assigned.
155- if (is_multi_layer) {
156- int layer_num = std::distance (layer_blk_cnt.begin (), std::max_element (layer_blk_cnt.begin (), layer_blk_cnt.end ()));
157- median_point.layer = layer_num;
158- to.layer = layer_num;
159- } else {
160- median_point.layer = from.layer ;
161- to.layer = from.layer ;
162- }
163176 if (!find_to_loc_centroid (cluster_from_type, from, median_point, range_limiters, to, b_from)) {
164177 return e_create_move::ABORT;
165178 }
@@ -194,6 +207,9 @@ static void get_bb_from_scratch_excluding_block(ClusterNetId net_id, t_bb& bb_co
194207 int ymin = OPEN;
195208 int ymax = OPEN;
196209
210+ int layer_min = OPEN;
211+ int layer_max = OPEN;
212+
197213 int pnum;
198214
199215 auto & cluster_ctx = g_vpr_ctx.clustering ();
@@ -208,11 +224,14 @@ static void get_bb_from_scratch_excluding_block(ClusterNetId net_id, t_bb& bb_co
208224 pnum = net_pin_to_tile_pin_index (net_id, 0 );
209225 int src_x = place_ctx.block_locs [bnum].loc .x + physical_tile_type (bnum)->pin_width_offset [pnum];
210226 int src_y = place_ctx.block_locs [bnum].loc .y + physical_tile_type (bnum)->pin_height_offset [pnum];
227+ int src_layer = place_ctx.block_locs [bnum].loc .layer ;
211228
212229 xmin = src_x;
213230 ymin = src_y;
214231 xmax = src_x;
215232 ymax = src_y;
233+ layer_min = src_layer;
234+ layer_max = src_layer;
216235 first_block = true ;
217236 }
218237
@@ -225,12 +244,15 @@ static void get_bb_from_scratch_excluding_block(ClusterNetId net_id, t_bb& bb_co
225244 const auto & block_loc = place_ctx.block_locs [bnum].loc ;
226245 int x = block_loc.x + physical_tile_type (bnum)->pin_width_offset [pnum];
227246 int y = block_loc.y + physical_tile_type (bnum)->pin_height_offset [pnum];
247+ int layer = block_loc.layer ;
228248
229249 if (!first_block) {
230250 xmin = x;
231251 ymin = y;
232252 xmax = x;
233253 ymax = y;
254+ layer_max = layer;
255+ layer_min = layer;
234256 first_block = true ;
235257 continue ;
236258 }
@@ -245,6 +267,12 @@ static void get_bb_from_scratch_excluding_block(ClusterNetId net_id, t_bb& bb_co
245267 } else if (y > ymax) {
246268 ymax = y;
247269 }
270+
271+ if (layer < layer_min) {
272+ layer_min = layer;
273+ } else if (layer > layer_max) {
274+ layer_max = layer;
275+ }
248276 }
249277
250278 /* Now I've found the coordinates of the bounding box. There are no *
@@ -256,8 +284,10 @@ static void get_bb_from_scratch_excluding_block(ClusterNetId net_id, t_bb& bb_co
256284 * is 0). See route_common.cpp for a channel diagram. */
257285 bb_coord_new.xmin = std::max (std::min<int >(xmin, device_ctx.grid .width () - 2 ), 1 ); // -2 for no perim channels
258286 bb_coord_new.ymin = std::max (std::min<int >(ymin, device_ctx.grid .height () - 2 ), 1 ); // -2 for no perim channels
287+ bb_coord_new.layer_min = std::max (std::min<int >(layer_min, device_ctx.grid .get_num_layers () - 1 ), 0 );
259288 bb_coord_new.xmax = std::max (std::min<int >(xmax, device_ctx.grid .width () - 2 ), 1 ); // -2 for no perim channels
260289 bb_coord_new.ymax = std::max (std::min<int >(ymax, device_ctx.grid .height () - 2 ), 1 ); // -2 for no perim channels
290+ bb_coord_new.layer_max = std::max (std::min<int >(layer_max, device_ctx.grid .get_num_layers () - 1 ), 0 );
261291}
262292
263293/*
@@ -273,20 +303,36 @@ static void get_bb_from_scratch_excluding_block(ClusterNetId net_id, t_bb& bb_co
273303 * the pins always lie on the outside of the bounding box. *
274304 * The x and y coordinates are the pin's x and y coordinates. */
275305/* IO blocks are considered to be one cell in for simplicity. */
276- static bool get_bb_incrementally (ClusterNetId net_id, t_bb& bb_coord_new, int xold, int yold, int xnew, int ynew) {
306+ static bool get_bb_incrementally (ClusterNetId net_id,
307+ t_bb& bb_coord_new,
308+ int xold,
309+ int yold,
310+ int layer_old,
311+ int xnew,
312+ int ynew,
313+ int layer_new) {
277314 // TODO: account for multiple physical pin instances per logical pin
278315
279316 auto & device_ctx = g_vpr_ctx.device ();
280317 auto & place_move_ctx = g_placer_ctx.move ();
281318
282319 xnew = std::max (std::min<int >(xnew, device_ctx.grid .width () - 2 ), 1 ); // -2 for no perim channels
283320 ynew = std::max (std::min<int >(ynew, device_ctx.grid .height () - 2 ), 1 ); // -2 for no perim channels
321+ layer_new = std::max (std::min<int >(layer_new, device_ctx.grid .get_num_layers () - 1 ), 0 );
322+
284323 xold = std::max (std::min<int >(xold, device_ctx.grid .width () - 2 ), 1 ); // -2 for no perim channels
285324 yold = std::max (std::min<int >(yold, device_ctx.grid .height () - 2 ), 1 ); // -2 for no perim channels
325+ layer_old = std::max (std::min<int >(layer_old, device_ctx.grid .get_num_layers () - 1 ), 0 );
286326
287327 t_bb union_bb_edge;
288328 t_bb union_bb;
289329 const bool & cube_bb = g_vpr_ctx.placement ().cube_bb ;
330+ /* Calculating per-layer bounding box is more time consuming compared to cube bounding box. To speed up
331+ * this move, the bounding box used for this move is of the type cube bounding box even if the per-layer
332+ * bounding box is used by placement SA engine.
333+ * If per-layer bounding box is used, we take a union of boundinx boxes on each layer to make a cube bounding box.
334+ * For example, the xmax of this cube boundix box is determined by the maximim x coordinate across all blocks on all layers.
335+ */
290336 if (!cube_bb) {
291337 std::tie (union_bb_edge, union_bb) = union_2d_bb_incr (place_move_ctx.layer_bb_num_on_edges [net_id],
292338 place_move_ctx.layer_bb_coords [net_id]);
@@ -410,5 +456,47 @@ static bool get_bb_incrementally(ClusterNetId net_id, t_bb& bb_coord_new, int xo
410456 bb_coord_new.ymin = curr_bb_coord.ymin ;
411457 bb_coord_new.ymax = curr_bb_coord.ymax ;
412458 }
459+
460+ if (layer_new < layer_old) {
461+ if (layer_old == curr_bb_coord.layer_max ) {
462+ if (curr_bb_edge.layer_max == 1 ) {
463+ return false ;
464+ } else {
465+ bb_coord_new.layer_max = curr_bb_coord.layer_max ;
466+ }
467+ } else {
468+ bb_coord_new.layer_max = curr_bb_coord.layer_max ;
469+ }
470+
471+ if (layer_new < curr_bb_coord.layer_min ) {
472+ bb_coord_new.layer_min = layer_new;
473+ } else if (layer_new == curr_bb_coord.layer_min ) {
474+ bb_coord_new.layer_min = layer_new;
475+ } else {
476+ bb_coord_new.layer_min = curr_bb_coord.layer_min ;
477+ }
478+
479+ } else if (layer_new > layer_old) {
480+ if (layer_old == curr_bb_coord.layer_min ) {
481+ if (curr_bb_edge.layer_min == 1 ) {
482+ return false ;
483+ } else {
484+ bb_coord_new.layer_min = curr_bb_coord.layer_min ;
485+ }
486+ } else {
487+ bb_coord_new.layer_min = curr_bb_coord.layer_min ;
488+ }
489+
490+ if (layer_new > curr_bb_coord.layer_max ) {
491+ bb_coord_new.layer_max = layer_new;
492+ } else if (layer_new == curr_bb_coord.layer_max ) {
493+ bb_coord_new.layer_max = layer_new;
494+ } else {
495+ bb_coord_new.layer_max = curr_bb_coord.layer_max ;
496+ }
497+ } else {
498+ bb_coord_new.layer_min = curr_bb_coord.layer_min ;
499+ bb_coord_new.layer_max = curr_bb_coord.layer_max ;
500+ }
413501 return true ;
414502}
0 commit comments