@@ -145,7 +145,39 @@ bool try_pack(const t_packer_opts& packer_opts,
145145
146146 g_vpr_ctx.mutable_atom ().mutable_lookup ().set_atom_pb_bimap_lock (true );
147147
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) {
149181 // Cluster the netlist
150182 // num_used_type_instances: A map used to save the number of used
151183 // instances from each logical block type.
@@ -170,48 +202,98 @@ bool try_pack(const t_packer_opts& packer_opts,
170202
171203 bool floorplan_not_fitting = (floorplan_regions_overfull || g_vpr_ctx.floorplanning ().constraints .get_num_partitions () > 0 );
172204
205+ // Next packer state logic
206+ e_packer_state next_packer_state = e_packer_state::FAILURE;
173207 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+ }
182253 }
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 ;
186277 }
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: {
207285 VTR_LOG (" Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n " );
208286 attraction_groups.create_att_groups_for_overfull_regions (overfull_partition_regions);
209287 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: {
211291 attraction_groups.create_att_groups_for_all_regions ();
212292 VTR_LOG (" Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n " );
213293 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: {
215297 attraction_groups.create_att_groups_for_all_regions ();
216298 VTR_LOG (" Floorplan regions are overfull: trying to pack again with more attraction groups exploration and higher target pin utilization. \n " );
217299 VTR_LOG (" Pack iteration is %d\n " , pack_iteration);
@@ -224,9 +306,18 @@ bool try_pack(const t_packer_opts& packer_opts,
224306 // do it for all block types. Doing it only for a clb
225307 // string is dangerous -VB.
226308 cluster_legalizer.get_target_external_pin_util ().set_block_pin_util (" clb" , pin_util);
309+ break ;
227310 }
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+ }
228318
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) {
230321 if (floorplan_regions_overfull) {
231322 VPR_FATAL_ERROR (VPR_ERROR_OTHER,
232323 " 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,
255346 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 ());
256347 }
257348
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;
260360
261- // Reset the cluster legalizer for re-clustering.
262- cluster_legalizer.reset ();
263361 ++pack_iteration;
264362 }
265363
364+ VTR_ASSERT (current_packer_state == e_packer_state::SUCCESS);
365+
266366 /* Packing iterative improvement can be done here */
267367 /* Use the re-cluster API to edit it */
268368 /* ****************** Start *************************/
0 commit comments