Skip to content

Commit 5596b80

Browse files
Merge pull request #3231 from AlexandreSinger/feature-appack-update
[APPack] Tuned Up APPack Code
2 parents 18f2b82 + a3d000a commit 5596b80

File tree

25 files changed

+494
-143
lines changed

25 files changed

+494
-143
lines changed

doc/src/vpr/command_line_usage.rst

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,41 @@ Analytical Placement is generally split into three stages:
13841384

13851385
**Default:** ``auto``
13861386

1387+
.. option:: --appack_unrelated_clustering_args { auto | <regex>:<float>,<float> }
1388+
1389+
Sets parameters used for unrelated clustering (the max search distance and max attempts)
1390+
used by APPack.
1391+
APPack uses the primitive-level placement produced by the
1392+
global placer to cluster primitives together. APPack uses this information
1393+
to help increase the density of clusters (if needed) by searching for
1394+
unrelated molecules to pack together. It does this by searching out from
1395+
the centroid of the cluster being created until it finds a valid molecule.
1396+
If a valid molecule is found, but it fails, the packer may do another attempt
1397+
(up to a maximum number of attempts).
1398+
This argument allows the user to select the maximum distance the code will
1399+
search and how many attempts it will try to search for each cluster.
1400+
1401+
When this option is set to auto, VPR will select good values for these
1402+
parameters based on the primitives contained within each logical block type.
1403+
1404+
This option is similar to the appack_max_dist_th argument, where the
1405+
parameters are passed by the user in the form <regex>:<float>,<float> where
1406+
regex is used to match the name of the logical block type to set, the
1407+
first float is the max unrelated tile distance, and the second float
1408+
is the max unrelated clustering attempts.
1409+
1410+
For example:
1411+
1412+
.. code-block:: none
1413+
1414+
--appack_max_dist_th "clb|LAB:10,5"
1415+
1416+
This will set all of the logical block types to their "auto" parameters, except
1417+
for logical blocks with the name clb/LAB which will have a max search distance of
1418+
10 tiles and a maximum of 5 unrelated clustering attempts.
1419+
1420+
**Default:** ``auto``
1421+
13871422
.. option:: --ap_high_fanout_threshold <int>
13881423

13891424
Defines the threshold for high fanout nets within AP flow.

libs/libarchfpga/src/arch_util.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,32 @@ bool pb_type_contains_blif_model(const t_pb_type* pb_type, const std::string& bl
10291029
return false;
10301030
}
10311031

