From 7f86bba0598733496507b46ad609e023da6e0de3 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 31 May 2021 21:12:09 -0400 Subject: [PATCH 01/12] Add constraints propogation to update the PartitionRegions of blocks in macros at the start of initial placement --- vpr/src/place/initial_placement.cpp | 16 ++++++++-------- vpr/src/place/place_constraints.cpp | 17 +++++++++++++++++ vpr/src/place/place_constraints.h | 2 ++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/vpr/src/place/initial_placement.cpp b/vpr/src/place/initial_placement.cpp index 45784d6e698..07806d9022d 100644 --- a/vpr/src/place/initial_placement.cpp +++ b/vpr/src/place/initial_placement.cpp @@ -82,20 +82,17 @@ static int check_macro_can_be_placed(t_pl_macro pl_macro, int itype, t_pl_loc he // Every macro can be placed until proven otherwise int macro_can_be_placed = true; + //Check whether head macro is in appropriate floorplan region + //return true if macro_can_be_placed = yes, false if no bool macro_constrained = is_macro_constrained(pl_macro); - PartitionRegion macro_pr; - - if (macro_constrained) { - macro_pr = constrained_macro_locs(pl_macro); - } // Check whether all the members can be placed for (size_t imember = 0; imember < pl_macro.members.size(); imember++) { t_pl_loc member_pos = head_pos + pl_macro.members[imember].offset; - //if the macro is constrained, check if the member position is within the PartitionRegion for the macro - if (macro_constrained) { - bool member_loc_good = macro_pr.is_loc_in_part_reg(member_pos); + //if the macro is constrained, check if the head position is within the PartitionRegion for the macro + if (macro_constrained && imember == 0) { + bool member_loc_good = cluster_floorplanning_legal(pl_macro.members[imember].blk_index, member_pos); if (!member_loc_good) { macro_can_be_placed = false; break; @@ -417,6 +414,9 @@ void initial_placement(enum e_pad_loc_type pad_loc_type, const char* constraints vtr::vector block_scores = assign_block_scores(); std::vector sorted_blocks = sort_blocks(block_scores); + //Perform constraints_propagation + constraints_propagation(); + // Loading legal placement locations zero_initialize_grid_blocks(); alloc_and_load_legal_placement_locations(legal_pos); diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index e17c78f2111..a8a046886d6 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -113,6 +113,23 @@ PartitionRegion constrained_macro_locs(const t_pl_macro& pl_macro) { return macro_pr; } +void constraints_propagation() { + auto& place_ctx = g_vpr_ctx.placement(); + auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); + + for (auto pl_macro : place_ctx.pl_macros) { + if (is_macro_constrained(pl_macro)) { + //Update the PartitionRegions of all the clusters in the macro + PartitionRegion macro_pr = constrained_macro_locs(pl_macro); + + for (size_t imember = 0; imember < pl_macro.members.size(); imember++) { + ClusterBlockId blk_id = pl_macro.members[imember].blk_index; + floorplanning_ctx.cluster_constraints[blk_id] = macro_pr; + } + } + } +} + /*returns true if location is compatible with floorplanning constraints, false if not*/ bool cluster_floorplanning_legal(ClusterBlockId blk_id, const t_pl_loc& loc) { auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); diff --git a/vpr/src/place/place_constraints.h b/vpr/src/place/place_constraints.h index 14da580c87f..1230192a3a6 100644 --- a/vpr/src/place/place_constraints.h +++ b/vpr/src/place/place_constraints.h @@ -37,6 +37,8 @@ bool is_macro_constrained(const t_pl_macro& pl_macro); */ PartitionRegion constrained_macro_locs(const t_pl_macro& pl_macro); +void constraints_propagation(); + inline bool floorplan_legal(const t_pl_blocks_to_be_moved& blocks_affected) { bool floorplan_legal; From 5b085c3bfdc664466eb2c481b5aeac6f64f9408b Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Wed, 2 Jun 2021 10:31:25 -0400 Subject: [PATCH 02/12] Added some comments for clarity and refactored constraints_propagation to only update PartitionRegion of head macro --- vpr/src/place/initial_placement.cpp | 11 ++++++++--- vpr/src/place/place_constraints.cpp | 20 +++++++++++--------- vpr/src/place/place_constraints.h | 2 +- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/vpr/src/place/initial_placement.cpp b/vpr/src/place/initial_placement.cpp index 07806d9022d..6f9cf89a29a 100644 --- a/vpr/src/place/initial_placement.cpp +++ b/vpr/src/place/initial_placement.cpp @@ -82,15 +82,20 @@ static int check_macro_can_be_placed(t_pl_macro pl_macro, int itype, t_pl_loc he // Every macro can be placed until proven otherwise int macro_can_be_placed = true; - //Check whether head macro is in appropriate floorplan region - //return true if macro_can_be_placed = yes, false if no + //Check whether macro contains blocks with floorplan constraints bool macro_constrained = is_macro_constrained(pl_macro); // Check whether all the members can be placed for (size_t imember = 0; imember < pl_macro.members.size(); imember++) { t_pl_loc member_pos = head_pos + pl_macro.members[imember].offset; - //if the macro is constrained, check if the head position is within the PartitionRegion for the macro + /* + * If the macro is constrained, check that the head member is in a legal position from + * a floorplanning perspective. It is enough to do this check for the head member alone, + * because constraints propagation was performed to calculate smallest floorplan region for the head + * macro, based on the constraints on all of the blocks in the macro. So, if the head macro is in a + * legal floorplan location, all other blocks in the macro will be as well. + */ if (macro_constrained && imember == 0) { bool member_loc_good = cluster_floorplanning_legal(pl_macro.members[imember].blk_index, member_pos); if (!member_loc_good) { diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index 76191cc6012..e0c387cebe4 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -54,7 +54,7 @@ bool is_macro_constrained(const t_pl_macro& pl_macro) { } /*Returns PartitionRegion of where the head of the macro could go*/ -PartitionRegion constrained_macro_locs(const t_pl_macro& pl_macro) { +PartitionRegion update_macro_pr(const t_pl_macro& pl_macro) { PartitionRegion macro_pr; bool is_member_constrained = false; int num_constrained_members = 0; @@ -90,7 +90,7 @@ PartitionRegion constrained_macro_locs(const t_pl_macro& pl_macro) { modified_reg.set_region_rect(modified_min_pl_loc.x, modified_min_pl_loc.y, modified_max_pl_loc.x, modified_max_pl_loc.y); //check that subtile is not an invalid value before changing, otherwise it just stays -1 - if (block_regions[i].get_sub_tile() != -1) { + if (block_regions[i].get_sub_tile() != NO_SUBTILE) { modified_reg.set_sub_tile(modified_min_pl_loc.sub_tile); } @@ -119,13 +119,15 @@ void constraints_propagation() { for (auto pl_macro : place_ctx.pl_macros) { if (is_macro_constrained(pl_macro)) { - //Update the PartitionRegions of all the clusters in the macro - PartitionRegion macro_pr = constrained_macro_locs(pl_macro); - - for (size_t imember = 0; imember < pl_macro.members.size(); imember++) { - ClusterBlockId blk_id = pl_macro.members[imember].blk_index; - floorplanning_ctx.cluster_constraints[blk_id] = macro_pr; - } + /* + * Update the PartitionRegion for the head of the macro + * based on the constraints of all blocks contained in the macro + */ + PartitionRegion macro_head_pr = update_macro_pr(pl_macro); + + //Get block id of head macro member and update its PartitionRegion + ClusterBlockId blk_id = pl_macro.members[0].blk_index; + floorplanning_ctx.cluster_constraints[blk_id] = macro_head_pr; } } } diff --git a/vpr/src/place/place_constraints.h b/vpr/src/place/place_constraints.h index 9c4de6b959f..cd259bd2a95 100644 --- a/vpr/src/place/place_constraints.h +++ b/vpr/src/place/place_constraints.h @@ -36,7 +36,7 @@ bool is_macro_constrained(const t_pl_macro& pl_macro); /* * Returns region of valid locations for the head of the macro based on floorplan constraints */ -PartitionRegion constrained_macro_locs(const t_pl_macro& pl_macro); +PartitionRegion update_macro_pr(const t_pl_macro& pl_macro); void constraints_propagation(); From d9026e4b1849487e5412718d66327d3cbc651291 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Wed, 2 Jun 2021 10:48:12 -0400 Subject: [PATCH 03/12] Added comments to explain constraints propagation --- vpr/src/place/place_constraints.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/vpr/src/place/place_constraints.h b/vpr/src/place/place_constraints.h index cd259bd2a95..fd39331c855 100644 --- a/vpr/src/place/place_constraints.h +++ b/vpr/src/place/place_constraints.h @@ -34,10 +34,18 @@ bool cluster_floorplanning_legal(ClusterBlockId blk_id, const t_pl_loc& loc); bool is_macro_constrained(const t_pl_macro& pl_macro); /* - * Returns region of valid locations for the head of the macro based on floorplan constraints + * Returns PartitionRegion for the head of the macro based on the floorplan constraints + * of all blocks in the macro. */ PartitionRegion update_macro_pr(const t_pl_macro& pl_macro); +/* + * Updates the floorplan constraints information for all constrained macros. + * The head member of each constrained macro is assigned a new PartitionRegion + * that is calculated based on the constraints of all the blocks in the macro. + * This is done at the start of initial placement to ease floorplan legality checking + * while placing macros during initial placement. + */ void constraints_propagation(); inline bool floorplan_legal(const t_pl_blocks_to_be_moved& blocks_affected) { From 9fddc1c749d9b7eb6daddbec257acb070b7372c2 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Thu, 3 Jun 2021 09:51:12 -0400 Subject: [PATCH 04/12] Changed name of variable in update macro head pr function to clarify what it is used for --- vpr/src/place/place_constraints.cpp | 14 +++++++------- vpr/src/place/place_constraints.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index e0c387cebe4..9e604de94e6 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -54,8 +54,8 @@ bool is_macro_constrained(const t_pl_macro& pl_macro) { } /*Returns PartitionRegion of where the head of the macro could go*/ -PartitionRegion update_macro_pr(const t_pl_macro& pl_macro) { - PartitionRegion macro_pr; +PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro) { + PartitionRegion macro_head_pr; bool is_member_constrained = false; int num_constrained_members = 0; auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); @@ -98,19 +98,19 @@ PartitionRegion update_macro_pr(const t_pl_macro& pl_macro) { } if (num_constrained_members == 1) { - macro_pr = modified_pr; + macro_head_pr = modified_pr; } else { - macro_pr = intersection(macro_pr, modified_pr); + macro_head_pr = intersection(macro_head_pr, modified_pr); } } } //if the intersection is empty, no way to place macro members together, give an error - if (macro_pr.empty()) { + if (macro_head_pr.empty()) { VPR_ERROR(VPR_ERROR_PLACE, " \n Feasible floorplanning constraints could not be calculated for the placement macro.\n"); } - return macro_pr; + return macro_head_pr; } void constraints_propagation() { @@ -123,7 +123,7 @@ void constraints_propagation() { * Update the PartitionRegion for the head of the macro * based on the constraints of all blocks contained in the macro */ - PartitionRegion macro_head_pr = update_macro_pr(pl_macro); + PartitionRegion macro_head_pr = update_macro_head_pr(pl_macro); //Get block id of head macro member and update its PartitionRegion ClusterBlockId blk_id = pl_macro.members[0].blk_index; diff --git a/vpr/src/place/place_constraints.h b/vpr/src/place/place_constraints.h index fd39331c855..1c6fc84032e 100644 --- a/vpr/src/place/place_constraints.h +++ b/vpr/src/place/place_constraints.h @@ -37,7 +37,7 @@ bool is_macro_constrained(const t_pl_macro& pl_macro); * Returns PartitionRegion for the head of the macro based on the floorplan constraints * of all blocks in the macro. */ -PartitionRegion update_macro_pr(const t_pl_macro& pl_macro); +PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro); /* * Updates the floorplan constraints information for all constrained macros. From be894882b627e9e5c7236d9a2c8504cb408bf8f0 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Thu, 3 Jun 2021 11:57:37 -0400 Subject: [PATCH 05/12] Update PartitionRegions of all macro members during constraints propagation, not just head --- vpr/src/place/place_constraints.cpp | 49 ++++++++++++++++++++++++++--- vpr/src/place/place_constraints.h | 5 +++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index 9e604de94e6..6fda20ff20f 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -82,11 +82,11 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro) { t_pl_loc min_pl_loc(reg_rect.xmin(), reg_rect.ymin(), block_regions[i].get_sub_tile()); - t_pl_loc modified_min_pl_loc = min_pl_loc + offset; + t_pl_loc modified_min_pl_loc = min_pl_loc - offset; t_pl_loc max_pl_loc(reg_rect.xmax(), reg_rect.ymax(), block_regions[i].get_sub_tile()); - t_pl_loc modified_max_pl_loc = max_pl_loc + offset; + t_pl_loc modified_max_pl_loc = max_pl_loc - offset; modified_reg.set_region_rect(modified_min_pl_loc.x, modified_min_pl_loc.y, modified_max_pl_loc.x, modified_max_pl_loc.y); //check that subtile is not an invalid value before changing, otherwise it just stays -1 @@ -113,6 +113,35 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro) { return macro_head_pr; } +PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offset& offset) { + std::vector block_regions = head_pr.get_partition_region(); + PartitionRegion macro_pr; + + for (unsigned int i = 0; i < block_regions.size(); i++) { + Region modified_reg; + + vtr::Rect reg_rect = block_regions[i].get_region_rect(); + + t_pl_loc min_pl_loc(reg_rect.xmin(), reg_rect.ymin(), block_regions[i].get_sub_tile()); + + t_pl_loc macro_min_pl_loc = min_pl_loc + offset; + + t_pl_loc max_pl_loc(reg_rect.xmax(), reg_rect.ymax(), block_regions[i].get_sub_tile()); + + t_pl_loc macro_max_pl_loc = max_pl_loc + offset; + + modified_reg.set_region_rect(macro_min_pl_loc.x, macro_min_pl_loc.y, macro_max_pl_loc.x, macro_max_pl_loc.y); + //check that subtile is not an invalid value before changing, otherwise it just stays -1 + if (block_regions[i].get_sub_tile() != NO_SUBTILE) { + modified_reg.set_sub_tile(macro_min_pl_loc.sub_tile); + } + + macro_pr.add_to_part_region(modified_reg); + } + + return macro_pr; +} + void constraints_propagation() { auto& place_ctx = g_vpr_ctx.placement(); auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); @@ -125,9 +154,19 @@ void constraints_propagation() { */ PartitionRegion macro_head_pr = update_macro_head_pr(pl_macro); - //Get block id of head macro member and update its PartitionRegion - ClusterBlockId blk_id = pl_macro.members[0].blk_index; - floorplanning_ctx.cluster_constraints[blk_id] = macro_head_pr; + //Update PartitionRegions of all members of the macro + for (size_t imember = 0; imember < pl_macro.members.size(); imember++) { + ClusterBlockId iblk = pl_macro.members[imember].blk_index; + auto offset = pl_macro.members[imember].offset; + + //Update head PR + if (imember == 0) { + floorplanning_ctx.cluster_constraints[iblk] = macro_head_pr; + } else { //Update macro member PR + PartitionRegion macro_pr = update_macro_member_pr(macro_head_pr, offset); + floorplanning_ctx.cluster_constraints[iblk] = macro_pr; + } + } } } } diff --git a/vpr/src/place/place_constraints.h b/vpr/src/place/place_constraints.h index 1c6fc84032e..443fb707ab0 100644 --- a/vpr/src/place/place_constraints.h +++ b/vpr/src/place/place_constraints.h @@ -39,6 +39,11 @@ bool is_macro_constrained(const t_pl_macro& pl_macro); */ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro); +/* + * Update macro member PR + */ +PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offset& offset); + /* * Updates the floorplan constraints information for all constrained macros. * The head member of each constrained macro is assigned a new PartitionRegion From b59daedc8fbedd9a1666d7887446dc83c813c619 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Sat, 5 Jun 2021 17:19:43 -0400 Subject: [PATCH 06/12] Added comments and add unit test to check macro routine that updates member PartitionRegions --- vpr/src/place/initial_placement.cpp | 4 ++-- vpr/src/place/place_constraints.cpp | 2 +- vpr/src/place/place_constraints.h | 9 +++++++-- vpr/test/test_vpr_constraints.cpp | 23 +++++++++++++++++++++++ 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/vpr/src/place/initial_placement.cpp b/vpr/src/place/initial_placement.cpp index 6f9cf89a29a..61d5ecb1eed 100644 --- a/vpr/src/place/initial_placement.cpp +++ b/vpr/src/place/initial_placement.cpp @@ -419,8 +419,8 @@ void initial_placement(enum e_pad_loc_type pad_loc_type, const char* constraints vtr::vector block_scores = assign_block_scores(); std::vector sorted_blocks = sort_blocks(block_scores); - //Perform constraints_propagation - constraints_propagation(); + //Go through blocks with floorplan constraints to ensure we have the tightest constraint on each one. + propagate_place_constraints(); // Loading legal placement locations zero_initialize_grid_blocks(); diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index 6fda20ff20f..04a064bb199 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -142,7 +142,7 @@ PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offs return macro_pr; } -void constraints_propagation() { +void propagate_place_constraints() { auto& place_ctx = g_vpr_ctx.placement(); auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); diff --git a/vpr/src/place/place_constraints.h b/vpr/src/place/place_constraints.h index 443fb707ab0..3fe0eeae29f 100644 --- a/vpr/src/place/place_constraints.h +++ b/vpr/src/place/place_constraints.h @@ -40,7 +40,12 @@ bool is_macro_constrained(const t_pl_macro& pl_macro); PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro); /* - * Update macro member PR + * Update the PartitionRegions of non-head members of a macro, + * based on the constraint that was calculated for the head region. + * The constraint that was calculated for the head region considered all + * constrained blocks in the macro, so to calculate the constraint for the rest + * of the blocks, it is just the head constraint with the offset of the member + * applied. */ PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offset& offset); @@ -51,7 +56,7 @@ PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offs * This is done at the start of initial placement to ease floorplan legality checking * while placing macros during initial placement. */ -void constraints_propagation(); +void propagate_place_constraints(); inline bool floorplan_legal(const t_pl_blocks_to_be_moved& blocks_affected) { bool floorplan_legal; diff --git a/vpr/test/test_vpr_constraints.cpp b/vpr/test/test_vpr_constraints.cpp index c6dbb9a81e4..0ae4e27ac61 100644 --- a/vpr/test/test_vpr_constraints.cpp +++ b/vpr/test/test_vpr_constraints.cpp @@ -6,6 +6,7 @@ #include "vpr_constraints.h" #include "partition.h" #include "region.h" +#include "place_constraints.h" /** * This file contains unit tests that check the functionality of all classes related to vpr constraints. These classes include @@ -425,6 +426,28 @@ TEST_CASE("RegionLocked", "[vpr]") { REQUIRE(is_r2_locked == false); } +//Test calculation of macro constraints +TEST_CASE("MacroConstraints", "[vpr]") { + PartitionRegion head_pr; + t_pl_offset offset(2, 1, 0); + + Region reg; + reg.set_region_rect(5, 2, 9, 6); + + head_pr.add_to_part_region(reg); + + PartitionRegion macro_pr = update_macro_member_pr(head_pr, offset); + + std::vector mac_regions = macro_pr.get_partition_region(); + + vtr::Rect mac_rect = mac_regions[0].get_region_rect(); + + REQUIRE(mac_rect.xmin() == 7); + REQUIRE(mac_rect.ymin() == 3); + REQUIRE(mac_rect.xmax() == 11); + REQUIRE(mac_rect.ymax() == 7); +} + static constexpr const char kArchFile[] = "test_read_arch_metadata.xml"; // Test that place constraints are not changed during placement From d8414cc69da8366bcd610eabf340a39f791676ee Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Sat, 5 Jun 2021 19:40:46 -0400 Subject: [PATCH 07/12] changed a comment about constraints propagation --- vpr/src/place/initial_placement.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vpr/src/place/initial_placement.cpp b/vpr/src/place/initial_placement.cpp index 61d5ecb1eed..d5662af4f47 100644 --- a/vpr/src/place/initial_placement.cpp +++ b/vpr/src/place/initial_placement.cpp @@ -419,7 +419,9 @@ void initial_placement(enum e_pad_loc_type pad_loc_type, const char* constraints vtr::vector block_scores = assign_block_scores(); std::vector sorted_blocks = sort_blocks(block_scores); - //Go through blocks with floorplan constraints to ensure we have the tightest constraint on each one. + /* Go through cluster blocks to calculate the tightest placement + * floorplan constraint for each constrained block + */ propagate_place_constraints(); // Loading legal placement locations From c8b4a59772ca5434727d4824350259856d14326a Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 7 Jun 2021 22:14:51 -0400 Subject: [PATCH 08/12] Added checks to ensure updated PartitionRegions do not go out of grid dimensions. --- vpr/src/place/place_constraints.cpp | 29 +++++++++++++++++++++++++---- vpr/src/place/place_constraints.h | 23 +++++++++++++---------- vpr/test/test_vpr_constraints.cpp | 7 ++++++- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index 04a064bb199..b0bc775f230 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -54,7 +54,7 @@ bool is_macro_constrained(const t_pl_macro& pl_macro) { } /*Returns PartitionRegion of where the head of the macro could go*/ -PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro) { +PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro, const PartitionRegion& grid_pr) { PartitionRegion macro_head_pr; bool is_member_constrained = false; int num_constrained_members = 0; @@ -105,6 +105,9 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro) { } } + //intersect to ensure the head pr does not go outside of grid dimensions + macro_head_pr = intersection(macro_head_pr, grid_pr); + //if the intersection is empty, no way to place macro members together, give an error if (macro_head_pr.empty()) { VPR_ERROR(VPR_ERROR_PLACE, " \n Feasible floorplanning constraints could not be calculated for the placement macro.\n"); @@ -113,7 +116,7 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro) { return macro_head_pr; } -PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offset& offset) { +PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offset& offset, const PartitionRegion& grid_pr) { std::vector block_regions = head_pr.get_partition_region(); PartitionRegion macro_pr; @@ -139,12 +142,30 @@ PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offs macro_pr.add_to_part_region(modified_reg); } + //intersect to ensure the head pr does not go outside of grid dimensions + macro_pr = intersection(macro_pr, grid_pr); + + //if the intersection is empty, no way to place macro members together, give an error + if (macro_pr.empty()) { + VPR_ERROR(VPR_ERROR_PLACE, " \n Feasible floorplanning constraints could not be calculated for the placement macro.\n"); + } + return macro_pr; } void propagate_place_constraints() { auto& place_ctx = g_vpr_ctx.placement(); auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); + auto& device_ctx = g_vpr_ctx.device(); + + //Create a PartitionRegion with grid dimensions + //Will be used to check that updated PartitionRegions are within grid bounds + int width = device_ctx.grid.width() - 1; + int height = device_ctx.grid.height() - 1; + Region grid_reg; + grid_reg.set_region_rect(0, 0, width, height); + PartitionRegion grid_pr; + grid_pr.add_to_part_region(grid_reg); for (auto pl_macro : place_ctx.pl_macros) { if (is_macro_constrained(pl_macro)) { @@ -152,7 +173,7 @@ void propagate_place_constraints() { * Update the PartitionRegion for the head of the macro * based on the constraints of all blocks contained in the macro */ - PartitionRegion macro_head_pr = update_macro_head_pr(pl_macro); + PartitionRegion macro_head_pr = update_macro_head_pr(pl_macro, grid_pr); //Update PartitionRegions of all members of the macro for (size_t imember = 0; imember < pl_macro.members.size(); imember++) { @@ -163,7 +184,7 @@ void propagate_place_constraints() { if (imember == 0) { floorplanning_ctx.cluster_constraints[iblk] = macro_head_pr; } else { //Update macro member PR - PartitionRegion macro_pr = update_macro_member_pr(macro_head_pr, offset); + PartitionRegion macro_pr = update_macro_member_pr(macro_head_pr, offset, grid_pr); floorplanning_ctx.cluster_constraints[iblk] = macro_pr; } } diff --git a/vpr/src/place/place_constraints.h b/vpr/src/place/place_constraints.h index 3fe0eeae29f..13c01915a78 100644 --- a/vpr/src/place/place_constraints.h +++ b/vpr/src/place/place_constraints.h @@ -35,24 +35,27 @@ bool is_macro_constrained(const t_pl_macro& pl_macro); /* * Returns PartitionRegion for the head of the macro based on the floorplan constraints - * of all blocks in the macro. + * of all blocks in the macro. For example, if there was a macro of length two and each block has + * a constraint, this routine will shift and intersect the two constraint regions to calculate + * the tightest region constraint for the head macro. */ -PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro); +PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro, const PartitionRegion& grid_pr); /* * Update the PartitionRegions of non-head members of a macro, - * based on the constraint that was calculated for the head region. - * The constraint that was calculated for the head region considered all - * constrained blocks in the macro, so to calculate the constraint for the rest - * of the blocks, it is just the head constraint with the offset of the member - * applied. + * based on the constraint that was calculated for the head region, head_pr. + * The constraint that was calculated for the head region must have + * calculated the tightest constraints for the head member + * by shifting and intersecting the constraints on all macro members. + * For each macro member, the updated constraint is essentially the head constraint + * with the member's offset applied. */ -PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offset& offset); +PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offset& offset, const PartitionRegion& grid_pr); /* * Updates the floorplan constraints information for all constrained macros. - * The head member of each constrained macro is assigned a new PartitionRegion - * that is calculated based on the constraints of all the blocks in the macro. + * Updates the constraints to be the tightest constraints possible while adhering + * to the floorplan constraints of each macro member. * This is done at the start of initial placement to ease floorplan legality checking * while placing macros during initial placement. */ diff --git a/vpr/test/test_vpr_constraints.cpp b/vpr/test/test_vpr_constraints.cpp index 0ae4e27ac61..fa9d258a264 100644 --- a/vpr/test/test_vpr_constraints.cpp +++ b/vpr/test/test_vpr_constraints.cpp @@ -436,7 +436,12 @@ TEST_CASE("MacroConstraints", "[vpr]") { head_pr.add_to_part_region(reg); - PartitionRegion macro_pr = update_macro_member_pr(head_pr, offset); + Region grid_reg; + grid_reg.set_region_rect(0, 0, 20, 20); + PartitionRegion grid_pr; + grid_pr.add_to_part_region(grid_reg); + + PartitionRegion macro_pr = update_macro_member_pr(head_pr, offset, grid_pr); std::vector mac_regions = macro_pr.get_partition_region(); From 1c608caa9b08b226bcc10d4415804086c54f20e8 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 14 Jun 2021 15:11:55 -0400 Subject: [PATCH 09/12] Applied offsets directly to region rectangles when updating macro PartitionRegions to reduce length of functions. Also improved error messages for constraints propagation --- vpr/src/place/place_constraints.cpp | 48 +++++++++++++---------------- vpr/src/place/place_constraints.h | 4 ++- vpr/test/test_vpr_constraints.cpp | 3 +- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index b0bc775f230..71dbf3426cf 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -80,18 +80,11 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro, const Partition vtr::Rect reg_rect = block_regions[i].get_region_rect(); - t_pl_loc min_pl_loc(reg_rect.xmin(), reg_rect.ymin(), block_regions[i].get_sub_tile()); + modified_reg.set_region_rect(reg_rect.xmin() - offset.x, reg_rect.ymin() - offset.y, reg_rect.xmax() - offset.x, reg_rect.ymax() - offset.y); - t_pl_loc modified_min_pl_loc = min_pl_loc - offset; - - t_pl_loc max_pl_loc(reg_rect.xmax(), reg_rect.ymax(), block_regions[i].get_sub_tile()); - - t_pl_loc modified_max_pl_loc = max_pl_loc - offset; - - modified_reg.set_region_rect(modified_min_pl_loc.x, modified_min_pl_loc.y, modified_max_pl_loc.x, modified_max_pl_loc.y); //check that subtile is not an invalid value before changing, otherwise it just stays -1 if (block_regions[i].get_sub_tile() != NO_SUBTILE) { - modified_reg.set_sub_tile(modified_min_pl_loc.sub_tile); + modified_reg.set_sub_tile(block_regions[i].get_sub_tile() - offset.sub_tile); } modified_pr.add_to_part_region(modified_reg); @@ -110,13 +103,13 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro, const Partition //if the intersection is empty, no way to place macro members together, give an error if (macro_head_pr.empty()) { - VPR_ERROR(VPR_ERROR_PLACE, " \n Feasible floorplanning constraints could not be calculated for the placement macro.\n"); + print_macro_constraint_error(pl_macro); } return macro_head_pr; } -PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offset& offset, const PartitionRegion& grid_pr) { +PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offset& offset, const PartitionRegion& grid_pr, const t_pl_macro& pl_macro) { std::vector block_regions = head_pr.get_partition_region(); PartitionRegion macro_pr; @@ -125,34 +118,38 @@ PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offs vtr::Rect reg_rect = block_regions[i].get_region_rect(); - t_pl_loc min_pl_loc(reg_rect.xmin(), reg_rect.ymin(), block_regions[i].get_sub_tile()); - - t_pl_loc macro_min_pl_loc = min_pl_loc + offset; - - t_pl_loc max_pl_loc(reg_rect.xmax(), reg_rect.ymax(), block_regions[i].get_sub_tile()); + modified_reg.set_region_rect(reg_rect.xmin() + offset.x, reg_rect.ymin() + offset.y, reg_rect.xmax() + offset.x, reg_rect.ymax() + offset.y); - t_pl_loc macro_max_pl_loc = max_pl_loc + offset; - - modified_reg.set_region_rect(macro_min_pl_loc.x, macro_min_pl_loc.y, macro_max_pl_loc.x, macro_max_pl_loc.y); //check that subtile is not an invalid value before changing, otherwise it just stays -1 if (block_regions[i].get_sub_tile() != NO_SUBTILE) { - modified_reg.set_sub_tile(macro_min_pl_loc.sub_tile); + modified_reg.set_sub_tile(block_regions[i].get_sub_tile() + offset.sub_tile); } macro_pr.add_to_part_region(modified_reg); } - //intersect to ensure the head pr does not go outside of grid dimensions + //intersect to ensure the macro pr does not go outside of grid dimensions macro_pr = intersection(macro_pr, grid_pr); //if the intersection is empty, no way to place macro members together, give an error if (macro_pr.empty()) { - VPR_ERROR(VPR_ERROR_PLACE, " \n Feasible floorplanning constraints could not be calculated for the placement macro.\n"); + print_macro_constraint_error(pl_macro); } return macro_pr; } +void print_macro_constraint_error(const t_pl_macro& pl_macro) { + VTR_LOG( + "Feasible floorplanning constraints could not be calculated for the placement macro. \n" + "The placement macro contains the following blocks: \n"); + for (unsigned int i = 0; i < pl_macro.members.size(); i++) { + VTR_LOG("Block #%zu ", size_t(pl_macro.members[i].blk_index)); + } + VTR_LOG("\n"); + VPR_ERROR(VPR_ERROR_PLACE, " \n Check that the above-mentioned placement macro blocks have compatible floorplan constraints.\n"); +} + void propagate_place_constraints() { auto& place_ctx = g_vpr_ctx.placement(); auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); @@ -170,7 +167,7 @@ void propagate_place_constraints() { for (auto pl_macro : place_ctx.pl_macros) { if (is_macro_constrained(pl_macro)) { /* - * Update the PartitionRegion for the head of the macro + * Get the PartitionRegion for the head of the macro * based on the constraints of all blocks contained in the macro */ PartitionRegion macro_head_pr = update_macro_head_pr(pl_macro, grid_pr); @@ -180,11 +177,10 @@ void propagate_place_constraints() { ClusterBlockId iblk = pl_macro.members[imember].blk_index; auto offset = pl_macro.members[imember].offset; - //Update head PR - if (imember == 0) { + if (imember == 0) { //Update head PR floorplanning_ctx.cluster_constraints[iblk] = macro_head_pr; } else { //Update macro member PR - PartitionRegion macro_pr = update_macro_member_pr(macro_head_pr, offset, grid_pr); + PartitionRegion macro_pr = update_macro_member_pr(macro_head_pr, offset, grid_pr, pl_macro); floorplanning_ctx.cluster_constraints[iblk] = macro_pr; } } diff --git a/vpr/src/place/place_constraints.h b/vpr/src/place/place_constraints.h index 13c01915a78..2c52ddb711c 100644 --- a/vpr/src/place/place_constraints.h +++ b/vpr/src/place/place_constraints.h @@ -50,7 +50,7 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro, const Partition * For each macro member, the updated constraint is essentially the head constraint * with the member's offset applied. */ -PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offset& offset, const PartitionRegion& grid_pr); +PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offset& offset, const PartitionRegion& grid_pr, const t_pl_macro& pl_macro); /* * Updates the floorplan constraints information for all constrained macros. @@ -61,6 +61,8 @@ PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offs */ void propagate_place_constraints(); +void print_macro_constraint_error(const t_pl_macro& pl_macro); + inline bool floorplan_legal(const t_pl_blocks_to_be_moved& blocks_affected) { bool floorplan_legal; diff --git a/vpr/test/test_vpr_constraints.cpp b/vpr/test/test_vpr_constraints.cpp index fa9d258a264..e620f439d6d 100644 --- a/vpr/test/test_vpr_constraints.cpp +++ b/vpr/test/test_vpr_constraints.cpp @@ -428,6 +428,7 @@ TEST_CASE("RegionLocked", "[vpr]") { //Test calculation of macro constraints TEST_CASE("MacroConstraints", "[vpr]") { + t_pl_macro pl_macro; PartitionRegion head_pr; t_pl_offset offset(2, 1, 0); @@ -441,7 +442,7 @@ TEST_CASE("MacroConstraints", "[vpr]") { PartitionRegion grid_pr; grid_pr.add_to_part_region(grid_reg); - PartitionRegion macro_pr = update_macro_member_pr(head_pr, offset, grid_pr); + PartitionRegion macro_pr = update_macro_member_pr(head_pr, offset, grid_pr, pl_macro); std::vector mac_regions = macro_pr.get_partition_region(); From 09f7411ec9a9167e37bedfd19429ff4f03b13d50 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 14 Jun 2021 15:28:00 -0400 Subject: [PATCH 10/12] Improved a function comment --- vpr/src/place/place_constraints.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vpr/src/place/place_constraints.h b/vpr/src/place/place_constraints.h index 2c52ddb711c..d6287287689 100644 --- a/vpr/src/place/place_constraints.h +++ b/vpr/src/place/place_constraints.h @@ -44,9 +44,8 @@ PartitionRegion update_macro_head_pr(const t_pl_macro& pl_macro, const Partition /* * Update the PartitionRegions of non-head members of a macro, * based on the constraint that was calculated for the head region, head_pr. - * The constraint that was calculated for the head region must have - * calculated the tightest constraints for the head member - * by shifting and intersecting the constraints on all macro members. + * The constraint on the head region must be the tightest possible (i.e. implied by the + * entire macro) before this routine is called. * For each macro member, the updated constraint is essentially the head constraint * with the member's offset applied. */ From 34641cb7d792e70efd3962d39c5564ff5383d103 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 14 Jun 2021 21:19:06 -0400 Subject: [PATCH 11/12] Added details to error messages and unit test comments --- vpr/src/place/place_constraints.cpp | 4 +++- vpr/test/test_vpr_constraints.cpp | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index 71dbf3426cf..f51417a3e4d 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -140,11 +140,13 @@ PartitionRegion update_macro_member_pr(PartitionRegion& head_pr, const t_pl_offs } void print_macro_constraint_error(const t_pl_macro& pl_macro) { + auto& cluster_ctx = g_vpr_ctx.clustering(); VTR_LOG( "Feasible floorplanning constraints could not be calculated for the placement macro. \n" "The placement macro contains the following blocks: \n"); for (unsigned int i = 0; i < pl_macro.members.size(); i++) { - VTR_LOG("Block #%zu ", size_t(pl_macro.members[i].blk_index)); + std::string blk_name = cluster_ctx.clb_nlist.block_name((pl_macro.members[i].blk_index)); + VTR_LOG("Block %s (#%zu) ", blk_name, size_t(pl_macro.members[i].blk_index)); } VTR_LOG("\n"); VPR_ERROR(VPR_ERROR_PLACE, " \n Check that the above-mentioned placement macro blocks have compatible floorplan constraints.\n"); diff --git a/vpr/test/test_vpr_constraints.cpp b/vpr/test/test_vpr_constraints.cpp index e620f439d6d..b0b1ad2afe6 100644 --- a/vpr/test/test_vpr_constraints.cpp +++ b/vpr/test/test_vpr_constraints.cpp @@ -427,6 +427,9 @@ TEST_CASE("RegionLocked", "[vpr]") { } //Test calculation of macro constraints +/* Checks that the PartitionRegion of a macro member is updated properly according + * to the head member's PartitionRegion that is passed in. + */ TEST_CASE("MacroConstraints", "[vpr]") { t_pl_macro pl_macro; PartitionRegion head_pr; From 5fe84dd71203845197d06b77c7c736bbe4c5b454 Mon Sep 17 00:00:00 2001 From: Sarah Khalid Date: Mon, 14 Jun 2021 22:06:26 -0400 Subject: [PATCH 12/12] Got rid of error in printing macro constraints prop error message - needed to convert std string to c string --- vpr/src/place/place_constraints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/place/place_constraints.cpp b/vpr/src/place/place_constraints.cpp index f51417a3e4d..1a07b65737b 100644 --- a/vpr/src/place/place_constraints.cpp +++ b/vpr/src/place/place_constraints.cpp @@ -146,7 +146,7 @@ void print_macro_constraint_error(const t_pl_macro& pl_macro) { "The placement macro contains the following blocks: \n"); for (unsigned int i = 0; i < pl_macro.members.size(); i++) { std::string blk_name = cluster_ctx.clb_nlist.block_name((pl_macro.members[i].blk_index)); - VTR_LOG("Block %s (#%zu) ", blk_name, size_t(pl_macro.members[i].blk_index)); + VTR_LOG("Block %s (#%zu) ", blk_name.c_str(), size_t(pl_macro.members[i].blk_index)); } VTR_LOG("\n"); VPR_ERROR(VPR_ERROR_PLACE, " \n Check that the above-mentioned placement macro blocks have compatible floorplan constraints.\n");