Skip to content

Commit d4c0df2

Browse files
[SQUASH ME] Added a clean method to save memory during packing.
1 parent 3747187 commit d4c0df2

File tree

5 files changed

+65
-37
lines changed

5 files changed

+65
-37
lines changed

vpr/src/pack/cluster.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,10 @@ std::map<t_logical_block_type_ptr, size_t> do_clustering(const t_packer_opts& pa
360360
cluster_stats.blocks_since_last_analysis += num_blocks_hill_added;
361361

362362
store_cluster_info_and_free(packer_opts, legalization_cluster_id, logic_block_type, le_pb_type, le_count, cluster_legalizer, clb_inter_blk_nets);
363+
// Since the cluster will no longer be added to beyond this point,
364+
// clean the cluster of any data not strictly necessary for
365+
// creating the clustered netlist.
366+
cluster_legalizer.clean_cluster(legalization_cluster_id);
363367
} else {
364368
// If the cluster is not legal, requeue used mols.
365369
num_used_type_instances[cluster_legalizer.get_cluster_type(legalization_cluster_id)]--;

vpr/src/pack/cluster_legalizer.cpp

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "atom_netlist.h"
2020
#include "cluster_placement.h"
2121
#include "cluster_router.h"
22+
#include "cluster_util.h"
2223
#include "globals.h"
2324
#include "logic_types.h"
2425
#include "netlist_utils.h"
@@ -139,6 +140,26 @@ static void check_cluster_atom_blocks(t_pb* pb, std::unordered_set<AtomBlockId>&
139140
}
140141
}
141142

