@@ -145,7 +145,39 @@ bool try_pack(const t_packer_opts& packer_opts,
145
145
146
146
g_vpr_ctx.mutable_atom ().mutable_lookup ().set_atom_pb_bimap_lock (true );
147
147
148
- while (true ) {
148
+ /* *
149
+ * @brief Enumeration for the state of the packer.
150
+ *
151
+ * If the packer fails to find a dense enough packing, depending on how the
152
+ * packer failed, the packer may iteratively retry packing with different
153
+ * setting to try and find a denser packing. These states represent a
154
+ * different type of iteration.
155
+ */
156
+ enum class e_packer_state {
157
+ // / @brief Default packer state.
158
+ DEFAULT,
159
+ // / @brief Succcess state for the packer.
160
+ SUCCESS,
161
+ // / @brief Standard fallback where there is not region constraints. Turns
162
+ // / on unrelated clustering and balanced packing if it can.
163
+ UNRELATED_AND_BALANCED,
164
+ // / @brief Region constraints: Turns on attraction groups for overfilled regions.
165
+ ATTRACTION_GROUPS,
166
+ // / @brief Region constraints: Turns on more attraction groups for overfilled regions.
167
+ MORE_ATTRACTION_GROUPS,
168
+ // / @brief Region constraints: Turns on more attraction groups for all regions.
169
+ ATTRACTION_GROUPS_ALL_REGIONS,
170
+ // / @brief Region constraints: Turns on more attraction groups for all regions
171
+ // / and increases the target density of clb blocks.
172
+ ATTRACTION_GROUPS_ALL_REGIONS_AND_INCREASED_TARGET_DENSITY,
173
+ // / @brief The failure state.
174
+ FAILURE
175
+ };
176
+
177
+ // The current state of the packer during iterative packing.
178
+ e_packer_state current_packer_state = e_packer_state::DEFAULT;
179
+
180
+ while (current_packer_state != e_packer_state::SUCCESS && current_packer_state != e_packer_state::FAILURE) {
149
181
// Cluster the netlist
150
182
// num_used_type_instances: A map used to save the number of used
151
183
// instances from each logical block type.
@@ -170,48 +202,98 @@ bool try_pack(const t_packer_opts& packer_opts,
170
202
171
203
bool floorplan_not_fitting = (floorplan_regions_overfull || g_vpr_ctx.floorplanning ().constraints .get_num_partitions () > 0 );
172
204
205
+ // Next packer state logic
206
+ e_packer_state next_packer_state = e_packer_state::FAILURE;
173
207
if (fits_on_device && !floorplan_regions_overfull) {
174
- break ; // Done
175
- } else if (pack_iteration == 1 && !floorplan_not_fitting) {
176
- // 1st pack attempt was unsuccessful (i.e. not dense enough) and we have control of unrelated clustering
177
- //
178
- // Turn it on to increase packing density
179
- if (packer_opts.allow_unrelated_clustering == e_unrelated_clustering::AUTO) {
180
- VTR_ASSERT (allow_unrelated_clustering == false );
181
- allow_unrelated_clustering = true ;
208
+ // If everything fits on the device and the floorplan regions are
209
+ // not overfilled, the next state is success.
210
+ next_packer_state = e_packer_state::SUCCESS;
211
+ } else {
212
+ if (floorplan_not_fitting) {
213
+ // If there are overfilled region constraints.
214
+ /*
215
+ * When running with tight floorplan constraints, some regions may become overfull with clusters (i.e.
216
+ * the number of blocks assigned to the region exceeds the number of blocks available). When this occurs, we
217
+ * cluster more densely to be able to adhere to the floorplan constraints. However, we do not want to cluster more
218
+ * densely unnecessarily, as this can negatively impact wirelength. So, we have iterative approach. We check at the end
219
+ * of every iteration if any floorplan regions are overfull. In the first iteration, we run
220
+ * with no attraction groups (not packing more densely). If regions are overfull at the end of the first iteration,
221
+ * we create attraction groups for partitions with overfull regions (pack those atoms more densely). We continue this way
222
+ * until the last iteration, when we create attraction groups for every partition, if needed.
223
+ */
224
+ switch (current_packer_state) {
225
+ case e_packer_state::DEFAULT:
226
+ next_packer_state = e_packer_state::ATTRACTION_GROUPS;
227
+ break ;
228
+ case e_packer_state::UNRELATED_AND_BALANCED:
229
+ case e_packer_state::ATTRACTION_GROUPS:
230
+ next_packer_state = e_packer_state::MORE_ATTRACTION_GROUPS;
231
+ break ;
232
+ case e_packer_state::MORE_ATTRACTION_GROUPS:
233
+ next_packer_state = e_packer_state::ATTRACTION_GROUPS_ALL_REGIONS;
234
+ break ;
235
+ case e_packer_state::ATTRACTION_GROUPS_ALL_REGIONS:
236
+ next_packer_state = e_packer_state::ATTRACTION_GROUPS_ALL_REGIONS_AND_INCREASED_TARGET_DENSITY;
237
+ break ;
238
+ case e_packer_state::ATTRACTION_GROUPS_ALL_REGIONS_AND_INCREASED_TARGET_DENSITY:
239
+ default :
240
+ next_packer_state = e_packer_state::FAILURE;
241
+ break ;
242
+ }
243
+ } else {
244
+ // If there are no overfilled region constraints.
245
+ switch (current_packer_state) {
246
+ case e_packer_state::DEFAULT:
247
+ next_packer_state = e_packer_state::UNRELATED_AND_BALANCED;
248
+ break ;
249
+ default :
250
+ next_packer_state = e_packer_state::FAILURE;
251
+ break ;
252
+ }
182
253
}
183
- if (packer_opts.balance_block_type_utilization == e_balance_block_type_util::AUTO) {
184
- VTR_ASSERT (balance_block_type_util == false );
185
- balance_block_type_util = true ;
254
+ }
255
+
256
+ // Set up for the next packer state.
257
+ switch (next_packer_state) {
258
+ case e_packer_state::UNRELATED_AND_BALANCED: {
259
+ // 1st pack attempt was unsuccessful (i.e. not dense enough) and we have control of unrelated clustering
260
+ //
261
+ // Turn it on to increase packing density
262
+ // TODO: This will have no affect if unrelated clustering and
263
+ // balance block type utilization is not auto. Should update
264
+ // the next state logic.
265
+ if (packer_opts.allow_unrelated_clustering == e_unrelated_clustering::AUTO) {
266
+ VTR_ASSERT (allow_unrelated_clustering == false );
267
+ allow_unrelated_clustering = true ;
268
+ }
269
+ if (packer_opts.balance_block_type_utilization == e_balance_block_type_util::AUTO) {
270
+ VTR_ASSERT (balance_block_type_util == false );
271
+ balance_block_type_util = true ;
272
+ }
273
+ VTR_LOG (" Packing failed to fit on device. Re-packing with: unrelated_logic_clustering=%s balance_block_type_util=%s\n " ,
274
+ (allow_unrelated_clustering ? " true" : " false" ),
275
+ (balance_block_type_util ? " true" : " false" ));
276
+ break ;
186
277
}
187
- VTR_LOG (" Packing failed to fit on device. Re-packing with: unrelated_logic_clustering=%s balance_block_type_util=%s\n " ,
188
- (allow_unrelated_clustering ? " true" : " false" ),
189
- (balance_block_type_util ? " true" : " false" ));
190
- /*
191
- * When running with tight floorplan constraints, some regions may become overfull with clusters (i.e.
192
- * the number of blocks assigned to the region exceeds the number of blocks available). When this occurs, we
193
- * cluster more densely to be able to adhere to the floorplan constraints. However, we do not want to cluster more
194
- * densely unnecessarily, as this can negatively impact wirelength. So, we have iterative approach. We check at the end
195
- * of every iteration if any floorplan regions are overfull. In the first iteration, we run
196
- * with no attraction groups (not packing more densely). If regions are overfull at the end of the first iteration,
197
- * we create attraction groups for partitions with overfull regions (pack those atoms more densely). We continue this way
198
- * until the last iteration, when we create attraction groups for every partition, if needed.
199
- */
200
- } else if (pack_iteration == 1 && floorplan_not_fitting) {
201
- VTR_LOG (" Floorplan regions are overfull: trying to pack again using cluster attraction groups. \n " );
202
- attraction_groups.create_att_groups_for_overfull_regions (overfull_partition_regions);
203
- attraction_groups.set_att_group_pulls (1 );
204
-
205
- } else if (pack_iteration >= 2 && pack_iteration < 5 && floorplan_not_fitting) {
206
- if (pack_iteration == 2 ) {
278
+ case e_packer_state::ATTRACTION_GROUPS: {
279
+ VTR_LOG (" Floorplan regions are overfull: trying to pack again using cluster attraction groups. \n " );
280
+ attraction_groups.create_att_groups_for_overfull_regions (overfull_partition_regions);
281
+ attraction_groups.set_att_group_pulls (1 );
282
+ break ;
283
+ }
284
+ case e_packer_state::MORE_ATTRACTION_GROUPS: {
207
285
VTR_LOG (" Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n " );
208
286
attraction_groups.create_att_groups_for_overfull_regions (overfull_partition_regions);
209
287
VTR_LOG (" Pack iteration is %d\n " , pack_iteration);
210
- } else if (pack_iteration == 3 ) {
288
+ break ;
289
+ }
290
+ case e_packer_state::ATTRACTION_GROUPS_ALL_REGIONS: {
211
291
attraction_groups.create_att_groups_for_all_regions ();
212
292
VTR_LOG (" Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n " );
213
293
VTR_LOG (" Pack iteration is %d\n " , pack_iteration);
214
- } else if (pack_iteration == 4 ) {
294
+ break ;
295
+ }
296
+ case e_packer_state::ATTRACTION_GROUPS_ALL_REGIONS_AND_INCREASED_TARGET_DENSITY: {
215
297
attraction_groups.create_att_groups_for_all_regions ();
216
298
VTR_LOG (" Floorplan regions are overfull: trying to pack again with more attraction groups exploration and higher target pin utilization. \n " );
217
299
VTR_LOG (" Pack iteration is %d\n " , pack_iteration);
@@ -224,9 +306,18 @@ bool try_pack(const t_packer_opts& packer_opts,
224
306
// do it for all block types. Doing it only for a clb
225
307
// string is dangerous -VB.
226
308
cluster_legalizer.get_target_external_pin_util ().set_block_pin_util (" clb" , pin_util);
309
+ break ;
227
310
}
311
+ case e_packer_state::DEFAULT:
312
+ case e_packer_state::SUCCESS:
313
+ case e_packer_state::FAILURE:
314
+ default :
315
+ // Nothing to set up.
316
+ break ;
317
+ }
228
318
229
- } else { // Unable to pack densely enough: Give Up
319
+ // Raise an error if the packer failed to pack.
320
+ if (next_packer_state == e_packer_state::FAILURE) {
230
321
if (floorplan_regions_overfull) {
231
322
VPR_FATAL_ERROR (VPR_ERROR_OTHER,
232
323
" Failed to find pack clusters densely enough to fit in the designated floorplan regions.\n "
@@ -255,14 +346,23 @@ bool try_pack(const t_packer_opts& packer_opts,
255
346
VPR_FATAL_ERROR (VPR_ERROR_OTHER, " Failed to find device which satisfies resource requirements required: %s (available %s)" , resource_reqs.c_str (), resource_avail.c_str ());
256
347
}
257
348
258
- // Reset floorplanning constraints for re-packing
259
- g_vpr_ctx.mutable_floorplanning ().cluster_constraints .clear ();
349
+ // If the packer was unsuccessful, reset the packed solution and try again.
350
+ if (next_packer_state != e_packer_state::SUCCESS) {
351
+ // Reset floorplanning constraints for re-packing
352
+ g_vpr_ctx.mutable_floorplanning ().cluster_constraints .clear ();
353
+
354
+ // Reset the cluster legalizer for re-clustering.
355
+ cluster_legalizer.reset ();
356
+ }
357
+
358
+ // Set the current state to the next state.
359
+ current_packer_state = next_packer_state;
260
360
261
- // Reset the cluster legalizer for re-clustering.
262
- cluster_legalizer.reset ();
263
361
++pack_iteration;
264
362
}
265
363
364
+ VTR_ASSERT (current_packer_state == e_packer_state::SUCCESS);
365
+
266
366
/* Packing iterative improvement can be done here */
267
367
/* Use the re-cluster API to edit it */
268
368
/* ****************** Start *************************/
0 commit comments