Skip to content

Commit 913008b

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 913008b

File tree

1 file changed

+140
-39
lines changed

1 file changed

+140
-39
lines changed

vpr/src/pack/pack.cpp

Lines changed: 140 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,40 @@ 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 &&
181+
current_packer_state != e_packer_state::FAILURE) {
149182
//Cluster the netlist
150183
// num_used_type_instances: A map used to save the number of used
151184
// instances from each logical block type.
@@ -170,48 +203,98 @@ bool try_pack(const t_packer_opts& packer_opts,
170203

171204
bool floorplan_not_fitting = (floorplan_regions_overfull || g_vpr_ctx.floorplanning().constraints.get_num_partitions() > 0);
172205

206+
// Next packer state logic
207+
e_packer_state next_packer_state = e_packer_state::FAILURE;
173208
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+
}
182254
}
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;
186278
}
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: {
207286
VTR_LOG("Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n");
208287
attraction_groups.create_att_groups_for_overfull_regions(overfull_partition_regions);
209288
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: {
211292
attraction_groups.create_att_groups_for_all_regions();
212293
VTR_LOG("Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n");
213294
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: {
215298
attraction_groups.create_att_groups_for_all_regions();
216299
VTR_LOG("Floorplan regions are overfull: trying to pack again with more attraction groups exploration and higher target pin utilization. \n");
217300
VTR_LOG("Pack iteration is %d\n", pack_iteration);
@@ -224,9 +307,18 @@ bool try_pack(const t_packer_opts& packer_opts,
224307
// do it for all block types. Doing it only for a clb
225308
// string is dangerous -VB.
226309
cluster_legalizer.get_target_external_pin_util().set_block_pin_util("clb", pin_util);
310+
break;
227311
}
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+
}
228319

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) {
230322
if (floorplan_regions_overfull) {
231323
VPR_FATAL_ERROR(VPR_ERROR_OTHER,
232324
"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,
255347
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());
256348
}
257349

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;
260361

261-
// Reset the cluster legalizer for re-clustering.
262-
cluster_legalizer.reset();
263362
++pack_iteration;
264363
}
265364

365+
VTR_ASSERT(current_packer_state == e_packer_state::SUCCESS);
366+
266367
/* Packing iterative improvement can be done here */
267368
/* Use the re-cluster API to edit it */
268369
/******************* Start *************************/

0 commit comments

Comments
 (0)