Skip to content

Mark fixed blocks #1759

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 27 commits into from
Jun 22, 2021
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
cd289a2
Added code for marking down blocks that constrained to one location o…
sfkhalid Jun 2, 2021
8ad3c1b
Region empty function now returns true if the rectangle either has im…
sfkhalid Jun 2, 2021
77786c8
Ran make format
sfkhalid Jun 2, 2021
25a5b7f
Changed default empty region values
sfkhalid Jun 9, 2021
6c6772d
Added helper function for marking block locations and grid usage with…
sfkhalid Jun 9, 2021
bf766f0
Changed placement consistency error messages to improve clarity
sfkhalid Jun 9, 2021
c915129
Add function to count number of tiles covered by a floorplan region
sfkhalid Jun 10, 2021
2f0dbf6
Changed comment
sfkhalid Jun 14, 2021
8165a5d
Changed name of function mark_block_location->set_block_location
sfkhalid Jun 15, 2021
8a90016
Added functions to check whether the PartitionRegion of a cluster blo…
sfkhalid Jun 16, 2021
2cc056b
Ran make format
sfkhalid Jun 16, 2021
904db47
Removed locked member function from Region class - was no longer need…
sfkhalid Jun 16, 2021
4f94cbd
Merge branch 'master' into mark_fixed_blocks
sfkhalid Jun 16, 2021
3a9096b
Got rid of unnecessary lines in mark_fixed_blocks
sfkhalid Jun 16, 2021
e359b20
merge branch 'mark_fixed_blocks' of https://github.com/verilog-to-rou…
sfkhalid Jun 16, 2021
3c9c93a
Ran make format
sfkhalid Jun 16, 2021
e1fa745
Initialized grid blocks earlier in flow of reading in place file
sfkhalid Jun 17, 2021
f2305df
Refactored read_place to make use of set_block_location utility function
sfkhalid Jun 17, 2021
7e0fe58
Improved error messaging during read place
sfkhalid Jun 17, 2021
0504d8c
Refactored region size routine to return an int instead of a bool
sfkhalid Jun 17, 2021
8c3c163
Refactored region tile cover routine to return int instead of bool
sfkhalid Jun 18, 2021
c3ad3b6
Modified is_pr_size_one to get rid of compiler warning
sfkhalid Jun 18, 2021
6ad75c3
Added check to partition region size check to see whether multiple re…
sfkhalid Jun 18, 2021
8887b6c
Added checks for whether subtile location is valid when marking fixed…
sfkhalid Jun 21, 2021
cbe935d
Merge branch 'master' into mark_fixed_blocks
sfkhalid Jun 21, 2021
58e2683
Check whether subtile is compatible when adding fixed blocks
sfkhalid Jun 21, 2021
57ae843
Moved initialization of placement structures during load place flow. …
sfkhalid Jun 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion vpr/src/base/read_place.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ void read_place_body(std::ifstream& placement_file,
}

