Skip to content

Commit 28e050f

Browse files
Merge pull request #3009 from AlexandreSinger/hotfix-ap-fixed-blocks-ip
[AP][HotFix] Placed Fixed Blocks First During IP
2 parents 971da65 + 8197dcb commit 28e050f

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)