143+
/// @brief Recursively frees the pb stats of the given pb, without freeing the
144+
/// pb itself.
145+
static void free_pb_stats_recursive(t_pb* pb) {
146+
/* Releases all the memory used by clustering data structures. */
147+
if (pb) {
148+
if (pb->pb_graph_node != nullptr) {
149+
if (!pb->pb_graph_node->is_primitive()) {
150+
for (int i = 0; i < pb->pb_graph_node->pb_type->modes[pb->mode].num_pb_type_children; i++) {
151+
for (int j = 0; j < pb->pb_graph_node->pb_type->modes[pb->mode].pb_type_children[i].num_pb; j++) {
152+
if (pb->child_pbs && pb->child_pbs[i]) {
153+
free_pb_stats_recursive(&pb->child_pbs[i][j]);
154+
}
155+
}
156+
}
157+
}
158+
}
159+
free_pb_stats(pb);
160+
}
161+
}
162+
142163
/* Record the failure of the molecule in this cluster in the current pb stats.
143164
* If a molecule fails repeatedly, it's gain will be penalized if packing with
144165
* attraction groups on. */
@@ -1468,6 +1489,7 @@ e_block_pack_status ClusterLegalizer::add_mol_to_cluster(t_pack_molecule* molecu
14681489

14691490
// Get the cluster.
14701491
LegalizationCluster& cluster = legalization_clusters[cluster_id];
1492+
VTR_ASSERT(cluster.router_data != nullptr && "Cannot add molecule to cleaned cluster!");
14711493
// Set the target_external_pin_util.
14721494
t_ext_pin_util target_ext_pin_util = target_external_pin_util.get_pin_util(cluster.type->name);
14731495
// Try to pack the molecule into the cluster.
@@ -1548,9 +1570,26 @@ void ClusterLegalizer::compress() {
15481570
atom_cluster.shrink_to_fit();
15491571
}
15501572

1573+
void ClusterLegalizer::clean_cluster(LegalizationClusterId cluster_id) {
1574+
// Safety asserts to make sure the inputs are valid.
1575+
VTR_ASSERT_SAFE(cluster_id.is_valid() && (size_t)cluster_id < legalization_clusters.size());
1576+
// Get the cluster.
1577+
LegalizationCluster& cluster = legalization_clusters[cluster_id];
1578+
// Free the pb stats.
1579+
free_pb_stats_recursive(cluster.pb);
1580+
// Load the pb_route so we can free the cluster router data.
1581+
// The pb_route is used when creating a netlist from the legalized clusters.
1582+
std::vector<t_intra_lb_net>* saved_lb_nets = cluster.router_data->saved_lb_nets;
1583+
t_pb_graph_node* pb_graph_node = cluster.pb->pb_graph_node;
1584+
cluster.pb->pb_route = alloc_and_load_pb_route(saved_lb_nets, pb_graph_node);
1585+
// Free the router data.
1586+
free_router_data(cluster.router_data);
1587+
cluster.router_data = nullptr;
1588+
}
1589+
15511590
bool ClusterLegalizer::check_cluster_legality(LegalizationClusterId cluster_id) {
15521591
// Safety asserts to make sure the inputs are valid.
1553-
VTR_ASSERT_DEBUG(cluster_id.is_valid() && (size_t)cluster_id < legalization_clusters.size());
1592+
VTR_ASSERT_SAFE(cluster_id.is_valid() && (size_t)cluster_id < legalization_clusters.size());
15541593
// To check if a cluster is fully legal, try to perform an intra logic block
15551594
// route on the cluster. If it succeeds, the cluster is fully legal.
15561595
t_mode_selection_status mode_status;
@@ -1616,8 +1655,6 @@ void ClusterLegalizer::reset() {
16161655
// Reset the molecule_cluster map
16171656
molecule_cluster.clear();
16181657
// Reset the cluster placement stats.
1619-
// FIXME: Is this necessary? Or is there a way to clear the cluster placement
1620-
// stats?
16211658
free_cluster_placement_stats(cluster_placement_stats);
16221659
cluster_placement_stats = alloc_and_load_cluster_placement_stats();
16231660
}
@@ -1692,12 +1729,11 @@ void ClusterLegalizer::finalize() {
16921729
for (LegalizationClusterId cluster_id : legalization_cluster_ids) {
16931730
if (!cluster_id.is_valid())
16941731
continue;
1695-
LegalizationCluster& cluster = legalization_clusters[cluster_id];
1696-
t_pb* cluster_pb = cluster.pb;
1697-
t_lb_router_data* cluster_router_data = cluster.router_data;
1698-
std::vector<t_intra_lb_net>* saved_lb_nets = cluster_router_data->saved_lb_nets;
1699-
t_pb_graph_node* pb_graph_node = cluster_pb->pb_graph_node;
1700-
cluster_pb->pb_route = alloc_and_load_pb_route(saved_lb_nets, pb_graph_node);
1732+
// If the cluster has not already been cleaned, clean it. This will
1733+
// generate the pb_route necessary for generating a clustered netlist.
1734+
const LegalizationCluster& cluster = legalization_clusters[cluster_id];
1735+
if (cluster.router_data != nullptr)
1736+
clean_cluster(cluster_id);
17011737
}
17021738
}
17031739

vpr/src/pack/cluster_legalizer.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -265,12 +265,22 @@ class ClusterLegalizer {
265265
*/
266266
bool check_cluster_legality(LegalizationClusterId cluster_id);
267267

268-
// TODO: Should make a clean method to clean 1 or all clusters.
269-
// - free_pb_stats_recursive for example.
270-
// - free the router data.
271-
// - etc.
272-
// - This is to help reduce the memory overhead of the class without
273-
// breaking anything.
268+
/*
269+
* @brief Cleans the cluster of unnessary data, reducing the memory footprint.
270+
*
271+
* After this function is called, no more molecules can be added to the
272+
* cluster. This will ensure that the cluster has enough information to
273+
* generate a clustered netlist from the legalized clusters.
274+
*
275+
* Specifically, this frees the pb stats (which is used by the clusterer
276+
* to compute the gain) and the router data of the cluster.
277+
*
278+
* TODO: The pb stats should really not be calculated or stored in the
279+
* cluster legalizer.
280+
*
281+
* @param cluster_id The ID of the cluster to clean.
282+
*/
283+
void clean_cluster(LegalizationClusterId cluster_id);
274284

275285
/*
276286
* @brief Verify that all atoms have been clustered into a cluster.

vpr/src/pack/cluster_util.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -398,26 +398,6 @@ void alloc_and_init_clustering(const t_molecule_stats& max_molecule_stats,
398398

399399
/*****************************************/
400400

401-
void free_pb_stats_recursive(t_pb* pb) {
402-
int i, j;
403-
/* Releases all the memory used by clustering data structures. */
404-
if (pb) {
405-
if (pb->pb_graph_node != nullptr) {
406-
if (!pb->pb_graph_node->is_primitive()) {
407-
for (i = 0; i < pb->pb_graph_node->pb_type->modes[pb->mode].num_pb_type_children; i++) {
408-
for (j = 0; j < pb->pb_graph_node->pb_type->modes[pb->mode].pb_type_children[i].num_pb; j++) {
409-
if (pb->child_pbs && pb->child_pbs[i]) {
410-
free_pb_stats_recursive(&pb->child_pbs[i][j]);
411-
}
412-
}
413-
}
414-
}
415-
}
416-
free_pb_stats(pb);
417-
}
418-
}
419-
420-
/*****************************************/
421401
t_pack_molecule* get_molecule_by_num_ext_inputs(const int ext_inps,
422402
const enum e_removal_policy remove_flag,
423403
t_cluster_placement_stats* cluster_placement_stats_ptr,

vpr/src/pack/cluster_util.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,6 @@ void alloc_and_init_clustering(const t_molecule_stats& max_molecule_stats,
133133
int& unclustered_list_head_size,
134134
int num_molecules);
135135

136-
void free_pb_stats_recursive(t_pb* pb);
137-
138136
t_pack_molecule* get_molecule_by_num_ext_inputs(const int ext_inps,
139137
const enum e_removal_policy remove_flag,
140138
t_cluster_placement_stats* cluster_placement_stats_ptr,

0 commit comments

Comments
 (0)