Skip to content

Commit 39f6227

Browse files
authored
Merge pull request #1983 from verilog-to-routing/optimize_floorplan_checks_during_place_moves
Optimize floorplan checks during place moves
2 parents 9fd351e + ab88ee1 commit 39f6227

13 files changed

+211
-38
lines changed

vpr/src/pack/attraction_groups.cpp

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,7 @@ AttractionInfo::AttractionInfo(bool attraction_groups_on) {
2626
}
2727

2828
//Then, fill in the group id for the atoms that do have an attraction group
29-
int num_att_grps = attraction_groups.size();
30-
31-
for (int igroup = 0; igroup < num_att_grps; igroup++) {
32-
AttractGroupId group_id(igroup);
33-
34-
AttractionGroup att_group = attraction_groups[group_id];
35-
36-
for (unsigned int iatom = 0; iatom < att_group.group_atoms.size(); iatom++) {
37-
atom_attraction_group[att_group.group_atoms[iatom]] = group_id;
38-
}
39-
}
29+
assign_atom_attraction_ids();
4030

4131
att_group_pulls = 1;
4232
}
@@ -90,6 +80,56 @@ void AttractionInfo::create_att_groups_for_overfull_regions() {
9080
}
9181

9282
//Then, fill in the group id for the atoms that do have an attraction group
83+
assign_atom_attraction_ids();
84+
85+
att_group_pulls = 1;
86+
87+
VTR_LOG("%d clustering attraction groups created. \n", attraction_groups.size());
88+
}
89+
90+
void AttractionInfo::create_att_groups_for_all_regions() {
91+
auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning();
92+
auto& atom_ctx = g_vpr_ctx.atom();
93+
int num_parts = floorplanning_ctx.constraints.get_num_partitions();
94+
95+
//clear the data structures before continuing
96+
atom_attraction_group.clear();
97+
attraction_groups.clear();
98+
99+
//Initialize every atom to have no attraction group id
100+
int num_atoms = atom_ctx.nlist.blocks().size();
101+
102+
atom_attraction_group.resize(num_atoms);
103+
fill(atom_attraction_group.begin(), atom_attraction_group.end(), AttractGroupId::INVALID());
104+
105+
/*
106+
* Create a PartitionRegion that contains all the overfull regions so that you can
107+
* make an attraction group for any partition that intersects with any of these regions
108+
*/
109+
110+
/*
111+
* Create an attraction group for each parition with an overfull region.
112+
*/
113+
114+
for (int ipart = 0; ipart < num_parts; ipart++) {
115+
PartitionId partid(ipart);
116+
117+
AttractionGroup group_info;
118+
group_info.group_atoms = floorplanning_ctx.constraints.get_part_atoms(partid);
119+
120+
attraction_groups.push_back(group_info);
121+
}
122+
123+
//Then, fill in the group id for the atoms that do have an attraction group
124+
assign_atom_attraction_ids();
125+
126+
att_group_pulls = 1;
127+
128+
VTR_LOG("%d clustering attraction groups created. \n", attraction_groups.size());
129+
}
130+
131+
void AttractionInfo::assign_atom_attraction_ids() {
132+
//Fill in the group id for the atoms that do have an attraction group
93133
int num_att_grps = attraction_groups.size();
94134

95135
for (int igroup = 0; igroup < num_att_grps; igroup++) {
@@ -101,10 +141,6 @@ void AttractionInfo::create_att_groups_for_overfull_regions() {
101141
atom_attraction_group[att_group.group_atoms[iatom]] = group_id;
102142
}
103143
}
104-
105-
att_group_pulls = 1;
106-
107-
VTR_LOG("%d clustering attraction groups created. \n", num_att_grps);
108144
}
109145

