Skip to content

Commit 8197dcb

Browse files
[AP][HotFix] Placed Fixed Blocks First During IP
The cost terms in the AP initial placer were not placing fixed blocks early enough, causing other blocks to take their place and causing the initial placer to not return a solution. Blocks which have region constraints are now placed first based on how constrained they are. More constrained blocks (can only be placed in a smaller region) will be placed first. Also found that macros that contained fixed blocks were not observing these constraints when calculating the centroid position of the macro. For constrained macros, projected the centroid position onto the partition region to get the closest point in the partition region to the calculated centroid. This new centroid is used to then perform the placement.
1 parent ec56feb commit 8197dcb

File tree

1 file changed

+64
-1
lines changed

1 file changed

+64
-1
lines changed

vpr/src/place/initial_placement.cpp

+64-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include <algorithm>
2626
#include <cmath>
27+
#include <cstdlib>
2728
#include <iterator>
2829
#include <limits>
2930
#include <optional>
@@ -579,6 +580,43 @@ static t_flat_pl_loc find_centroid_loc_from_flat_placement(const t_pl_macro& pl_
579580
if (acc_weight > 0.f) {
580581
centroid /= acc_weight;
581582
}
583+
584+
// If the root cluster is constrained, project the centroid onto its
585+
// partition region. This will move the centroid position to the closest
586+
// position within the partition region.
587+
ClusterBlockId head_cluster_id = pl_macro.members[0].blk_index;
588+
if (is_cluster_constrained(head_cluster_id)) {
589+
// Get the partition region of the head. This is the partition region
590+
// that affects the entire macro.
591+
const PartitionRegion& head_pr = g_vpr_ctx.floorplanning().cluster_constraints[head_cluster_id];
592+
// For each region, find the closest point in that region to the centroid
593+
// and save the closest of all regions.
594+
t_flat_pl_loc best_projected_pos = centroid;
595+
float best_distance = std::numeric_limits<float>::max();
596+
VTR_ASSERT_MSG(centroid.layer == 0,
597+
"3D FPGAs not supported for this part of the code yet");
598+
for (const Region& region : head_pr.get_regions()) {
599+
const vtr::Rect<int>& rect = region.get_rect();
600+
// Note: We add 0.999 here since the partition region is in grid
601+
// space, so it treats tile positions as having size 0x0 when
602+
// they really are 1x1.
603+
float proj_x = std::clamp<float>(centroid.x, rect.xmin(), rect.xmax() + 0.999);
604+
float proj_y = std::clamp<float>(centroid.y, rect.ymin(), rect.ymax() + 0.999);
605+
float dx = std::abs(proj_x - centroid.x);
606+
float dy = std::abs(proj_y - centroid.y);
607+
float dist = dx + dy;
608+
if (dist < best_distance) {
609+
best_projected_pos.x = proj_x;
610+
best_projected_pos.y = proj_y;
611+
best_distance = dist;
612+
}
613+
}
614+
VTR_ASSERT_SAFE(best_distance != std::numeric_limits<float>::max());
615+
// Return the point within the partition region that is closest to the
616+
// original centroid.
617+
return best_projected_pos;
618+
}
619+
582620
return centroid;
583621
}
584622

@@ -1594,6 +1632,7 @@ static inline void place_all_blocks_ap(enum e_pad_loc_type pad_loc_type,
15941632
const FlatPlacementInfo& flat_placement_info) {
15951633
const ClusteredNetlist& cluster_netlist = g_vpr_ctx.clustering().clb_nlist;
15961634
const DeviceGrid& device_grid = g_vpr_ctx.device().grid;
1635+
const auto& cluster_constraints = g_vpr_ctx.floorplanning().cluster_constraints;
15971636

15981637
// Create a list of clusters to place.
15991638
std::vector<ClusterBlockId> clusters_to_place;
@@ -1615,6 +1654,7 @@ static inline void place_all_blocks_ap(enum e_pad_loc_type pad_loc_type,
16151654
constexpr float macro_size_weight = 1.0f;
16161655
constexpr float std_dev_weight = 4.0f;
16171656
vtr::vector<ClusterBlockId, float> cluster_score(cluster_netlist.blocks().size(), 0.0f);
1657+
vtr::vector<ClusterBlockId, float> cluster_constr_area(cluster_netlist.blocks().size(), std::numeric_limits<float>::max());
16181658
for (ClusterBlockId blk_id : cluster_netlist.blocks()) {
16191659
// Compute the standard deviation of the positions of all atoms in the
16201660
// given macro. This is a measure of how much the atoms "want" to be
@@ -1642,9 +1682,32 @@ static inline void place_all_blocks_ap(enum e_pad_loc_type pad_loc_type,
16421682
// should be placed first.
16431683
cluster_score[blk_id] = (macro_size_weight * normalized_macro_size)
16441684
+ (std_dev_weight * (1.0f - normalized_std_dev));
1685+
1686+
// If the cluster is constrained, compute how much area its constrained
1687+
// region takes up. This will be used to place "more constrained" blocks
1688+
// first.
1689+
// TODO: The cluster constrained area can be incorperated into the cost
1690+
// somehow.
1691+
if (is_cluster_constrained(blk_id)) {
1692+
const PartitionRegion& pr = cluster_constraints[blk_id];
1693+
float area = 0.0f;
1694+
for (const Region& region : pr.get_regions()) {
1695+
const vtr::Rect<int> region_rect = region.get_rect();
1696+
// Note: Add 1 here since the width is in grid space (i.e. width
1697+
// of 0 means it can only be placed in 1 x coordinate).
1698+
area += (region_rect.width() + 1) * (region_rect.height() + 1);
1699+
}
1700+
cluster_constr_area[blk_id] = area;
1701+
}
16451702
}
16461703
std::stable_sort(clusters_to_place.begin(), clusters_to_place.end(), [&](ClusterBlockId lhs, ClusterBlockId rhs) {
1647-
// Sort list such that higher score clusters are placed first.
1704+
// Sort the list such that:
1705+
// 1) Clusters that are constrained to less area on the device are placed
1706+
// first.
1707+
if (cluster_constr_area[lhs] != cluster_constr_area[rhs]) {
1708+
return cluster_constr_area[lhs] < cluster_constr_area[rhs];
1709+
}
1710+
// 2) Higher score clusters are placed first.
16481711
return cluster_score[lhs] > cluster_score[rhs];
16491712
});
16501713

0 commit comments

Comments
 (0)