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