@@ -1179,6 +1179,76 @@ static void alloc_and_load_pb_stats(t_pb* pb, const int feasible_block_array_siz
1179
1179
}
1180
1180
/* ****************************************/
1181
1181
1182
+ /* *
1183
+ * Cleans up a pb after unsuccessful molecule packing
1184
+ *
1185
+ * Recursively frees pbs from a t_pb tree. The given root pb itself is not
1186
+ * deleted.
1187
+ *
1188
+ * If a pb object has its children allocated then before freeing them the
1189
+ * function checks if there is no atom that corresponds to any of them. The
1190
+ * check is performed only for leaf (primitive) pbs. The function recurses for
1191
+ * non-primitive pbs.
1192
+ *
1193
+ * The cleaning itself includes deleting all child pbs, resetting mode of the
1194
+ * pb and also freeing its name. This prepares the pb for another round of
1195
+ * molecule packing tryout.
1196
+ */
1197
+ static bool cleanup_pb (t_pb* pb) {
1198
+ bool can_free = true ;
1199
+
1200
+ /* Recursively check if there are any children with already assigned atoms */
1201
+ if (pb->child_pbs != nullptr ) {
1202
+ const t_mode* mode = &pb->pb_graph_node ->pb_type ->modes [pb->mode ];
1203
+ VTR_ASSERT (mode != nullptr );
1204
+
1205
+ /* Check each mode */
1206
+ for (int i = 0 ; i < mode->num_pb_type_children ; ++i) {
1207
+ /* Check each child */
1208
+ if (pb->child_pbs [i] != nullptr ) {
1209
+ for (int j = 0 ; j < mode->pb_type_children [i].num_pb ; ++j) {
1210
+ t_pb* pb_child = &pb->child_pbs [i][j];
1211
+ t_pb_type* pb_type = pb_child->pb_graph_node ->pb_type ;
1212
+
1213
+ /* Primitive, check occupancy */
1214
+ if (pb_type->num_modes == 0 ) {
1215
+ if (pb_child->name != nullptr ) {
1216
+ can_free = false ;
1217
+ }
1218
+ }
1219
+
1220
+ /* Non-primitive, recurse */
1221
+ else {
1222
+ if (!cleanup_pb (pb_child)) {
1223
+ can_free = false ;
1224
+ }
1225
+ }
1226
+ }
1227
+ }
1228
+ }
1229
+
1230
+ /* Free if can */
1231
+ if (can_free) {
1232
+ for (int i = 0 ; i < mode->num_pb_type_children ; ++i) {
1233
+ if (pb->child_pbs [i] != nullptr ) {
1234
+ delete[] pb->child_pbs [i];
1235
+ }
1236
+ }
1237
+
1238
+ delete[] pb->child_pbs ;
1239
+ pb->child_pbs = nullptr ;
1240
+ pb->mode = 0 ;
1241
+
1242
+ if (pb->name ) {
1243
+ free (pb->name );
1244
+ pb->name = nullptr ;
1245
+ }
1246
+ }
1247
+ }
1248
+
1249
+ return can_free;
1250
+ }
1251
+
1182
1252
/* *
1183
1253
* Try pack molecule into current cluster
1184
1254
*/
@@ -1358,6 +1428,12 @@ static enum e_block_pack_status try_pack_molecule(t_cluster_placement_stats* clu
1358
1428
revert_place_atom_block (molecule->atom_block_ids [i], router_data, atom_molecules);
1359
1429
}
1360
1430
}
1431
+
1432
+ /* Packing failed, but a part of the pb tree is still allocated and pbs have their modes set.
1433
+ * Before trying to pack next molecule the unused pbs need to be freed and, the most important,
1434
+ * their modes reset. This task is performed by the cleanup_pb() function below. */
1435
+ cleanup_pb (pb);
1436
+
1361
1437
} else {
1362
1438
VTR_LOGV (verbosity > 3 , " \t\t PASSED pack molecule\n " );
1363
1439
}
0 commit comments