Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Packer] Created GreedySeedSelector Class #2822

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 0 additions & 182 deletions vpr/src/pack/cluster_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1523,156 +1523,6 @@ t_molecule_stats calc_molecule_stats(const t_pack_molecule* molecule, const Atom
return molecule_stats;
}

std::vector<AtomBlockId> initialize_seed_atoms(const e_cluster_seed seed_type,
const t_molecule_stats& max_molecule_stats,
const Prepacker& prepacker,
const vtr::vector<AtomBlockId, float>& atom_criticality) {
const AtomNetlist& atom_nlist = g_vpr_ctx.atom().nlist;

//Put all atoms in seed list
std::vector<AtomBlockId> seed_atoms(atom_nlist.blocks().begin(), atom_nlist.blocks().end());

//Initially all gains are zero
vtr::vector<AtomBlockId, float> atom_gains(atom_nlist.blocks().size(), 0.);

if (seed_type == e_cluster_seed::TIMING) {
VTR_ASSERT(atom_gains.size() == atom_criticality.size());

//By criticality
atom_gains = atom_criticality;

} else if (seed_type == e_cluster_seed::MAX_INPUTS) {
//By number of used molecule input pins
for (auto blk : atom_nlist.blocks()) {
const t_pack_molecule* blk_mol = prepacker.get_atom_molecule(blk);
const t_molecule_stats molecule_stats = calc_molecule_stats(blk_mol, atom_nlist);
atom_gains[blk] = molecule_stats.num_used_ext_inputs;
}

} else if (seed_type == e_cluster_seed::BLEND) {
//By blended gain (criticality and inputs used)
for (auto blk : atom_nlist.blocks()) {
/* Score seed gain of each block as a weighted sum of timing criticality,
* number of tightly coupled blocks connected to it, and number of external inputs */
float seed_blend_fac = 0.5;

const t_pack_molecule* blk_mol = prepacker.get_atom_molecule(blk);
const t_molecule_stats molecule_stats = calc_molecule_stats(blk_mol, atom_nlist);
VTR_ASSERT(max_molecule_stats.num_used_ext_inputs > 0);

float blend_gain = (seed_blend_fac * atom_criticality[blk]
+ (1 - seed_blend_fac) * (molecule_stats.num_used_ext_inputs / max_molecule_stats.num_used_ext_inputs));
blend_gain *= (1 + 0.2 * (molecule_stats.num_blocks - 1));
atom_gains[blk] = blend_gain;
}

} else if (seed_type == e_cluster_seed::MAX_PINS || seed_type == e_cluster_seed::MAX_INPUT_PINS) {
//By pins per molecule (i.e. available pins on primitives, not pins in use)

for (auto blk : atom_nlist.blocks()) {
const t_pack_molecule* mol = prepacker.get_atom_molecule(blk);
const t_molecule_stats molecule_stats = calc_molecule_stats(mol, atom_nlist);

int molecule_pins = 0;
if (seed_type == e_cluster_seed::MAX_PINS) {
//All pins
molecule_pins = molecule_stats.num_pins;
} else {
VTR_ASSERT(seed_type == e_cluster_seed::MAX_INPUT_PINS);
//Input pins only
molecule_pins = molecule_stats.num_input_pins;
}

atom_gains[blk] = molecule_pins;
}

} else if (seed_type == e_cluster_seed::BLEND2) {
for (auto blk : atom_nlist.blocks()) {
const t_pack_molecule* mol = prepacker.get_atom_molecule(blk);
const t_molecule_stats molecule_stats = calc_molecule_stats(mol, atom_nlist);

float pin_ratio = vtr::safe_ratio<float>(molecule_stats.num_pins, max_molecule_stats.num_pins);
float input_pin_ratio = vtr::safe_ratio<float>(molecule_stats.num_input_pins, max_molecule_stats.num_input_pins);
float output_pin_ratio = vtr::safe_ratio<float>(molecule_stats.num_output_pins, max_molecule_stats.num_output_pins);
float used_ext_pin_ratio = vtr::safe_ratio<float>(molecule_stats.num_used_ext_pins, max_molecule_stats.num_used_ext_pins);
float used_ext_input_pin_ratio = vtr::safe_ratio<float>(molecule_stats.num_used_ext_inputs, max_molecule_stats.num_used_ext_inputs);
float used_ext_output_pin_ratio = vtr::safe_ratio<float>(molecule_stats.num_used_ext_outputs, max_molecule_stats.num_used_ext_outputs);
float num_blocks_ratio = vtr::safe_ratio<float>(molecule_stats.num_blocks, max_molecule_stats.num_blocks);
float criticality = atom_criticality[blk];

constexpr float PIN_WEIGHT = 0.;
constexpr float INPUT_PIN_WEIGHT = 0.5;
constexpr float OUTPUT_PIN_WEIGHT = 0.;
constexpr float USED_PIN_WEIGHT = 0.;
constexpr float USED_INPUT_PIN_WEIGHT = 0.2;
constexpr float USED_OUTPUT_PIN_WEIGHT = 0.;
constexpr float BLOCKS_WEIGHT = 0.2;
constexpr float CRITICALITY_WEIGHT = 0.1;

float gain = PIN_WEIGHT * pin_ratio
+ INPUT_PIN_WEIGHT * input_pin_ratio
+ OUTPUT_PIN_WEIGHT * output_pin_ratio

+ USED_PIN_WEIGHT * used_ext_pin_ratio
+ USED_INPUT_PIN_WEIGHT * used_ext_input_pin_ratio
+ USED_OUTPUT_PIN_WEIGHT * used_ext_output_pin_ratio

+ BLOCKS_WEIGHT * num_blocks_ratio
+ CRITICALITY_WEIGHT * criticality;

atom_gains[blk] = gain;
}

} else {
VPR_FATAL_ERROR(VPR_ERROR_PACK, "Unrecognized cluster seed type");
}

//Sort seeds in descending order of gain (i.e. highest gain first)
//
// Note that we use a *stable* sort here. It has been observed that different
// standard library implementations (e.g. gcc-4.9 vs gcc-5) use sorting algorithms
// which produce different orderings for seeds of equal gain (which is allowed with
// std::sort which does not specify how equal values are handled). Using a stable
// sort ensures that regardless of the underlying sorting algorithm the same seed
// order is produced regardless of compiler.
auto by_descending_gain = [&](const AtomBlockId lhs, const AtomBlockId rhs) {
return atom_gains[lhs] > atom_gains[rhs];
};
std::stable_sort(seed_atoms.begin(), seed_atoms.end(), by_descending_gain);

if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_CLUSTERING_BLOCK_CRITICALITIES)) {
print_seed_gains(getEchoFileName(E_ECHO_CLUSTERING_BLOCK_CRITICALITIES), seed_atoms, atom_gains, atom_criticality);
}

