Skip to content

Floorplan constraints tuning #1741

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

Merged
merged 9 commits into from
Jun 1, 2021
4 changes: 1 addition & 3 deletions vpr/src/base/gen/vpr_constraints_uxsdcxx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
30 changes: 23 additions & 7 deletions vpr/src/base/partition_region.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ std::vector<Region> PartitionRegion::get_partition_region() {
return partition_region;
}

void PartitionRegion::set_partition_region(std::vector<Region> pr) {
partition_region = pr;
}

bool PartitionRegion::empty() {
return partition_region.size() == 0;
}
Expand All @@ -26,20 +30,18 @@ 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
* Rectangles are not merged even if it would be possible
*/
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]);
if (regions_intersect) {
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()) {
pr.partition_region.push_back(intersect_region);
}
}
Expand All @@ -48,6 +50,20 @@ PartitionRegion intersection(PartitionRegion& pr1, PartitionRegion& pr2) {
return pr;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's talk about this in our meeting this week. I can merge this to get it going, but this update_cluster_part_reg has a few problems:

  1. name is overly specific; this is an "in-place" intersection, rather than having anything to do with clustering specifically. We should at least change the name to reflect what the routine does, rather than who calls it right now.
  2. As written it is probably not faster than the other intersection routine, since it still creates a new partition_region and assigns it to the cluster_pr. So if the other routine is leading to a negligible cluster time increase we can delete this one. I know I requested an in-place version for speed, but looking at this I don't think it is "in place" enough to be faster.

void update_cluster_part_reg(PartitionRegion& cluster_pr, const PartitionRegion& new_pr) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just delete this one and keep the original

Region intersect_region;
std::vector<Region> 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<Region> part_region = pr.get_partition_region();

Expand Down
20 changes: 17 additions & 3 deletions vpr/src/base/partition_region.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ class PartitionRegion {
*/
std::vector<Region> get_partition_region();

/**
* @brief Set the union of regions
*/
void set_partition_region(std::vector<Region> pr);

/**
* @brief Check if the PartitionRegion is empty (meaning there is no constraint on the object the PartitionRegion belongs to)
*/
Expand All @@ -43,10 +48,19 @@ 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 PartitionRegion intersection(PartitionRegion& pr1, PartitionRegion& pr2);
friend void update_cluster_part_reg(PartitionRegion& cluster_pr, const PartitionRegion& new_pr);

private:
std::vector<Region> partition_region; ///< union of rectangular regions that a partition can be placed in
Expand Down
9 changes: 3 additions & 6 deletions vpr/src/base/region.cpp
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -14,7 +11,7 @@ Region::Region() {
region_bounds.set_ymax(-1);
}

vtr::Rect<int> Region::get_region_rect() {
vtr::Rect<int> Region::get_region_rect() const {
return region_bounds;
}

Expand All @@ -25,7 +22,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;
}

Expand Down Expand Up @@ -82,7 +79,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;

/**
Expand Down
9 changes: 6 additions & 3 deletions vpr/src/base/region.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
*
*/

/// @brief sentinel value for indicating that a subtile has not been specified
constexpr int NO_SUBTILE = -1;

class Region {
public:
/**
Expand All @@ -23,7 +26,7 @@ class Region {
/**
* @brief Accessor for the region's rectangle
*/
vtr::Rect<int> get_region_rect();
vtr::Rect<int> get_region_rect() const;

/**
* @brief Mutator for the region's rectangle
Expand All @@ -33,7 +36,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
Expand Down Expand Up @@ -84,7 +87,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);
Expand Down
16 changes: 7 additions & 9 deletions vpr/src/pack/cluster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1726,17 +1726,15 @@ 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*/

//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;
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
Expand All @@ -1748,7 +1746,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];
Expand All @@ -1761,18 +1759,20 @@ 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);
}
cluster_pr_needs_update = false;
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);
Expand Down Expand Up @@ -2229,8 +2229,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);
Expand Down
4 changes: 4 additions & 0 deletions vpr/src/place/place_constraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,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();

Expand Down
1 change: 1 addition & 0 deletions vpr/src/place/place_constraints.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* Author: khalid88
*/
#include "move_transactions.h"
#include "region.h"
#include "clustered_netlist_utils.h"

#ifndef VPR_SRC_PLACE_PLACE_CONSTRAINTS_H_
Expand Down