@@ -54,8 +54,8 @@ bool is_macro_constrained(const t_pl_macro& pl_macro) {
54
54
}
55
55
56
56
/* Returns PartitionRegion of where the head of the macro could go*/
57
- PartitionRegion constrained_macro_locs (const t_pl_macro& pl_macro) {
58
- PartitionRegion macro_pr ;
57
+ PartitionRegion update_macro_head_pr (const t_pl_macro& pl_macro, const PartitionRegion& grid_pr ) {
58
+ PartitionRegion macro_head_pr ;
59
59
bool is_member_constrained = false ;
60
60
int num_constrained_members = 0 ;
61
61
auto & floorplanning_ctx = g_vpr_ctx.floorplanning ();
@@ -80,39 +80,116 @@ PartitionRegion constrained_macro_locs(const t_pl_macro& pl_macro) {
80
80
81
81
vtr::Rect <int > reg_rect = block_regions[i].get_region_rect ();
82
82
83
- t_pl_loc min_pl_loc (reg_rect.xmin (), reg_rect.ymin (), block_regions[i].get_sub_tile ());
84
-
85
- t_pl_loc modified_min_pl_loc = min_pl_loc + offset;
86
-
87
- t_pl_loc max_pl_loc (reg_rect.xmax (), reg_rect.ymax (), block_regions[i].get_sub_tile ());
83
+ modified_reg.set_region_rect (reg_rect.xmin () - offset.x , reg_rect.ymin () - offset.y , reg_rect.xmax () - offset.x , reg_rect.ymax () - offset.y );
88
84
89
- t_pl_loc modified_max_pl_loc = max_pl_loc + offset;
90
-
91
- modified_reg.set_region_rect (modified_min_pl_loc.x , modified_min_pl_loc.y , modified_max_pl_loc.x , modified_max_pl_loc.y );
92
85
// check that subtile is not an invalid value before changing, otherwise it just stays -1
93
- if (block_regions[i].get_sub_tile () != - 1 ) {
94
- modified_reg.set_sub_tile (modified_min_pl_loc .sub_tile );
86
+ if (block_regions[i].get_sub_tile () != NO_SUBTILE ) {
87
+ modified_reg.set_sub_tile (block_regions[i]. get_sub_tile () - offset .sub_tile );
95
88
}
96
89
97
90
modified_pr.add_to_part_region (modified_reg);
98
91
}
99
92
100
93
if (num_constrained_members == 1 ) {
101
- macro_pr = modified_pr;
94
+ macro_head_pr = modified_pr;
102
95
} else {
103
- macro_pr = intersection (macro_pr , modified_pr);
96
+ macro_head_pr = intersection (macro_head_pr , modified_pr);
104
97
}
105
98
}
106
99
}
107
100
101
+ // intersect to ensure the head pr does not go outside of grid dimensions
102
+ macro_head_pr = intersection (macro_head_pr, grid_pr);
103
+
104
+ // if the intersection is empty, no way to place macro members together, give an error
105
+ if (macro_head_pr.empty ()) {
106
+ print_macro_constraint_error (pl_macro);
107
+ }
108
+
109
+ return macro_head_pr;
110
+ }
111
+
112
+ PartitionRegion update_macro_member_pr (PartitionRegion& head_pr, const t_pl_offset& offset, const PartitionRegion& grid_pr, const t_pl_macro& pl_macro) {
113
+ std::vector<Region> block_regions = head_pr.get_partition_region ();
114
+ PartitionRegion macro_pr;
115
+
116
+ for (unsigned int i = 0 ; i < block_regions.size (); i++) {
117
+ Region modified_reg;
118
+
119
+ vtr::Rect <int > reg_rect = block_regions[i].get_region_rect ();
120
+
121
+ modified_reg.set_region_rect (reg_rect.xmin () + offset.x , reg_rect.ymin () + offset.y , reg_rect.xmax () + offset.x , reg_rect.ymax () + offset.y );
122
+
123
+ // check that subtile is not an invalid value before changing, otherwise it just stays -1
124
+ if (block_regions[i].get_sub_tile () != NO_SUBTILE) {
125
+ modified_reg.set_sub_tile (block_regions[i].get_sub_tile () + offset.sub_tile );
126
+ }
127
+
128
+ macro_pr.add_to_part_region (modified_reg);
129
+ }
130
+
131
+ // intersect to ensure the macro pr does not go outside of grid dimensions
132
+ macro_pr = intersection (macro_pr, grid_pr);
133
+
108
134
// if the intersection is empty, no way to place macro members together, give an error
109
135
if (macro_pr.empty ()) {
110
- VPR_ERROR (VPR_ERROR_PLACE, " \n Feasible floorplanning constraints could not be calculated for the placement macro. \n " );
136
+ print_macro_constraint_error (pl_macro );
111
137
}
112
138
113
139
return macro_pr;
114
140
}
115
141
142
+ void print_macro_constraint_error (const t_pl_macro& pl_macro) {
143
+ auto & cluster_ctx = g_vpr_ctx.clustering ();
144
+ VTR_LOG (
145
+ " Feasible floorplanning constraints could not be calculated for the placement macro. \n "
146
+ " The placement macro contains the following blocks: \n " );
147
+ for (unsigned int i = 0 ; i < pl_macro.members .size (); i++) {
148
+ std::string blk_name = cluster_ctx.clb_nlist .block_name ((pl_macro.members [i].blk_index ));
149
+ VTR_LOG (" Block %s (#%zu) " , blk_name.c_str (), size_t (pl_macro.members [i].blk_index ));
150
+ }
151
+ VTR_LOG (" \n " );
152
+ VPR_ERROR (VPR_ERROR_PLACE, " \n Check that the above-mentioned placement macro blocks have compatible floorplan constraints.\n " );
153
+ }
154
+
155
+ void propagate_place_constraints () {
156
+ auto & place_ctx = g_vpr_ctx.placement ();
157
+ auto & floorplanning_ctx = g_vpr_ctx.mutable_floorplanning ();
158
+ auto & device_ctx = g_vpr_ctx.device ();
159
+
160
+ // Create a PartitionRegion with grid dimensions
161
+ // Will be used to check that updated PartitionRegions are within grid bounds
162
+ int width = device_ctx.grid .width () - 1 ;
163
+ int height = device_ctx.grid .height () - 1 ;
164
+ Region grid_reg;
165
+ grid_reg.set_region_rect (0 , 0 , width, height);
166
+ PartitionRegion grid_pr;
167
+ grid_pr.add_to_part_region (grid_reg);
168
+
169
+ for (auto pl_macro : place_ctx.pl_macros ) {
170
+ if (is_macro_constrained (pl_macro)) {
171
+ /*
172
+ * Get the PartitionRegion for the head of the macro
173
+ * based on the constraints of all blocks contained in the macro
174
+ */
175
+ PartitionRegion macro_head_pr = update_macro_head_pr (pl_macro, grid_pr);
176
+
177
+ // Update PartitionRegions of all members of the macro
178
+ for (size_t imember = 0 ; imember < pl_macro.members .size (); imember++) {
179
+ ClusterBlockId iblk = pl_macro.members [imember].blk_index ;
180
+ auto offset = pl_macro.members [imember].offset ;
181
+
182
+ if (imember == 0 ) { // Update head PR
183
+ floorplanning_ctx.cluster_constraints [iblk] = macro_head_pr;
184
+ } else { // Update macro member PR
185
+ PartitionRegion macro_pr = update_macro_member_pr (macro_head_pr, offset, grid_pr, pl_macro);
186
+ floorplanning_ctx.cluster_constraints [iblk] = macro_pr;
187
+ }
188
+ }
189
+ }
190
+ }
191
+ }
192
+
116
193
/* returns true if location is compatible with floorplanning constraints, false if not*/
117
194
/*
118
195
* Even if the block passed in is from a macro, it will work because of the constraints
0 commit comments