Skip to content

Commit

Permalink
[Packer] Clean Up Clustering Algorithm
Browse files Browse the repository at this point in the history
Cleaned up the overall clustering algorithm in the greedy clusterer
class. This change is non-functional, the control flow was rearanged and
inlined / outlined to make the overall clustering algorithm more clear.

More needs to be done to abstract timing and the gain calculation.
  • Loading branch information
AlexandreSinger committed Nov 22, 2024
1 parent b007516 commit 102ef79
Show file tree
Hide file tree
Showing 11 changed files with 678 additions and 666 deletions.
1 change: 0 additions & 1 deletion vpr/src/base/SetupVPR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,6 @@ void SetupPackerOpts(const t_options& Options,

//TODO: document?
PackerOpts->global_clocks = true; /* DEFAULT */
PackerOpts->hill_climbing_flag = false; /* DEFAULT */

PackerOpts->allow_unrelated_clustering = Options.allow_unrelated_clustering;
PackerOpts->connection_driven = Options.connection_driven_clustering;
Expand Down
1 change: 0 additions & 1 deletion vpr/src/base/ShowSetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,6 @@ static void ShowPackerOpts(const t_packer_opts& PackerOpts) {
}
VTR_LOG("PackerOpts.connection_driven: %s", (PackerOpts.connection_driven ? "true\n" : "false\n"));
VTR_LOG("PackerOpts.global_clocks: %s", (PackerOpts.global_clocks ? "true\n" : "false\n"));
VTR_LOG("PackerOpts.hill_climbing_flag: %s", (PackerOpts.hill_climbing_flag ? "true\n" : "false\n"));
VTR_LOG("PackerOpts.inter_cluster_net_delay: %f\n", PackerOpts.inter_cluster_net_delay);
VTR_LOG("PackerOpts.timing_driven: %s", (PackerOpts.timing_driven ? "true\n" : "false\n"));
VTR_LOG("PackerOpts.target_external_pin_util: %s", vtr::join(PackerOpts.target_external_pin_util, " ").c_str());
Expand Down
1 change: 0 additions & 1 deletion vpr/src/base/vpr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,6 @@ struct t_packer_opts {
std::string sdc_file_name;
std::string output_file;
bool global_clocks;
bool hill_climbing_flag;
bool timing_driven;
enum e_cluster_seed cluster_seed_type;
float alpha;
Expand Down
1 change: 1 addition & 0 deletions vpr/src/pack/attraction_groups.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "attraction_groups.h"
#include "globals.h"

AttractionInfo::AttractionInfo(bool attraction_groups_on) {
const auto& floorplanning_ctx = g_vpr_ctx.floorplanning();
Expand Down
7 changes: 3 additions & 4 deletions vpr/src/pack/attraction_groups.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

#include "vtr_strong_id.h"
#include "vtr_vector.h"
#include "atom_netlist.h"
#include "globals.h"
#include "atom_netlist_fwd.h"

/**
* @file
Expand Down Expand Up @@ -78,7 +77,7 @@ class AttractionInfo {

void add_attraction_group(const AttractionGroup& group_info);

int num_attraction_groups();
int num_attraction_groups() const;

int get_att_group_pulls() const;

Expand Down Expand Up @@ -118,7 +117,7 @@ inline void AttractionInfo::set_atom_attraction_group(const AtomBlockId atom_id,
attraction_groups[group_id].group_atoms.push_back(atom_id);
}

inline int AttractionInfo::num_attraction_groups() {
inline int AttractionInfo::num_attraction_groups() const {
return attraction_groups.size();
}

Expand Down
354 changes: 44 additions & 310 deletions vpr/src/pack/cluster_util.cpp

Large diffs are not rendered by default.

107 changes: 19 additions & 88 deletions vpr/src/pack/cluster_util.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef CLUSTER_UTIL_H
#define CLUSTER_UTIL_H

#include <unordered_set>
#include <vector>
#include "cluster_legalizer.h"
#include "pack_types.h"
Expand Down Expand Up @@ -63,18 +64,9 @@ struct t_molecule_stats {
int num_used_ext_outputs = 0; //Number of *used external* output pins across all primitives in molecule
};

struct t_cluster_progress_stats {
int num_molecules = 0;
int num_molecules_processed = 0;
int mols_since_last_print = 0;
int blocks_since_last_analysis = 0;
int num_unrelated_clustering_attempts = 0;
};

/* Useful data structures for creating or modifying clusters */
struct t_clustering_data {
int* hill_climbing_inputs_avail;

int unclustered_list_head_size = 0;
/* Keeps a linked list of the unclustered blocks to speed up looking for *
* unclustered blocks with a certain number of *external* inputs. *
* [0..lut_size]. Unclustered_list_head[i] points to the head of the *
Expand All @@ -83,16 +75,6 @@ struct t_clustering_data {

//Maintaining a linked list of free molecule data for speed
t_molecule_link* memory_pool = nullptr;

/* Does the atom block that drives the output of this atom net also appear as a *
* receiver (input) pin of the atom net? If so, then by how much?
*
* This is used in the gain routines to avoid double counting the connections from *
* the current cluster to other blocks (hence yielding better clusterings). *
* The only time an atom block should connect to the same atom net *
* twice is when one connection is an output and the other is an input, *
* so this should take care of all multiple connections. */
std::unordered_map<AtomNetId, int> net_output_feeds_driving_block_input;
};

/***********************************/
Expand All @@ -112,8 +94,7 @@ void calc_init_packing_timing(const t_packer_opts& packer_opts,
/*
* @brief Free the clustering data structures.
*/
void free_clustering_data(const t_packer_opts& packer_opts,
t_clustering_data& clustering_data);
void free_clustering_data(t_clustering_data& clustering_data);

/*
* @brief Check clustering legality and output it.
Expand Down Expand Up @@ -154,8 +135,6 @@ void remove_molecule_from_pb_stats_candidates(t_pack_molecule* molecule,
void alloc_and_init_clustering(const t_molecule_stats& max_molecule_stats,
const Prepacker& prepacker,
t_clustering_data& clustering_data,
std::unordered_map<AtomNetId, int>& net_output_feeds_driving_block_input,
int& unclustered_list_head_size,
int num_molecules);

/*
Expand Down Expand Up @@ -195,8 +174,7 @@ void print_pack_status_header();
/*
* @brief Incrementally print progress updates during clustering.
*/
void print_pack_status(int num_clb,
int tot_num_molecules,
void print_pack_status(int tot_num_molecules,
int num_molecules_processed,
int& mols_since_last_print,
int device_width,
Expand All @@ -212,42 +190,6 @@ void print_pack_status(int num_clb,
void rebuild_attraction_groups(AttractionInfo& attraction_groups,
const ClusterLegalizer& cluster_legalizer);

/*
* @brief Try to pack next_molecule into the given cluster. If this succeeds
* prepares the next_molecule with a new value to pack next iteration.
*
* This method will print the pack status and update the cluster stats.
*/
void try_fill_cluster(ClusterLegalizer& cluster_legalizer,
const Prepacker& prepacker,
const t_packer_opts& packer_opts,
t_pack_molecule*& prev_molecule,
t_pack_molecule*& next_molecule,
int& num_same_molecules,
t_cluster_progress_stats& cluster_stats,
int num_clb,
const LegalizationClusterId legalization_cluster_id,
AttractionInfo& attraction_groups,
vtr::vector<LegalizationClusterId, std::vector<AtomNetId>>& clb_inter_blk_nets,
bool allow_unrelated_clustering,
const int& high_fanout_threshold,
const std::unordered_set<AtomNetId>& is_clock,
const std::unordered_set<AtomNetId>& is_global,
const std::shared_ptr<SetupTimingInfo>& timing_info,
e_block_pack_status& block_pack_status,
t_molecule_link* unclustered_list_head,
const int& unclustered_list_head_size,
std::unordered_map<AtomNetId, int>& net_output_feeds_driving_block_input,
std::map<const t_model*, std::vector<t_logical_block_type_ptr>>& primitive_candidate_block_types);

void store_cluster_info_and_free(const t_packer_opts& packer_opts,
const LegalizationClusterId clb_index,
const t_logical_block_type_ptr logic_block_type,
const t_pb_type* le_pb_type,
std::vector<int>& le_count,
const ClusterLegalizer& cluster_legalizer,
vtr::vector<LegalizationClusterId, std::vector<AtomNetId>>& clb_inter_blk_nets);

void update_connection_gain_values(const AtomNetId net_id,
const AtomBlockId clustered_blk_id,
t_pb* cur_pb,
Expand All @@ -260,7 +202,7 @@ void update_timing_gain_values(const AtomNetId net_id,
enum e_net_relation_to_clustered_block net_relation_to_clustered_block,
const SetupTimingInfo& timing_info,
const std::unordered_set<AtomNetId>& is_global,
std::unordered_map<AtomNetId, int>& net_output_feeds_driving_block_input);
const std::unordered_set<AtomNetId>& net_output_feeds_driving_block_input);

/*
* @brief Updates the marked data structures, and if gain_flag is GAIN, the gain
Expand All @@ -281,7 +223,7 @@ void mark_and_update_partial_gain(const AtomNetId net_id,
const SetupTimingInfo& timing_info,
const std::unordered_set<AtomNetId>& is_global,
const int high_fanout_net_threshold,
std::unordered_map<AtomNetId, int>& net_output_feeds_driving_block_input);
const std::unordered_set<AtomNetId>& net_output_feeds_driving_block_input);

/*
* @brief Updates the total gain array to reflect the desired tradeoff between
Expand Down Expand Up @@ -309,24 +251,7 @@ void update_cluster_stats(const t_pack_molecule* molecule,
const int high_fanout_net_threshold,
const SetupTimingInfo& timing_info,
AttractionInfo& attraction_groups,
std::unordered_map<AtomNetId, int>& net_output_feeds_driving_block_input);

/*
* @brief Given a starting seed block, start_new_cluster determines the next
* cluster type to use.
*
* It expands the FPGA if it cannot find a legal cluster for the atom block
*/
void start_new_cluster(ClusterLegalizer& cluster_legalizer,
LegalizationClusterId& legalization_cluster_id,
t_pack_molecule* molecule,
std::map<t_logical_block_type_ptr, size_t>& num_used_type_instances,
const float target_device_utilization,
const t_arch* arch,
const std::string& device_layout_name,
const std::map<const t_model*, std::vector<t_logical_block_type_ptr>>& primitive_candidate_block_types,
int verbosity,
bool balance_block_type_utilization);
const std::unordered_set<AtomNetId>& net_output_feeds_driving_block_input);

/*
* @brief Get candidate molecule to pack into currently open cluster
Expand All @@ -351,7 +276,7 @@ t_pack_molecule* get_highest_gain_molecule(t_pb* cur_pb,
bool prioritize_transitive_connectivity,
int transitive_fanout_threshold,
const int feasible_block_array_size,
std::map<const t_model*, std::vector<t_logical_block_type_ptr>>& primitive_candidate_block_types);
const std::map<const t_model*, std::vector<t_logical_block_type_ptr>>& primitive_candidate_block_types);

/*
* @brief Add molecules with strong connectedness to the current cluster to the
Expand Down Expand Up @@ -392,7 +317,7 @@ void add_cluster_molecule_candidates_by_attraction_group(t_pb* cur_pb,
AttractionInfo& attraction_groups,
const int feasible_block_array_size,
LegalizationClusterId clb_index,
std::map<const t_model*, std::vector<t_logical_block_type_ptr>>& primitive_candidate_block_types);
const std::map<const t_model*, std::vector<t_logical_block_type_ptr>>& primitive_candidate_block_types);

/*
* @brief Add molecules based on transitive connections (eg. 2 hops away) with
Expand Down Expand Up @@ -421,7 +346,7 @@ t_pack_molecule* get_molecule_for_cluster(t_pb* cur_pb,
int verbosity,
t_molecule_link* unclustered_list_head,
const int& unclustered_list_head_size,
std::map<const t_model*, std::vector<t_logical_block_type_ptr>>& primitive_candidate_block_types);
const std::map<const t_model*, std::vector<t_logical_block_type_ptr>>& primitive_candidate_block_types);

/*
* @brief Calculates molecule statistics for a single molecule.
Expand Down Expand Up @@ -455,6 +380,12 @@ void load_transitive_fanout_candidates(LegalizationClusterId cluster_index,

std::map<const t_model*, std::vector<t_logical_block_type_ptr>> identify_primitive_candidate_block_types();

/**
* @brief Identify which nets in the atom netlist are driven by the same atom
* block that they appear as a receiver (input) pin of.
*/
std::unordered_set<AtomNetId> identify_net_output_feeds_driving_block_input(const AtomNetlist& atom_netlist);

/**
* @brief This function update the pb_type_count data structure by incrementing
* the number of used pb_types in the given packed cluster t_pb
Expand All @@ -465,7 +396,7 @@ size_t update_pb_type_count(const t_pb* pb, std::map<t_pb_type*, int>& pb_type_c
* @brief This function updates the le_count data structure from the given
* packed cluster.
*/
void update_le_count(const t_pb* pb, const t_logical_block_type_ptr logic_block_type, const t_pb_type* le_pb_type, std::vector<int>& le_count);
void update_le_count(const t_pb* pb, const t_logical_block_type_ptr logic_block_type, const t_pb_type* le_pb_type, std::array<int, 3>& le_count);

void print_pb_type_count_recurr(t_pb_type* type, size_t max_name_chars, size_t curr_depth, std::map<t_pb_type*, int>& pb_type_count);

Expand All @@ -478,7 +409,7 @@ 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.
*/
t_logical_block_type_ptr identify_logic_block_type(std::map<const t_model*, std::vector<t_logical_block_type_ptr>>& primitive_candidate_block_types);
t_logical_block_type_ptr identify_logic_block_type(const std::map<const t_model*, std::vector<t_logical_block_type_ptr>>& primitive_candidate_block_types);

/*
* @brief This function returns the pb_type that is similar to Logic Element (LE)
Expand All @@ -499,7 +430,7 @@ bool pb_used_for_blif_model(const t_pb* pb, const std::string& blif_model_name);
/*
* @brief Print the LE count data strurture.
*/
void print_le_count(std::vector<int>& le_count, const t_pb_type* le_pb_type);
void print_le_count(const std::array<int, 3>& le_count, const t_pb_type* le_pb_type);

/*
* @brief Given a pointer to a pb in a cluster, this routine returns a pointer
Expand Down
Loading

0 comments on commit 102ef79

Please sign in to comment.