5
5
#include " placer_globals.h"
6
6
#include " move_utils.h"
7
7
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);
9
16
10
17
static void get_bb_from_scratch_excluding_block (ClusterNetId net_id, t_bb& bb_coord_new, ClusterBlockId block_id, bool & skip_net);
11
18
@@ -29,7 +36,7 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_
29
36
auto & place_move_ctx = g_placer_ctx.mutable_move ();
30
37
31
38
const int num_layers = device_ctx.grid .get_num_layers ();
32
- bool is_multi_layer = (num_layers > 1 );
39
+
33
40
34
41
t_pl_loc from = place_ctx.block_locs [b_from].loc ;
35
42
int from_layer = from.layer ;
@@ -43,12 +50,13 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_
43
50
t_bb coords (OPEN, OPEN, OPEN, OPEN, OPEN, OPEN);
44
51
t_bb limit_coords;
45
52
ClusterBlockId bnum;
46
- int pnum, xnew, xold, ynew, yold;
53
+ int pnum, xnew, xold, ynew, yold, layer_new, layer_old ;
47
54
48
55
// clear the vectors that saves X & Y coords
49
56
// reused to save allocation time
50
57
place_move_ctx.X_coord .clear ();
51
58
place_move_ctx.Y_coord .clear ();
59
+ place_move_ctx.layer_coord .clear ();
52
60
std::vector<int > layer_blk_cnt (num_layers, 0 );
53
61
54
62
// 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_
84
92
VTR_ASSERT (pnum >= 0 );
85
93
xold = place_ctx.block_locs [bnum].loc .x + physical_tile_type (bnum)->pin_width_offset [pnum];
86
94
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
+
87
97
xold = std::max (std::min (xold, (int )device_ctx.grid .width () - 2 ), 1 ); // -2 for no perim channels
88
98
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 );
89
100
90
101
// To calulate the bb incrementally while excluding the moving block
91
102
// 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_
101
112
ynew = net_bb_coords.ymin ;
102
113
}
103
114
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)) {
105
132
get_bb_from_scratch_excluding_block (net_id, coords, b_from, skip_net);
106
133
if (skip_net)
107
134
continue ;
@@ -112,34 +139,29 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_
112
139
place_move_ctx.X_coord .push_back (coords.xmax );
113
140
place_move_ctx.Y_coord .push_back (coords.ymin );
114
141
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 );
126
144
}
127
145
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 " );
130
148
return e_create_move::ABORT;
131
149
}
132
150
133
151
// calculate the median region
134
152
std::stable_sort (place_move_ctx.X_coord .begin (), place_move_ctx.X_coord .end ());
135
153
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 ());
136
155
137
156
limit_coords.xmin = place_move_ctx.X_coord [floor ((place_move_ctx.X_coord .size () - 1 ) / 2 )];
138
157
limit_coords.xmax = place_move_ctx.X_coord [floor ((place_move_ctx.X_coord .size () - 1 ) / 2 ) + 1 ];
139
158
140
159
limit_coords.ymin = place_move_ctx.Y_coord [floor ((place_move_ctx.Y_coord .size () - 1 ) / 2 )];
141
160
limit_coords.ymax = place_move_ctx.Y_coord [floor ((place_move_ctx.Y_coord .size () - 1 ) / 2 ) + 1 ];
142
161
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
+
143
165
// arrange the different range limiters
144
166
t_range_limiters range_limiters{rlim,
145
167
place_move_ctx.first_rlim ,
@@ -149,17 +171,8 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_
149
171
t_pl_loc median_point;
150
172
median_point.x = (limit_coords.xmin + limit_coords.xmax ) / 2 ;
151
173
median_point.y = (limit_coords.ymin + limit_coords.ymax ) / 2 ;
174
+ median_point.layer = (limit_coords.layer_min + limit_coords.layer_max ) / 2 ;
152
175
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
- }
163
176
if (!find_to_loc_centroid (cluster_from_type, from, median_point, range_limiters, to, b_from)) {
164
177
return e_create_move::ABORT;
165
178
}
@@ -194,6 +207,9 @@ static void get_bb_from_scratch_excluding_block(ClusterNetId net_id, t_bb& bb_co
194
207
int ymin = OPEN;
195
208
int ymax = OPEN;
196
209
210
+ int layer_min = OPEN;
211
+ int layer_max = OPEN;
212
+
197
213
int pnum;
198
214
199
215
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
208
224
pnum = net_pin_to_tile_pin_index (net_id, 0 );
209
225
int src_x = place_ctx.block_locs [bnum].loc .x + physical_tile_type (bnum)->pin_width_offset [pnum];
210
226
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 ;
211
228
212
229
xmin = src_x;
213
230
ymin = src_y;
214
231
xmax = src_x;
215
232
ymax = src_y;
233
+ layer_min = src_layer;
234
+ layer_max = src_layer;
216
235
first_block = true ;
217
236
}
218
237
@@ -225,12 +244,15 @@ static void get_bb_from_scratch_excluding_block(ClusterNetId net_id, t_bb& bb_co
225
244
const auto & block_loc = place_ctx.block_locs [bnum].loc ;
226
245
int x = block_loc.x + physical_tile_type (bnum)->pin_width_offset [pnum];
227
246
int y = block_loc.y + physical_tile_type (bnum)->pin_height_offset [pnum];
247
+ int layer = block_loc.layer ;
228
248
229
249
if (!first_block) {
230
250
xmin = x;
231
251
ymin = y;
232
252
xmax = x;
233
253
ymax = y;
254
+ layer_max = layer;
255
+ layer_min = layer;
234
256
first_block = true ;
235
257
continue ;
236
258
}
@@ -245,6 +267,12 @@ static void get_bb_from_scratch_excluding_block(ClusterNetId net_id, t_bb& bb_co
245
267
} else if (y > ymax) {
246
268
ymax = y;
247
269
}
270
+
271
+ if (layer < layer_min) {
272
+ layer_min = layer;
273
+ } else if (layer > layer_max) {
274
+ layer_max = layer;
275
+ }
248
276
}
249
277
250
278
/* 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
256
284
* is 0). See route_common.cpp for a channel diagram. */
257
285
bb_coord_new.xmin = std::max (std::min<int >(xmin, device_ctx.grid .width () - 2 ), 1 ); // -2 for no perim channels
258
286
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 );
259
288
bb_coord_new.xmax = std::max (std::min<int >(xmax, device_ctx.grid .width () - 2 ), 1 ); // -2 for no perim channels
260
289
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 );
261
291
}
262
292
263
293
/*
@@ -273,20 +303,36 @@ static void get_bb_from_scratch_excluding_block(ClusterNetId net_id, t_bb& bb_co
273
303
* the pins always lie on the outside of the bounding box. *
274
304
* The x and y coordinates are the pin's x and y coordinates. */
275
305
/* 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) {
277
314
// TODO: account for multiple physical pin instances per logical pin
278
315
279
316
auto & device_ctx = g_vpr_ctx.device ();
280
317
auto & place_move_ctx = g_placer_ctx.move ();
281
318
282
319
xnew = std::max (std::min<int >(xnew, device_ctx.grid .width () - 2 ), 1 ); // -2 for no perim channels
283
320
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
+
284
323
xold = std::max (std::min<int >(xold, device_ctx.grid .width () - 2 ), 1 ); // -2 for no perim channels
285
324
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 );
286
326
287
327
t_bb union_bb_edge;
288
328
t_bb union_bb;
289
329
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
+ */
290
336
if (!cube_bb) {
291
337
std::tie (union_bb_edge, union_bb) = union_2d_bb_incr (place_move_ctx.layer_bb_num_on_edges [net_id],
292
338
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
410
456
bb_coord_new.ymin = curr_bb_coord.ymin ;
411
457
bb_coord_new.ymax = curr_bb_coord.ymax ;
412
458
}
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
+ }
413
501
return true ;
414
502
}
0 commit comments