110146
void AttractionInfo::set_attraction_group_info(AttractGroupId group_id, const AttractionGroup& group_info) {

vpr/src/pack/attraction_groups.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,19 @@ class AttractionInfo {
5050
//If no constraints were specified, then no attraction groups will be created.
5151
AttractionInfo(bool attraction_groups_on);
5252

53+
/*
54+
* Create attraction groups for the partitions that contain overfull regions (i.e.
55+
* The region has more blocks of a certain type assigned to than are actually available).
56+
*/
5357
void create_att_groups_for_overfull_regions();
5458

59+
/*
60+
* Create attraction groups for all partitions.
61+
*/
62+
void create_att_groups_for_all_regions();
63+
64+
void assign_atom_attraction_ids();
65+
5566
//Setters and getters for the class
5667
AttractGroupId get_atom_attraction_group(const AtomBlockId atom_id);
5768

vpr/src/pack/cluster.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2764,13 +2764,29 @@ static void add_cluster_molecule_candidates_by_attraction_group(t_pb* cur_pb,
27642764
}
27652765

27662766
AttractionGroup& group = attraction_groups.get_attraction_group_info(grp_id);
2767-
int num_available_atoms = group.group_atoms.size();
2767+
std::vector<AtomBlockId> available_atoms;
2768+
for (AtomBlockId atom_id : group.group_atoms) {
2769+
const auto& atom_model = atom_ctx.nlist.block_model(atom_id);
2770+
auto itr = primitive_candidate_block_types.find(atom_model);
2771+
VTR_ASSERT(itr != primitive_candidate_block_types.end());
2772+
std::vector<t_logical_block_type_ptr>& candidate_types = itr->second;
2773+
2774+
//Only consider molecules that are unpacked and of the correct type
2775+
if (atom_ctx.lookup.atom_clb(atom_id) == ClusterBlockId::INVALID()
2776+
&& std::find(candidate_types.begin(), candidate_types.end(), cluster_type) != candidate_types.end()) {
2777+
available_atoms.push_back(atom_id);
2778+
}
2779+
}
2780+
2781+
//int num_available_atoms = group.group_atoms.size();
2782+
int num_available_atoms = available_atoms.size();
27682783
if (num_available_atoms == 0) {
27692784
return;
27702785
}
27712786

27722787
if (num_available_atoms < 500) {
2773-
for (AtomBlockId atom_id : group.group_atoms) {
2788+
//for (AtomBlockId atom_id : group.group_atoms) {
2789+
for (AtomBlockId atom_id : available_atoms) {
27742790
const auto& atom_model = atom_ctx.nlist.block_model(atom_id);
27752791
auto itr = primitive_candidate_block_types.find(atom_model);
27762792
VTR_ASSERT(itr != primitive_candidate_block_types.end());
@@ -2804,7 +2820,8 @@ static void add_cluster_molecule_candidates_by_attraction_group(t_pb* cur_pb,
28042820
std::uniform_int_distribution<> distr(min, max);
28052821
int selected_atom = distr(gen);
28062822

2807-
AtomBlockId blk_id = group.group_atoms[selected_atom];
2823+
//AtomBlockId blk_id = group.group_atoms[selected_atom];
2824+
AtomBlockId blk_id = available_atoms[selected_atom];
28082825
const auto& atom_model = atom_ctx.nlist.block_model(blk_id);
28092826
auto itr = primitive_candidate_block_types.find(atom_model);
28102827
VTR_ASSERT(itr != primitive_candidate_block_types.end());

vpr/src/pack/pack.cpp

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -178,18 +178,38 @@ bool try_pack(t_packer_opts* packer_opts,
178178
VTR_LOG("Packing failed to fit on device. Re-packing with: unrelated_logic_clustering=%s balance_block_type_util=%s\n",
179179
(allow_unrelated_clustering ? "true" : "false"),
180180
(balance_block_type_util ? "true" : "false"));
181+
/*
182+
* When running with tight floorplan constraints, some regions may become overfull with clusters (i.e.
183+
* the number of blocks assigned to the region exceeds the number of blocks available). When this occurs, we
184+
* cluster more densely to be able to adhere to the floorplan constraints. However, we do not want to cluster more
185+
* densely unnecessarily, as this can negatively impact wirelength. So, we have iterative approach. We check at the end
186+
* of every iteration if any floorplan regions are overfull. In the first iteration, we run
187+
* with no attraction groups (not packing more densely). If regions are overfull at the end of the first iteration,
188+
* we create attraction groups for partitions with overfull regions (pack those atoms more densely). We continue this way
189+
* until the last iteration, when we create attraction groups for every partition, if needed.
190+
*/
181191
} else if (pack_iteration == 1 && floorplan_not_fitting) {
182192
VTR_LOG("Floorplan regions are overfull: trying to pack again using cluster attraction groups. \n");
183193
attraction_groups.create_att_groups_for_overfull_regions();
184194
attraction_groups.set_att_group_pulls(1);
185195

186196
} else if (pack_iteration >= 2 && pack_iteration < 5 && floorplan_not_fitting) {
187-
VTR_LOG("Floorplan regions are overfull: trying to pack again with more attraction groups exploration and higher target pin utilization. \n");
188-
attraction_groups.create_att_groups_for_overfull_regions();
189-
VTR_LOG("Pack iteration is %d\n", pack_iteration);
190-
attraction_groups.set_att_group_pulls(4);
191-
t_ext_pin_util pin_util(1.0, 1.0);
192-
target_external_pin_util.set_block_pin_util("clb", pin_util);
197+
if (pack_iteration == 2) {
198+
VTR_LOG("Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n");
199+
attraction_groups.create_att_groups_for_overfull_regions();
200+
VTR_LOG("Pack iteration is %d\n", pack_iteration);
201+
} else if (pack_iteration == 3) {
202+
attraction_groups.create_att_groups_for_all_regions();
203+
VTR_LOG("Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n");
204+
VTR_LOG("Pack iteration is %d\n", pack_iteration);
205+
} else if (pack_iteration == 4) {
206+
attraction_groups.create_att_groups_for_all_regions();
207+
VTR_LOG("Floorplan regions are overfull: trying to pack again with more attraction groups exploration and higher target pin utilization. \n");
208+
VTR_LOG("Pack iteration is %d\n", pack_iteration);
209+
attraction_groups.set_att_group_pulls(4);
210+
t_ext_pin_util pin_util(1.0, 1.0);
211+
target_external_pin_util.set_block_pin_util("clb", pin_util);
212+
}
193213

194214
} else {
195215
//Unable to pack densely enough: Give Up

vpr/src/place/centroid_move_generator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& block
3232
calculate_centroid_loc(b_from, false, centroid, NULL);
3333

3434
/* Find a location near the weighted centroid_loc */
35-
if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to)) {
35+
if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to, b_from)) {
3636
return e_create_move::ABORT;
3737
}
3838

vpr/src/place/critical_uniform_move_generator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ e_create_move CriticalUniformMoveGenerator::propose_move(t_pl_blocks_to_be_moved
3030

3131
t_pl_loc to;
3232

33-
if (!find_to_loc_uniform(cluster_from_type, rlim, from, to)) {
33+
if (!find_to_loc_uniform(cluster_from_type, rlim, from, to, b_from)) {
3434
return e_create_move::ABORT;
3535
}
3636

vpr/src/place/feasible_region_move_generator.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,14 @@ e_create_move FeasibleRegionMoveGenerator::propose_move(t_pl_blocks_to_be_moved&
112112
range_limiters.first_rlim = place_move_ctx.first_rlim;
113113

114114
// Try to find a legal location inside the feasible region
115-
if (!find_to_loc_median(cluster_from_type, from, &FR_coords, to)) {
115+
if (!find_to_loc_median(cluster_from_type, from, &FR_coords, to, b_from)) {
116116
/** If there is no legal location in the feasible region, calculate the center of the FR and try to find a legal location
117117
* in a range around this center.
118118
*/
119119
t_pl_loc center;
120120
center.x = (FR_coords.xmin + FR_coords.xmax) / 2;
121121
center.y = (FR_coords.ymin + FR_coords.ymax) / 2;
122-
if (!find_to_loc_centroid(cluster_from_type, from, center, range_limiters, to))
122+
if (!find_to_loc_centroid(cluster_from_type, from, center, range_limiters, to, b_from))
123123
return e_create_move::ABORT;
124124
}
125125

vpr/src/place/median_move_generator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_
119119
t_pl_loc median_point;
120120
median_point.x = (limit_coords.xmin + limit_coords.xmax) / 2;
121121
median_point.y = (limit_coords.ymin + limit_coords.ymax) / 2;
122-
if (!find_to_loc_centroid(cluster_from_type, from, median_point, range_limiters, to))
122+
if (!find_to_loc_centroid(cluster_from_type, from, median_point, range_limiters, to, b_from))
123123
return e_create_move::ABORT;
124124

125125
e_create_move create_move = ::create_move(blocks_affected, b_from, to);

vpr/src/place/move_utils.cpp

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include "draw_debug.h"
99
#include "draw.h"
1010

11+
#include "place_constraints.h"
12+
1113
//f_placer_breakpoint_reached is used to stop the placer when a breakpoint is reached. When this flag is true, it stops the placer after the current perturbation. Thus, when a breakpoint is reached, this flag is set to true.
1214
//Note: The flag is only effective if compiled with VTR_ENABLE_DEBUG_LOGGING
1315
bool f_placer_breakpoint_reached = false;
@@ -532,7 +534,8 @@ ClusterBlockId pick_from_block() {
532534
bool find_to_loc_uniform(t_logical_block_type_ptr type,
533535
float rlim,
534536
const t_pl_loc from,
535-
t_pl_loc& to) {
537+
t_pl_loc& to,
538+
ClusterBlockId b_from) {
536539
//Finds a legal swap to location for the given type, starting from 'from.x' and 'from.y'
537540
//
538541
//Note that the range limit (rlim) is applied in a logical sense (i.e. 'compressed' grid space consisting
@@ -566,6 +569,13 @@ bool find_to_loc_uniform(t_logical_block_type_ptr type,
566569
int cy_to = OPEN;
567570
bool legal = false;
568571

572+
if (is_cluster_constrained(b_from)) {
573+
bool intersect = intersect_range_limit_with_floorplan_constraints(type, b_from, min_cx, min_cy, max_cx, max_cy, delta_cx);
574+
if (!intersect) {
575+
return false;
576+
}
577+
}
578+
569579
legal = find_compatible_compressed_loc_in_range(type, min_cx, max_cx, min_cy, max_cy, delta_cx, cx_from, cy_from, cx_to, cy_to, false);
570580

571581
if (!legal) {
@@ -601,7 +611,8 @@ void set_placer_breakpoint_reached(bool flag) {
601611
bool find_to_loc_median(t_logical_block_type_ptr blk_type,
602612
const t_pl_loc& from_loc,
603613
const t_bb* limit_coords,
604-
t_pl_loc& to_loc) {
614+
t_pl_loc& to_loc,
615+
ClusterBlockId b_from) {
605616
const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[blk_type->index];
606617

607618
//Determine the coordinates in the compressed grid space of the current block
@@ -630,6 +641,13 @@ bool find_to_loc_median(t_logical_block_type_ptr blk_type,
630641
int cy_to = OPEN;
631642
bool legal = false;
632643

644+
if (is_cluster_constrained(b_from)) {
645+
bool intersect = intersect_range_limit_with_floorplan_constraints(blk_type, b_from, min_cx, min_cy, max_cx, max_cy, delta_cx);
646+
if (!intersect) {
647+
return false;
648+
}
649+
}
650+
633651
legal = find_compatible_compressed_loc_in_range(blk_type, min_cx, max_cx, min_cy, max_cy, delta_cx, cx_from, cy_from, cx_to, cy_to, true);
634652

635653
if (!legal) {
@@ -657,7 +675,8 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type,
657675
const t_pl_loc& from_loc,
658676
const t_pl_loc& centroid,
659677
const t_range_limiters& range_limiters,
660-
t_pl_loc& to_loc) {
678+
t_pl_loc& to_loc,
679+
ClusterBlockId b_from) {
661680
//Retrieve the compressed block grid for this block type
662681
const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[blk_type->index];
663682

@@ -707,6 +726,13 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type,
707726
int cy_to = OPEN;
708727
bool legal = false;
709728

729+
if (is_cluster_constrained(b_from)) {
730+
bool intersect = intersect_range_limit_with_floorplan_constraints(blk_type, b_from, min_cx, min_cy, max_cx, max_cy, delta_cx);
731+
if (!intersect) {
732+
return false;
733+
}
734+
}
735+
710736
legal = find_compatible_compressed_loc_in_range(blk_type, min_cx, max_cx, min_cy, max_cy, delta_cx, cx_from, cy_from, cx_to, cy_to, false);
711737

712738
if (!legal) {
@@ -848,6 +874,50 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type, int
848874
return legal;
849875
}
850876

877+
bool intersect_range_limit_with_floorplan_constraints(t_logical_block_type_ptr type, ClusterBlockId b_from, int& min_cx, int& min_cy, int& max_cx, int& max_cy, int& delta_cx) {
878+
//Retrieve the compressed block grid for this block type
879+
const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[type->index];
880+
881+
int min_x = compressed_block_grid.compressed_to_grid_x[min_cx];
882+
int max_x = compressed_block_grid.compressed_to_grid_x[max_cx];
883+
int min_y = compressed_block_grid.compressed_to_grid_y[min_cy];
884+
int max_y = compressed_block_grid.compressed_to_grid_y[max_cy];
885+
Region range_reg;
886+
range_reg.set_region_rect(min_x, min_y, max_x, max_y);
887+
888+
auto& floorplanning_ctx = g_vpr_ctx.floorplanning();
889+
890+
PartitionRegion pr = floorplanning_ctx.cluster_constraints[b_from];
891+
std::vector<Region> regions;
892+
if (!pr.empty()) {
893+
regions = pr.get_partition_region();
894+
}
895+
Region intersect_reg;
896+
/*
897+
* If region size is greater than 1, the block is constrained to more than one rectangular region.
898+
* In this case, we return true (i.e. the range limit intersects with
899+
* the floorplan constraints) to simplify the problem. This simplification can be done because
900+
* this routine is done for cpu time optimization, so we do not have to necessarily check each
901+
* complicated case to get correct functionality during place moves.
902+
*/
903+
if (regions.size() == 1) {
904+
intersect_reg = intersection(regions[0], range_reg);
905+
906+
if (intersect_reg.empty()) {
907+
return false;
908+
} else {
909+
vtr::Rect<int> rect = intersect_reg.get_region_rect();
910+
min_cx = grid_to_compressed_approx(compressed_block_grid.compressed_to_grid_x, rect.xmin());
911+
max_cx = grid_to_compressed_approx(compressed_block_grid.compressed_to_grid_x, rect.xmax());
912+
min_cy = grid_to_compressed_approx(compressed_block_grid.compressed_to_grid_y, rect.ymin());
913+
max_cy = grid_to_compressed_approx(compressed_block_grid.compressed_to_grid_y, rect.ymax());
914+
delta_cx = max_cx - min_cx;
915+
}
916+
}
917+
918+
return true;
919+
}
920+
851921
std::string e_move_result_to_string(e_move_result move_outcome) {
852922
std::string move_result_to_string[] = {"Rejected", "Accepted", "Aborted"};
853923
return move_result_to_string[move_outcome];

0 commit comments

Comments
 (0)