From 96322ff26ea8497f81baf4c4be93f2556d817f4e Mon Sep 17 00:00:00 2001 From: AlexandreSinger Date: Tue, 19 Nov 2024 20:25:02 -0500 Subject: [PATCH] [Packer] Created GreedyClusterer Class Began encapsulating the different parts of the packer into classes. This will help organize the packer better, which will make it easier to modify in the future. My plan is to clean up the different parts of the packer so I can add flat placement information into the gain calculation so it can be integrated into the AP flow. --- vpr/src/analytical_place/full_legalizer.cpp | 1 - vpr/src/base/vpr_api.cpp | 1 - vpr/src/pack/cluster.h | 32 ---- vpr/src/pack/cluster_util.cpp | 29 +++ vpr/src/pack/cluster_util.h | 2 + .../{cluster.cpp => greedy_clusterer.cpp} | 177 +++++++----------- vpr/src/pack/greedy_clusterer.h | 123 ++++++++++++ vpr/src/pack/pack.cpp | 39 ++-- 8 files changed, 240 insertions(+), 164 deletions(-) delete mode 100644 vpr/src/pack/cluster.h rename vpr/src/pack/{cluster.cpp => greedy_clusterer.cpp} (73%) create mode 100644 vpr/src/pack/greedy_clusterer.h diff --git a/vpr/src/analytical_place/full_legalizer.cpp b/vpr/src/analytical_place/full_legalizer.cpp index 3a6f985ef72..e0850479118 100644 --- a/vpr/src/analytical_place/full_legalizer.cpp +++ b/vpr/src/analytical_place/full_legalizer.cpp @@ -17,7 +17,6 @@ #include "ShowSetup.h" #include "ap_netlist_fwd.h" #include "check_netlist.h" -#include "cluster.h" #include "cluster_legalizer.h" #include "cluster_util.h" #include "clustered_netlist.h" diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index b763c368da5..251c271e84e 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -64,7 +64,6 @@ #include "check_route.h" #include "constant_nets.h" #include "atom_netlist_utils.h" -#include "cluster.h" #include "output_clustering.h" #include "vpr_constraints_reader.h" #include "place_constraints.h" diff --git a/vpr/src/pack/cluster.h b/vpr/src/pack/cluster.h deleted file mode 100644 index a10d7ccf21a..00000000000 --- a/vpr/src/pack/cluster.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef CLUSTER_H -#define CLUSTER_H - -#include -#include - -#include "physical_types.h" -#include "vpr_types.h" - -class AtomNetid; -class AttractionInfo; -class ClusterLegalizer; -class ClusteredNetlist; -class Prepacker; -struct t_clustering_data; - -std::map do_clustering(const t_packer_opts& packer_opts, - const t_analysis_opts& analysis_opts, - const t_arch* arch, - Prepacker& prepacker, - ClusterLegalizer& cluster_legalizer, - const std::unordered_set& is_clock, - const std::unordered_set& is_global, - bool allow_unrelated_clustering, - bool balance_block_type_utilization, - AttractionInfo& attraction_groups, - bool& floorplan_regions_overfull, - const t_pack_high_fanout_thresholds& high_fanout_thresholds, - t_clustering_data& clustering_data); - -void print_pb_type_count(const ClusteredNetlist& clb_nlist); -#endif diff --git a/vpr/src/pack/cluster_util.cpp b/vpr/src/pack/cluster_util.cpp index e9b6a846ce0..ee003f0e46d 100644 --- a/vpr/src/pack/cluster_util.cpp +++ b/vpr/src/pack/cluster_util.cpp @@ -1879,6 +1879,35 @@ void print_pb_type_count_recurr(t_pb_type* pb_type, size_t max_name_chars, size_ } } +/** + * Print the total number of used physical blocks for each pb type in the architecture + */ +void print_pb_type_count(const ClusteredNetlist& clb_nlist) { + auto& device_ctx = g_vpr_ctx.device(); + + std::map pb_type_count; + + size_t max_depth = 0; + for (ClusterBlockId blk : clb_nlist.blocks()) { + size_t pb_max_depth = update_pb_type_count(clb_nlist.block_pb(blk), pb_type_count, 0); + + max_depth = std::max(max_depth, pb_max_depth); + } + + size_t max_pb_type_name_chars = 0; + for (auto& pb_type : pb_type_count) { + max_pb_type_name_chars = std::max(max_pb_type_name_chars, strlen(pb_type.first->name)); + } + + VTR_LOG("\nPb types usage...\n"); + for (const auto& logical_block_type : device_ctx.logical_block_types) { + if (!logical_block_type.pb_type) continue; + + print_pb_type_count_recurr(logical_block_type.pb_type, max_pb_type_name_chars + max_depth, 0, pb_type_count); + } + VTR_LOG("\n"); +} + t_logical_block_type_ptr identify_logic_block_type(std::map>& primitive_candidate_block_types) { std::string lut_name = ".names"; diff --git a/vpr/src/pack/cluster_util.h b/vpr/src/pack/cluster_util.h index c55dcab2922..10a5d10ee52 100644 --- a/vpr/src/pack/cluster_util.h +++ b/vpr/src/pack/cluster_util.h @@ -481,6 +481,8 @@ void update_le_count(const t_pb* pb, const t_logical_block_type_ptr logic_block_ void print_pb_type_count_recurr(t_pb_type* type, size_t max_name_chars, size_t curr_depth, std::map& pb_type_count); +void print_pb_type_count(const ClusteredNetlist& clb_nlist); + /* * @brief This function identifies the logic block type which is defined by the * block type which has a lut primitive. diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/greedy_clusterer.cpp similarity index 73% rename from vpr/src/pack/cluster.cpp rename to vpr/src/pack/greedy_clusterer.cpp index 354135f2097..3e89e2bd3c1 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/greedy_clusterer.cpp @@ -1,10 +1,9 @@ -/* - * Main clustering algorithm - * Author(s): Vaughn Betz (first revision - VPack), Alexander Marquardt (second revision - T-VPack), Jason Luu (third revision - AAPack) - * June 8, 2011 - */ - -/* +/** + * @file + * @author Vaughn Betz (first revision - VPack), Alexander Marquardt (second revision - T-VPack), Jason Luu (third revision - AAPack) + * @date June 8, 2011 + * @brief Main clustering algorithm + * * The clusterer uses several key data structures: * * t_pb_type (and related types): @@ -33,51 +32,40 @@ * The output of clustering is 400 t_pb of type BLE which represent the clustered user netlist. * Each of the 400 t_pb will reference one of the 4 BLE-type t_pb_graph_nodes. */ -#include "cluster.h" -#include -#include -#include -#include -#include +#include "greedy_clusterer.h" #include - -#include "PreClusterDelayCalculator.h" #include "atom_netlist.h" +#include "attraction_groups.h" #include "cluster_legalizer.h" #include "cluster_util.h" #include "constraints_report.h" -#include "globals.h" +#include "physical_types.h" #include "prepack.h" -#include "timing_info.h" -#include "vpr_types.h" -#include "vpr_utils.h" -#include "vtr_assert.h" -#include "vtr_log.h" - -/* - * When attraction groups are created, the purpose is to pack more densely by adding more molecules - * from the cluster's attraction group to the cluster. In a normal flow, (when attraction groups are - * not on), the cluster keeps being packed until the get_molecule routines return either a repeated - * molecule or a nullptr. When attraction groups are on, we want to keep exploring molecules for the - * cluster until a nullptr is returned. So, the number of repeated molecules is changed from 1 to 500, - * effectively making the clusterer pack a cluster until a nullptr is returned. - */ -static constexpr int ATTRACTION_GROUPS_MAX_REPEATED_MOLECULES = 500; - -std::map do_clustering(const t_packer_opts& packer_opts, - const t_analysis_opts& analysis_opts, - const t_arch* arch, - Prepacker& prepacker, - ClusterLegalizer& cluster_legalizer, - const std::unordered_set& is_clock, - const std::unordered_set& is_global, - bool allow_unrelated_clustering, - bool balance_block_type_utilization, - AttractionInfo& attraction_groups, - bool& floorplan_regions_overfull, - const t_pack_high_fanout_thresholds& high_fanout_thresholds, - t_clustering_data& clustering_data) { + +GreedyClusterer::GreedyClusterer(const t_packer_opts& packer_opts, + const t_analysis_opts& analysis_opts, + const AtomNetlist& atom_netlist, + const t_arch* arch, + const t_pack_high_fanout_thresholds& high_fanout_thresholds, + const std::unordered_set& is_clock, + const std::unordered_set& is_global) + : packer_opts_(packer_opts), + analysis_opts_(analysis_opts), + atom_netlist_(atom_netlist), + arch_(arch), + high_fanout_thresholds_(high_fanout_thresholds), + is_clock_(is_clock), + is_global_(is_global), + primitive_candidate_block_types_(identify_primitive_candidate_block_types()) {} + +std::map +GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer, + Prepacker& prepacker, + bool allow_unrelated_clustering, + bool balance_block_type_utilization, + AttractionInfo& attraction_groups) { + /* Does the actual work of clustering multiple netlist blocks * * into clusters. */ @@ -97,12 +85,13 @@ std::map do_clustering(const t_packer_opts& pa /**************************************************************** * Initialization *****************************************************************/ + t_clustering_data clustering_data; t_cluster_progress_stats cluster_stats; //int num_molecules, num_molecules_processed, mols_since_last_print, blocks_since_last_analysis, int num_blocks_hill_added; - const int verbosity = packer_opts.pack_verbosity; + const int verbosity = packer_opts_.pack_verbosity; int unclustered_list_head_size; std::unordered_map net_output_feeds_driving_block_input; @@ -116,7 +105,6 @@ std::map do_clustering(const t_packer_opts& pa t_pack_molecule *istart, *next_molecule, *prev_molecule; - auto& atom_ctx = g_vpr_ctx.atom(); auto& device_ctx = g_vpr_ctx.mutable_device(); std::shared_ptr clustering_delay_calc; @@ -137,15 +125,15 @@ std::map do_clustering(const t_packer_opts& pa /* TODO: This is memory inefficient, fix if causes problems */ /* Store stats on nets used by packed block, useful for determining transitively connected blocks * (eg. [A1, A2, ..]->[B1, B2, ..]->C implies cluster [A1, A2, ...] and C have a weak link) */ - vtr::vector> clb_inter_blk_nets(atom_ctx.nlist.blocks().size()); + vtr::vector> clb_inter_blk_nets(atom_netlist_.blocks().size()); istart = nullptr; - const t_molecule_stats max_molecule_stats = prepacker.calc_max_molecule_stats(atom_ctx.nlist); + const t_molecule_stats max_molecule_stats = prepacker.calc_max_molecule_stats(atom_netlist_); cluster_stats.num_molecules = prepacker.get_num_molecules(); - if (packer_opts.hill_climbing_flag) { + if (packer_opts_.hill_climbing_flag) { size_t max_cluster_size = cluster_legalizer.get_max_cluster_size(); clustering_data.hill_climbing_inputs_avail = new int[max_cluster_size + 1]; for (size_t i = 0; i < max_cluster_size + 1; i++) @@ -163,9 +151,8 @@ std::map do_clustering(const t_packer_opts& pa clustering_data, net_output_feeds_driving_block_input, unclustered_list_head_size, cluster_stats.num_molecules); - auto primitive_candidate_block_types = identify_primitive_candidate_block_types(); // find the cluster type that has lut primitives - auto logic_block_type = identify_logic_block_type(primitive_candidate_block_types); + auto logic_block_type = identify_logic_block_type(primitive_candidate_block_types_); // find a LE pb_type within the found logic_block_type auto le_pb_type = identify_le_block_type(logic_block_type); @@ -173,15 +160,15 @@ std::map do_clustering(const t_packer_opts& pa num_blocks_hill_added = 0; //Default criticalities set to zero (e.g. if not timing driven) - vtr::vector atom_criticality(atom_ctx.nlist.blocks().size(), 0.); + vtr::vector atom_criticality(atom_netlist_.blocks().size(), 0.); - if (packer_opts.timing_driven) { - calc_init_packing_timing(packer_opts, analysis_opts, prepacker, + if (packer_opts_.timing_driven) { + calc_init_packing_timing(packer_opts_, analysis_opts_, prepacker, clustering_delay_calc, timing_info, atom_criticality); } // Assign gain scores to atoms and sort them based on the scores. - auto seed_atoms = initialize_seed_atoms(packer_opts.cluster_seed_type, + auto seed_atoms = initialize_seed_atoms(packer_opts_.cluster_seed_type, max_molecule_stats, prepacker, atom_criticality); @@ -225,9 +212,9 @@ std::map do_clustering(const t_packer_opts& pa legalization_cluster_id, istart, num_used_type_instances, - packer_opts.target_device_utilization, - arch, packer_opts.device_layout, - primitive_candidate_block_types, + packer_opts_.target_device_utilization, + arch_, packer_opts_.device_layout, + primitive_candidate_block_types_, verbosity, balance_block_type_utilization); @@ -251,21 +238,21 @@ std::map do_clustering(const t_packer_opts& pa //Progress dot for seed-block fflush(stdout); - int high_fanout_threshold = high_fanout_thresholds.get_threshold(cluster_legalizer.get_cluster_type(legalization_cluster_id)->name); + int high_fanout_threshold = high_fanout_thresholds_.get_threshold(cluster_legalizer.get_cluster_type(legalization_cluster_id)->name); update_cluster_stats(istart, cluster_legalizer, - is_clock, //Set of clock nets - is_global, //Set of global nets (currently all clocks) - packer_opts.global_clocks, - packer_opts.alpha, packer_opts.beta, - packer_opts.timing_driven, packer_opts.connection_driven, + is_clock_, //Set of clock nets + is_global_, //Set of global nets (currently all clocks) + packer_opts_.global_clocks, + packer_opts_.alpha, packer_opts_.beta, + packer_opts_.timing_driven, packer_opts_.connection_driven, high_fanout_threshold, *timing_info, attraction_groups, net_output_feeds_driving_block_input); total_clb_num++; - if (packer_opts.timing_driven) { + if (packer_opts_.timing_driven) { cluster_stats.blocks_since_last_analysis++; /*it doesn't make sense to do a timing analysis here since there* *is only one atom block clustered it would not change anything */ @@ -274,9 +261,9 @@ std::map do_clustering(const t_packer_opts& pa next_molecule = get_molecule_for_cluster(cluster_legalizer.get_cluster_pb(legalization_cluster_id), attraction_groups, allow_unrelated_clustering, - packer_opts.prioritize_transitive_connectivity, - packer_opts.transitive_fanout_threshold, - packer_opts.feasible_block_array_size, + packer_opts_.prioritize_transitive_connectivity, + packer_opts_.transitive_fanout_threshold, + packer_opts_.feasible_block_array_size, &cluster_stats.num_unrelated_clustering_attempts, prepacker, cluster_legalizer, @@ -285,7 +272,7 @@ std::map do_clustering(const t_packer_opts& pa verbosity, clustering_data.unclustered_list_head, unclustered_list_head_size, - primitive_candidate_block_types); + primitive_candidate_block_types_); prev_molecule = istart; /* @@ -298,7 +285,7 @@ std::map do_clustering(const t_packer_opts& pa */ int max_num_repeated_molecules = 0; if (attraction_groups.num_attraction_groups() > 0) { - max_num_repeated_molecules = ATTRACTION_GROUPS_MAX_REPEATED_MOLECULES; + max_num_repeated_molecules = attraction_groups_max_repeated_molecules_; } else { max_num_repeated_molecules = 1; } @@ -309,7 +296,7 @@ std::map do_clustering(const t_packer_opts& pa try_fill_cluster(cluster_legalizer, prepacker, - packer_opts, + packer_opts_, prev_molecule, next_molecule, num_repeated_molecules, @@ -320,14 +307,14 @@ std::map do_clustering(const t_packer_opts& pa clb_inter_blk_nets, allow_unrelated_clustering, high_fanout_threshold, - is_clock, - is_global, + is_clock_, + is_global_, timing_info, block_pack_status, clustering_data.unclustered_list_head, unclustered_list_head_size, net_output_feeds_driving_block_input, - primitive_candidate_block_types); + primitive_candidate_block_types_); } if (strategy == ClusterLegalizationStrategy::FULL) { @@ -348,10 +335,10 @@ std::map do_clustering(const t_packer_opts& pa prepacker, cluster_legalizer); // Update cluster stats. - if (packer_opts.timing_driven && num_blocks_hill_added > 0) + if (packer_opts_.timing_driven && num_blocks_hill_added > 0) cluster_stats.blocks_since_last_analysis += num_blocks_hill_added; - store_cluster_info_and_free(packer_opts, legalization_cluster_id, logic_block_type, le_pb_type, le_count, cluster_legalizer, clb_inter_blk_nets); + store_cluster_info_and_free(packer_opts_, legalization_cluster_id, logic_block_type, le_pb_type, le_count, cluster_legalizer, clb_inter_blk_nets); // Since the cluster will no longer be added to beyond this point, // clean the cluster of any data not strictly necessary for // creating the clustered netlist. @@ -373,42 +360,16 @@ std::map do_clustering(const t_packer_opts& pa print_le_count(le_count, le_pb_type); } - //check_floorplan_regions(floorplan_regions_overfull); - floorplan_regions_overfull = floorplan_constraints_regions_overfull(cluster_legalizer); - // Ensure that we have kept track of the number of clusters correctly. // TODO: The total_clb_num variable could probably just be replaced by // clusters().size(). VTR_ASSERT(cluster_legalizer.clusters().size() == (size_t)total_clb_num); + // Free the clustering data. + // FIXME: This struct should use standard data structures so it does not + // have to be freed like this. + free_clustering_data(packer_opts_, clustering_data); + return num_used_type_instances; } -/** - * Print the total number of used physical blocks for each pb type in the architecture - */ -void print_pb_type_count(const ClusteredNetlist& clb_nlist) { - auto& device_ctx = g_vpr_ctx.device(); - - std::map pb_type_count; - - size_t max_depth = 0; - for (ClusterBlockId blk : clb_nlist.blocks()) { - size_t pb_max_depth = update_pb_type_count(clb_nlist.block_pb(blk), pb_type_count, 0); - - max_depth = std::max(max_depth, pb_max_depth); - } - - size_t max_pb_type_name_chars = 0; - for (auto& pb_type : pb_type_count) { - max_pb_type_name_chars = std::max(max_pb_type_name_chars, strlen(pb_type.first->name)); - } - - VTR_LOG("\nPb types usage...\n"); - for (const auto& logical_block_type : device_ctx.logical_block_types) { - if (!logical_block_type.pb_type) continue; - - print_pb_type_count_recurr(logical_block_type.pb_type, max_pb_type_name_chars + max_depth, 0, pb_type_count); - } - VTR_LOG("\n"); -} diff --git a/vpr/src/pack/greedy_clusterer.h b/vpr/src/pack/greedy_clusterer.h new file mode 100644 index 00000000000..2c3d41825cc --- /dev/null +++ b/vpr/src/pack/greedy_clusterer.h @@ -0,0 +1,123 @@ +/** + * @file + * @author Alex Singer + * @date November 2024 + * @brief The declarations of the Greedy Clusterer class which is used to + * encapsulate the process of greedy clustering. + */ + +#pragma once + +#include +#include +#include "physical_types.h" + +// Forward declarations +class AtomNetId; +class AtomNetlist; +class AttractionInfo; +class ClusterLegalizer; +class Prepacker; +struct t_analysis_opts; +struct t_clustering_data; +struct t_pack_high_fanout_thresholds; +struct t_packer_opts; + +/** + * @brief A clusterer that generates clusters by greedily choosing the clusters + * which appear to have the best gain for a given neighbor. + * + * This clusterer generates one cluster at a time by finding candidate molecules + * and selecting the molecule with the highest gain. + */ +class GreedyClusterer { +public: + /** + * @brief Constructor of the Greedy Clusterer class. + * + * The clusterer may be invoked many times during the packing flow. This + * constructor will pre-compute information before clustering which can + * improve the performance of the clusterer. + * + * @param packer_opts + * Options passed by the user to configure the packing and + * clustering algorithms. + * @param analysis_opts + * Options passed by the user to configure timing analysis in + * the clusterer. + * @param atom_netlist + * The atom netlist to cluster over. + * @param arch + * The architecture to cluster over. + * @param high_fanout_thresholds + * The thresholds for what to consider as a high-fanout net + * for each logical block type. + * @param is_clock + * The set of clock nets in the Atom Netlist. + * @param is_global + * The set of global nets in the Atom Netlist. + */ + GreedyClusterer(const t_packer_opts& packer_opts, + const t_analysis_opts& analysis_opts, + const AtomNetlist& atom_netlist, + const t_arch* arch, + const t_pack_high_fanout_thresholds& high_fanout_thresholds, + const std::unordered_set& is_clock, + const std::unordered_set& is_global); + + /** + * @brief Performs clustering on the pack molecules formed by the prepacker. + * + * The clustering is contained within the Cluster Legalizer. + * + * @param cluster_legalizer + * The cluster legalizer which is used to create clusters and + * grow clusters by adding molecules to a cluster. + * @param prepacker + * The prepacker object which contains the pack molecules that + * atoms are pre-packed into before clustering. + * @param allow_unrelated_clustering + * Allows primitives which have no attraction to the given + * cluster to be packed into it. + * @param balance_block_type_utilization + * When true, tries to create clusters that balance the logical + * block type utilization. + * @param attraction_groups + * Information on the attraction groups used during the + * clustering process. + * + * @return num_used_type_instances + * The number of used logical block types by the clustering. + * This information may be useful when detecting if the + * clustering can fit on the device. + */ + std::map + do_clustering(ClusterLegalizer& cluster_legalizer, + Prepacker& prepacker, + bool allow_unrelated_clustering, + bool balance_block_type_utilization, + AttractionInfo& attraction_groups); + +private: + /* + * When attraction groups are created, the purpose is to pack more densely by adding more molecules + * from the cluster's attraction group to the cluster. In a normal flow, (when attraction groups are + * not on), the cluster keeps being packed until the get_molecule routines return either a repeated + * molecule or a nullptr. When attraction groups are on, we want to keep exploring molecules for the + * cluster until a nullptr is returned. So, the number of repeated molecules is changed from 1 to 500, + * effectively making the clusterer pack a cluster until a nullptr is returned. + */ + static constexpr int attraction_groups_max_repeated_molecules_ = 500; + + const t_packer_opts& packer_opts_; + const t_analysis_opts& analysis_opts_; + const AtomNetlist& atom_netlist_; + const t_arch* arch_ = nullptr; + const t_pack_high_fanout_thresholds& high_fanout_thresholds_; + const std::unordered_set& is_clock_; + const std::unordered_set& is_global_; + + /// @brief Pre-computed logical block types for each model in the architecture. + std::map> primitive_candidate_block_types_; +}; + diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index dae3443900c..73970032131 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -1,10 +1,11 @@ #include #include "SetupGrid.h" -#include "cluster.h" #include "cluster_legalizer.h" #include "cluster_util.h" +#include "constraints_report.h" #include "globals.h" +#include "greedy_clusterer.h" #include "pack.h" #include "prepack.h" #include "vpr_context.h" @@ -29,7 +30,6 @@ bool try_pack(t_packer_opts* packer_opts, const DeviceContext& device_ctx = g_vpr_ctx.device(); std::unordered_set is_clock, is_global; - t_clustering_data clustering_data; VTR_LOG("Begin packing '%s'.\n", packer_opts->circuit_file_name.c_str()); is_clock = alloc_and_load_is_clock(); @@ -91,7 +91,6 @@ bool try_pack(t_packer_opts* packer_opts, } int pack_iteration = 1; - bool floorplan_regions_overfull = false; // Initialize the cluster legalizer. ClusterLegalizer cluster_legalizer(atom_ctx.nlist, @@ -110,27 +109,25 @@ bool try_pack(t_packer_opts* packer_opts, VTR_LOG("Packing with pin utilization targets: %s\n", cluster_legalizer.get_target_external_pin_util().to_string().c_str()); VTR_LOG("Packing with high fanout thresholds: %s\n", high_fanout_thresholds.to_string().c_str()); - while (true) { - free_clustering_data(*packer_opts, clustering_data); - + // Initialize the greedy clusterer. + GreedyClusterer clusterer(*packer_opts, + *analysis_opts, + atom_ctx.nlist, + arch, + high_fanout_thresholds, + is_clock, + is_global); + while (true) { //Cluster the netlist // num_used_type_instances: A map used to save the number of used // instances from each logical block type. std::map num_used_type_instances; - num_used_type_instances = do_clustering(*packer_opts, - *analysis_opts, - arch, - prepacker, - cluster_legalizer, - is_clock, - is_global, - allow_unrelated_clustering, - balance_block_type_util, - attraction_groups, - floorplan_regions_overfull, - high_fanout_thresholds, - clustering_data); + num_used_type_instances = clusterer.do_clustering(cluster_legalizer, + prepacker, + allow_unrelated_clustering, + balance_block_type_util, + attraction_groups); //Try to size/find a device bool fits_on_device = try_size_device_grid(*arch, num_used_type_instances, packer_opts->target_device_utilization, packer_opts->device_layout); @@ -139,6 +136,7 @@ bool try_pack(t_packer_opts* packer_opts, * is not dense enough and there are floorplan constraints, it is presumed that the constraints are the cause * of the floorplan not fitting, so attraction groups are turned on for later iterations. */ + bool floorplan_regions_overfull = floorplan_constraints_regions_overfull(cluster_legalizer); bool floorplan_not_fitting = (floorplan_regions_overfull || g_vpr_ctx.floorplanning().constraints.get_num_partitions() > 0); if (fits_on_device && !floorplan_regions_overfull) { @@ -261,9 +259,6 @@ bool try_pack(t_packer_opts* packer_opts, //check clustering and output it check_and_output_clustering(cluster_legalizer, *packer_opts, is_clock, arch); - // Free Data Structures - free_clustering_data(*packer_opts, clustering_data); - VTR_LOG("\n"); VTR_LOG("Netlist conversion complete.\n"); VTR_LOG("\n");