//need to lock down blocks and mark grid block usage if it is a constraints file
//for a place file, grid usage is marked during initial placement instead
//for a place file, grid usage is marked elsewhere
if (!is_place_file) {
place_ctx.block_locs[blk_id].is_fixed = true;
place_ctx.grid_blocks[block_x][block_y].blocks[sub_tile_index] = blk_id;
Expand Down
12 changes: 4 additions & 8 deletions vpr/src/base/region.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
Region::Region() {
sub_tile = NO_SUBTILE;

//default rect for a region is (-1, -1, -1, -1)
//default rect for a region is (999, 999, -1, -1)
//these values indicate an empty rectangle, they are set as default values to help catch uninitialized use
region_bounds.set_xmin(-1);
region_bounds.set_ymin(-1);
region_bounds.set_xmin(999);
region_bounds.set_ymin(999);
region_bounds.set_xmax(-1);
region_bounds.set_ymax(-1);
}
Expand All @@ -30,12 +30,8 @@ void Region::set_sub_tile(int _sub_tile) {
sub_tile = _sub_tile;
}

bool Region::locked() {
return region_bounds.xmin() == region_bounds.xmax() && region_bounds.ymin() == region_bounds.ymax() && sub_tile != NO_SUBTILE;
}

bool Region::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) {
Expand Down
8 changes: 2 additions & 6 deletions vpr/src/base/region.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,11 @@ class Region {
void set_sub_tile(int _sub_tile);

/**
* @brief Return whether the region is empty, based on whether the region rectangle is empty
* @brief Return whether the region is empty (i. e. the region bounds rectangle
* covers no area)
*/
bool empty();

/**
* @brief Checks whether a block is locked down to a specific x, y, subtile location
*/
bool locked();

/**
* @brief Check if the location is in the region (at a valid x, y, subtile location within the region bounds, inclusive)
* If the region has no subtile specified, then the location subtile does not have to match. If it does, the location
Expand Down
4 changes: 4 additions & 0 deletions vpr/src/place/initial_placement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,10 @@ void initial_placement(enum e_pad_loc_type pad_loc_type, const char* constraints
read_constraints(constraints_file);
}

/*Mark the blocks that have already been locked to one spot via floorplan constraints
* as fixed so they do not get moved during initial placement or during simulated annealing*/
mark_fixed_blocks();

initial_placement_pl_macros(MAX_NUM_TRIES_TO_PLACE_MACROS_RANDOMLY, free_locations);

// All the macros are placed, update the legal_pos[][] array and free_locations[] array
Expand Down
10 changes: 5 additions & 5 deletions vpr/src/place/place.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2644,8 +2644,8 @@ static int check_block_placement_consistency() {
for (size_t i = 0; i < device_ctx.grid.width(); i++)
for (size_t j = 0; j < device_ctx.grid.height(); j++) {
if (place_ctx.grid_blocks[i][j].usage > device_ctx.grid[i][j].type->capacity) {
VTR_LOG_ERROR("Block at grid location (%zu,%zu) overused. Usage is %d.\n",
i, j, place_ctx.grid_blocks[i][j].usage);
VTR_LOG_ERROR("%d blocks were placed at grid location (%zu,%zu), but location capacity is %d.\n",
place_ctx.grid_blocks[i][j].usage, i, j, device_ctx.grid[i][j].type->capacity);
error++;
}
int usage_check = 0;
Expand Down Expand Up @@ -2674,16 +2674,16 @@ static int check_block_placement_consistency() {
bdone[bnum]++;
}
if (usage_check != place_ctx.grid_blocks[i][j].usage) {
VTR_LOG_ERROR("Location (%zu,%zu) usage is %d, but has actual usage %d.\n",
i, j, place_ctx.grid_blocks[i][j].usage, usage_check);
VTR_LOG_ERROR("%d block(s) were placed at location (%zu,%zu), but location contains %d block(s).\n",
place_ctx.grid_blocks[i][j].usage, i, j, usage_check);
error++;
}
}

/* Check that every block exists in the device_ctx.grid and cluster_ctx.blocks arrays somewhere. */
for (auto blk_id : cluster_ctx.clb_nlist.blocks())
if (bdone[blk_id] != 1) {
VTR_LOG_ERROR("Block %zu listed %d times in data structures.\n",
VTR_LOG_ERROR("Block %zu listed %d times in device context grid.\n",
size_t(blk_id), bdone[blk_id]);
error++;
}
Expand Down
93 changes: 93 additions & 0 deletions vpr/src/place/place_constraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "globals.h"
#include "place_constraints.h"
#include "place_util.h"

/*checks that each block's location is compatible with its floorplanning constraints if it has any*/
int check_placement_floorplanning() {
Expand Down Expand Up @@ -257,3 +258,95 @@ void load_cluster_constraints() {
}
}
}

void mark_fixed_blocks() {
auto& cluster_ctx = g_vpr_ctx.clustering();
auto& place_ctx = g_vpr_ctx.mutable_placement();
auto& floorplanning_ctx = g_vpr_ctx.floorplanning();

for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
if (!is_cluster_constrained(blk_id)) {
continue;
}
PartitionRegion pr = floorplanning_ctx.cluster_constraints[blk_id];
auto block_type = cluster_ctx.clb_nlist.block_type(blk_id);
t_pl_loc loc;

if (is_pr_size_one(pr, block_type, loc)) {
//Set block location and grid usage
set_block_location(blk_id, loc);

//Set as fixed
place_ctx.block_locs[blk_id].is_fixed = true;
}
}
}

bool is_region_size_one(const Region& reg, t_logical_block_type_ptr block_type) {
auto& device_ctx = g_vpr_ctx.device();
vtr::Rect<int> rb = reg.get_region_rect();
bool size_one = false;

if (rb.xmin() == rb.xmax() && rb.ymin() == rb.ymax()) {
if (reg.get_sub_tile() != NO_SUBTILE) {
size_one = true;
} else {
int x = rb.xmin();
int y = rb.ymin();
auto tile = device_ctx.grid[x][y].type;
if (is_tile_compatible(tile, block_type)) {
auto cap = tile->capacity;
if (cap == 1) {
size_one = true;
} else {
size_one = false;
}
} else {
return false;
//give an error because somehow tile and block type not compatible;
}
}
} else {
size_one = false;
}

return size_one;
}

bool is_pr_size_one(PartitionRegion& pr, t_logical_block_type_ptr block_type, t_pl_loc& loc) {
std::vector<Region> regions = pr.get_partition_region();
bool pr_size_one;
bool reg_size_one;
Region intersect_reg;

for (unsigned int i = 0; i < regions.size(); i++) {
reg_size_one = is_region_size_one(regions[i], block_type);
if (!reg_size_one) {
pr_size_one = false;
break;
} else {
if (i == 0) {
intersect_reg = regions[0];
} else {
intersect_reg = intersection(intersect_reg, regions[i]);
}
if (intersect_reg.empty()) {
pr_size_one = false;
break;
} else {
pr_size_one = true;
}
}
}

vtr::Rect<int> rect = intersect_reg.get_region_rect();
loc.x = rect.xmin();
loc.y = rect.ymin();
if (intersect_reg.get_sub_tile() == NO_SUBTILE) {
loc.sub_tile = 0;
} else {
loc.sub_tile = intersect_reg.get_sub_tile();
}

return pr_size_one;
}
14 changes: 14 additions & 0 deletions vpr/src/place/place_constraints.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,18 @@ inline bool floorplan_legal(const t_pl_blocks_to_be_moved& blocks_affected) {
*/
void load_cluster_constraints();

/*
* Marks blocks as fixed if they have a constraint region that specifies exactly one x, y,
* subtile location as legal.
* Marking them as fixed indicates that they cannot be moved during initial placement and simulated annealing
*/
void mark_fixed_blocks();

/*
* Number of tiles covered by a region
*/
bool is_region_size_one(const Region& reg, t_logical_block_type_ptr block_type);

bool is_pr_size_one(PartitionRegion& pr, t_logical_block_type_ptr block_type, t_pl_loc& loc);

#endif /* VPR_SRC_PLACE_PLACE_CONSTRAINTS_H_ */
35 changes: 35 additions & 0 deletions vpr/src/place/place_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,3 +427,38 @@ void alloc_and_load_legal_placement_locations(std::vector<std::vector<std::vecto
//avoid any memory waste
legal_pos.shrink_to_fit();
}

void set_block_location(ClusterBlockId blk_id, const t_pl_loc& location) {
auto& place_ctx = g_vpr_ctx.mutable_placement();
auto& device_ctx = g_vpr_ctx.device();
auto& cluster_ctx = g_vpr_ctx.clustering();

std::string block_name = cluster_ctx.clb_nlist.block_name(blk_id);

//Check if block location is out of range of grid dimensions
if (location.x < 0 || location.x > int(device_ctx.grid.width() - 1)
|| location.y < 0 || location.y > int(device_ctx.grid.height() - 1)) {
VPR_THROW(VPR_ERROR_PLACE, "Block %s with ID %d is out of range at location (%d, %d). \n", block_name.c_str(), blk_id, location.x, location.y);
}

//Set the location of the block
place_ctx.block_locs[blk_id].loc.x = location.x;
place_ctx.block_locs[blk_id].loc.y = location.y;
place_ctx.block_locs[blk_id].loc.sub_tile = location.sub_tile;

//Check if block is at an illegal location
auto physical_tile = device_ctx.grid[location.x][location.y].type;
auto logical_block = cluster_ctx.clb_nlist.block_type(blk_id);

if (location.sub_tile >= physical_tile->capacity || location.sub_tile < 0) {
VPR_THROW(VPR_ERROR_PLACE, "Block %s subtile number (%d) is out of range. \n", block_name.c_str(), location.sub_tile);
}

if (!is_sub_tile_compatible(physical_tile, logical_block, place_ctx.block_locs[blk_id].loc.sub_tile)) {
VPR_THROW(VPR_ERROR_PLACE, "Attempt to place block %s with ID %d at illegal location (%d, %d). \n", block_name.c_str(), blk_id, location.x, location.y);
}

//Mark the grid location and usage of the block
place_ctx.grid_blocks[location.x][location.y].blocks[location.sub_tile] = blk_id;
place_ctx.grid_blocks[location.x][location.y].usage++;
}
3 changes: 3 additions & 0 deletions vpr/src/place/place_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,7 @@ void load_grid_blocks_from_block_locs();

///@brief Builds legal_pos structure. legal_pos[type->index] is an array that gives every legal value of (x,y,z) that can accommodate a block.
void alloc_and_load_legal_placement_locations(std::vector<std::vector<std::vector<t_pl_loc>>>& legal_pos);

///@brief Marks the location and grid usage for a block that is set at a location
void set_block_location(ClusterBlockId blk_id, const t_pl_loc& location);
#endif
36 changes: 2 additions & 34 deletions vpr/test/test_vpr_constraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ TEST_CASE("Region", "[vpr]") {
REQUIRE(rect.ymax() == 4);
REQUIRE(r1.get_sub_tile() == 2);

//checking that default constructor creates an empty rectangle (-1,-1,-1,-1)
//checking that default constructor creates an empty rectangle (999, 999,-1,-1)
Region def_region;
bool is_def_empty = false;

vtr::Rect<int> def_rect = def_region.get_region_rect();
is_def_empty = def_rect.empty();
REQUIRE(is_def_empty == true);
REQUIRE(def_rect.xmin() == -1);
REQUIRE(def_rect.xmin() == 999);
REQUIRE(def_region.get_sub_tile() == -1);
}

Expand Down Expand Up @@ -394,38 +394,6 @@ TEST_CASE("PartRegionIntersect6", "[vpr]") {
REQUIRE(regions[3].get_region_rect() == int_r2r4);
}

//Test the locked member function of the Region class
TEST_CASE("RegionLocked", "[vpr]") {
Region r1;
bool is_r1_locked = false;

//set the region to a specific x, y, subtile location - region is locked
r1.set_region_rect(2, 3, 2, 3); //point (2,3) to point (2,3) - locking to specific x, y location
r1.set_sub_tile(3); //locking down to subtile 3

is_r1_locked = r1.locked();

REQUIRE(is_r1_locked == true);

//do not set region to specific x, y location - region is not locked even if a subtile is specified
r1.set_region_rect(2, 3, 5, 6); //point (2,3) to point (5,6) - not locking to specific x, y location
r1.set_sub_tile(3); //locking down to subtile 3

is_r1_locked = r1.locked();

REQUIRE(is_r1_locked == false);

//do not specify a subtile for the region - region is not locked even if it is set at specific x, y location
Region r2;
bool is_r2_locked = true;

r2.set_region_rect(2, 3, 2, 3);

is_r2_locked = r2.locked();

REQUIRE(is_r2_locked == false);
}

//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.
Expand Down