Skip to content

Packer feasible candidates list to priority queue #2993

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

Closed
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
122 changes: 45 additions & 77 deletions vpr/src/pack/greedy_candidate_selector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,13 +216,11 @@ ClusterGainStats GreedyCandidateSelector::create_cluster_gain_stats(
// Initialize the cluster gain stats.
ClusterGainStats cluster_gain_stats;
cluster_gain_stats.seed_molecule_id = cluster_seed_mol_id;
cluster_gain_stats.num_feasible_blocks = NOT_VALID;
cluster_gain_stats.has_done_connectivity_and_timing = false;
// TODO: The reason this is being resized and not reserved is due to legacy
// code which should be updated.
cluster_gain_stats.feasible_blocks.resize(packer_opts_.feasible_block_array_size);
for (int i = 0; i < packer_opts_.feasible_block_array_size; i++)
cluster_gain_stats.feasible_blocks[i] = PackMoleculeId::INVALID();
cluster_gain_stats.initial_search_for_feasible_blocks = true;
cluster_gain_stats.num_search_for_feasible_blocks_occured = 0;
cluster_gain_stats.num_search_for_feasible_blocks_occurred_limit = packer_opts_.feasible_block_array_size;
cluster_gain_stats.feasible_blocks.clear();
cluster_gain_stats.tie_break_high_fanout_net = AtomNetId::INVALID();
cluster_gain_stats.explore_transitive_fanout = true;

Expand Down Expand Up @@ -285,8 +283,10 @@ void GreedyCandidateSelector::update_cluster_gain_stats_candidate_success(
AttractGroupId atom_grp_id = attraction_groups.get_atom_attraction_group(blk_id);

/* reset list of feasible blocks */
cluster_gain_stats.num_feasible_blocks = NOT_VALID;
cluster_gain_stats.has_done_connectivity_and_timing = false;
cluster_gain_stats.initial_search_for_feasible_blocks = true;
cluster_gain_stats.num_search_for_feasible_blocks_occured = 0;
cluster_gain_stats.feasible_blocks.clear();
/* TODO: Allow clusters to have more than one attraction group. */
if (atom_grp_id.is_valid())
cluster_gain_stats.attraction_grp_id = atom_grp_id;
Expand Down Expand Up @@ -681,8 +681,7 @@ PackMoleculeId GreedyCandidateSelector::get_next_candidate_for_cluster(
*/

// 1. Find unpacked molecules based on criticality and strong connectedness (connected by low fanout nets) with current cluster
if (cluster_gain_stats.num_feasible_blocks == NOT_VALID) {
cluster_gain_stats.num_feasible_blocks = 0;
if (cluster_gain_stats.initial_search_for_feasible_blocks) {
add_cluster_molecule_candidates_by_connectivity_and_timing(cluster_gain_stats,
cluster_id,
cluster_legalizer,
Expand All @@ -692,31 +691,31 @@ PackMoleculeId GreedyCandidateSelector::get_next_candidate_for_cluster(

if (packer_opts_.prioritize_transitive_connectivity) {
// 2. Find unpacked molecules based on transitive connections (eg. 2 hops away) with current cluster
if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.explore_transitive_fanout) {
if (!cluster_gain_stats.initial_search_for_feasible_blocks && cluster_gain_stats.feasible_blocks.size() == 0 && cluster_gain_stats.explore_transitive_fanout) {
add_cluster_molecule_candidates_by_transitive_connectivity(cluster_gain_stats,
cluster_id,
cluster_legalizer,
attraction_groups);
}

// 3. Find unpacked molecules based on weak connectedness (connected by high fanout nets) with current cluster
if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.tie_break_high_fanout_net) {
if (!cluster_gain_stats.initial_search_for_feasible_blocks && cluster_gain_stats.feasible_blocks.size() == 0 && cluster_gain_stats.tie_break_high_fanout_net) {
add_cluster_molecule_candidates_by_highfanout_connectivity(cluster_gain_stats,
cluster_id,
cluster_legalizer,
attraction_groups);
}
} else { //Reverse order
// 3. Find unpacked molecules based on weak connectedness (connected by high fanout nets) with current cluster
if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.tie_break_high_fanout_net) {
if (!cluster_gain_stats.initial_search_for_feasible_blocks && cluster_gain_stats.feasible_blocks.size() == 0 && cluster_gain_stats.tie_break_high_fanout_net) {
add_cluster_molecule_candidates_by_highfanout_connectivity(cluster_gain_stats,
cluster_id,
cluster_legalizer,
attraction_groups);
}

// 2. Find unpacked molecules based on transitive connections (eg. 2 hops away) with current cluster
if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.explore_transitive_fanout) {
if (!cluster_gain_stats.initial_search_for_feasible_blocks && cluster_gain_stats.feasible_blocks.size() == 0 && cluster_gain_stats.explore_transitive_fanout) {
add_cluster_molecule_candidates_by_transitive_connectivity(cluster_gain_stats,
cluster_id,
cluster_legalizer,
Expand All @@ -725,21 +724,35 @@ PackMoleculeId GreedyCandidateSelector::get_next_candidate_for_cluster(
}

// 4. Find unpacked molecules based on attraction group of the current cluster (if the cluster has an attraction group)
if (cluster_gain_stats.num_feasible_blocks == 0) {
if (!cluster_gain_stats.initial_search_for_feasible_blocks && cluster_gain_stats.feasible_blocks.size() == 0) {
add_cluster_molecule_candidates_by_attraction_group(cluster_gain_stats,
cluster_id,
cluster_legalizer,
attraction_groups);
}

/* Grab highest gain molecule */
// If this was a vector, this would just be a pop_back.
PackMoleculeId best_molecule = PackMoleculeId::INVALID();
if (cluster_gain_stats.num_feasible_blocks > 0) {
cluster_gain_stats.num_feasible_blocks--;
int index = cluster_gain_stats.num_feasible_blocks;
best_molecule = cluster_gain_stats.feasible_blocks[index];
VTR_ASSERT(!cluster_legalizer.is_mol_clustered(best_molecule));
// checking if there are feasible blocks being proposed
// checking if number of suggestion reached the limit
if (cluster_gain_stats.feasible_blocks.size() > 0 && cluster_gain_stats.num_search_for_feasible_blocks_occured < cluster_gain_stats.num_search_for_feasible_blocks_occurred_limit) {
best_molecule = cluster_gain_stats.feasible_blocks.pop().first;
if (best_molecule != PackMoleculeId::INVALID()) {
cluster_gain_stats.num_search_for_feasible_blocks_occured++;
VTR_ASSERT(!cluster_legalizer.is_mol_clustered(best_molecule));
}
}

// If we have no feasible blocks, or we have reached the limit of number of pops,
// then we need to clear the feasible blocks list and reset the number of pops.
// This ensures that we can continue searching for feasible blocks for the remaining
// steps (2.transitive, 3.high fanout, 4.attraction group).
if (cluster_gain_stats.feasible_blocks.size() == 0 ||
cluster_gain_stats.num_search_for_feasible_blocks_occured >= cluster_gain_stats.num_search_for_feasible_blocks_occurred_limit ||
cluster_gain_stats.feasible_blocks.delete_pending_set.size() == cluster_gain_stats.feasible_blocks.content_set.size()
){
cluster_gain_stats.feasible_blocks.clear();
cluster_gain_stats.num_search_for_feasible_blocks_occured = 0;
}

// If we are allowing unrelated clustering and no molecule has been found,
Expand Down Expand Up @@ -775,6 +788,9 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_connectivity_an
LegalizationClusterId legalization_cluster_id,
const ClusterLegalizer& cluster_legalizer,
AttractionInfo& attraction_groups) {

VTR_ASSERT(cluster_gain_stats.initial_search_for_feasible_blocks);
cluster_gain_stats.initial_search_for_feasible_blocks = false;
cluster_gain_stats.explore_transitive_fanout = true; /* If no legal molecules found, enable exploration of molecules two hops away */

for (AtomBlockId blk_id : cluster_gain_stats.marked_blocks) {
Expand Down Expand Up @@ -1001,45 +1017,17 @@ static void add_molecule_to_pb_stats_candidates(PackMoleculeId molecule_id,
}
}

for (int i = 0; i < cluster_gain_stats.num_feasible_blocks; i++) {
if (cluster_gain_stats.feasible_blocks[i] == molecule_id) {
return; // already in queue, do nothing
}
// if already in queue, do nothing
if (cluster_gain_stats.feasible_blocks.contains(molecule_id)) {
return;
}

if (cluster_gain_stats.num_feasible_blocks >= max_queue_size - 1) {
/* maximum size for array, remove smallest gain element and sort */
if (get_molecule_gain(molecule_id, cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist, appack_ctx) > get_molecule_gain(cluster_gain_stats.feasible_blocks[0], cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist, appack_ctx)) {
/* single loop insertion sort */
int j;
for (j = 0; j < cluster_gain_stats.num_feasible_blocks - 1; j++) {
if (get_molecule_gain(molecule_id, cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist, appack_ctx) <= get_molecule_gain(cluster_gain_stats.feasible_blocks[j + 1], cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist, appack_ctx)) {
cluster_gain_stats.feasible_blocks[j] = molecule_id;
break;
} else {
cluster_gain_stats.feasible_blocks[j] = cluster_gain_stats.feasible_blocks[j + 1];
}
}
if (j == cluster_gain_stats.num_feasible_blocks - 1) {
cluster_gain_stats.feasible_blocks[j] = molecule_id;
}
}
} else {
/* Expand array and single loop insertion sort */
int j;
for (j = cluster_gain_stats.num_feasible_blocks - 1; j >= 0; j--) {
if (get_molecule_gain(cluster_gain_stats.feasible_blocks[j], cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist, appack_ctx) > get_molecule_gain(molecule_id, cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist, appack_ctx)) {
cluster_gain_stats.feasible_blocks[j + 1] = cluster_gain_stats.feasible_blocks[j];
} else {
cluster_gain_stats.feasible_blocks[j + 1] = molecule_id;
break;
}
}
if (j < 0) {
cluster_gain_stats.feasible_blocks[0] = molecule_id;
}
cluster_gain_stats.num_feasible_blocks++;
for (std::pair<PackMoleculeId, float>& feasible_block : cluster_gain_stats.feasible_blocks.heap) {
VTR_ASSERT_DEBUG(get_molecule_gain(feasible_block.first, cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist, appack_ctx) == feasible_block.second);
}

// Insert the molecule into the queue sorted by gain, and maintain the heap property
cluster_gain_stats.feasible_blocks.push(molecule_id, get_molecule_gain(molecule_id, cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist, appack_ctx));
}

/*
Expand All @@ -1050,27 +1038,7 @@ static void add_molecule_to_pb_stats_candidates(PackMoleculeId molecule_id,
*/
static void remove_molecule_from_pb_stats_candidates(PackMoleculeId molecule_id,
ClusterGainStats& cluster_gain_stats) {
int molecule_index;
bool found_molecule = false;

//find the molecule index
for (int i = 0; i < cluster_gain_stats.num_feasible_blocks; i++) {
if (cluster_gain_stats.feasible_blocks[i] == molecule_id) {
found_molecule = true;
molecule_index = i;
}
}

//if it is not in the array, return
if (found_molecule == false) {
return;
}

//Otherwise, shift the molecules while removing the specified molecule
for (int j = molecule_index; j < cluster_gain_stats.num_feasible_blocks - 1; j++) {
cluster_gain_stats.feasible_blocks[j] = cluster_gain_stats.feasible_blocks[j + 1];
}
cluster_gain_stats.num_feasible_blocks--;
cluster_gain_stats.feasible_blocks.remove_at_pop_time(molecule_id);
}

/*
Expand Down
32 changes: 21 additions & 11 deletions vpr/src/pack/greedy_candidate_selector.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "vtr_ndmatrix.h"
#include "vtr_vector.h"
#include "vtr_random.h"
#include "lazy_pop_unique_priority_queue.h"

// Forward declarations
class AtomNetlist;
Expand All @@ -33,6 +34,8 @@ struct t_model;
struct t_molecule_stats;
struct t_packer_opts;



/**
* @brief Stats on the gain of a cluster.
*
Expand Down Expand Up @@ -96,13 +99,6 @@ struct ClusterGainStats {
/// with the cluster.
AttractGroupId attraction_grp_id;

/// @brief Array of feasible blocks to select from [0..max_array_size-1]
///
/// Sorted in ascending gain order so that the last cluster_ctx.blocks is
/// the most desirable (this makes it easy to pop blocks off the list.
std::vector<PackMoleculeId> feasible_blocks;
int num_feasible_blocks;

/// @brief The flat placement location of this cluster.
///
/// This is some function of the positions of the molecules which have been
Expand All @@ -125,6 +121,20 @@ struct ClusterGainStats {
/// set when the stats are created based on the primitive pb type
/// of the seed.
bool is_memory = false;

/// @brief List of feasible block and its gain pairs.
/// The list is maintained in heap structure with the highest gain block
/// at the front.
LazyPopUniquePriorityQueue<PackMoleculeId, float> feasible_blocks;

/// @brief Indicator for the initial search for feasible blocks.
bool initial_search_for_feasible_blocks;

/// @brief Limit for the number of pop.
unsigned num_search_for_feasible_blocks_occurred_limit;

/// @brief Counter for the number of pop.
unsigned num_search_for_feasible_blocks_occured;
};

/**
Expand Down Expand Up @@ -441,7 +451,7 @@ class GreedyCandidateSelector {
// Cluster Candidate Selection
// ===================================================================== //

/*
/**
* @brief Add molecules with strong connectedness to the current cluster to
* the list of feasible blocks.
*/
Expand All @@ -468,7 +478,7 @@ class GreedyCandidateSelector {
LegalizationClusterId legalization_cluster_id,
const ClusterLegalizer& cluster_legalizer);

/*
/**
* @brief Add molecules based on transitive connections (eg. 2 hops away)
* with current cluster.
*/
Expand All @@ -478,7 +488,7 @@ class GreedyCandidateSelector {
const ClusterLegalizer& cluster_legalizer,
AttractionInfo& attraction_groups);

/*
/**
* @brief Add molecules based on weak connectedness (connected by high
* fanout nets) with current cluster.
*/
Expand All @@ -488,7 +498,7 @@ class GreedyCandidateSelector {
const ClusterLegalizer& cluster_legalizer,
AttractionInfo& attraction_groups);

/*
/**
* @brief If the current cluster being packed has an attraction group
* associated with it (i.e. there are atoms in it that belong to an
* attraction group), this routine adds molecules from the associated
Expand Down
Loading