2222#include " vtr_assert.h"
2323#include " vtr_log.h"
2424
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+
2561static bool try_size_device_grid (const t_arch& arch,
2662 const std::map<t_logical_block_type_ptr, size_t >& num_type_instances,
2763 float target_device_utilization,
2864 const std::string& device_layout_name);
2965
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+
30141bool try_pack (const t_packer_opts& packer_opts,
31142 const t_analysis_opts& analysis_opts,
32143 const t_ap_opts& ap_opts,
@@ -145,7 +256,10 @@ bool try_pack(const t_packer_opts& packer_opts,
145256
146257 g_vpr_ctx.mutable_atom ().mutable_lookup ().set_atom_pb_bimap_lock (true );
147258
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) {
149263 // Cluster the netlist
150264 // num_used_type_instances: A map used to save the number of used
151265 // instances from each logical block type.
@@ -157,7 +271,7 @@ bool try_pack(const t_packer_opts& packer_opts,
157271 attraction_groups,
158272 mutable_device_ctx);
159273
160- // Try to size/find a device
274+ // Try to size/find a device
161275 bool fits_on_device = try_size_device_grid (arch, num_used_type_instances, packer_opts.target_device_utilization , packer_opts.device_layout );
162276
163277 /* 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,
170284
171285 bool floorplan_not_fitting = (floorplan_regions_overfull || g_vpr_ctx.floorplanning ().constraints .get_num_partitions () > 0 );
172286
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 ;
182317 }
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 ;
186323 }
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: {
207325 VTR_LOG (" Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n " );
208326 attraction_groups.create_att_groups_for_overfull_regions (overfull_partition_regions);
209327 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: {
211331 attraction_groups.create_att_groups_for_all_regions ();
212332 VTR_LOG (" Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n " );
213333 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: {
215337 attraction_groups.create_att_groups_for_all_regions ();
216338 VTR_LOG (" Floorplan regions are overfull: trying to pack again with more attraction groups exploration and higher target pin utilization. \n " );
217339 VTR_LOG (" Pack iteration is %d\n " , pack_iteration);
@@ -224,9 +346,18 @@ bool try_pack(const t_packer_opts& packer_opts,
224346 // do it for all block types. Doing it only for a clb
225347 // string is dangerous -VB.
226348 cluster_legalizer.get_target_external_pin_util ().set_block_pin_util (" clb" , pin_util);
349+ break ;
227350 }
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+ }
228358
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) {
230361 if (floorplan_regions_overfull) {
231362 VPR_FATAL_ERROR (VPR_ERROR_OTHER,
232363 " 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,
255386 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 ());
256387 }
257388
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;
260400
261- // Reset the cluster legalizer for re-clustering.
262- cluster_legalizer.reset ();
263401 ++pack_iteration;
264402 }
265403
404+ VTR_ASSERT (current_packer_state == e_packer_state::SUCCESS);
405+
266406 /* Packing iterative improvement can be done here */
267407 /* Use the re-cluster API to edit it */
268408 /* ****************** Start *************************/
0 commit comments