Skip to content

Commit 37709a0

Browse files
[Packer] Reorganized Iterative Packer Algorithm
The packer iteratively restarts itself with different options if the packer fails to find a dense enough clustering. The way this was written was very hard to follow and was error prone. Rewrote the iterative packer code to be more like a state-machine. This makes it easier to add new states in the future and maintain the current states.
1 parent 7840430 commit 37709a0

File tree

1 file changed

+139
-39
lines changed

1 file changed

+139
-39
lines changed

vpr/src/pack/pack.cpp

Lines changed: 139 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)