Skip to content

Refactor init place for floorplanning #1817

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 15 commits into from
Aug 31, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
84 changes: 50 additions & 34 deletions vpr/src/place/initial_placement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
struct t_block_score {
int macro_size = 0; //how many members does the macro have, if the block is part of one, this value is zero if the block is not in a macro

int floorplan_constraints = 0; //how many floorplan constraints does it have, if any
/*
* The number of tiles NOT covered by the block's floorplan constraints. The higher this number, the more
* difficult the block is to place.
*/
int tiles_outside_of_floorplan_constraints = 0;

int num_equivalent_tiles = 1; //num of physical locations at which this block could be placed
};
Expand All @@ -31,9 +35,9 @@ static int get_free_sub_tile(std::vector<std::vector<int>>& free_locations, int

static int check_macro_can_be_placed(t_pl_macro pl_macro, int itype, t_pl_loc head_pos);
static int try_place_macro(int itype, int ipos, int isub_tile, t_pl_macro pl_macro);
static void initial_placement_pl_macros(int macros_max_num_tries, std::vector<std::vector<int>>& free_locations);
static void initial_placement_pl_macros(int macros_max_num_tries, std::vector<std::vector<int>>& free_locations, const std::vector<t_pl_macro>& sorted_macros);

static void initial_placement_blocks(std::vector<std::vector<int>>& free_locations, enum e_pad_loc_type pad_loc_type, std::vector<ClusterBlockId> sorted_blocks);
static void initial_placement_blocks(std::vector<std::vector<int>>& free_locations, enum e_pad_loc_type pad_loc_type, const std::vector<ClusterBlockId>& sorted_blocks);

static t_physical_tile_type_ptr pick_placement_type(t_logical_block_type_ptr logical_block,
int num_needed_types,
Expand All @@ -49,6 +53,9 @@ vtr::vector<ClusterBlockId, t_block_score> assign_block_scores();
//Sort the blocks according to how difficult they are to place, prior to initial placement
std::vector<ClusterBlockId> sort_blocks(const vtr::vector<ClusterBlockId, t_block_score>& block_scores);

//Sort the macros according to how difficult they are to place, prior to initial placement
std::vector<t_pl_macro> sort_macros(const vtr::vector<ClusterBlockId, t_block_score>& block_scores);

void print_sorted_blocks(const std::vector<ClusterBlockId>& sorted_blocks, const vtr::vector<ClusterBlockId, t_block_score>& block_scores);

static int get_free_sub_tile(std::vector<std::vector<int>>& free_locations, int itype, std::vector<int> possible_sub_tiles) {
Expand Down Expand Up @@ -161,33 +168,15 @@ static int try_place_macro(int itype, int ipos, int isub_tile, t_pl_macro pl_mac
return (macro_placed);
}

static void initial_placement_pl_macros(int macros_max_num_tries, std::vector<std::vector<int>>& free_locations) {
static void initial_placement_pl_macros(int macros_max_num_tries, std::vector<std::vector<int>>& free_locations, const std::vector<t_pl_macro>& sorted_macros) {
int macro_placed;
int itype, itry, ipos, isub_tile;
ClusterBlockId blk_id;

auto& cluster_ctx = g_vpr_ctx.clustering();
auto& place_ctx = g_vpr_ctx.placement();

auto& pl_macros = place_ctx.pl_macros;

// Sorting blocks to place to have most constricted ones to be placed first
std::vector<t_pl_macro> sorted_pl_macros(pl_macros.begin(), pl_macros.end());

auto criteria = [&cluster_ctx](const t_pl_macro lhs, t_pl_macro rhs) {
auto lhs_logical_block = cluster_ctx.clb_nlist.block_type(lhs.members[0].blk_index);
auto rhs_logical_block = cluster_ctx.clb_nlist.block_type(rhs.members[0].blk_index);

auto lhs_num_tiles = lhs_logical_block->equivalent_tiles.size();
auto rhs_num_tiles = rhs_logical_block->equivalent_tiles.size();

return lhs_num_tiles < rhs_num_tiles;
};

std::stable_sort(sorted_pl_macros.begin(), sorted_pl_macros.end(), criteria);

/* Macros are harder to place. Do them first */
for (auto pl_macro : sorted_pl_macros) {
for (auto pl_macro : sorted_macros) {
// Every macro are not placed in the beginnning
macro_placed = false;

Expand Down Expand Up @@ -255,7 +244,7 @@ static void initial_placement_pl_macros(int macros_max_num_tries, std::vector<st

/* Place blocks that are NOT a part of any macro.
* We'll randomly place each block in the clustered netlist, one by one. */
static void initial_placement_blocks(std::vector<std::vector<int>>& free_locations, enum e_pad_loc_type pad_loc_type, std::vector<ClusterBlockId> sorted_blocks) {
static void initial_placement_blocks(std::vector<std::vector<int>>& free_locations, enum e_pad_loc_type pad_loc_type, const std::vector<ClusterBlockId>& sorted_blocks) {
auto& cluster_ctx = g_vpr_ctx.clustering();
auto& place_ctx = g_vpr_ctx.mutable_placement();

Expand Down Expand Up @@ -349,9 +338,13 @@ static t_physical_tile_type_ptr pick_placement_type(t_logical_block_type_ptr log
vtr::vector<ClusterBlockId, t_block_score> assign_block_scores() {
auto& cluster_ctx = g_vpr_ctx.clustering();
auto& place_ctx = g_vpr_ctx.placement();
auto& floorplan_ctx = g_vpr_ctx.floorplanning();
auto& device_ctx = g_vpr_ctx.device();

int num_grid_tiles = device_ctx.grid.height() * device_ctx.grid.width();

auto blocks = cluster_ctx.clb_nlist.blocks();
auto pl_macros = place_ctx.pl_macros;
auto& pl_macros = place_ctx.pl_macros;

t_block_score score;

Expand All @@ -368,7 +361,9 @@ vtr::vector<ClusterBlockId, t_block_score> assign_block_scores() {
//go through all blocks and store floorplan constraints and num equivalent tiles
for (auto blk_id : blocks) {
if (is_cluster_constrained(blk_id)) {
block_scores[blk_id].floorplan_constraints = 1;
PartitionRegion pr = floorplan_ctx.cluster_constraints[blk_id];
auto block_type = cluster_ctx.clb_nlist.block_type(blk_id);
block_scores[blk_id].tiles_outside_of_floorplan_constraints = num_grid_tiles - get_part_reg_size(pr, block_type);
}
auto logical_block = cluster_ctx.clb_nlist.block_type(blk_id);
auto num_tiles = logical_block->equivalent_tiles.size();
Expand All @@ -394,8 +389,8 @@ std::vector<ClusterBlockId> sort_blocks(const vtr::vector<ClusterBlockId, t_bloc
std::vector<ClusterBlockId> sorted_blocks(blocks.begin(), blocks.end());

auto criteria = [block_scores](ClusterBlockId lhs, ClusterBlockId rhs) {
int lhs_score = 100 * block_scores[lhs].macro_size + 10 * block_scores[lhs].floorplan_constraints + 10 / (block_scores[lhs].num_equivalent_tiles);
int rhs_score = 100 * block_scores[rhs].macro_size + 10 * block_scores[rhs].floorplan_constraints + 10 / (block_scores[rhs].num_equivalent_tiles);
int lhs_score = 10 * block_scores[lhs].macro_size + block_scores[lhs].tiles_outside_of_floorplan_constraints + 10 / (block_scores[lhs].num_equivalent_tiles);
int rhs_score = 10 * block_scores[rhs].macro_size + block_scores[rhs].tiles_outside_of_floorplan_constraints + 10 / (block_scores[rhs].num_equivalent_tiles);

return lhs_score > rhs_score;
};
Expand All @@ -406,10 +401,30 @@ std::vector<ClusterBlockId> sort_blocks(const vtr::vector<ClusterBlockId, t_bloc
return sorted_blocks;
}

std::vector<t_pl_macro> sort_macros(const vtr::vector<ClusterBlockId, t_block_score>& block_scores) {
auto& place_ctx = g_vpr_ctx.placement();

auto& pl_macros = place_ctx.pl_macros;

// Sorting blocks to place to have most constricted ones to be placed first
std::vector<t_pl_macro> sorted_pl_macros(pl_macros.begin(), pl_macros.end());

auto criteria = [block_scores](const t_pl_macro lhs, t_pl_macro rhs) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should be refactored to place blocks & macros in one loop, with the sorted_blocks vector controlling it all.

int lhs_score = 10 * block_scores[lhs.members[0].blk_index].macro_size + block_scores[lhs.members[0].blk_index].tiles_outside_of_floorplan_constraints + 10 / (block_scores[lhs.members[0].blk_index].num_equivalent_tiles);
int rhs_score = 10 * block_scores[rhs.members[0].blk_index].macro_size + block_scores[rhs.members[0].blk_index].tiles_outside_of_floorplan_constraints + 10 / (block_scores[rhs.members[0].blk_index].num_equivalent_tiles);

return lhs_score > rhs_score;
};

std::stable_sort(sorted_pl_macros.begin(), sorted_pl_macros.end(), criteria);

return sorted_pl_macros;
}

void print_sorted_blocks(const std::vector<ClusterBlockId>& sorted_blocks, const vtr::vector<ClusterBlockId, t_block_score>& block_scores) {
VTR_LOG("\nPrinting sorted blocks: \n");
for (unsigned int i = 0; i < sorted_blocks.size(); i++) {
VTR_LOG("Block_Id: %zu, Macro size: %d, Num floorplan constraints: %d, Num equivalent tiles %d \n", sorted_blocks[i], block_scores[sorted_blocks[i]].macro_size, block_scores[sorted_blocks[i]].floorplan_constraints, block_scores[sorted_blocks[i]].num_equivalent_tiles);
VTR_LOG("Block_Id: %zu, Macro size: %d, Num floorplan constraints tiles: %d, Num equivalent tiles %d \n", sorted_blocks[i], block_scores[sorted_blocks[i]].macro_size, block_scores[sorted_blocks[i]].tiles_outside_of_floorplan_constraints, block_scores[sorted_blocks[i]].num_equivalent_tiles);
}
}

Expand All @@ -421,15 +436,16 @@ void initial_placement(enum e_pad_loc_type pad_loc_type, const char* constraints
* array that gives every legal value of (x,y,z) that can accommodate a block.
*/

//Sort blocks
vtr::vector<ClusterBlockId, t_block_score> block_scores = assign_block_scores();
std::vector<ClusterBlockId> sorted_blocks = sort_blocks(block_scores);

/* Go through cluster blocks to calculate the tightest placement
* floorplan constraint for each constrained block
*/
propagate_place_constraints();

//Sort blocks and placement macros according to how difficult they are to place
vtr::vector<ClusterBlockId, t_block_score> block_scores = assign_block_scores();
std::vector<ClusterBlockId> sorted_blocks = sort_blocks(block_scores);
std::vector<t_pl_macro> sorted_macros = sort_macros(block_scores);

// Loading legal placement locations
zero_initialize_grid_blocks();
alloc_and_load_legal_placement_locations(legal_pos);
Expand Down Expand Up @@ -483,7 +499,7 @@ void initial_placement(enum e_pad_loc_type pad_loc_type, const char* 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);
initial_placement_pl_macros(MAX_NUM_TRIES_TO_PLACE_MACROS_RANDOMLY, free_locations, sorted_macros);

// All the macros are placed, update the legal_pos[][] array and free_locations[] array
for (const auto& type : device_ctx.physical_tile_types) {
Expand Down
50 changes: 50 additions & 0 deletions vpr/src/place/place_constraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,3 +413,53 @@ bool is_pr_size_one(PartitionRegion& pr, t_logical_block_type_ptr block_type, t_

return pr_size_one;
}

int get_region_size(const Region& reg, t_logical_block_type_ptr block_type) {
auto& device_ctx = g_vpr_ctx.device();
vtr::Rect<int> reg_rect = reg.get_region_rect();

int xdim = reg_rect.xmax() - reg_rect.xmin() + 1;
int ydim = reg_rect.ymax() - reg_rect.ymin() + 1;

std::vector<std::vector<int>> region_grid(xdim, std::vector<int>(ydim, 0));

for (int i_col = region_grid.size() - 1; i_col >= 0; i_col--) {
for (int j_row = region_grid[i_col].size() - 1; j_row >= 0; j_row--) {
auto& tile = device_ctx.grid[i_col + reg_rect.xmin()][j_row + reg_rect.ymin()].type;

if (is_tile_compatible(tile, block_type)) {
if (reg.get_sub_tile() != NO_SUBTILE) {
if (is_sub_tile_compatible(tile, block_type, reg.get_sub_tile())) {
region_grid[i_col][j_row] = 1;
}
} else {
region_grid[i_col][j_row] = 1;
}
}

if (i_col < signed(region_grid.size() - 1)) {
region_grid[i_col][j_row] += region_grid[i_col + 1][j_row];
}
if (j_row < signed(region_grid[i_col].size() - 1)) {
region_grid[i_col][j_row] += region_grid[i_col][j_row + 1];
}
if (i_col < signed(region_grid.size()) - 1 && j_row < signed(region_grid[i_col].size() - 1)) {
region_grid[i_col][j_row] -= region_grid[i_col + 1][j_row + 1];
}
}
}
int num_tiles = region_grid[0][0];

return num_tiles;
}

int get_part_reg_size(PartitionRegion& pr, t_logical_block_type_ptr block_type) {
std::vector<Region> part_reg = pr.get_partition_region();
int num_tiles = 0;

for (unsigned int i_reg = 0; i_reg < part_reg.size(); i_reg++) {
num_tiles += get_region_size(part_reg[i_reg], block_type);
}

return num_tiles;
}
14 changes: 14 additions & 0 deletions vpr/src/place/place_constraints.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,18 @@ int region_tile_cover(const Region& reg, t_logical_block_type_ptr block_type, t_
*/
bool is_pr_size_one(PartitionRegion& pr, t_logical_block_type_ptr block_type, t_pl_loc& loc);

/*
* Returns the number of grid tiles that are covered by the region and compatible
* with the cluster's block type.
*/
int get_region_size(const Region& reg, t_logical_block_type_ptr block_type);

/*
* Returns the number of grid tiles that are covered by the partition region and
* compatible with the cluster's block type.
* Used prior to initial placement to help sort blocks based on how difficult they
* are to place.
*/
int get_part_reg_size(PartitionRegion& pr, t_logical_block_type_ptr block_type);

#endif /* VPR_SRC_PLACE_PLACE_CONSTRAINTS_H_ */