24
24
25
25
#include < algorithm>
26
26
#include < cmath>
27
+ #include < cstdlib>
27
28
#include < iterator>
28
29
#include < limits>
29
30
#include < optional>
@@ -579,6 +580,43 @@ static t_flat_pl_loc find_centroid_loc_from_flat_placement(const t_pl_macro& pl_
579
580
if (acc_weight > 0 .f ) {
580
581
centroid /= acc_weight;
581
582
}
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
+
582
620
return centroid;
583
621
}
584
622
@@ -1594,6 +1632,7 @@ static inline void place_all_blocks_ap(enum e_pad_loc_type pad_loc_type,
1594
1632
const FlatPlacementInfo& flat_placement_info) {
1595
1633
const ClusteredNetlist& cluster_netlist = g_vpr_ctx.clustering ().clb_nlist ;
1596
1634
const DeviceGrid& device_grid = g_vpr_ctx.device ().grid ;
1635
+ const auto & cluster_constraints = g_vpr_ctx.floorplanning ().cluster_constraints ;
1597
1636
1598
1637
// Create a list of clusters to place.
1599
1638
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,
1615
1654
constexpr float macro_size_weight = 1 .0f ;
1616
1655
constexpr float std_dev_weight = 4 .0f ;
1617
1656
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 ());
1618
1658
for (ClusterBlockId blk_id : cluster_netlist.blocks ()) {
1619
1659
// Compute the standard deviation of the positions of all atoms in the
1620
1660
// 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,
1642
1682
// should be placed first.
1643
1683
cluster_score[blk_id] = (macro_size_weight * normalized_macro_size)
1644
1684
+ (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
+ }
1645
1702
}
1646
1703
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.
1648
1711
return cluster_score[lhs] > cluster_score[rhs];
1649
1712
});
1650
1713
0 commit comments