diff --git a/vpr/src/pack/attraction_groups.cpp b/vpr/src/pack/attraction_groups.cpp index 3509900f23a..2c70d9d11cd 100644 --- a/vpr/src/pack/attraction_groups.cpp +++ b/vpr/src/pack/attraction_groups.cpp @@ -26,17 +26,7 @@ AttractionInfo::AttractionInfo(bool attraction_groups_on) { } //Then, fill in the group id for the atoms that do have an attraction group - int num_att_grps = attraction_groups.size(); - - for (int igroup = 0; igroup < num_att_grps; igroup++) { - AttractGroupId group_id(igroup); - - AttractionGroup att_group = attraction_groups[group_id]; - - for (unsigned int iatom = 0; iatom < att_group.group_atoms.size(); iatom++) { - atom_attraction_group[att_group.group_atoms[iatom]] = group_id; - } - } + assign_atom_attraction_ids(); att_group_pulls = 1; } @@ -90,6 +80,56 @@ void AttractionInfo::create_att_groups_for_overfull_regions() { } //Then, fill in the group id for the atoms that do have an attraction group + assign_atom_attraction_ids(); + + att_group_pulls = 1; + + VTR_LOG("%d clustering attraction groups created. \n", attraction_groups.size()); +} + +void AttractionInfo::create_att_groups_for_all_regions() { + auto& floorplanning_ctx = g_vpr_ctx.mutable_floorplanning(); + auto& atom_ctx = g_vpr_ctx.atom(); + int num_parts = floorplanning_ctx.constraints.get_num_partitions(); + + //clear the data structures before continuing + atom_attraction_group.clear(); + attraction_groups.clear(); + + //Initialize every atom to have no attraction group id + int num_atoms = atom_ctx.nlist.blocks().size(); + + atom_attraction_group.resize(num_atoms); + fill(atom_attraction_group.begin(), atom_attraction_group.end(), AttractGroupId::INVALID()); + + /* + * Create a PartitionRegion that contains all the overfull regions so that you can + * make an attraction group for any partition that intersects with any of these regions + */ + + /* + * Create an attraction group for each parition with an overfull region. + */ + + for (int ipart = 0; ipart < num_parts; ipart++) { + PartitionId partid(ipart); + + AttractionGroup group_info; + group_info.group_atoms = floorplanning_ctx.constraints.get_part_atoms(partid); + + attraction_groups.push_back(group_info); + } + + //Then, fill in the group id for the atoms that do have an attraction group + assign_atom_attraction_ids(); + + att_group_pulls = 1; + + VTR_LOG("%d clustering attraction groups created. \n", attraction_groups.size()); +} + +void AttractionInfo::assign_atom_attraction_ids() { + //Fill in the group id for the atoms that do have an attraction group int num_att_grps = attraction_groups.size(); for (int igroup = 0; igroup < num_att_grps; igroup++) { @@ -101,10 +141,6 @@ void AttractionInfo::create_att_groups_for_overfull_regions() { atom_attraction_group[att_group.group_atoms[iatom]] = group_id; } } - - att_group_pulls = 1; - - VTR_LOG("%d clustering attraction groups created. \n", num_att_grps); } void AttractionInfo::set_attraction_group_info(AttractGroupId group_id, const AttractionGroup& group_info) { diff --git a/vpr/src/pack/attraction_groups.h b/vpr/src/pack/attraction_groups.h index af85af26144..109afa667cc 100644 --- a/vpr/src/pack/attraction_groups.h +++ b/vpr/src/pack/attraction_groups.h @@ -50,8 +50,19 @@ class AttractionInfo { //If no constraints were specified, then no attraction groups will be created. AttractionInfo(bool attraction_groups_on); + /* + * Create attraction groups for the partitions that contain overfull regions (i.e. + * The region has more blocks of a certain type assigned to than are actually available). + */ void create_att_groups_for_overfull_regions(); + /* + * Create attraction groups for all partitions. + */ + void create_att_groups_for_all_regions(); + + void assign_atom_attraction_ids(); + //Setters and getters for the class AttractGroupId get_atom_attraction_group(const AtomBlockId atom_id); diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index e27bd617a54..bf6354adda3 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -2764,13 +2764,29 @@ static void add_cluster_molecule_candidates_by_attraction_group(t_pb* cur_pb, } AttractionGroup& group = attraction_groups.get_attraction_group_info(grp_id); - int num_available_atoms = group.group_atoms.size(); + std::vector available_atoms; + for (AtomBlockId atom_id : group.group_atoms) { + const auto& atom_model = atom_ctx.nlist.block_model(atom_id); + auto itr = primitive_candidate_block_types.find(atom_model); + VTR_ASSERT(itr != primitive_candidate_block_types.end()); + std::vector& candidate_types = itr->second; + + //Only consider molecules that are unpacked and of the correct type + if (atom_ctx.lookup.atom_clb(atom_id) == ClusterBlockId::INVALID() + && std::find(candidate_types.begin(), candidate_types.end(), cluster_type) != candidate_types.end()) { + available_atoms.push_back(atom_id); + } + } + + //int num_available_atoms = group.group_atoms.size(); + int num_available_atoms = available_atoms.size(); if (num_available_atoms == 0) { return; } if (num_available_atoms < 500) { - for (AtomBlockId atom_id : group.group_atoms) { + //for (AtomBlockId atom_id : group.group_atoms) { + for (AtomBlockId atom_id : available_atoms) { const auto& atom_model = atom_ctx.nlist.block_model(atom_id); auto itr = primitive_candidate_block_types.find(atom_model); VTR_ASSERT(itr != primitive_candidate_block_types.end()); @@ -2804,7 +2820,8 @@ static void add_cluster_molecule_candidates_by_attraction_group(t_pb* cur_pb, std::uniform_int_distribution<> distr(min, max); int selected_atom = distr(gen); - AtomBlockId blk_id = group.group_atoms[selected_atom]; + //AtomBlockId blk_id = group.group_atoms[selected_atom]; + AtomBlockId blk_id = available_atoms[selected_atom]; const auto& atom_model = atom_ctx.nlist.block_model(blk_id); auto itr = primitive_candidate_block_types.find(atom_model); VTR_ASSERT(itr != primitive_candidate_block_types.end()); diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 28bcc7ac84f..f6490f2d1a5 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -178,18 +178,38 @@ bool try_pack(t_packer_opts* packer_opts, VTR_LOG("Packing failed to fit on device. Re-packing with: unrelated_logic_clustering=%s balance_block_type_util=%s\n", (allow_unrelated_clustering ? "true" : "false"), (balance_block_type_util ? "true" : "false")); + /* + * When running with tight floorplan constraints, some regions may become overfull with clusters (i.e. + * the number of blocks assigned to the region exceeds the number of blocks available). When this occurs, we + * cluster more densely to be able to adhere to the floorplan constraints. However, we do not want to cluster more + * densely unnecessarily, as this can negatively impact wirelength. So, we have iterative approach. We check at the end + * of every iteration if any floorplan regions are overfull. In the first iteration, we run + * with no attraction groups (not packing more densely). If regions are overfull at the end of the first iteration, + * we create attraction groups for partitions with overfull regions (pack those atoms more densely). We continue this way + * until the last iteration, when we create attraction groups for every partition, if needed. + */ } else if (pack_iteration == 1 && floorplan_not_fitting) { VTR_LOG("Floorplan regions are overfull: trying to pack again using cluster attraction groups. \n"); attraction_groups.create_att_groups_for_overfull_regions(); attraction_groups.set_att_group_pulls(1); } else if (pack_iteration >= 2 && pack_iteration < 5 && floorplan_not_fitting) { - VTR_LOG("Floorplan regions are overfull: trying to pack again with more attraction groups exploration and higher target pin utilization. \n"); - attraction_groups.create_att_groups_for_overfull_regions(); - VTR_LOG("Pack iteration is %d\n", pack_iteration); - attraction_groups.set_att_group_pulls(4); - t_ext_pin_util pin_util(1.0, 1.0); - target_external_pin_util.set_block_pin_util("clb", pin_util); + if (pack_iteration == 2) { + VTR_LOG("Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n"); + attraction_groups.create_att_groups_for_overfull_regions(); + VTR_LOG("Pack iteration is %d\n", pack_iteration); + } else if (pack_iteration == 3) { + attraction_groups.create_att_groups_for_all_regions(); + VTR_LOG("Floorplan regions are overfull: trying to pack again with more attraction groups exploration. \n"); + VTR_LOG("Pack iteration is %d\n", pack_iteration); + } else if (pack_iteration == 4) { + attraction_groups.create_att_groups_for_all_regions(); + VTR_LOG("Floorplan regions are overfull: trying to pack again with more attraction groups exploration and higher target pin utilization. \n"); + VTR_LOG("Pack iteration is %d\n", pack_iteration); + attraction_groups.set_att_group_pulls(4); + t_ext_pin_util pin_util(1.0, 1.0); + target_external_pin_util.set_block_pin_util("clb", pin_util); + } } else { //Unable to pack densely enough: Give Up diff --git a/vpr/src/place/centroid_move_generator.cpp b/vpr/src/place/centroid_move_generator.cpp index 9a1b665941f..a4d39bd740c 100644 --- a/vpr/src/place/centroid_move_generator.cpp +++ b/vpr/src/place/centroid_move_generator.cpp @@ -32,7 +32,7 @@ e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& block calculate_centroid_loc(b_from, false, centroid, NULL); /* Find a location near the weighted centroid_loc */ - if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to)) { + if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to, b_from)) { return e_create_move::ABORT; } diff --git a/vpr/src/place/critical_uniform_move_generator.cpp b/vpr/src/place/critical_uniform_move_generator.cpp index 15d7867c6bb..c62e349c4ef 100644 --- a/vpr/src/place/critical_uniform_move_generator.cpp +++ b/vpr/src/place/critical_uniform_move_generator.cpp @@ -30,7 +30,7 @@ e_create_move CriticalUniformMoveGenerator::propose_move(t_pl_blocks_to_be_moved t_pl_loc to; - if (!find_to_loc_uniform(cluster_from_type, rlim, from, to)) { + if (!find_to_loc_uniform(cluster_from_type, rlim, from, to, b_from)) { return e_create_move::ABORT; } diff --git a/vpr/src/place/feasible_region_move_generator.cpp b/vpr/src/place/feasible_region_move_generator.cpp index 2d075b9a4e2..9e7d6a6c684 100644 --- a/vpr/src/place/feasible_region_move_generator.cpp +++ b/vpr/src/place/feasible_region_move_generator.cpp @@ -112,14 +112,14 @@ e_create_move FeasibleRegionMoveGenerator::propose_move(t_pl_blocks_to_be_moved& range_limiters.first_rlim = place_move_ctx.first_rlim; // Try to find a legal location inside the feasible region - if (!find_to_loc_median(cluster_from_type, from, &FR_coords, to)) { + if (!find_to_loc_median(cluster_from_type, from, &FR_coords, to, b_from)) { /** If there is no legal location in the feasible region, calculate the center of the FR and try to find a legal location * in a range around this center. */ t_pl_loc center; center.x = (FR_coords.xmin + FR_coords.xmax) / 2; center.y = (FR_coords.ymin + FR_coords.ymax) / 2; - if (!find_to_loc_centroid(cluster_from_type, from, center, range_limiters, to)) + if (!find_to_loc_centroid(cluster_from_type, from, center, range_limiters, to, b_from)) return e_create_move::ABORT; } diff --git a/vpr/src/place/median_move_generator.cpp b/vpr/src/place/median_move_generator.cpp index 1d1f3335268..03c37ad205d 100644 --- a/vpr/src/place/median_move_generator.cpp +++ b/vpr/src/place/median_move_generator.cpp @@ -119,7 +119,7 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_ t_pl_loc median_point; median_point.x = (limit_coords.xmin + limit_coords.xmax) / 2; median_point.y = (limit_coords.ymin + limit_coords.ymax) / 2; - if (!find_to_loc_centroid(cluster_from_type, from, median_point, range_limiters, to)) + if (!find_to_loc_centroid(cluster_from_type, from, median_point, range_limiters, to, b_from)) return e_create_move::ABORT; e_create_move create_move = ::create_move(blocks_affected, b_from, to); diff --git a/vpr/src/place/move_utils.cpp b/vpr/src/place/move_utils.cpp index 8822b8b8db3..6b6c2dfa440 100644 --- a/vpr/src/place/move_utils.cpp +++ b/vpr/src/place/move_utils.cpp @@ -8,6 +8,8 @@ #include "draw_debug.h" #include "draw.h" +#include "place_constraints.h" + //f_placer_breakpoint_reached is used to stop the placer when a breakpoint is reached. When this flag is true, it stops the placer after the current perturbation. Thus, when a breakpoint is reached, this flag is set to true. //Note: The flag is only effective if compiled with VTR_ENABLE_DEBUG_LOGGING bool f_placer_breakpoint_reached = false; @@ -532,7 +534,8 @@ ClusterBlockId pick_from_block() { bool find_to_loc_uniform(t_logical_block_type_ptr type, float rlim, const t_pl_loc from, - t_pl_loc& to) { + t_pl_loc& to, + ClusterBlockId b_from) { //Finds a legal swap to location for the given type, starting from 'from.x' and 'from.y' // //Note that the range limit (rlim) is applied in a logical sense (i.e. 'compressed' grid space consisting @@ -566,6 +569,13 @@ bool find_to_loc_uniform(t_logical_block_type_ptr type, int cy_to = OPEN; bool legal = false; + if (is_cluster_constrained(b_from)) { + bool intersect = intersect_range_limit_with_floorplan_constraints(type, b_from, min_cx, min_cy, max_cx, max_cy, delta_cx); + if (!intersect) { + return false; + } + } + legal = find_compatible_compressed_loc_in_range(type, min_cx, max_cx, min_cy, max_cy, delta_cx, cx_from, cy_from, cx_to, cy_to, false); if (!legal) { @@ -601,7 +611,8 @@ void set_placer_breakpoint_reached(bool flag) { bool find_to_loc_median(t_logical_block_type_ptr blk_type, const t_pl_loc& from_loc, const t_bb* limit_coords, - t_pl_loc& to_loc) { + t_pl_loc& to_loc, + ClusterBlockId b_from) { const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[blk_type->index]; //Determine the coordinates in the compressed grid space of the current block @@ -630,6 +641,13 @@ bool find_to_loc_median(t_logical_block_type_ptr blk_type, int cy_to = OPEN; bool legal = false; + if (is_cluster_constrained(b_from)) { + bool intersect = intersect_range_limit_with_floorplan_constraints(blk_type, b_from, min_cx, min_cy, max_cx, max_cy, delta_cx); + if (!intersect) { + return false; + } + } + legal = find_compatible_compressed_loc_in_range(blk_type, min_cx, max_cx, min_cy, max_cy, delta_cx, cx_from, cy_from, cx_to, cy_to, true); if (!legal) { @@ -657,7 +675,8 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type, const t_pl_loc& from_loc, const t_pl_loc& centroid, const t_range_limiters& range_limiters, - t_pl_loc& to_loc) { + t_pl_loc& to_loc, + ClusterBlockId b_from) { //Retrieve the compressed block grid for this block type const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[blk_type->index]; @@ -707,6 +726,13 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type, int cy_to = OPEN; bool legal = false; + if (is_cluster_constrained(b_from)) { + bool intersect = intersect_range_limit_with_floorplan_constraints(blk_type, b_from, min_cx, min_cy, max_cx, max_cy, delta_cx); + if (!intersect) { + return false; + } + } + legal = find_compatible_compressed_loc_in_range(blk_type, min_cx, max_cx, min_cy, max_cy, delta_cx, cx_from, cy_from, cx_to, cy_to, false); if (!legal) { @@ -848,6 +874,50 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type, int return legal; } +bool intersect_range_limit_with_floorplan_constraints(t_logical_block_type_ptr type, ClusterBlockId b_from, int& min_cx, int& min_cy, int& max_cx, int& max_cy, int& delta_cx) { + //Retrieve the compressed block grid for this block type + const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[type->index]; + + int min_x = compressed_block_grid.compressed_to_grid_x[min_cx]; + int max_x = compressed_block_grid.compressed_to_grid_x[max_cx]; + int min_y = compressed_block_grid.compressed_to_grid_y[min_cy]; + int max_y = compressed_block_grid.compressed_to_grid_y[max_cy]; + Region range_reg; + range_reg.set_region_rect(min_x, min_y, max_x, max_y); + + auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); + + PartitionRegion pr = floorplanning_ctx.cluster_constraints[b_from]; + std::vector regions; + if (!pr.empty()) { + regions = pr.get_partition_region(); + } + Region intersect_reg; + /* + * If region size is greater than 1, the block is constrained to more than one rectangular region. + * In this case, we return true (i.e. the range limit intersects with + * the floorplan constraints) to simplify the problem. This simplification can be done because + * this routine is done for cpu time optimization, so we do not have to necessarily check each + * complicated case to get correct functionality during place moves. + */ + if (regions.size() == 1) { + intersect_reg = intersection(regions[0], range_reg); + + if (intersect_reg.empty()) { + return false; + } else { + vtr::Rect rect = intersect_reg.get_region_rect(); + min_cx = grid_to_compressed_approx(compressed_block_grid.compressed_to_grid_x, rect.xmin()); + max_cx = grid_to_compressed_approx(compressed_block_grid.compressed_to_grid_x, rect.xmax()); + min_cy = grid_to_compressed_approx(compressed_block_grid.compressed_to_grid_y, rect.ymin()); + max_cy = grid_to_compressed_approx(compressed_block_grid.compressed_to_grid_y, rect.ymax()); + delta_cx = max_cx - min_cx; + } + } + + return true; +} + std::string e_move_result_to_string(e_move_result move_outcome) { std::string move_result_to_string[] = {"Rejected", "Accepted", "Aborted"}; return move_result_to_string[move_outcome]; diff --git a/vpr/src/place/move_utils.h b/vpr/src/place/move_utils.h index 3b0f01f9bcb..29a796a7f7f 100644 --- a/vpr/src/place/move_utils.h +++ b/vpr/src/place/move_utils.h @@ -102,7 +102,8 @@ ClusterBlockId pick_from_block(); bool find_to_loc_uniform(t_logical_block_type_ptr type, float rlim, const t_pl_loc from, - t_pl_loc& to); + t_pl_loc& to, + ClusterBlockId b_from); // Accessor f_placer_breakpoint_reached // return true when a placer breakpoint is reached @@ -125,7 +126,7 @@ void set_placer_breakpoint_reached(bool); * @param limit_coords: the region where I can move the block to * @param to_loc: the new location that the function picked for the block */ -bool find_to_loc_median(t_logical_block_type_ptr blk_type, const t_pl_loc& from_loc, const t_bb* limit_coords, t_pl_loc& to_loc); +bool find_to_loc_median(t_logical_block_type_ptr blk_type, const t_pl_loc& from_loc, const t_bb* limit_coords, t_pl_loc& to_loc, ClusterBlockId b_from); /** * @brief Find a legal swap to location for the given type in a range around a specific location. @@ -145,7 +146,8 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type, const t_pl_loc& from_loc, const t_pl_loc& centeroid, const t_range_limiters& range_limiters, - t_pl_loc& to_loc); + t_pl_loc& to_loc, + ClusterBlockId b_from); std::string move_type_to_string(e_move_type); @@ -171,6 +173,23 @@ void compressed_grid_to_loc(t_logical_block_type_ptr blk_type, int cx, int cy, t */ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type, int min_cx, int max_cx, int min_cy, int max_cy, int delta_cx, int cx_from, int cy_from, int& cx_to, int& cy_to, bool is_median); +/* + * If the block to be moved (b_from) has a floorplan constraint, this routine changes the max and min coords + * in the compressed grid (min_cx, min_cy, max_cx, max_cy) to make sure the range limit is within the floorplan constraint. + * + * Returns false if there is no intersection between the range limit and the floorplan constraint, + * true otherwise. + * + * + * If region size of the block's floorplan constraints is greater than 1, the block is constrained to more than one rectangular region. + * In this case, we return true (i.e. the range limit intersects with + * the floorplan constraints) to simplify the problem. This simplification can be done because + * this routine is done for cpu time optimization, so we do not have to necessarily check each + * complicated case to get correct functionality during place moves. + * + */ +bool intersect_range_limit_with_floorplan_constraints(t_logical_block_type_ptr type, ClusterBlockId b_from, int& min_cx, int& min_cy, int& max_cx, int& max_cy, int& delta_cx); + std::string e_move_result_to_string(e_move_result move_outcome); #endif diff --git a/vpr/src/place/uniform_move_generator.cpp b/vpr/src/place/uniform_move_generator.cpp index cbb0d2c2401..19fc735f014 100644 --- a/vpr/src/place/uniform_move_generator.cpp +++ b/vpr/src/place/uniform_move_generator.cpp @@ -18,7 +18,7 @@ e_create_move UniformMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks t_pl_loc to; - if (!find_to_loc_uniform(cluster_from_type, rlim, from, to)) { + if (!find_to_loc_uniform(cluster_from_type, rlim, from, to, b_from)) { return e_create_move::ABORT; } diff --git a/vpr/src/place/weighted_centroid_move_generator.cpp b/vpr/src/place/weighted_centroid_move_generator.cpp index 34060f56a5d..5870c08f317 100644 --- a/vpr/src/place/weighted_centroid_move_generator.cpp +++ b/vpr/src/place/weighted_centroid_move_generator.cpp @@ -32,7 +32,7 @@ e_create_move WeightedCentroidMoveGenerator::propose_move(t_pl_blocks_to_be_move calculate_centroid_loc(b_from, true, centroid, criticalities); /* Find a */ - if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to)) { + if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to, b_from)) { return e_create_move::ABORT; } diff --git a/vpr/src/place/weighted_median_move_generator.cpp b/vpr/src/place/weighted_median_move_generator.cpp index 761c9b30c5a..a69ebc17b92 100644 --- a/vpr/src/place/weighted_median_move_generator.cpp +++ b/vpr/src/place/weighted_median_move_generator.cpp @@ -99,7 +99,7 @@ e_create_move WeightedMedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& t_pl_loc w_median_point; w_median_point.x = (limit_coords.xmin + limit_coords.xmax) / 2; w_median_point.y = (limit_coords.ymin + limit_coords.ymax) / 2; - if (!find_to_loc_centroid(cluster_from_type, from, w_median_point, range_limiters, to)) { + if (!find_to_loc_centroid(cluster_from_type, from, w_median_point, range_limiters, to, b_from)) { return e_create_move::ABORT; }