From 523368e481ca8779ab3b7d542b000a77c17b9989 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 24 May 2021 10:32:50 -0400 Subject: [PATCH 1/6] Fixed floorplan check process during clustering to reduce pack time. Changes made to atom_cluster_floorplanning_check and related functions --- vpr/src/base/partition_region.cpp | 9 +++++---- vpr/src/base/region.cpp | 6 +++--- vpr/src/base/region.h | 6 +++--- vpr/src/pack/cluster.cpp | 7 ++++--- vpr/src/place/place_constraints.cpp | 7 +++++++ 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/vpr/src/base/partition_region.cpp b/vpr/src/base/partition_region.cpp index 8fe004b8585..3000dadf0e8 100644 --- a/vpr/src/base/partition_region.cpp +++ b/vpr/src/base/partition_region.cpp @@ -34,12 +34,13 @@ PartitionRegion intersection(PartitionRegion& pr1, PartitionRegion& pr2) { */ PartitionRegion pr; Region intersect_region; - bool regions_intersect; + //bool regions_intersect; for (unsigned int i = 0; i < pr1.partition_region.size(); i++) { for (unsigned int j = 0; j < pr2.partition_region.size(); j++) { - regions_intersect = do_regions_intersect(pr1.partition_region[i], pr2.partition_region[j]); - if (regions_intersect) { - intersect_region = intersection(pr1.partition_region[i], pr2.partition_region[j]); + //regions_intersect = do_regions_intersect(pr1.partition_region[i], pr2.partition_region[j]); + intersect_region = intersection(pr1.partition_region[i], pr2.partition_region[j]); + if (!intersect_region.empty()) { + //intersect_region = intersection(pr1.partition_region[i], pr2.partition_region[j]); pr.partition_region.push_back(intersect_region); } } diff --git a/vpr/src/base/region.cpp b/vpr/src/base/region.cpp index 54150ab2cfd..018dcb2c565 100644 --- a/vpr/src/base/region.cpp +++ b/vpr/src/base/region.cpp @@ -14,7 +14,7 @@ Region::Region() { region_bounds.set_ymax(-1); } -vtr::Rect Region::get_region_rect() { +vtr::Rect Region::get_region_rect() const { return region_bounds; } @@ -25,7 +25,7 @@ void Region::set_region_rect(int _xmin, int _ymin, int _xmax, int _ymax) { region_bounds.set_ymax(_ymax); } -int Region::get_sub_tile() { +int Region::get_sub_tile() const { return sub_tile; } @@ -82,7 +82,7 @@ bool do_regions_intersect(Region r1, Region r2) { return intersect; } -Region intersection(Region r1, Region r2) { +Region intersection(const Region& r1, const Region& r2) { Region intersect; /** diff --git a/vpr/src/base/region.h b/vpr/src/base/region.h index 1240f55acbb..89a3f1ec34d 100644 --- a/vpr/src/base/region.h +++ b/vpr/src/base/region.h @@ -23,7 +23,7 @@ class Region { /** * @brief Accessor for the region's rectangle */ - vtr::Rect get_region_rect(); + vtr::Rect get_region_rect() const; /** * @brief Mutator for the region's rectangle @@ -33,7 +33,7 @@ class Region { /** * @brief Accessor for the region's subtile */ - int get_sub_tile(); + int get_sub_tile() const; /** * @brief Mutator for the region's subtile @@ -84,7 +84,7 @@ bool do_regions_intersect(Region r1, Region r2); * @param r2 One of the regions to intersect * */ -Region intersection(Region r1, Region r2); +Region intersection(const Region& r1, const Region& r2); ///@brief Used to print data from a Region void print_region(FILE* fp, Region region); diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index cef6943d0cb..4df698d28d9 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -1726,13 +1726,13 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock PartitionRegion& temp_cluster_pr, bool& cluster_pr_needs_update) { auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); - VprConstraints ctx_constraints = floorplanning_ctx.constraints; + //VprConstraints ctx_constraints = floorplanning_ctx.constraints; /*check if the atom can go in the cluster by checking if the atom and cluster have intersecting PartitionRegions*/ //get partition that atom belongs to PartitionId partid; - partid = ctx_constraints.get_atom_partition(blk_id); + partid = floorplanning_ctx.constraints.get_atom_partition(blk_id); PartitionRegion atom_pr; PartitionRegion cluster_pr; @@ -1748,7 +1748,7 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock return BLK_PASSED; } else { //get pr of that partition - atom_pr = ctx_constraints.get_partition_pr(partid); + atom_pr = floorplanning_ctx.constraints.get_partition_pr(partid); //intersect it with the pr of the current cluster cluster_pr = floorplanning_ctx.cluster_constraints[clb_index]; @@ -1780,6 +1780,7 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock return BLK_PASSED; } } + } /* Revert trial atom block iblock and free up memory space accordingly diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index 0b4da8eb26c..fd7d3f02a75 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -11,6 +11,9 @@ #include "globals.h" #include "place_constraints.h" +/// @brief sentinel value for indicating that a subtile has not been specified +constexpr int NO_SUBTILE = -1; + /*checks that each block's location is compatible with its floorplanning constraints if it has any*/ int check_placement_floorplanning() { int error = 0; @@ -114,6 +117,10 @@ PartitionRegion constrained_macro_locs(const t_pl_macro& pl_macro) { } /*returns true if location is compatible with floorplanning constraints, false if not*/ +/* + * Even if the block passed in is from a macro, it will work because of the constraints + * propagation that was done during initial placement. + */ bool cluster_floorplanning_legal(ClusterBlockId blk_id, const t_pl_loc& loc) { auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); From ea4e6dff2db31359324e859356c246ac4a5caab9 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Wed, 26 May 2021 20:55:42 -0400 Subject: [PATCH 2/6] Optimized floorplan constraint related functions in cluster.cpp to reduce pack time --- vpr/src/base/partition_region.cpp | 11 ++++------- vpr/src/base/partition_region.h | 2 +- vpr/src/pack/cluster.cpp | 4 ---- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/vpr/src/base/partition_region.cpp b/vpr/src/base/partition_region.cpp index 3000dadf0e8..8c49d3c3b4f 100644 --- a/vpr/src/base/partition_region.cpp +++ b/vpr/src/base/partition_region.cpp @@ -26,7 +26,7 @@ bool PartitionRegion::is_loc_in_part_reg(t_pl_loc loc) { return is_in_pr; } -PartitionRegion intersection(PartitionRegion& pr1, PartitionRegion& pr2) { +PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionRegion& new_pr) { /**for N regions in part_region and M in the calling object you can get anywhere from * 0 to M*N regions in the resulting vector. Only intersection regions with non-zero area rectangles and * equivalent subtiles are put in the resulting vector @@ -34,13 +34,10 @@ PartitionRegion intersection(PartitionRegion& pr1, PartitionRegion& pr2) { */ PartitionRegion pr; Region intersect_region; - //bool regions_intersect; - for (unsigned int i = 0; i < pr1.partition_region.size(); i++) { - for (unsigned int j = 0; j < pr2.partition_region.size(); j++) { - //regions_intersect = do_regions_intersect(pr1.partition_region[i], pr2.partition_region[j]); - intersect_region = intersection(pr1.partition_region[i], pr2.partition_region[j]); + for (unsigned int i = 0; i < cluster_pr.partition_region.size(); i++) { + for (unsigned int j = 0; j < new_pr.partition_region.size(); j++) { + intersect_region = intersection(cluster_pr.partition_region[i], new_pr.partition_region[j]); if (!intersect_region.empty()) { - //intersect_region = intersection(pr1.partition_region[i], pr2.partition_region[j]); pr.partition_region.push_back(intersect_region); } } diff --git a/vpr/src/base/partition_region.h b/vpr/src/base/partition_region.h index 25aa4949c31..77b98575e00 100644 --- a/vpr/src/base/partition_region.h +++ b/vpr/src/base/partition_region.h @@ -46,7 +46,7 @@ class PartitionRegion { * @param pr1 One of the PartitionRegions to be intersected * @param pr2 One of the PartitionRegions to be intersected */ - friend PartitionRegion intersection(PartitionRegion& pr1, PartitionRegion& pr2); + friend PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionRegion& new_pr); private: std::vector partition_region; ///< union of rectangular regions that a partition can be placed in diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index 4df698d28d9..9b2ebe7e6b1 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -1726,7 +1726,6 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock PartitionRegion& temp_cluster_pr, bool& cluster_pr_needs_update) { auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); - //VprConstraints ctx_constraints = floorplanning_ctx.constraints; /*check if the atom can go in the cluster by checking if the atom and cluster have intersecting PartitionRegions*/ @@ -1780,7 +1779,6 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock return BLK_PASSED; } } - } /* Revert trial atom block iblock and free up memory space accordingly @@ -2230,8 +2228,6 @@ static void start_new_cluster(t_cluster_placement_stats* cluster_placement_stats auto& device_ctx = g_vpr_ctx.mutable_device(); auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); - VprConstraints ctx_constraints = floorplanning_ctx.constraints; - /*Cluster's PartitionRegion is empty initially, meaning it has no floorplanning constraints*/ PartitionRegion empty_pr; floorplanning_ctx.cluster_constraints.push_back(empty_pr); From b07b9de8011ee2c9d4033e2b0072807de9551c93 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Thu, 27 May 2021 12:38:49 -0400 Subject: [PATCH 3/6] Modified check for if region is empty. --- vpr/src/base/region.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vpr/src/base/region.cpp b/vpr/src/base/region.cpp index 018dcb2c565..4a06d906d31 100644 --- a/vpr/src/base/region.cpp +++ b/vpr/src/base/region.cpp @@ -38,7 +38,8 @@ bool Region::locked() { } bool Region::empty() { - return region_bounds.empty(); + //return region_bounds.empty(); + return region_bounds.xmax() < region_bounds.xmin() || region_bounds.ymax() < region_bounds.ymin(); } bool Region::is_loc_in_reg(t_pl_loc loc) { From 9d4ed2efdfc22d6704135a289f37360cf2ee64b5 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 31 May 2021 12:01:13 -0400 Subject: [PATCH 4/6] Moved the declaration for the NO_SUBTILE constant to region.h, and included that file in any file which uses NO_SUBTILE --- vpr/src/base/gen/vpr_constraints_uxsdcxx.h | 4 +--- vpr/src/base/region.cpp | 3 --- vpr/src/base/region.h | 3 +++ vpr/src/place/place_constraints.cpp | 3 --- vpr/src/place/place_constraints.h | 1 + 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h index f2cd1bf64c4..4983c68486c 100644 --- a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h +++ b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h @@ -25,9 +25,7 @@ #include "pugixml.hpp" #include "vpr_constraints_uxsdcxx_interface.h" - -//sentinel value for indicating that a subtile has not been specified -constexpr int NO_SUBTILE = -1; +#include "region.h" /* All uxsdcxx functions and structs live in this namespace. */ namespace uxsd { diff --git a/vpr/src/base/region.cpp b/vpr/src/base/region.cpp index 4a06d906d31..bad7608de26 100644 --- a/vpr/src/base/region.cpp +++ b/vpr/src/base/region.cpp @@ -1,8 +1,5 @@ #include "region.h" -/// @brief sentinel value for indicating that a subtile has not been specified -constexpr int NO_SUBTILE = -1; - Region::Region() { sub_tile = NO_SUBTILE; diff --git a/vpr/src/base/region.h b/vpr/src/base/region.h index 89a3f1ec34d..9069ba180f6 100644 --- a/vpr/src/base/region.h +++ b/vpr/src/base/region.h @@ -13,6 +13,9 @@ * */ +/// @brief sentinel value for indicating that a subtile has not been specified +constexpr int NO_SUBTILE = -1; + class Region { public: /** diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index fd7d3f02a75..c827d8047f2 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -11,9 +11,6 @@ #include "globals.h" #include "place_constraints.h" -/// @brief sentinel value for indicating that a subtile has not been specified -constexpr int NO_SUBTILE = -1; - /*checks that each block's location is compatible with its floorplanning constraints if it has any*/ int check_placement_floorplanning() { int error = 0; diff --git a/vpr/src/place/place_constraints.h b/vpr/src/place/place_constraints.h index 90ea1e03be1..2d29d230052 100644 --- a/vpr/src/place/place_constraints.h +++ b/vpr/src/place/place_constraints.h @@ -6,6 +6,7 @@ * Author: khalid88 */ #include "move_transactions.h" +#include "region.h" #ifndef VPR_SRC_PLACE_PLACE_CONSTRAINTS_H_ # define VPR_SRC_PLACE_PLACE_CONSTRAINTS_H_ From 3a86fac3a9cb48506ce2d31594dacd12497b5c28 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 31 May 2021 14:33:02 -0400 Subject: [PATCH 5/6] Added function to directly update a cluster's PartitionRegion that is passed in, rather than returning a new PartitionRegion. This function is a more efficient version of the PartitionRegion intersection function, and is now used during the atom floorplanning checks that happen during clustering --- vpr/src/base/partition_region.cpp | 18 ++++++++++++++++++ vpr/src/base/partition_region.h | 18 ++++++++++++++++-- vpr/src/pack/cluster.cpp | 9 +++++---- vpr/src/place/place_constraints.h | 1 - 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/vpr/src/base/partition_region.cpp b/vpr/src/base/partition_region.cpp index 8c49d3c3b4f..d06bfa37240 100644 --- a/vpr/src/base/partition_region.cpp +++ b/vpr/src/base/partition_region.cpp @@ -9,6 +9,10 @@ std::vector PartitionRegion::get_partition_region() { return partition_region; } +void PartitionRegion::set_partition_region(std::vector pr) { + partition_region = pr; +} + bool PartitionRegion::empty() { return partition_region.size() == 0; } @@ -46,6 +50,20 @@ PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionR return pr; } +void update_cluster_part_reg(PartitionRegion& cluster_pr, const PartitionRegion& new_pr) { + Region intersect_region; + std::vector int_regions; + for (unsigned int i = 0; i < cluster_pr.partition_region.size(); i++) { + for (unsigned int j = 0; j < new_pr.partition_region.size(); j++) { + intersect_region = intersection(cluster_pr.partition_region[i], new_pr.partition_region[j]); + if (!intersect_region.empty()) { + int_regions.push_back(intersect_region); + } + } + } + cluster_pr.set_partition_region(int_regions); +} + void print_partition_region(FILE* fp, PartitionRegion pr) { std::vector part_region = pr.get_partition_region(); diff --git a/vpr/src/base/partition_region.h b/vpr/src/base/partition_region.h index 77b98575e00..799a530cbdc 100644 --- a/vpr/src/base/partition_region.h +++ b/vpr/src/base/partition_region.h @@ -27,6 +27,11 @@ class PartitionRegion { */ std::vector get_partition_region(); + /** + * @brief Set the union of regions + */ + void set_partition_region(std::vector pr); + /** * @brief Check if the PartitionRegion is empty (meaning there is no constraint on the object the PartitionRegion belongs to) */ @@ -43,11 +48,20 @@ class PartitionRegion { /** * @brief Global friend function that returns the intersection of two PartitionRegions * - * @param pr1 One of the PartitionRegions to be intersected - * @param pr2 One of the PartitionRegions to be intersected + * @param cluster_pr One of the PartitionRegions to be intersected + * @param new_pr One of the PartitionRegions to be intersected */ friend PartitionRegion intersection(const PartitionRegion& cluster_pr, const PartitionRegion& new_pr); + /** + * @brief Global friend function that updates the PartitionRegion of a cluster with the intersection + * of the cluster PartitionRegion and a new PartitionRegion + * + * @param cluster_pr The cluster PartitionRegion that is to be updated + * @param new_pr The new PartitionRegion that the cluster PartitionRegion will be intersected with + */ + friend void update_cluster_part_reg(PartitionRegion& cluster_pr, const PartitionRegion& new_pr); + private: std::vector partition_region; ///< union of rectangular regions that a partition can be placed in }; diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index 9b2ebe7e6b1..e8a26d590a1 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -1735,7 +1735,6 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock PartitionRegion atom_pr; PartitionRegion cluster_pr; - PartitionRegion intersect_pr; //if the atom does not belong to a partition, it can be put in the cluster //regardless of what the cluster's PartitionRegion is because it has no constraints @@ -1760,10 +1759,12 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock } return BLK_PASSED; } else { - intersect_pr = intersection(cluster_pr, atom_pr); + //update cluster_pr with the intersection of the cluster's PartitionRegion + //and the atom's PartitionRegion + update_cluster_part_reg(cluster_pr, atom_pr); } - if (intersect_pr.empty() == true) { + if (cluster_pr.empty() == true) { if (verbosity > 3) { VTR_LOG("\t\t\t Intersect: Atom block %d failed floorplanning check for cluster %d \n", blk_id, clb_index); } @@ -1771,7 +1772,7 @@ static enum e_block_pack_status atom_cluster_floorplanning_check(const AtomBlock return BLK_FAILED_FLOORPLANNING; } else { //update the cluster's PartitionRegion with the intersecting PartitionRegion - temp_cluster_pr = intersect_pr; + temp_cluster_pr = cluster_pr; cluster_pr_needs_update = true; if (verbosity > 3) { VTR_LOG("\t\t\t Intersect: Atom block %d passed cluster %d, cluster PR was updated with intersection result \n", blk_id, clb_index); diff --git a/vpr/src/place/place_constraints.h b/vpr/src/place/place_constraints.h index 26c7919b791..b9121ebdcd7 100644 --- a/vpr/src/place/place_constraints.h +++ b/vpr/src/place/place_constraints.h @@ -9,7 +9,6 @@ #include "region.h" #include "clustered_netlist_utils.h" - #ifndef VPR_SRC_PLACE_PLACE_CONSTRAINTS_H_ # define VPR_SRC_PLACE_PLACE_CONSTRAINTS_H_ From 8c6dc01d9c7f8b03475f06b1c28e8540035e80d6 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 31 May 2021 17:27:14 -0400 Subject: [PATCH 6/6] Took out a change that was previously made to the empty member function of the Region class. This change was causing the vpr unit test to fail, and so it will be moved to another pull request where the unit test will also be updated accordingly with the change. The change is not necessary on this pull request --- vpr/src/base/region.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vpr/src/base/region.cpp b/vpr/src/base/region.cpp index bad7608de26..2035a57e717 100644 --- a/vpr/src/base/region.cpp +++ b/vpr/src/base/region.cpp @@ -35,8 +35,7 @@ bool Region::locked() { } bool Region::empty() { - //return region_bounds.empty(); - return region_bounds.xmax() < region_bounds.xmin() || region_bounds.ymax() < region_bounds.ymin(); + return region_bounds.empty(); } bool Region::is_loc_in_reg(t_pl_loc loc) {