Skip to content

Commit 81a73cd

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 c60f967 commit 81a73cd

File tree

3 files changed

+285
-97
lines changed

3 files changed

+285
-97
lines changed

vpr/src/pack/greedy_candidate_selector.cpp

+45-86
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;
@@ -684,8 +683,8 @@ PackMoleculeId GreedyCandidateSelector::get_next_candidate_for_cluster(
684683
*/
685684

686685
// 1. Find unpacked molecules based on criticality and strong connectedness (connected by low fanout nets) with current cluster
687-
if (cluster_gain_stats.num_feasible_blocks == NOT_VALID) {
688-
cluster_gain_stats.num_feasible_blocks = 0;
686+
if (cluster_gain_stats.initial_search_for_feasible_blocks) {
687+
cluster_gain_stats.initial_search_for_feasible_blocks = false;
689688
add_cluster_molecule_candidates_by_connectivity_and_timing(cluster_gain_stats,
690689
cluster_id,
691690
cluster_legalizer,
@@ -695,31 +694,31 @@ PackMoleculeId GreedyCandidateSelector::get_next_candidate_for_cluster(
695694

696695
if (packer_opts_.prioritize_transitive_connectivity) {
697696
// 2. Find unpacked molecules based on transitive connections (eg. 2 hops away) with current cluster
698-
if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.explore_transitive_fanout) {
697+
if (cluster_gain_stats.feasible_blocks.empty() && cluster_gain_stats.explore_transitive_fanout) {
699698
add_cluster_molecule_candidates_by_transitive_connectivity(cluster_gain_stats,
700699
cluster_id,
701700
cluster_legalizer,
702701
attraction_groups);
703702
}
704703

705704
// 3. Find unpacked molecules based on weak connectedness (connected by high fanout nets) with current cluster
706-
if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.tie_break_high_fanout_net) {
705+
if (cluster_gain_stats.feasible_blocks.empty() && cluster_gain_stats.tie_break_high_fanout_net) {
707706
add_cluster_molecule_candidates_by_highfanout_connectivity(cluster_gain_stats,
708707
cluster_id,
709708
cluster_legalizer,
710709
attraction_groups);
711710
}
712711
} else { //Reverse order
713712
// 3. Find unpacked molecules based on weak connectedness (connected by high fanout nets) with current cluster
714-
if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.tie_break_high_fanout_net) {
713+
if (cluster_gain_stats.feasible_blocks.empty() && cluster_gain_stats.tie_break_high_fanout_net) {
715714
add_cluster_molecule_candidates_by_highfanout_connectivity(cluster_gain_stats,
716715
cluster_id,
717716
cluster_legalizer,
718717
attraction_groups);
719718
}
720719

721720
// 2. Find unpacked molecules based on transitive connections (eg. 2 hops away) with current cluster
722-
if (cluster_gain_stats.num_feasible_blocks == 0 && cluster_gain_stats.explore_transitive_fanout) {
721+
if (cluster_gain_stats.feasible_blocks.empty() && cluster_gain_stats.explore_transitive_fanout) {
723722
add_cluster_molecule_candidates_by_transitive_connectivity(cluster_gain_stats,
724723
cluster_id,
725724
cluster_legalizer,
@@ -728,23 +727,33 @@ PackMoleculeId GreedyCandidateSelector::get_next_candidate_for_cluster(
728727
}
729728

730729
// 4. Find unpacked molecules based on attraction group of the current cluster (if the cluster has an attraction group)
731-
if (cluster_gain_stats.num_feasible_blocks == 0) {
730+
if (cluster_gain_stats.feasible_blocks.empty()) {
732731
add_cluster_molecule_candidates_by_attraction_group(cluster_gain_stats,
733732
cluster_id,
734733
cluster_legalizer,
735734
attraction_groups);
736735
}
737736

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

748+
// If we have no feasible blocks, or we have reached the limit of number of pops,
749+
// then we need to clear the feasible blocks list and reset the number of pops.
750+
// This ensures that we can continue searching for feasible blocks for the remaining
751+
// steps (2.transitive, 3.high fanout, 4.attraction group).
752+
if (cluster_gain_stats.feasible_blocks.empty() || cluster_gain_stats.current_stage_candidates_proposed_limit_reached()) {
753+
cluster_gain_stats.feasible_blocks.clear();
754+
cluster_gain_stats.num_candidates_proposed = 0;
755+
}
756+
748757
// If we are allowing unrelated clustering and no molecule has been found,
749758
// get unrelated candidate for cluster.
750759
if (allow_unrelated_clustering_ && best_molecule == PackMoleculeId::INVALID()) {
@@ -778,7 +787,9 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_connectivity_an
778787
LegalizationClusterId legalization_cluster_id,
779788
const ClusterLegalizer& cluster_legalizer,
780789
AttractionInfo& attraction_groups) {
781-
cluster_gain_stats.explore_transitive_fanout = true; /* If no legal molecules found, enable exploration of molecules two hops away */
790+
791+
cluster_gain_stats.explore_transitive_fanout = true; /* If no legal molecules found, enable exploration of molecules two hops away */
792+
cluster_gain_stats.candidates_propose_limit = packer_opts_.feasible_block_array_size; // set the limit of candidates to propose
782793

783794
for (AtomBlockId blk_id : cluster_gain_stats.marked_blocks) {
784795
// Get the molecule that contains this block.
@@ -789,7 +800,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_connectivity_an
789800
add_molecule_to_pb_stats_candidates(molecule_id,
790801
cluster_gain_stats,
791802
cluster_legalizer.get_cluster_type(legalization_cluster_id),
792-
packer_opts_.feasible_block_array_size,
793803
attraction_groups,
794804
prepacker_,
795805
atom_netlist_,
@@ -805,6 +815,7 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_transitive_conn
805815
AttractionInfo& attraction_groups) {
806816
//TODO: For now, only done by fan-out; should also consider fan-in
807817
cluster_gain_stats.explore_transitive_fanout = false;
818+
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
808819

809820
/* First time finding transitive fanout candidates therefore alloc and load them */
810821
load_transitive_fanout_candidates(cluster_gain_stats,
@@ -818,8 +829,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_transitive_conn
818829
add_molecule_to_pb_stats_candidates(molecule_id,
819830
cluster_gain_stats,
820831
cluster_legalizer.get_cluster_type(legalization_cluster_id),
821-
std::min(packer_opts_.feasible_block_array_size,
822-
AAPACK_MAX_TRANSITIVE_EXPLORE),
823832
attraction_groups,
824833
prepacker_,
825834
atom_netlist_,
@@ -838,6 +847,7 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_highfanout_conn
838847
* related blocks */
839848

840849
AtomNetId net_id = cluster_gain_stats.tie_break_high_fanout_net;
850+
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
841851

842852
int count = 0;
843853
for (AtomPinId pin_id : atom_netlist_.net_pins(net_id)) {
@@ -852,8 +862,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_highfanout_conn
852862
add_molecule_to_pb_stats_candidates(molecule_id,
853863
cluster_gain_stats,
854864
cluster_legalizer.get_cluster_type(legalization_cluster_id),
855-
std::min(packer_opts_.feasible_block_array_size,
856-
AAPACK_MAX_HIGH_FANOUT_EXPLORE),
857865
attraction_groups,
858866
prepacker_,
859867
atom_netlist_,
@@ -881,6 +889,7 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_attraction_grou
881889
* group molecules for candidate molecules.
882890
*/
883891
AttractGroupId grp_id = cluster_gain_stats.attraction_grp_id;
892+
cluster_gain_stats.candidates_propose_limit = packer_opts_.feasible_block_array_size; // set the limit of candidates to propose
884893
if (grp_id == AttractGroupId::INVALID()) {
885894
return;
886895
}
@@ -913,7 +922,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_attraction_grou
913922
add_molecule_to_pb_stats_candidates(molecule_id,
914923
cluster_gain_stats,
915924
cluster_legalizer.get_cluster_type(legalization_cluster_id),
916-
packer_opts_.feasible_block_array_size,
917925
attraction_groups,
918926
prepacker_,
919927
atom_netlist_,
@@ -935,7 +943,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_attraction_grou
935943
add_molecule_to_pb_stats_candidates(molecule_id,
936944
cluster_gain_stats,
937945
cluster_legalizer.get_cluster_type(legalization_cluster_id),
938-
packer_opts_.feasible_block_array_size,
939946
attraction_groups,
940947
prepacker_,
941948
atom_netlist_,
@@ -950,7 +957,6 @@ void GreedyCandidateSelector::add_cluster_molecule_candidates_by_attraction_grou
950957
static void add_molecule_to_pb_stats_candidates(PackMoleculeId molecule_id,
951958
ClusterGainStats& cluster_gain_stats,
952959
t_logical_block_type_ptr cluster_type,
953-
int max_queue_size,
954960
AttractionInfo& attraction_groups,
955961
const Prepacker& prepacker,
956962
const AtomNetlist& atom_netlist,
@@ -1004,45 +1010,18 @@ static void add_molecule_to_pb_stats_candidates(PackMoleculeId molecule_id,
10041010
}
10051011
}
10061012

1007-
for (int i = 0; i < cluster_gain_stats.num_feasible_blocks; i++) {
1008-
if (cluster_gain_stats.feasible_blocks[i] == molecule_id) {
1009-
return; // already in queue, do nothing
1010-
}
1013+
// if already in queue, do nothing
1014+
if (cluster_gain_stats.feasible_blocks.contains(molecule_id)) {
1015+
return;
10111016
}
10121017

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

10481027
/*
@@ -1053,27 +1032,7 @@ static void add_molecule_to_pb_stats_candidates(PackMoleculeId molecule_id,
10531032
*/
10541033
static void remove_molecule_from_pb_stats_candidates(PackMoleculeId molecule_id,
10551034
ClusterGainStats& cluster_gain_stats) {
1056-
int molecule_index;
1057-
bool found_molecule = false;
1058-
1059-
//find the molecule index
1060-
for (int i = 0; i < cluster_gain_stats.num_feasible_blocks; i++) {
1061-
if (cluster_gain_stats.feasible_blocks[i] == molecule_id) {
1062-
found_molecule = true;
1063-
molecule_index = i;
1064-
}
1065-
}
1066-
1067-
//if it is not in the array, return
1068-
if (found_molecule == false) {
1069-
return;
1070-
}
1071-
1072-
//Otherwise, shift the molecules while removing the specified molecule
1073-
for (int j = molecule_index; j < cluster_gain_stats.num_feasible_blocks - 1; j++) {
1074-
cluster_gain_stats.feasible_blocks[j] = cluster_gain_stats.feasible_blocks[j + 1];
1075-
}
1076-
cluster_gain_stats.num_feasible_blocks--;
1035+
cluster_gain_stats.feasible_blocks.remove_at_pop_time(molecule_id);
10771036
}
10781037

10791038
/*

0 commit comments

Comments
 (0)