22
22
#include " vtr_assert.h"
23
23
#include " vtr_log.h"
24
24
25
+ namespace {
26
+
27
+ /* *
28
+ * @brief Enumeration for the state of the packer.
29
+ *
30
+ * If the packer fails to find a dense enough packing, depending on how the
31
+ * packer failed, the packer may iteratively retry packing with different
32
+ * settings to try and find a denser packing. These states represent a
33
+ * different type of iteration.
34
+ */
35
+ enum class e_packer_state {
36
+ // / @brief Default packer state.
37
+ DEFAULT,
38
+ // / @brief Succcess state for the packer. The packing looks feasible to
39
+ // / fit on the device (does not exceed number of blocks of each
40
+ // / type in the grid) and meets floorplanning constraints.
41
+ SUCCESS,
42
+ // / @brief Standard fallback where there are no region constraints. Turns
43
+ // / on unrelated clustering and balanced packing if it can.
44
+ UNRELATED_AND_BALANCED,
45
+ // / @brief Region constraints: Turns on attraction groups for overfilled regions.
46
+ ATTRACTION_GROUPS,
47
+ // / @brief Region constraints: Turns on more attraction groups for overfilled regions.
48
+ MORE_ATTRACTION_GROUPS,
49
+ // / @brief Region constraints: Turns on more attraction groups for all regions.
50
+ ATTRACTION_GROUPS_ALL_REGIONS,
51
+ // / @brief Region constraints: Turns on more attraction groups for all regions
52
+ // / and increases the target density of "clb" blocks.
53
+ // / TODO: This should increase the target density of all overused blocks.
54
+ ATTRACTION_GROUPS_ALL_REGIONS_AND_INCREASED_TARGET_DENSITY,
55
+ // / @brief The failure state.
56
+ FAILURE
57
+ };
58
+
59
+ } // namespace
60
+
25
61
static bool try_size_device_grid (const t_arch& arch,
26
62
const std::map<t_logical_block_type_ptr, size_t >& num_type_instances,
27
63
float target_device_utilization,
28
64
const std::string& device_layout_name);
29
65
66
+ /* *
67
+ * @brief The packer iteratively re-packes the netlist if it fails to find a
68
+ * valid clustering. Each iteration is a state the packer is in, where
69
+ * each state uses a different set of options. This method gets the next
70
+ * state of the packer given the current state of the packer.
71
+ *
72
+ * @param current_packer_state
73
+ * The current state of the packer (the state used to make the most recent
74
+ * clustering).
75
+ * @param fits_on_device
76
+ * Whether the current clustering fits on the device or not.
77
+ * @param floorplan_regions_overfull
78
+ * Whether the current clustering has overfilled regions.
79
+ * @param floorplan_not_fitting
80
+ * Whether the current clustering is fitting on the current floorplan.
81
+ */
82
+ static e_packer_state get_next_packer_state (e_packer_state current_packer_state,
83
+ bool fits_on_device,
84
+ bool floorplan_regions_overfull,
85
+ bool floorplan_not_fitting) {
86
+ // Next packer state logic
87
+ e_packer_state next_packer_state = e_packer_state::FAILURE;
88
+ if (fits_on_device && !floorplan_regions_overfull) {
89
+ // If everything fits on the device and the floorplan regions are
90
+ // not overfilled, the next state is success.
91
+ next_packer_state = e_packer_state::SUCCESS;
92
+ } else {
93
+ if (floorplan_not_fitting) {
94
+ // If there are overfilled region constraints.
95
+
96
+ // When running with tight floorplan constraints, some regions may become overfull with clusters (i.e.
97
+ // the number of blocks assigned to the region exceeds the number of blocks available). When this occurs, we
98
+ // cluster more densely to be able to adhere to the floorplan constraints. However, we do not want to cluster more
99
+ // densely unnecessarily, as this can negatively impact wirelength. So, we have iterative approach. We check at the end
100
+ // of every iteration if any floorplan regions are overfull. In the first iteration, we run
101
+ // with no attraction groups (not packing more densely). If regions are overfull at the end of the first iteration,
102
+ // we create attraction groups for partitions with overfull regions (pack those atoms more densely). We continue this way
103
+ // until the last iteration, when we create attraction groups for every partition, if needed.
104
+
105
+ switch (current_packer_state) {
106
+ case e_packer_state::DEFAULT:
107
+ next_packer_state = e_packer_state::ATTRACTION_GROUPS;
108
+ break ;
109
+ case e_packer_state::UNRELATED_AND_BALANCED:
110
+ case e_packer_state::ATTRACTION_GROUPS:
111
+ next_packer_state = e_packer_state::MORE_ATTRACTION_GROUPS;
112
+ break ;
113
+ case e_packer_state::MORE_ATTRACTION_GROUPS:
114
+ next_packer_state = e_packer_state::ATTRACTION_GROUPS_ALL_REGIONS;
115
+ break ;
116
+ case e_packer_state::ATTRACTION_GROUPS_ALL_REGIONS:
117
+ next_packer_state = e_packer_state::ATTRACTION_GROUPS_ALL_REGIONS_AND_INCREASED_TARGET_DENSITY;
118
+ break ;
119
+ case e_packer_state::ATTRACTION_GROUPS_ALL_REGIONS_AND_INCREASED_TARGET_DENSITY:
120
+ default :
121
+ next_packer_state = e_packer_state::FAILURE;
122
+ break ;
123
+ }
124
+ } else {
125
+ // If there are no overfilled region constraints, but some block
126
+ // types on the grid are overfilled.
127
+ switch (current_packer_state) {
128
+ case e_packer_state::DEFAULT:
129
+ next_packer_state = e_packer_state::UNRELATED_AND_BALANCED;
130
+ break ;
131
+ default :
132
+ next_packer_state = e_packer_state::FAILURE;
133
+ break ;
134
+ }
135
+ }
136
+ }
137
+
138
+ return next_packer_state;
139
+ }
140
+
30
141
bool try_pack (const t_packer_opts& packer_opts,
31
142
const t_analysis_opts& analysis_opts,
32
143
const t_ap_opts& ap_opts,
@@ -145,7 +256,10 @@ bool try_pack(const t_packer_opts& packer_opts,
145
256
146
257
g_vpr_ctx.mutable_atom ().mutable_lookup ().set_atom_pb_bimap_lock (true );
147
258
148
- while (true ) {
259
+ // The current state of the packer during iterative packing.
260
+ e_packer_state current_packer_state = e_packer_state::DEFAULT;
261
+
262
+ while (current_packer_state != e_packer_state::SUCCESS && current_packer_state != e_packer_state::FAILURE) {
149
263
// Cluster the netlist
150
264
// num_used_type_instances: A map used to save the number of used
151
265
// instances from each logical block type.
@@ -157,7 +271,7 @@ bool try_pack(const t_packer_opts& packer_opts,
157
271
attraction_groups,
158
272
mutable_device_ctx);
159
273
160
- // Try to size/find a device
274
+ // Try to size/find a device
161
275
bool fits_on_device = try_size_device_grid (arch, num_used_type_instances, packer_opts.target_device_utilization , packer_opts.device_layout );
162
276
163
277
/* We use this bool to determine the cause for the clustering not being dense enough. If the clustering
@@ -170,48 +284,56 @@ bool try_pack(const t_packer_opts& packer_opts,
170
284
171
285
bool floorplan_not_fitting = (floorplan_regions_overfull || g_vpr_ctx.floorplanning ().constraints .get_num_partitions () > 0 );
172
286
173
- 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 ;
287
+ // Next packer state logic
288
+ e_packer_state next_packer_state = get_next_packer_state (current_packer_state,
289
+ fits_on_device,
290
+ floorplan_regions_overfull,
291
+ floorplan_not_fitting);
292
+
293
+ // Set up for the options used for the next packer state.
294
+ // NOTE: This must be done here (and not at the start of the next packer
295
+ // iteration) since we need to know information about the current
296
+ // clustering to change the options for the next iteration.
297
+ switch (next_packer_state) {
298
+ case e_packer_state::UNRELATED_AND_BALANCED: {
299
+ // 1st pack attempt was unsuccessful (i.e. not dense enough) and we have control of unrelated clustering
300
+ //
301
+ // Turn it on to increase packing density
302
+ // TODO: This will have no affect if unrelated clustering and
303
+ // balance block type utilization is not auto. Should update
304
+ // the next state logic.
305
+ if (packer_opts.allow_unrelated_clustering == e_unrelated_clustering::AUTO) {
306
+ VTR_ASSERT (allow_unrelated_clustering == false );
307
+ allow_unrelated_clustering = true ;
308
+ }
309
+ if (packer_opts.balance_block_type_utilization == e_balance_block_type_util::AUTO) {
310
+ VTR_ASSERT (balance_block_type_util == false );
311
+ balance_block_type_util = true ;
312
+ }
313
+ VTR_LOG (" Packing failed to fit on device. Re-packing with: unrelated_logic_clustering=%s balance_block_type_util=%s\n " ,
314
+ (allow_unrelated_clustering ? " true" : " false" ),
315
+ (balance_block_type_util ? " true" : " false" ));
316
+ break ;
182
317
}
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 ;
318
+ case e_packer_state::ATTRACTION_GROUPS: {
319
+ VTR_LOG (" Floorplan regions are overfull: trying to pack again using cluster attraction groups. \n " );
320
+ attraction_groups.create_att_groups_for_overfull_regions (overfull_partition_regions);
321
+ attraction_groups.set_att_group_pulls (1 );
322
+ break ;
186
323
}
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 ) {
324
+ case e_packer_state::MORE_ATTRACTION_GROUPS: {
207
325
VTR_LOG (" Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n " );
208
326
attraction_groups.create_att_groups_for_overfull_regions (overfull_partition_regions);
209
327
VTR_LOG (" Pack iteration is %d\n " , pack_iteration);
210
- } else if (pack_iteration == 3 ) {
328
+ break ;
329
+ }
330
+ case e_packer_state::ATTRACTION_GROUPS_ALL_REGIONS: {
211
331
attraction_groups.create_att_groups_for_all_regions ();
212
332
VTR_LOG (" Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n " );
213
333
VTR_LOG (" Pack iteration is %d\n " , pack_iteration);
214
- } else if (pack_iteration == 4 ) {
334
+ break ;
335
+ }
336
+ case e_packer_state::ATTRACTION_GROUPS_ALL_REGIONS_AND_INCREASED_TARGET_DENSITY: {
215
337
attraction_groups.create_att_groups_for_all_regions ();
216
338
VTR_LOG (" Floorplan regions are overfull: trying to pack again with more attraction groups exploration and higher target pin utilization. \n " );
217
339
VTR_LOG (" Pack iteration is %d\n " , pack_iteration);
@@ -224,9 +346,18 @@ bool try_pack(const t_packer_opts& packer_opts,
224
346
// do it for all block types. Doing it only for a clb
225
347
// string is dangerous -VB.
226
348
cluster_legalizer.get_target_external_pin_util ().set_block_pin_util (" clb" , pin_util);
349
+ break ;
227
350
}
351
+ case e_packer_state::DEFAULT:
352
+ case e_packer_state::SUCCESS:
353
+ case e_packer_state::FAILURE:
354
+ default :
355
+ // Nothing to set up.
356
+ break ;
357
+ }
228
358
229
- } else { // Unable to pack densely enough: Give Up
359
+ // Raise an error if the packer failed to pack.
360
+ if (next_packer_state == e_packer_state::FAILURE) {
230
361
if (floorplan_regions_overfull) {
231
362
VPR_FATAL_ERROR (VPR_ERROR_OTHER,
232
363
" Failed to find pack clusters densely enough to fit in the designated floorplan regions.\n "
@@ -255,14 +386,23 @@ bool try_pack(const t_packer_opts& packer_opts,
255
386
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
387
}
257
388
258
- // Reset floorplanning constraints for re-packing
259
- g_vpr_ctx.mutable_floorplanning ().cluster_constraints .clear ();
389
+ // If the packer was unsuccessful, reset the packed solution and try again.
390
+ if (next_packer_state != e_packer_state::SUCCESS) {
391
+ // Reset floorplanning constraints for re-packing
392
+ g_vpr_ctx.mutable_floorplanning ().cluster_constraints .clear ();
393
+
394
+ // Reset the cluster legalizer for re-clustering.
395
+ cluster_legalizer.reset ();
396
+ }
397
+
398
+ // Set the current state to the next state.
399
+ current_packer_state = next_packer_state;
260
400
261
- // Reset the cluster legalizer for re-clustering.
262
- cluster_legalizer.reset ();
263
401
++pack_iteration;
264
402
}
265
403
404
+ VTR_ASSERT (current_packer_state == e_packer_state::SUCCESS);
405
+
266
406
/* Packing iterative improvement can be done here */
267
407
/* Use the re-cluster API to edit it */
268
408
/* ****************** Start *************************/
0 commit comments