return seed_atoms;
}

t_pack_molecule* get_highest_gain_seed_molecule(int& seed_index,
const std::vector<AtomBlockId>& seed_atoms,
const Prepacker& prepacker,
const ClusterLegalizer& cluster_legalizer) {
while (seed_index < static_cast<int>(seed_atoms.size())) {
AtomBlockId blk_id = seed_atoms[seed_index++];

// Check if the atom has already been assigned to a cluster
if (!cluster_legalizer.is_atom_clustered(blk_id)) {
t_pack_molecule* best = nullptr;

t_pack_molecule* molecule = prepacker.get_atom_molecule(blk_id);
if (!cluster_legalizer.is_mol_clustered(molecule)) {
if (best == nullptr || (best->base_gain) < (molecule->base_gain)) {
best = molecule;
}
}
VTR_ASSERT(best != nullptr);
return best;
}
}

/*if it makes it to here , there are no more blocks available*/
return nullptr;
}

float get_molecule_gain(t_pack_molecule* molecule, std::map<AtomBlockId, float>& blk_gain, AttractGroupId cluster_attraction_group_id, AttractionInfo& attraction_groups, int num_molecule_failures) {
float gain;
int i;
Expand Down Expand Up @@ -1804,38 +1654,6 @@ std::map<const t_model*, std::vector<t_logical_block_type_ptr>> identify_primiti
return model_candidates;
}

void print_seed_gains(const char* fname, const std::vector<AtomBlockId>& seed_atoms, const vtr::vector<AtomBlockId, float>& atom_gain, const vtr::vector<AtomBlockId, float>& atom_criticality) {
FILE* fp = vtr::fopen(fname, "w");

const AtomContext& atom_ctx = g_vpr_ctx.atom();

//For prett formatting determine the maximum name length
int max_name_len = strlen("atom_block_name");
int max_type_len = strlen("atom_block_type");
for (auto blk_id : atom_ctx.nlist.blocks()) {
max_name_len = std::max(max_name_len, (int)atom_ctx.nlist.block_name(blk_id).size());

const t_model* model = atom_ctx.nlist.block_model(blk_id);
max_type_len = std::max(max_type_len, (int)strlen(model->name));
}

fprintf(fp, "%-*s %-*s %8s %8s\n", max_name_len, "atom_block_name", max_type_len, "atom_block_type", "gain", "criticality");
fprintf(fp, "\n");
for (auto blk_id : seed_atoms) {
std::string name = atom_ctx.nlist.block_name(blk_id);
fprintf(fp, "%-*s ", max_name_len, name.c_str());

const t_model* model = atom_ctx.nlist.block_model(blk_id);
fprintf(fp, "%-*s ", max_type_len, model->name);

fprintf(fp, "%*f ", std::max((int)strlen("gain"), 8), atom_gain[blk_id]);
fprintf(fp, "%*f ", std::max((int)strlen("criticality"), 8), atom_criticality[blk_id]);
fprintf(fp, "\n");
}

fclose(fp);
}

