Skip to content

Commit 6cb6da5

Browse files
authored
Merge pull request #2960 from verilog-to-routing/placement_search_range
[Place] Expand search range for sparse blocks
2 parents dd8ea05 + f382bb5 commit 6cb6da5

File tree

15 files changed

+130
-50
lines changed

15 files changed

+130
-50
lines changed

libs/libarchfpga/src/physical_types.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,20 @@ bool t_logical_block_type::is_empty() const {
230230
return name == std::string(EMPTY_BLOCK_NAME);
231231
}
232232

233+
bool t_logical_block_type::is_io() const {
234+
// Iterate over all equivalent tiles and return true if any
235+
// of them are IO tiles
236+
for (t_physical_tile_type_ptr tile : equivalent_tiles) {
237+
if (tile->is_io()) {
238+
return true;
239+
}
240+
}
241+
return false;
242+
}
243+
233244
const t_port* t_logical_block_type::get_port(std::string_view port_name) const {
234245
for (int i = 0; i < pb_type->num_ports; i++) {
235-
auto port = pb_type->ports[i];
246+
const t_port& port = pb_type->ports[i];
236247
if (port_name == port.name) {
237248
return &pb_type->ports[port.index];
238249
}

libs/libarchfpga/src/physical_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,9 @@ struct t_logical_block_type {
10021002
// Is this t_logical_block_type empty?
10031003
bool is_empty() const;
10041004

1005+
// Returns true if this logical block type is an IO block
1006+
bool is_io() const;
1007+
10051008
public:
10061009
/**
10071010
* @brief Returns the logical block port given the port name and the corresponding logical block type

vpr/src/base/vpr_types.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,13 @@ struct t_net_power {
411411
/**
412412
* @brief Stores a 3D bounding box in terms of the minimum and
413413
* maximum coordinates: x, y, layer
414+
*
415+
* @var xmin: The minimum x-coordinate of the bounding box
416+
* @var xmax: The maximum x-coordinate of the bounding box
417+
* @var ymin: The minimum y-coordinate of the bounding box
418+
* @var ymax: The maximum y-coordinate of the bounding box
419+
* @var layer_min: The minimum layer of the bounding box
420+
* @var layer_max: The maximum layer of the bounding box
414421
*/
415422
struct t_bb {
416423
t_bb() = default;

vpr/src/place/initial_placement.cpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ static std::vector<ClusterBlockId> find_centroid_loc(const t_pl_macro& pl_macro,
203203
*
204204
* @return true if the function can find any location near the centroid one, false otherwise.
205205
*/
206-
static bool find_centroid_neighbor(t_pl_loc& centroid_loc,
206+
static bool find_centroid_neighbor(ClusterBlockId block_id,
207+
t_pl_loc& centroid_loc,
207208
t_logical_block_type_ptr block_type,
208209
bool search_for_empty,
209210
int r_lim,
@@ -212,7 +213,8 @@ static bool find_centroid_neighbor(t_pl_loc& centroid_loc,
212213

213214
/**
214215
* @brief tries to place a macro at a centroid location of its placed connections.
215-
*
216+
*
217+
* @param block_id The block to be placed.
216218
* @param pl_macro The macro to be placed.
217219
* @param pr The PartitionRegion of the macro - represents its floorplanning constraints, is the size of the whole chip if the macro is not
218220
* constrained.
@@ -225,7 +227,8 @@ static bool find_centroid_neighbor(t_pl_loc& centroid_loc,
225227
*
226228
* @return true if the macro gets placed, false if not.
227229
*/
228-
static bool try_centroid_placement(const t_pl_macro& pl_macro,
230+
static bool try_centroid_placement(ClusterBlockId block_id,
231+
const t_pl_macro& pl_macro,
229232
const PartitionRegion& pr,
230233
t_logical_block_type_ptr block_type,
231234
e_pad_loc_type pad_loc_type,
@@ -400,7 +403,8 @@ bool find_subtile_in_location(t_pl_loc& centroid,
400403
return false;
401404
}
402405

403-
static bool find_centroid_neighbor(t_pl_loc& centroid_loc,
406+
static bool find_centroid_neighbor(ClusterBlockId block_id,
407+
t_pl_loc& centroid_loc,
404408
t_logical_block_type_ptr block_type,
405409
bool search_for_empty,
406410
int rlim,
@@ -425,6 +429,18 @@ static bool find_centroid_neighbor(t_pl_loc& centroid_loc,
425429

426430
int delta_cx = search_range.xmax - search_range.xmin;
427431

432+
bool block_constrained = is_cluster_constrained(block_id);
433+
434+
if (block_constrained) {
435+
bool intersect = intersect_range_limit_with_floorplan_constraints(block_id,
436+
search_range,
437+
delta_cx,
438+
centroid_loc_layer_num);
439+
if (!intersect) {
440+
return false;
441+
}
442+
}
443+
428444
//Block has not been placed yet, so the "from" coords will be (-1, -1)
429445
int cx_from = OPEN;
430446
int cy_from = OPEN;
@@ -441,7 +457,8 @@ static bool find_centroid_neighbor(t_pl_loc& centroid_loc,
441457
centroid_loc_layer_num,
442458
search_for_empty,
443459
blk_loc_registry,
444-
rng);
460+
rng,
461+
block_constrained);
445462

446463
if (!legal) {
447464
return false;
@@ -832,7 +849,8 @@ static inline t_pl_loc find_nearest_compatible_loc(const t_flat_pl_loc& src_flat
832849
return best_loc;
833850
}
834851

835-
static bool try_centroid_placement(const t_pl_macro& pl_macro,
852+
static bool try_centroid_placement(ClusterBlockId block_id,
853+
const t_pl_macro& pl_macro,
836854
const PartitionRegion& pr,
837855
t_logical_block_type_ptr block_type,
838856
e_pad_loc_type pad_loc_type,
@@ -889,7 +907,7 @@ static bool try_centroid_placement(const t_pl_macro& pl_macro,
889907
//centroid suggestion was either occupied or does not match block type
890908
//try to find a near location that meet these requirements
891909
if (!found_legal_subtile) {
892-
bool neighbor_legal_loc = find_centroid_neighbor(centroid_loc, block_type, false, rlim, blk_loc_registry, rng);
910+
bool neighbor_legal_loc = find_centroid_neighbor(block_id, centroid_loc, block_type, false, rlim, blk_loc_registry, rng);
893911
if (!neighbor_legal_loc) { //no neighbor candidate found
894912
return false;
895913
}
@@ -1065,6 +1083,9 @@ bool try_place_macro_randomly(const t_pl_macro& pl_macro,
10651083

10661084
bool legal;
10671085

1086+
// is_fixed_range is true since even if the block is not constrained,
1087+
// the search range covers the entire region, so there is no need for
1088+
// the search range to be adjusted
10681089
legal = find_compatible_compressed_loc_in_range(block_type,
10691090
delta_cx,
10701091
{cx_from, cy_from, selected_layer},
@@ -1076,7 +1097,8 @@ bool try_place_macro_randomly(const t_pl_macro& pl_macro,
10761097
selected_layer,
10771098
/*search_for_empty=*/false,
10781099
blk_loc_registry,
1079-
rng);
1100+
rng,
1101+
/*is_range_fixed=*/true);
10801102

10811103
if (!legal) {
10821104
//No valid position found
@@ -1300,7 +1322,7 @@ static bool place_macro(int macros_max_num_tries,
13001322

13011323
if (!macro_placed) {
13021324
VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "\t\t\tTry centroid placement\n");
1303-
macro_placed = try_centroid_placement(pl_macro, pr, block_type, pad_loc_type, block_scores, blk_loc_registry, flat_placement_info, rng);
1325+
macro_placed = try_centroid_placement(blk_id, pl_macro, pr, block_type, pad_loc_type, block_scores, blk_loc_registry, flat_placement_info, rng);
13041326
}
13051327
VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "\t\t\tMacro is placed: %d\n", macro_placed);
13061328
// If macro is not placed yet, try to place the macro randomly for the max number of random tries

vpr/src/place/move_utils.cpp

Lines changed: 65 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,24 @@
1616
//Note: The flag is only effective if compiled with VTR_ENABLE_DEBUG_LOGGING
1717
bool f_placer_breakpoint_reached = false;
1818

19+
/**
20+
* @brief Adjust the search range based on how many blocks are in the column.
21+
* If the number of blocks in the column is less than MIN_NUM_BLOCKS_IN_COLUMN,
22+
* expand the search range to cover the entire column.
23+
*
24+
* @param block_type The type of the block to move
25+
* @param compressed_column_num The compressed column to move the block to
26+
* @param to_layer_num The layer that the block is moving to
27+
* @param is_range_fixed Whether the search range is fixed (e.g., in case of placement constraints)
28+
* @param search_range The search range to adjust
29+
*
30+
*/
31+
static void adjust_search_range(t_logical_block_type_ptr block_type,
32+
const int compressed_column_num,
33+
const int to_layer_num,
34+
const bool is_range_fixed,
35+
t_bb& search_range);
36+
1937
//Accessor for f_placer_breakpoint_reached
2038
bool placer_breakpoint_reached() {
2139
return f_placer_breakpoint_reached;
@@ -666,10 +684,9 @@ bool find_to_loc_uniform(t_logical_block_type_ptr type,
666684
rlim);
667685
int delta_cx = search_range.xmax - search_range.xmin;
668686

669-
t_physical_tile_loc to_compressed_loc;
670-
bool legal = false;
687+
bool block_constrained = is_cluster_constrained(b_from);
671688

672-
if (is_cluster_constrained(b_from)) {
689+
if (block_constrained) {
673690
bool intersect = intersect_range_limit_with_floorplan_constraints(b_from,
674691
search_range,
675692
delta_cx,
@@ -678,6 +695,9 @@ bool find_to_loc_uniform(t_logical_block_type_ptr type,
678695
return false;
679696
}
680697
}
698+
699+
t_physical_tile_loc to_compressed_loc;
700+
bool legal = false;
681701
//TODO: For now, we only move the blocks on the same tile
682702
legal = find_compatible_compressed_loc_in_range(type,
683703
delta_cx,
@@ -688,7 +708,8 @@ bool find_to_loc_uniform(t_logical_block_type_ptr type,
688708
to_layer_num,
689709
/*search_for_empty=*/false,
690710
blk_loc_registry,
691-
rng);
711+
rng,
712+
block_constrained);
692713

693714
if (!legal) {
694715
//No valid position found
@@ -758,10 +779,9 @@ bool find_to_loc_median(t_logical_block_type_ptr blk_type,
758779
to_layer_num,
759780
to_layer_num);
760781

761-
t_physical_tile_loc to_compressed_loc;
762-
bool legal = false;
782+
bool block_constrained = is_cluster_constrained(b_from);
763783

764-
if (is_cluster_constrained(b_from)) {
784+
if (block_constrained) {
765785
bool intersect = intersect_range_limit_with_floorplan_constraints(b_from,
766786
search_range,
767787
delta_cx,
@@ -771,6 +791,8 @@ bool find_to_loc_median(t_logical_block_type_ptr blk_type,
771791
}
772792
}
773793

794+
t_physical_tile_loc to_compressed_loc;
795+
bool legal = false;
774796
legal = find_compatible_compressed_loc_in_range(blk_type,
775797
delta_cx,
776798
from_compressed_locs[to_layer_num],
@@ -780,7 +802,8 @@ bool find_to_loc_median(t_logical_block_type_ptr blk_type,
780802
to_layer_num,
781803
/*search_for_empty=*/false,
782804
blk_loc_registry,
783-
rng);
805+
rng,
806+
block_constrained);
784807

785808
if (!legal) {
786809
//No valid position found
@@ -847,10 +870,9 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type,
847870
}
848871
delta_cx = search_range.xmax - search_range.xmin;
849872

850-
t_physical_tile_loc to_compressed_loc;
851-
bool legal = false;
873+
bool block_constrained = is_cluster_constrained(b_from);
852874

853-
if (is_cluster_constrained(b_from)) {
875+
if (block_constrained) {
854876
bool intersect = intersect_range_limit_with_floorplan_constraints(b_from,
855877
search_range,
856878
delta_cx,
@@ -860,7 +882,10 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type,
860882
}
861883
}
862884

863-
//TODO: For now, we only move the blocks on the same tile
885+
t_physical_tile_loc to_compressed_loc;
886+
bool legal = false;
887+
888+
//TODO: For now, we only move the blocks on the same layer
864889
legal = find_compatible_compressed_loc_in_range(blk_type,
865890
delta_cx,
866891
from_compressed_loc[to_layer_num],
@@ -870,7 +895,8 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type,
870895
to_layer_num,
871896
/*search_for_empty=*/false,
872897
blk_loc_registry,
873-
rng);
898+
rng,
899+
block_constrained);
874900

875901
if (!legal) {
876902
//No valid position found
@@ -964,7 +990,8 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type,
964990
int to_layer_num,
965991
bool search_for_empty,
966992
const BlkLocRegistry& blk_loc_registry,
967-
vtr::RngContainer& rng) {
993+
vtr::RngContainer& rng,
994+
const bool is_range_fixed) {
968995
//TODO For the time being, the blocks only moved in the same layer. This assertion should be removed after VPR is updated to move blocks between layers
969996
VTR_ASSERT(to_layer_num == from_loc.layer_num);
970997
const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[type->index];
@@ -999,28 +1026,17 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type,
9991026
//The candidates are stored in a flat_map so we can efficiently find the set of valid
10001027
//candidates with upper/lower bound.
10011028
const auto& block_rows = compressed_block_grid.get_column_block_map(to_loc.x, to_layer_num);
1029+
adjust_search_range(type,
1030+
to_loc.x,
1031+
to_layer_num,
1032+
is_range_fixed,
1033+
search_range);
10021034
auto y_lower_iter = block_rows.lower_bound(search_range.ymin);
10031035
if (y_lower_iter == block_rows.end()) {
10041036
continue;
10051037
}
1006-
10071038
auto y_upper_iter = block_rows.upper_bound(search_range.ymax);
10081039

1009-
if (y_lower_iter->first > search_range.ymin) {
1010-
//No valid blocks at this x location which are within rlim_y
1011-
//
1012-
if (type->index != 1)
1013-
continue;
1014-
else {
1015-
//Fall back to allow the whole y range
1016-
y_lower_iter = block_rows.begin();
1017-
y_upper_iter = block_rows.end();
1018-
1019-
search_range.ymin = y_lower_iter->first;
1020-
search_range.ymax = (y_upper_iter - 1)->first;
1021-
}
1022-
}
1023-
10241040
int y_range = std::distance(y_lower_iter, y_upper_iter);
10251041
VTR_ASSERT(y_range >= 0);
10261042

@@ -1199,6 +1215,25 @@ bool intersect_range_limit_with_floorplan_constraints(ClusterBlockId b_from,
11991215
return true;
12001216
}
12011217

1218+
static void adjust_search_range(t_logical_block_type_ptr block_type,
1219+
const int compressed_column_num,
1220+
const int to_layer_num,
1221+
const bool is_range_fixed,
1222+
t_bb& search_range) {
1223+
// The value is chosen empirically to expand the search range for sparse blocks,
1224+
// or blocks located on the perimeter of the FPGA (e.g., IO blocks)
1225+
constexpr int MIN_NUM_BLOCKS_IN_COLUMN = 3;
1226+
1227+
const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[block_type->index];
1228+
1229+
size_t num_blocks_in_column = compressed_block_grid.get_column_block_map(compressed_column_num, to_layer_num).size();
1230+
1231+
if (num_blocks_in_column < MIN_NUM_BLOCKS_IN_COLUMN && !is_range_fixed) {
1232+
search_range.ymin = 0;
1233+
search_range.ymax = compressed_block_grid.get_num_rows(to_layer_num) - 1;
1234+
}
1235+
}
1236+
12021237
std::string e_move_result_to_string(e_move_result move_outcome) {
12031238
switch (move_outcome) {
12041239
case e_move_result::REJECTED:

vpr/src/place/move_utils.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ int find_empty_compatible_subtile(t_logical_block_type_ptr type,
327327
* is_median: true if this is called from find_to_loc_median
328328
* to_layer_num: the layer number of the new location (set by the caller)
329329
* search_for_empty: indicates that the returned location must be empty
330+
* is_range_fixed: indicates that the search range is fixed and should not be adjusted
330331
*/
331332
bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type,
332333
int delta_cx,
@@ -337,7 +338,8 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type,
337338
int to_layer_num,
338339
bool search_for_empty,
339340
const BlkLocRegistry& blk_loc_registry,
340-
vtr::RngContainer& rng);
341+
vtr::RngContainer& rng,
342+
const bool is_range_fixed);
341343

342344
/**
343345
* @brief Get the the compressed loc from the uncompressed loc (grid_loc)

0 commit comments

Comments
 (0)