Skip to content

Commit 16140e6

Browse files
Rongbo ZhangRonZ13
Rongbo Zhang
authored andcommitted
[packer] Changing the vector of candidate molecules into LazyPopUniquePriorityQueue.
The class LazyPopUniquePriorityQueue is a priority queue that allows for lazy deletion of elements. It is implemented using a vector and 2 sets, one set keeps track of the elements in the queue, and the other set keeps track of the elements that are pending deletion. The queue is sorted by the sort-value(SV) of the elements, and the elements are stored in a vector. The set is used to keep track of the elements that are pending deletion, so that they can be removed from the queue when they are popped. The class definiation can be found in vpr/src/util/lazy_pop_unique_priority_queue.h Currently, the class supports the following functions: LazyPopUniquePriorityQueue::push(): Pushes a key-sort-value (K-SV) pair into the priority queue and adds the key to the tracking set. LazyPopUniquePriorityQueue::pop(): Returns the K-SV pair with the highest SV whose key is not pending deletion. LazyPopUniquePriorityQueue::remove(): Removes an element from the priority queue immediately. LazyPopUniquePriorityQueue::remove_at_pop_time(): Removes an element from the priority queue when it is popped. LazyPopUniquePriorityQueue::empty(): Returns whether the queue is empty. LazyPopUniquePriorityQueue::clear(): Clears the priority queue vector and the tracking sets. LazyPopUniquePriorityQueue::size(): Returns the number of elements in the queue. LazyPopUniquePriorityQueue::contains(): Returns true if the key is in the queue, false otherwise.
1 parent 532bc04 commit 16140e6

File tree

3 files changed

+285
-97
lines changed

3 files changed

+285
-97
lines changed

vpr/src/pack/greedy_candidate_selector.cpp