size_t update_pb_type_count(const t_pb* pb, std::map<t_pb_type*, int>& pb_type_count, size_t depth) {
size_t max_depth = depth;

Expand Down
12 changes: 0 additions & 12 deletions vpr/src/pack/cluster_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,16 +428,6 @@ t_pack_molecule* get_molecule_for_cluster(t_pb* cur_pb,
*/
t_molecule_stats calc_molecule_stats(const t_pack_molecule* molecule, const AtomNetlist& atom_nlist);

std::vector<AtomBlockId> initialize_seed_atoms(const e_cluster_seed seed_type,
const t_molecule_stats& max_molecule_stats,
const Prepacker& prepacker,
const vtr::vector<AtomBlockId, float>& atom_criticality);

t_pack_molecule* get_highest_gain_seed_molecule(int& seed_index,
const std::vector<AtomBlockId>& seed_atoms,
const Prepacker& prepacker,
const ClusterLegalizer& cluster_legalizer);

/*
* @brief Get gain of packing molecule into current cluster.
*
Expand All @@ -448,8 +438,6 @@ t_pack_molecule* get_highest_gain_seed_molecule(int& seed_index,
*/
float get_molecule_gain(t_pack_molecule* molecule, std::map<AtomBlockId, float>& blk_gain, AttractGroupId cluster_attraction_group_id, AttractionInfo& attraction_groups, int num_molecule_failures);

void print_seed_gains(const char* fname, const std::vector<AtomBlockId>& seed_atoms, const vtr::vector<AtomBlockId, float>& atom_gain, const vtr::vector<AtomBlockId, float>& atom_criticality);

/**
* @brief Score unclustered atoms that are two hops away from current cluster
*
Expand Down
35 changes: 15 additions & 20 deletions vpr/src/pack/greedy_clusterer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,16 @@

#include "greedy_clusterer.h"
#include <map>
#include <vector>
#include "atom_netlist.h"
#include "attraction_groups.h"
#include "cluster_legalizer.h"
#include "cluster_util.h"
#include "constraints_report.h"
#include "greedy_seed_selector.h"
#include "physical_types.h"
#include "prepack.h"
#include "vtr_vector.h"

GreedyClusterer::GreedyClusterer(const t_packer_opts& packer_opts,
const t_analysis_opts& analysis_opts,
Expand Down Expand Up @@ -106,7 +109,7 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer,

enum e_block_pack_status block_pack_status;

t_pack_molecule *istart, *next_molecule, *prev_molecule;
t_pack_molecule *next_molecule, *prev_molecule;

auto& device_ctx = g_vpr_ctx.mutable_device();

Expand All @@ -130,8 +133,6 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer,
* (eg. [A1, A2, ..]->[B1, B2, ..]->C implies cluster [A1, A2, ...] and C have a weak link) */
vtr::vector<LegalizationClusterId, std::vector<AtomNetId>> clb_inter_blk_nets(atom_netlist_.blocks().size());

istart = nullptr;

const t_molecule_stats max_molecule_stats = prepacker.calc_max_molecule_stats(atom_netlist_);

cluster_stats.num_molecules = prepacker.get_num_molecules();
Expand Down Expand Up @@ -170,18 +171,16 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer,
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,
max_molecule_stats,
prepacker,
atom_criticality);
// Create the greedy seed selector.
GreedySeedSelector seed_selector(atom_netlist_,
prepacker,
packer_opts_.cluster_seed_type,
max_molecule_stats,
atom_criticality);

/* index of next most timing critical block */
int seed_index = 0;
istart = get_highest_gain_seed_molecule(seed_index,
seed_atoms,
prepacker,
cluster_legalizer);
// Pick the first seed molecule.
t_pack_molecule* istart = seed_selector.get_next_seed(prepacker,
cluster_legalizer);

print_pack_status_header();

Expand All @@ -191,7 +190,6 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer,

while (istart != nullptr) {
bool is_cluster_legal = false;
int saved_seed_index = seed_index;
// The basic algorithm:
// 1) Try to put all the molecules in that you can without doing the
// full intra-lb route. Then do full legalization at the end.
Expand Down Expand Up @@ -333,10 +331,8 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer,

if (is_cluster_legal) {
// Pick new seed.
istart = get_highest_gain_seed_molecule(seed_index,
seed_atoms,
prepacker,
cluster_legalizer);
istart = seed_selector.get_next_seed(prepacker,
cluster_legalizer);
// Update cluster stats.
if (packer_opts_.timing_driven && num_blocks_hill_added > 0)
cluster_stats.blocks_since_last_analysis += num_blocks_hill_added;
Expand All @@ -350,7 +346,6 @@ GreedyClusterer::do_clustering(ClusterLegalizer& cluster_legalizer,
// If the cluster is not legal, requeue used mols.
num_used_type_instances[cluster_legalizer.get_cluster_type(legalization_cluster_id)]--;
total_clb_num--;
seed_index = saved_seed_index;
// Destroy the illegal cluster.
cluster_legalizer.destroy_cluster(legalization_cluster_id);
cluster_legalizer.compress();
Expand Down
Loading