@@ -571,12 +571,42 @@ static std::vector<ClusterBlockId> find_centroid_loc(const t_pl_macro& pl_macro,
571571 return connected_blocks_to_update;
572572}
573573
574+ /* *
575+ * @brief Helper method for getting the flat position of an atom relative to a
576+ * given offset.
577+ *
578+ * This method is useful for chained blocks where an atom may be a member of a
579+ * chain with the given offset. This gives the atom's position relative to the
580+ * head macro's tile location.
581+ */
582+ static t_flat_pl_loc get_atom_relative_flat_loc (AtomBlockId atom_blk_id,
583+ const t_pl_offset& offset,
584+ const FlatPlacementInfo& flat_placement_info,
585+ const DeviceGrid& device_grid) {
586+ // Get the flat location of the atom and the offset.
587+ t_flat_pl_loc atom_pos = flat_placement_info.get_pos (atom_blk_id);
588+ t_flat_pl_loc flat_offset = t_flat_pl_loc ((float )offset.x ,
589+ (float )offset.y ,
590+ (float )offset.layer );
591+ // Get the position of the head macro of the chain that this atom is a part of.
592+ atom_pos -= flat_offset;
593+
594+ // This may put the atom off device (due to the flat placement not being fully
595+ // legal), so we clamp this to be within the device.
596+ atom_pos.x = std::clamp (atom_pos.x , 0 .0f , (float )device_grid.width () - 0 .001f );
597+ atom_pos.y = std::clamp (atom_pos.y , 0 .0f , (float )device_grid.height () - 0 .001f );
598+ atom_pos.layer = std::clamp (atom_pos.layer , 0 .0f , (float )device_grid.get_num_layers () - 0 .001f );
599+
600+ return atom_pos;
601+ }
602+
574603// TODO: Should this return the unplaced_blocks_to_update_their_score?
575604static t_flat_pl_loc find_centroid_loc_from_flat_placement (const t_pl_macro& pl_macro,
576605 const FlatPlacementInfo& flat_placement_info) {
577606 // Use the flat placement to compute the centroid of the given macro.
578607 // TODO: Instead of averaging, maybe use MODE (most frequently placed location).
579- float acc_weight = 0 .f ;
608+ const DeviceGrid& device_grid = g_vpr_ctx.device ().grid ;
609+ unsigned acc_weight = 0 ;
580610 t_flat_pl_loc centroid ({0 .0f , 0 .0f , 0 .0f });
581611 for (const t_pl_macro_member& member : pl_macro.members ) {
582612 const auto & cluster_atoms = g_vpr_ctx.clustering ().atoms_lookup [member.blk_index ];
@@ -585,19 +615,19 @@ static t_flat_pl_loc find_centroid_loc_from_flat_placement(const t_pl_macro& pl_
585615 VTR_ASSERT (flat_placement_info.blk_x_pos [atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS && flat_placement_info.blk_y_pos [atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS && flat_placement_info.blk_layer [atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS && flat_placement_info.blk_sub_tile [atom_blk_id] != FlatPlacementInfo::UNDEFINED_SUB_TILE);
586616
587617 // Accumulate the x, y, layer, and sub_tile for each atom in each
588- // member of the macro. Remove the offset so the centroid would be
589- // where the head macro should be placed to put the members in the
590- // correct place .
591- t_flat_pl_loc cluster_offset ({( float )member. offset . x ,
592- ( float ) member.offset . y ,
593- ( float )member. offset . layer });
594- centroid += flat_placement_info. get_pos (atom_blk_id );
595- centroid -= cluster_offset ;
618+ // member of the macro. The position should be relative to the head
619+ // macro's position such that the centroid is where all blocks think
620+ // the head macro should be .
621+ t_flat_pl_loc atom_pos = get_atom_relative_flat_loc (atom_blk_id ,
622+ member.offset ,
623+ flat_placement_info,
624+ device_grid );
625+ centroid += atom_pos ;
596626 acc_weight++;
597627 }
598628 }
599- if (acc_weight > 0 . f ) {
600- centroid /= acc_weight;
629+ if (acc_weight > 0 ) {
630+ centroid /= static_cast < float >( acc_weight) ;
601631 }
602632
603633 // If the root cluster is constrained, project the centroid onto its
@@ -1532,26 +1562,28 @@ bool place_one_block(const ClusterBlockId blk_id,
15321562static inline float get_flat_variance (const t_pl_macro& macro,
15331563 const FlatPlacementInfo& flat_placement_info) {
15341564
1565+ const DeviceGrid& device_grid = g_vpr_ctx.device ().grid ;
1566+
15351567 // Find the flat centroid location of this macro. Then find the grid location
15361568 // that this would be.
15371569 t_flat_pl_loc centroid_flat_loc = find_centroid_loc_from_flat_placement (macro, flat_placement_info);
15381570 t_physical_tile_loc centroid_grid_loc (centroid_flat_loc.x ,
15391571 centroid_flat_loc.y ,
15401572 centroid_flat_loc.layer );
1573+ VTR_ASSERT (is_loc_on_chip (centroid_grid_loc));
15411574
15421575 // Compute the variance.
1543- float num_atoms = 0 ;
1576+ unsigned num_atoms = 0 ;
15441577 float variance = 0 .0f ;
15451578 for (const t_pl_macro_member& member : macro.members ) {
15461579 const auto & cluster_atoms = g_vpr_ctx.clustering ().atoms_lookup [member.blk_index ];
15471580 for (AtomBlockId atom_blk_id : cluster_atoms) {
15481581 // Get the atom position, offset by the member offset. This translates
15491582 // all atoms to be as if they are in the head position of the macro.
1550- t_flat_pl_loc atom_pos = flat_placement_info.get_pos (atom_blk_id);
1551- t_flat_pl_loc cluster_offset ({(float )member.offset .x ,
1552- (float )member.offset .y ,
1553- (float )member.offset .layer });
1554- atom_pos -= cluster_offset;
1583+ t_flat_pl_loc atom_pos = get_atom_relative_flat_loc (atom_blk_id,
1584+ member.offset ,
1585+ flat_placement_info,
1586+ device_grid);
15551587
15561588 // Get the amount this atom needs to be displaced in order to be
15571589 // within the same tile as the centroid.
@@ -1564,8 +1596,8 @@ static inline float get_flat_variance(const t_pl_macro& macro,
15641596 num_atoms++;
15651597 }
15661598 }
1567- if (num_atoms > 0 . f ) {
1568- variance /= num_atoms;
1599+ if (num_atoms > 0 ) {
1600+ variance /= static_cast < float >( num_atoms) ;
15691601 }
15701602 return variance;
15711603}
@@ -1676,8 +1708,9 @@ static inline std::vector<ClusterBlockId> get_sorted_clusters_to_place(
16761708 // first.
16771709 // TODO: The cluster constrained area can be incorperated into the cost
16781710 // somehow.
1679- if (is_cluster_constrained (blk_id)) {
1680- const PartitionRegion& pr = cluster_constraints[blk_id];
1711+ ClusterBlockId macro_head_blk = pl_macro.members [0 ].blk_index ;
1712+ if (is_cluster_constrained (macro_head_blk)) {
1713+ const PartitionRegion& pr = cluster_constraints[macro_head_blk];
16811714 float area = 0 .0f ;
16821715 for (const Region& region : pr.get_regions ()) {
16831716 const vtr::Rect<int > region_rect = region.get_rect ();
@@ -1705,6 +1738,7 @@ static inline std::vector<ClusterBlockId> get_sorted_clusters_to_place(
17051738/* *
17061739 * @brief Tries to place all of the given clusters as closed to their flat
17071740 * placement as possible (minimum displacement from flat placement).
1741+ * Returns false if any clusters could not be placed.
17081742 *
17091743 * This function will place clusters in passes. In the first pass, it will try
17101744 * to place clusters exactly where their global placement is (according to the
@@ -1713,7 +1747,7 @@ static inline std::vector<ClusterBlockId> get_sorted_clusters_to_place(
17131747 * Subsequent passes will then try to place clusters at exponentially farther
17141748 * distances.
17151749 */
1716- static inline void place_blocks_min_displacement (std::vector<ClusterBlockId>& clusters_to_place,
1750+ static inline bool place_blocks_min_displacement (std::vector<ClusterBlockId>& clusters_to_place,
17171751 enum e_pad_loc_type pad_loc_type,
17181752 BlkLocRegistry& blk_loc_registry,
17191753 const PlaceMacros& place_macros,
@@ -1841,28 +1875,30 @@ static inline void place_blocks_min_displacement(std::vector<ClusterBlockId>& cl
18411875 if (clusters_to_place.size () > 0 ) {
18421876 VTR_LOG (" Unable to place all clusters.\n " );
18431877 VTR_LOG (" Clusters left unplaced:\n " );
1878+ // TODO: Increase the log verbosity of this.
18441879 for (ClusterBlockId blk_id : clusters_to_place) {
18451880 VTR_LOG (" \t %s\n " , cluster_netlist.block_name (blk_id).c_str ());
18461881 }
18471882 }
18481883
1849- // Check if anything has not been placed, if so just crash for now .
1850- // TODO: Should fall back on the original initial placer. Unless there is a
1851- // bug in the code above, it could be that it is challenging to place
1852- // for this circuit.
1853- VTR_ASSERT (clusters_to_place. size () == 0 ) ;
1884+ // Check if anything has not been placed, if so, signal to the calling function .
1885+ if (clusters_to_place. size () > 0 )
1886+ return false ;
1887+
1888+ return true ;
18541889}
18551890
18561891/* *
18571892 * @brief Places all blocks in the clustered netlist as close to the global
1858- * placement produced by the AP flow.
1893+ * placement produced by the AP flow. Returns false if any blocks could
1894+ * not be placed.
18591895 *
18601896 * This function places the blocks in stages. The goal of this stage-based
18611897 * approach is to place clusters which are challenging to place first. Within
18621898 * each stage, the clusters are ordered based on heuristics such that the most
18631899 * impactful clusters get first dibs on placement.
18641900 */
1865- static inline void place_all_blocks_ap (enum e_pad_loc_type pad_loc_type,
1901+ static inline bool place_all_blocks_ap (enum e_pad_loc_type pad_loc_type,
18661902 BlkLocRegistry& blk_loc_registry,
18671903 const PlaceMacros& place_macros,
18681904 const FlatPlacementInfo& flat_placement_info) {
@@ -1892,13 +1928,17 @@ static inline void place_all_blocks_ap(enum e_pad_loc_type pad_loc_type,
18921928
18931929 if (constrained_clusters.size () > 0 ) {
18941930 VTR_LOG (" Placing constrained clusters...\n " );
1895- place_blocks_min_displacement (constrained_clusters,
1931+ bool all_clusters_placed = place_blocks_min_displacement (constrained_clusters,
18961932 pad_loc_type,
18971933 blk_loc_registry,
18981934 place_macros,
18991935 cluster_netlist,
19001936 flat_placement_info);
19011937 VTR_LOG (" \n " );
1938+ if (!all_clusters_placed) {
1939+ VTR_LOG (" Could not place all constrained clusters, falling back on the non-AP initial placement.\n " );
1940+ return false ;
1941+ }
19021942 }
19031943
19041944 // 2. Get all of the large macros and place them next. Large macros have a
@@ -1924,13 +1964,17 @@ static inline void place_all_blocks_ap(enum e_pad_loc_type pad_loc_type,
19241964
19251965 if (large_macro_clusters.size () > 0 ) {
19261966 VTR_LOG (" Placing clusters that are part of larger macros...\n " );
1927- place_blocks_min_displacement (large_macro_clusters,
1967+ bool all_clusters_placed = place_blocks_min_displacement (large_macro_clusters,
19281968 pad_loc_type,
19291969 blk_loc_registry,
19301970 place_macros,
19311971 cluster_netlist,
19321972 flat_placement_info);
19331973 VTR_LOG (" \n " );
1974+ if (!all_clusters_placed) {
1975+ VTR_LOG (" Could not place all large macros, falling back on the non-AP initial placement.\n " );
1976+ return false ;
1977+ }
19341978 }
19351979
19361980 // 3. Place the rest of the clusters. These clusters will be unconstrained
@@ -1948,14 +1992,20 @@ static inline void place_all_blocks_ap(enum e_pad_loc_type pad_loc_type,
19481992
19491993 if (clusters_to_place.size () > 0 ) {
19501994 VTR_LOG (" Placing general clusters...\n " );
1951- place_blocks_min_displacement (clusters_to_place,
1995+ bool all_clusters_placed = place_blocks_min_displacement (clusters_to_place,
19521996 pad_loc_type,
19531997 blk_loc_registry,
19541998 place_macros,
19551999 cluster_netlist,
19562000 flat_placement_info);
19572001 VTR_LOG (" \n " );
2002+ if (!all_clusters_placed) {
2003+ VTR_LOG (" Could not place all clusters, falling back on the non-AP initial placement.\n " );
2004+ return false ;
2005+ }
19582006 }
2007+
2008+ return true ;
19592009}
19602010
19612011void initial_placement (const t_placer_opts& placer_opts,
@@ -1991,13 +2041,29 @@ void initial_placement(const t_placer_opts& placer_opts,
19912041 }
19922042
19932043 // Place all blocks
2044+ bool all_blocks_placed = false ;
2045+
2046+ // First try to place all of the blocks using AP
19942047 if (flat_placement_info.valid ) {
1995- place_all_blocks_ap (placer_opts.pad_loc_type ,
1996- blk_loc_registry,
1997- place_macros,
1998- flat_placement_info);
1999- } else {
2000- // Assign scores to blocks and placement macros according to how difficult they are to place
2048+ all_blocks_placed = place_all_blocks_ap (placer_opts.pad_loc_type ,
2049+ blk_loc_registry,
2050+ place_macros,
2051+ flat_placement_info);
2052+
2053+ // If AP failed to place all of the blocks, reset the placement solution
2054+ // so we can fall back on the original initial placement algorithm.
2055+ if (!all_blocks_placed) {
2056+ blk_loc_registry.clear_all_grid_locs ();
2057+ if (strlen (constraints_file) != 0 ) {
2058+ read_constraints (constraints_file, blk_loc_registry);
2059+ }
2060+ }
2061+ }
2062+
2063+ // If all of the blocks have not been placed (i.e. AP is turned off or
2064+ // is disabled), try to place all of the clusters using heuristics.
2065+ if (!all_blocks_placed) {
2066+ // Assign scores to blocks and placement macros according to how difficult they are to place
20012067 vtr::vector<ClusterBlockId, t_block_score> block_scores = assign_block_scores (place_macros);
20022068
20032069 place_all_blocks (placer_opts, block_scores, placer_opts.pad_loc_type ,
0 commit comments