Lines changed: 45 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ static void add_molecule_to_pb_stats_candidates(
6464
PackMoleculeId molecule_id,
6565
ClusterGainStats& cluster_gain_stats,
6666
t_logical_block_type_ptr cluster_type,
67-
int max_queue_size,
6867
AttractionInfo& attraction_groups,
6968
const Prepacker& prepacker,
7069
const AtomNetlist& atom_netlist,
@@ -219,13 +218,11 @@ ClusterGainStats GreedyCandidateSelector::create_cluster_gain_stats(
219218
// Initialize the cluster gain stats.
220219
ClusterGainStats cluster_gain_stats;
221220
cluster_gain_stats.seed_molecule_id = cluster_seed_mol_id;
222-
cluster_gain_stats.num_feasible_blocks = NOT_VALID;
223221
cluster_gain_stats.has_done_connectivity_and_timing = false;
224-
// TODO: The reason this is being resized and not reserved is due to legacy
225-
// code which should be updated.
226-
cluster_gain_stats.feasible_blocks.resize(packer_opts_.feasible_block_array_size);
227-
for (int i = 0; i < packer_opts_.feasible_block_array_size; i++)
228-
cluster_gain_stats.feasible_blocks[i] = PackMoleculeId::INVALID();
222+
cluster_gain_stats.initial_search_for_feasible_blocks = true;
223+
cluster_gain_stats.num_candidates_proposed = 0;
224+
cluster_gain_stats.candidates_propose_limit = packer_opts_.feasible_block_array_size;
225+
cluster_gain_stats.feasible_blocks.clear();
229226
cluster_gain_stats.tie_break_high_fanout_net = AtomNetId::INVALID();
230227
cluster_gain_stats.explore_transitive_fanout = true;
231228

@@ -288,8 +285,10 @@ void GreedyCandidateSelector::update_cluster_gain_stats_candidate_success(
288285
AttractGroupId atom_grp_id = attraction_groups.get_atom_attraction_group(blk_id);
289286

290287
/* reset list of feasible blocks */
291-
cluster_gain_stats.num_feasible_blocks = NOT_VALID;
292288
cluster_gain_stats.has_done_connectivity_and_timing = false;
289+
cluster_gain_stats.initial_search_for_feasible_blocks = true;
290+
cluster_gain_stats.num_candidates_proposed = 0;
291+
cluster_gain_stats.feasible_blocks.clear();
293292
/* TODO: Allow clusters to have more than one attraction group. */
294293
if (atom_grp_id.is_valid())
295294
cluster_gain_stats.attraction_grp_id = atom_grp_id;
@@ -680,8 +679,8 @@ PackMoleculeId GreedyCandidateSelector::get_next_candidate_for_cluster(
680679
*/
681680

682681
// 1. Find unpacked molecules based on criticality and strong connectedness (connected by low fanout nets) with current cluster
683-
if (cluster_gain_stats.num_feasible_blocks == NOT_VALID) {
684-
cluster_gain_stats.num_feasible_blocks = 0;
682+
if (cluster_gain_stats.initial_search_for_feasible_blocks) {
683+
cluster_gain_stats.initial_search_for_feasible_blocks = false;
685684
add_cluster_molecule_candidates_by_connectivity_and_timing(cluster_gain_stats,
686685
cluster_id,
687686
cluster_legalizer,
@@ -691,31 +690,31 @@ PackMoleculeId GreedyCandidateSelector::get_next_candidate_for_cluster(
691690

692691
if (packer_opts_.prioritize_transitive_connectivity) {
693692
// 2. Find unpacked molecules based on transitive connections (eg. 2 hops away) with current cluster
694-
if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.explore_transitive_fanout) {
693+
if (cluster_gain_stats.feasible_blocks.empty() && cluster_gain_stats.explore_transitive_fanout) {
695694
add_cluster_molecule_candidates_by_transitive_connectivity(cluster_gain_stats,
696695
cluster_id,
697696
cluster_legalizer,
698697
attraction_groups);
699698
}
700699

701700
// 3. Find unpacked molecules based on weak connectedness (connected by high fanout nets) with current cluster
702-
if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.tie_break_high_fanout_net) {
701+
if (cluster_gain_stats.feasible_blocks.empty() && cluster_gain_stats.tie_break_high_fanout_net) {
703702
add_cluster_molecule_candidates_by_highfanout_connectivity(cluster_gain_stats,
704703
cluster_id,
705704
cluster_legalizer,
706705
attraction_groups);
707706
}
708707
} else { //Reverse order
709708
// 3. Find unpacked molecules based on weak connectedness (connected by high fanout nets) with current cluster
710-
if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.tie_break_high_fanout_net) {
709+
if (cluster_gain_stats.feasible_blocks.empty() && cluster_gain_stats.tie_break_high_fanout_net) {
711710
add_cluster_molecule_candidates_by_highfanout_connectivity(cluster_gain_stats,
712711
cluster_id,
713712
cluster_legalizer,
714713
attraction_groups);
715714
}
716715

717716
// 2. Find unpacked molecules based on transitive connections (eg. 2 hops away) with current cluster
718-
if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.explore_transitive_fanout) {
717+
if (cluster_gain_stats.feasible_blocks.empty() && cluster_gain_stats.explore_transitive_fanout) {
719718
add_cluster_molecule_candidates_by_transitive_connectivity(cluster_gain_stats,
720719
cluster_id,
721720
cluster_legalizer,
@@ -724,23 +723,33 @@ PackMoleculeId GreedyCandidateSelector::get_next_candidate_for_cluster(
724723
}
725724

726725
// 4. Find unpacked molecules based on attraction group of the current cluster (if the cluster has an attraction group)
727-
if (cluster_gain_stats.num_feasible_blocks == 0) {
726+
if (cluster_gain_stats.feasible_blocks.empty()) {
728727
add_cluster_molecule_candidates_by_attraction_group(cluster_gain_stats,
729728
cluster_id,
730729
cluster_legalizer,
731730
attraction_groups);
732731
}
733732

734733
/* Grab highest gain molecule */
735-
// If this was a vector, this would just be a pop_back.
736734
PackMoleculeId best_molecule = PackMoleculeId::INVALID();
737-
if (cluster_gain_stats.num_feasible_blocks > 0) {
738-
cluster_gain_stats.num_feasible_blocks--;
739-
int index = cluster_gain_stats.num_feasible_blocks;
740-
best_molecule = cluster_gain_stats.feasible_blocks[index];
735+
// If there are feasible blocks being proposed and the number of suggestions did not reach the limit.
736+
// Get the block with highest gain from the top of the priority queue.
737+
if (!cluster_gain_stats.feasible_blocks.empty() && !cluster_gain_stats.current_stage_candidates_proposed_limit_reached()) {
738+
best_molecule = cluster_gain_stats.feasible_blocks.pop().first;
739+
VTR_ASSERT(best_molecule != PackMoleculeId::INVALID());
740+
cluster_gain_stats.num_candidates_proposed++;
741741
VTR_ASSERT(!cluster_legalizer.is_mol_clustered(best_molecule));
742742
}
743743

744+
// If we have no feasible blocks, or we have reached the limit of number of pops,
745+
// then we need to clear the feasible blocks list and reset the number of pops.
746+
// This ensures that we can continue searching for feasible blocks for the remaining
747+
// steps (2.transitive, 3.high fanout, 4.attraction group).
748+
if (cluster_gain_stats.feasible_blocks.empty() || cluster_gain_stats.current_stage_candidates_proposed_limit_reached()) {
749+
cluster_gain_stats.feasible_blocks.clear();
750+
cluster_gain_stats.num_candidates_proposed = 0;
751+
}
752+
744753
// If we are allowing unrelated clustering and no molecule has been found,
745754
// get unrelated candidate for cluster.
746755
if (allow_unrelated_clustering_ && best_molecule == PackMoleculeId::INVALID()) {
@@ -774,7 +783,9 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_connectivity_an
774783
LegalizationClusterId legalization_cluster_id,
775784
const ClusterLegalizer& cluster_legalizer,
776785
AttractionInfo& attraction_groups) {
777-
cluster_gain_stats.explore_transitive_fanout = true; /* If no legal molecules found, enable exploration of molecules two hops away */
786+
787+
cluster_gain_stats.explore_transitive_fanout = true; /* If no legal molecules found, enable exploration of molecules two hops away */
788+
cluster_gain_stats.candidates_propose_limit = packer_opts_.feasible_block_array_size; // set the limit of candidates to propose
778789

779790
for (AtomBlockId blk_id : cluster_gain_stats.marked_blocks) {
780791
// Get the molecule that contains this block.
@@ -785,7 +796,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_connectivity_an
785796
add_molecule_to_pb_stats_candidates(molecule_id,
786797
cluster_gain_stats,
787798
cluster_legalizer.get_cluster_type(legalization_cluster_id),
788-
packer_opts_.feasible_block_array_size,
789799
attraction_groups,
790800
prepacker_,
791801
atom_netlist_,
@@ -801,6 +811,7 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_transitive_conn
801811
AttractionInfo& attraction_groups) {
802812
//TODO: For now, only done by fan-out; should also consider fan-in
803813
cluster_gain_stats.explore_transitive_fanout = false;
814+
cluster_gain_stats.candidates_propose_limit = std::min(packer_opts_.feasible_block_array_size, AAPACK_MAX_TRANSITIVE_EXPLORE); // set the limit of candidates to propose
804815

805816
/* First time finding transitive fanout candidates therefore alloc and load them */
806817
load_transitive_fanout_candidates(cluster_gain_stats,
@@ -814,8 +825,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_transitive_conn
814825
add_molecule_to_pb_stats_candidates(molecule_id,
815826
cluster_gain_stats,
816827
cluster_legalizer.get_cluster_type(legalization_cluster_id),
817-
std::min(packer_opts_.feasible_block_array_size,
818-
AAPACK_MAX_TRANSITIVE_EXPLORE),
819828
attraction_groups,
820829
prepacker_,
821830
atom_netlist_,
@@ -834,6 +843,7 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_highfanout_conn
834843
* related blocks */
835844

836845
AtomNetId net_id = cluster_gain_stats.tie_break_high_fanout_net;
846+
cluster_gain_stats.candidates_propose_limit = std::min(packer_opts_.feasible_block_array_size, AAPACK_MAX_TRANSITIVE_EXPLORE); // set the limit of candidates to propose
837847

838848
int count = 0;
839849
for (AtomPinId pin_id : atom_netlist_.net_pins(net_id)) {
@@ -848,8 +858,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_highfanout_conn
848858
add_molecule_to_pb_stats_candidates(molecule_id,
849859
cluster_gain_stats,
850860
cluster_legalizer.get_cluster_type(legalization_cluster_id),
851-
std::min(packer_opts_.feasible_block_array_size,
852-
AAPACK_MAX_HIGH_FANOUT_EXPLORE),
853861
attraction_groups,
854862
prepacker_,
855863
atom_netlist_,
@@ -877,6 +885,7 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_attraction_grou
877885
* group molecules for candidate molecules.
878886
*/
879887
AttractGroupId grp_id = cluster_gain_stats.attraction_grp_id;
888+
cluster_gain_stats.candidates_propose_limit = packer_opts_.feasible_block_array_size; // set the limit of candidates to propose
880889
if (grp_id == AttractGroupId::INVALID()) {
881890
return;
882891
}
@@ -909,7 +918,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_attraction_grou
909918
add_molecule_to_pb_stats_candidates(molecule_id,
910919
cluster_gain_stats,
911920
cluster_legalizer.get_cluster_type(legalization_cluster_id),
912-
packer_opts_.feasible_block_array_size,
913921
attraction_groups,
914922
prepacker_,
915923
atom_netlist_,
@@ -931,7 +939,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_attraction_grou
931939
add_molecule_to_pb_stats_candidates(molecule_id,
932940
cluster_gain_stats,
933941
cluster_legalizer.get_cluster_type(legalization_cluster_id),
934-
packer_opts_.feasible_block_array_size,
935942
attraction_groups,
936943
prepacker_,
937944
atom_netlist_,
@@ -946,7 +953,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_attraction_grou
946953
static void add_molecule_to_pb_stats_candidates(PackMoleculeId molecule_id,
947954
ClusterGainStats& cluster_gain_stats,
948955
t_logical_block_type_ptr cluster_type,
949-
int max_queue_size,
950956
AttractionInfo& attraction_groups,
951957
const Prepacker& prepacker,
952958
const AtomNetlist& atom_netlist,
@@ -996,45 +1002,18 @@ static void add_molecule_to_pb_stats_candidates(PackMoleculeId molecule_id,
9961002
}
9971003
}
9981004

999-
for (int i = 0; i < cluster_gain_stats.num_feasible_blocks; i++) {
1000-
if (cluster_gain_stats.feasible_blocks[i] == molecule_id) {
1001-
return; // already in queue, do nothing
1002-
}
1005+
// if already in queue, do nothing
1006+
if (cluster_gain_stats.feasible_blocks.contains(molecule_id)) {
1007+
return;
10031008
}
10041009

1005-
if (cluster_gain_stats.num_feasible_blocks >= max_queue_size - 1) {
1006-
/* maximum size for array, remove smallest gain element and sort */
1007-
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)) {
1008-
/* single loop insertion sort */
1009-
int j;
1010-
for (j = 0; j < cluster_gain_stats.num_feasible_blocks - 1; j++) {
1011-
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)) {
1012-
cluster_gain_stats.feasible_blocks[j] = molecule_id;
1013-
break;
1014-
} else {
1015-
cluster_gain_stats.feasible_blocks[j] = cluster_gain_stats.feasible_blocks[j + 1];
1016-
}
1017-
}
1018-
if (j == cluster_gain_stats.num_feasible_blocks - 1) {
1019-
cluster_gain_stats.feasible_blocks[j] = molecule_id;
1020-
}
1021-
}
1022-
} else {
1023-
/* Expand array and single loop insertion sort */
1024-
int j;
1025-
for (j = cluster_gain_stats.num_feasible_blocks - 1; j >= 0; j--) {
1026-
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)) {
1027-
cluster_gain_stats.feasible_blocks[j + 1] = cluster_gain_stats.feasible_blocks[j];
1028-
} else {
1029-
cluster_gain_stats.feasible_blocks[j + 1] = molecule_id;
1030-
break;
1031-
}
1032-
}
1033-
if (j < 0) {
1034-
cluster_gain_stats.feasible_blocks[0] = molecule_id;
1035-
}
1036-
cluster_gain_stats.num_feasible_blocks++;
1010+
for (std::pair<PackMoleculeId, float>& feasible_block : cluster_gain_stats.feasible_blocks.heap) {
1011+
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);
10371012
}
1013+
1014+
// Insert the molecule into the queue sorted by gain, and maintain the heap property
1015+
float molecule_gain = get_molecule_gain(molecule_id, cluster_gain_stats, cluster_att_grp, attraction_groups, num_molecule_failures, prepacker, atom_netlist, appack_ctx);
1016+
cluster_gain_stats.feasible_blocks.push(molecule_id, molecule_gain);
10381017
}
10391018

10401019
/*
@@ -1045,27 +1024,7 @@ static void add_molecule_to_pb_stats_candidates(PackMoleculeId molecule_id,
10451024
*/
10461025
static void remove_molecule_from_pb_stats_candidates(PackMoleculeId molecule_id,
10471026
ClusterGainStats& cluster_gain_stats) {
1048-
int molecule_index;
1049-
bool found_molecule = false;
1050-
1051-
//find the molecule index
1052-
for (int i = 0; i < cluster_gain_stats.num_feasible_blocks; i++) {
1053-
if (cluster_gain_stats.feasible_blocks[i] == molecule_id) {
1054-
found_molecule = true;
1055-
molecule_index = i;
1056-
}
1057-
}
1058-
1059-
//if it is not in the array, return
1060-
if (found_molecule == false) {
1061-
return;
1062-
}
1063-
1064-
//Otherwise, shift the molecules while removing the specified molecule
1065-
for (int j = molecule_index; j < cluster_gain_stats.num_feasible_blocks - 1; j++) {
1066-
cluster_gain_stats.feasible_blocks[j] = cluster_gain_stats.feasible_blocks[j + 1];
1067-
}
1068-
cluster_gain_stats.num_feasible_blocks--;
1027+
cluster_gain_stats.feasible_blocks.remove_at_pop_time(molecule_id);
10691028
}
10701029

10711030
/*

0 commit comments

Comments
 (0)