1032+
bool pb_type_contains_memory_pbs(const t_pb_type* pb_type) {
1033+
// TODO: This should be a graph traversal instead of a recursive function.
1034+
1035+
if (pb_type == nullptr)
1036+
return false;
1037+
1038+
// Check if this pb_type is a memory class. If so return true. This acts as
1039+
// a base case for the recursion.
1040+
if (pb_type->class_type == e_pb_type_class::MEMORY_CLASS)
1041+
return true;
1042+
1043+
// Go through all modes of this pb_type and check if any of those modes'
1044+
// children have memory pb_types, if so return true.
1045+
for (int mode_idx = 0; mode_idx < pb_type->num_modes; mode_idx++) {
1046+
const t_mode& mode = pb_type->modes[mode_idx];
1047+
for (int child_idx = 0; child_idx < mode.num_pb_type_children; child_idx++) {
1048+
if (pb_type_contains_memory_pbs(&mode.pb_type_children[child_idx]))
1049+
return true;
1050+
}
1051+
}
1052+
1053+
// If this pb_type is not a memory and its modes do not have memory pbs in
1054+
// them, then this pb_type is not a memory.
1055+
return false;
1056+
}
1057+
10321058
bool has_sequential_annotation(const t_pb_type* pb_type, const t_model_ports* port, enum e_pin_to_pin_delay_annotations annot_type) {
10331059
VTR_ASSERT(annot_type == E_ANNOT_PIN_TO_PIN_DELAY_TSETUP
10341060
|| annot_type == E_ANNOT_PIN_TO_PIN_DELAY_THOLD

libs/libarchfpga/src/arch_util.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ bool block_type_contains_blif_model(t_logical_block_type_ptr type, const std::st
9696
//Returns true of a pb_type (or it's children) contain the specified blif model name
9797
bool pb_type_contains_blif_model(const t_pb_type* pb_type, const std::string& blif_model_name);
9898

99+
/**
100+
* @brief Recursive helper method to deduce if the given pb_type is or contains
101+
* pb_types which are of the memory class.
102+
*/
103+
bool pb_type_contains_memory_pbs(const t_pb_type* pb_type);
104+
99105
bool has_sequential_annotation(const t_pb_type* pb_type, const t_model_ports* port, enum e_pin_to_pin_delay_annotations annot_type);
100106
bool has_combinational_annotation(const t_pb_type* pb_type, std::string_view in_port, std::string_view out_port);
101107

vpr/src/analytical_place/analytical_solver.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,17 @@ std::pair<double, double> B2BSolver::get_delay_derivative(APBlockId driver_blk,
877877
VTR_ASSERT_SAFE_MSG(p_placement.block_layer_nums[driver_blk] == layer_num && p_placement.block_layer_nums[sink_blk] == layer_num,
878878
"3D FPGAs not supported yet in the B2B solver");
879879

880+
// Special case: If the distance between the driver and sink is as large as
881+
// the device, we cannot take the forward difference (since it will go off
882+
// chip). We can still approximate the derivative by taking one tile step
883+
// back and getting the central difference at that point. This avoids the
884+
// boundary condition, which should be very rare to occur.
885+
// TODO: Investigate better ways of doing this.
886+
if ((int)flat_dx + 1 > (int)device_grid_width_ - 1)
887+
flat_dx = device_grid_width_ - 2;
888+
if ((int)flat_dy + 1 > (int)device_grid_height_ - 1)
889+
flat_dy = device_grid_height_ - 2;
890+
880891
// Get the physical tile location of the legalized driver block. The PlaceDelayModel
881892
// may use this position to determine the physical tile the wire is coming from.
882893
// When the placement is being solved, the driver may be moved to a physical tile
@@ -899,8 +910,10 @@ std::pair<double, double> B2BSolver::get_delay_derivative(APBlockId driver_blk,
899910

900911
int tile_dx = sink_block_loc.x - driver_block_loc.x;
901912
int tile_dy = sink_block_loc.y - driver_block_loc.y;
902-
VTR_ASSERT_SAFE(tile_dx < (int)device_grid_width_);
903-
VTR_ASSERT_SAFE(tile_dy < (int)device_grid_height_);
913+
// The following asserts are to protect the "delay" calls used for the forward
914+
// difference calculations below.
915+
VTR_ASSERT_SAFE(tile_dx + 1 < (int)device_grid_width_);
916+
VTR_ASSERT_SAFE(tile_dy + 1 < (int)device_grid_height_);
904917

905918
// Get the delay of a wire going from the given driver block location to the
906919
// given sink block location. This should only use the physical tile type of

vpr/src/base/read_options.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,6 +2010,32 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio
20102010
.default_value({"auto"})
20112011
.show_in(argparse::ShowIn::HELP_ONLY);
20122012

2013+
ap_grp.add_argument(args.appack_unrelated_clustering_args, "--appack_unrelated_clustering_args")
2014+
.help(
2015+
"Sets parameters used for unrelated clustering (the max search distance and max attempts) "
2016+
"used by APPack. "
2017+
"APPack uses the primitive-level placement produced by the "
2018+
"global placer to cluster primitives together. APPack uses this information "
2019+
"to help increase the density of clusters (if needed) by searching for "
2020+
"unrelated molecules to pack together. It does this by searching out from "
2021+
"the centroid of the cluster being created until it finds a valid molecule. "
2022+
"If a valid molecule is found, but it fails, the packer may do another attempt "
2023+
"(up to a maximum number of attempts). "
2024+
"This argument allows the user to select the maximum distance the code will "
2025+
"search and how many attempts it will try to search for each cluster."
2026+
"\n"
2027+
"When this option is set to auto, VPR will select good values for these "
2028+
"parameters based on the primitives contained within each logical block type."
2029+
"\n"
2030+
"This option is similar to the appack_max_dist_th argument, where the "
2031+
"parameters are passed by the user in the form <regex>:<float>,<float> where "
2032+
"regex is used to match the name of the logical block type to set, the "
2033+
"first float is the max unrelated tile distance, and the second float "
2034+
"is the max unrelated clustering attempts.")
2035+
.nargs('+')
2036+
.default_value({"auto"})
2037+
.show_in(argparse::ShowIn::HELP_ONLY);
2038+
20132039
ap_grp.add_argument<int>(args.ap_verbosity, "--ap_verbosity")
20142040
.help(
20152041
"Controls how verbose the AP flow's log messages will be. Higher "

vpr/src/base/read_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ struct t_options {
106106
argparse::ArgValue<e_ap_detailed_placer> ap_detailed_placer;
107107
argparse::ArgValue<std::vector<std::string>> ap_partial_legalizer_target_density;
108108
argparse::ArgValue<std::vector<std::string>> appack_max_dist_th;
109+
argparse::ArgValue<std::vector<std::string>> appack_unrelated_clustering_args;
109110
argparse::ArgValue<int> ap_verbosity;
110111
argparse::ArgValue<float> ap_timing_tradeoff;
111112
argparse::ArgValue<int> ap_high_fanout_threshold;

vpr/src/base/setup_vpr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,7 @@ void setup_ap_opts(const t_options& options,
586586
apOpts.ap_high_fanout_threshold = options.ap_high_fanout_threshold.value();
587587
apOpts.ap_partial_legalizer_target_density = options.ap_partial_legalizer_target_density.value();
588588
apOpts.appack_max_dist_th = options.appack_max_dist_th.value();
589+
apOpts.appack_unrelated_clustering_args = options.appack_unrelated_clustering_args.value();
589590
apOpts.num_threads = options.num_workers.value();
590591
apOpts.log_verbosity = options.ap_verbosity.value();
591592
apOpts.generate_mass_report = options.ap_generate_mass_report.value();

vpr/src/base/vpr_types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,9 @@ struct t_placer_opts {
11281128
* @param appack_max_dist_th
11291129
* Array of string passed by the user to configure the max candidate
11301130
* distance thresholds.
1131+
* @param appack_unrelated_clustering_args
1132+
* Array of strings passed by the user to configure the unrelated
1133+
* clustering parameters used by APPack.
11311134
* @param num_threads
11321135
* The number of threads the AP flow can use.
11331136
* @param log_verbosity
@@ -1155,6 +1158,8 @@ struct t_ap_opts {
11551158

11561159
std::vector<std::string> appack_max_dist_th;
11571160

1161+
std::vector<std::string> appack_unrelated_clustering_args;
1162+
11581163
unsigned num_threads;
11591164

11601165
int log_verbosity;

vpr/src/pack/appack_context.h

Lines changed: 11 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99

1010
#include "appack_max_dist_th_manager.h"
11+
#include "appack_unrelated_clustering_manager.h"
1112
#include "device_grid.h"
1213
#include "flat_placement_types.h"
1314
#include "physical_types.h"
@@ -68,43 +69,6 @@ struct t_appack_options {
6869
// Squared scaling factor for the quadratic decay term.
6970
static constexpr float quad_fac_sqr = (1.0f - attenuation_th) / (dist_th * dist_th);
7071

71-
// =========== Unrelated clustering ==================================== //
72-
// After searching for candidates by connectivity and timing, the user may
73-
// turn on unrelated clustering, which will allow molecules which are
74-
// unrelated to the cluster being created to be attempted to be packed in.
75-
// APPack uses flat placement information to decide which unrelated
76-
// molecules to try.
77-
78-
// APPack will search for unrelated molecules in the tile which contains
79-
// the flat location of the cluster. It will then look farther out, tile
80-
// by tile. This parameter is the maximum distance from the cluster's tile
81-
// that APPack will search. Setting this to 0 would only allow APPack to
82-
// search within the cluster's tile. Setting this to a higher number would
83-
// allow APPack to search farther away; but may bring in molecules which
84-
// do not "want" to be in the cluster.
85-
//
86-
// [block_type_index] -> unrelated_tile_distance
87-
std::vector<float> max_unrelated_tile_distance;
88-
89-
// Unrelated clustering occurs after all other candidate selection methods
90-
// have failed. This attempts to cluster in molecules that are not attracted
91-
// (using the packer's heuristics) to the molecules within a given cluster.
92-
// This parameter sets how many times we will attempt unrelated
93-
// clustering between failures of unrelated clustering. If a molecule used
94-
// for unrelated clustering failed to cluster it will not be attempted
95-
// again for that cluster (note: if it succeeds, the number of attempts get
96-
// reset).
97-
// NOTE: A similar option exists in the candidate selector class. This was
98-
// duplicated since it is very likely that APPack would need a
99-
// different value for this option than the non-APPack flow.
100-
//
101-
// [block_type_index] -> max_unrelated_attempts
102-
std::vector<int> max_unrelated_clustering_attempts;
103-
// By default, we perform 10 unrelated clustering attempts. This is used
104-
// to aggresivly resolve density while adhering to the GP solution as much
105-
// as possible.
106-
static constexpr int default_max_unrelated_clustering_attempts = 10;
107-
10872
// TODO: Investigate adding flat placement info to seed selection.
10973
};
11074

@@ -126,22 +90,16 @@ struct APPackContext : public Context {
12690
, flat_placement_info(fplace_info) {
12791

12892
// If the flat placement info has been provided, calculate max distance
129-
// thresholds for all logical block types.
93+
// thresholds for all logical block types and the unrelated clustering
94+
// arguments.
13095
if (fplace_info.valid) {
13196
max_distance_threshold_manager.init(ap_opts.appack_max_dist_th,
13297
logical_block_types,
13398
device_grid);
134-
}
13599

136-
// Set the max unrelated tile distances for all logical block types.
137-
// By default, we set this to a low value to only allow unrelated molecules
138-
// that are very close to the cluster being created.
139-
// NOTE: Molecules within the same tile as the centroid are considered to have
140-
// 0 distance. The distance is computed relative to the bounds of the
141-
// tile containing the centroid.
142-
appack_options.max_unrelated_tile_distance.resize(logical_block_types.size(), 1.0);
143-
appack_options.max_unrelated_clustering_attempts.resize(logical_block_types.size(),
144-
appack_options.default_max_unrelated_clustering_attempts);
100+
unrelated_clustering_manager.init(ap_opts.appack_unrelated_clustering_args,
101+
logical_block_types);
102+
}
145103
}
146104

147105
/**
@@ -157,4 +115,9 @@ struct APPackContext : public Context {
157115
// When selecting candidates, what distance from the cluster will we
158116
// consider? Any candidate beyond this distance will not be proposed.
159117
APPackMaxDistThManager max_distance_threshold_manager;
118+
119+
// When performing unrelated clustering, the following manager class decides
120+
// how far we should search for unrelated candidates and how many attempts
121+
// we should perform.
122+
APPackUnrelatedClusteringManager unrelated_clustering_manager;
160123
};

vpr/src/pack/appack_max_dist_th_manager.cpp

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
* @file
33
* @author Alex Singer
44
* @date May 2025
5-
* @breif Definition of the max distance threshold manager class.
5+
* @brief Definition of the max distance threshold manager class.
66
*/
77

88
#include "appack_max_dist_th_manager.h"
99
#include <string>
1010
#include <unordered_map>
1111
#include <vector>
1212
#include "ap_argparse_utils.h"
13+
#include "arch_util.h"
1314
#include "device_grid.h"
1415
#include "physical_types.h"
1516
#include "physical_types_util.h"
@@ -18,14 +19,6 @@
1819
#include "vtr_assert.h"
1920
#include "vtr_log.h"
2021

21-
/**
22-
* @brief Recursive helper method to deduce if the given pb_type is or contains
23-
* pb_types which are of the memory class.
24-
*
25-
* TODO: This should be a graph traversal instead of a recursive function.
26-
*/
27-
static bool has_memory_pbs(const t_pb_type* pb_type);
28-
2922
void APPackMaxDistThManager::init(const std::vector<std::string>& max_dist_ths,
3023
const std::vector<t_logical_block_type>& logical_block_types,
3124
const DeviceGrid& device_grid) {
@@ -85,7 +78,7 @@ void APPackMaxDistThManager::auto_set_max_distance_thresholds(const std::vector<
8578
continue;
8679

8780
// Find which type(s) this logical block type looks like.
88-
bool has_memory = has_memory_pbs(lb_ty.pb_type);
81+
bool has_memory = pb_type_contains_memory_pbs(lb_ty.pb_type);
8982
bool is_logic_block_type = (lb_ty.index == logic_block_type->index);
9083
bool is_io_block = pick_physical_type(&lb_ty)->is_io();
9184

@@ -113,30 +106,6 @@ void APPackMaxDistThManager::auto_set_max_distance_thresholds(const std::vector<
113106
}
114107
}
115108

116-
static bool has_memory_pbs(const t_pb_type* pb_type) {
117-
if (pb_type == nullptr)
118-
return false;
119-
120-
// Check if this pb_type is a memory class. If so return true. This acts as
121-
// a base case for the recursion.
122-
if (pb_type->class_type == e_pb_type_class::MEMORY_CLASS)
123-
return true;
124-
125-
// Go through all modes of this pb_type and check if any of those modes'
126-
// children have memory pb_types, if so return true.
127-
for (int mode_idx = 0; mode_idx < pb_type->num_modes; mode_idx++) {
128-
const t_mode& mode = pb_type->modes[mode_idx];
129-
for (int child_idx = 0; child_idx < mode.num_pb_type_children; child_idx++) {
130-
if (has_memory_pbs(&mode.pb_type_children[child_idx]))
131-
return true;
132-
}
133-
}
134-
135-
// If this pb_type is not a memory and its modes do not have memory pbs in
136-
// them, then this pb_type is not a memory.
137-
return false;
138-
}
139-
140109
void APPackMaxDistThManager::set_max_distance_thresholds_from_strings(
141110
const std::vector<std::string>& max_dist_ths,
142111
const std::vector<t_logical_block_type>& logical_block_types) {

0 commit comments

Comments
 (0)