From 4079c04dc5cd542ea3306b0577ea9940a51394e1 Mon Sep 17 00:00:00 2001 From: AlexandreSinger Date: Sat, 3 May 2025 21:27:23 -0400 Subject: [PATCH] [APPack] Updated Max Candidate Distance Interface The max candidate distance is used by APPack to decide which molecules to ignore when packing, based on their distance from the cluster being formed. Cleaned up the interface of this by pre-computing the max candidate distance of all logical blocks ahead of time and reading from these pre-computed values during packing. Added a command-line option to allow the user to override some or all of these max distance thresholds. By default, VPR will select values based on the type of logical block and the primitives it contains. Fixed issue with APPack creating too many IO blocks for some circuits due to the max candidate distance thresholds for IO blocks being too low. More tuning should be done on these values once the mass legalizer has been cleaned up a bit more. --- doc/src/vpr/command_line_usage.rst | 43 ++++ vpr/src/analytical_place/full_legalizer.cpp | 1 + vpr/src/base/SetupVPR.cpp | 1 + vpr/src/base/read_options.cpp | 25 ++ vpr/src/base/read_options.h | 1 + vpr/src/base/vpr_api.cpp | 2 +- vpr/src/base/vpr_types.h | 5 + vpr/src/pack/appack_context.h | 63 ++--- vpr/src/pack/appack_max_dist_th_manager.cpp | 271 ++++++++++++++++++++ vpr/src/pack/appack_max_dist_th_manager.h | 118 +++++++++ vpr/src/pack/greedy_candidate_selector.cpp | 6 +- vpr/src/pack/pack.cpp | 6 +- vpr/src/pack/pack.h | 2 + 13 files changed, 496 insertions(+), 48 deletions(-) create mode 100644 vpr/src/pack/appack_max_dist_th_manager.cpp create mode 100644 vpr/src/pack/appack_max_dist_th_manager.h diff --git a/doc/src/vpr/command_line_usage.rst b/doc/src/vpr/command_line_usage.rst index 7a87605e6d2..d064b586231 100644 --- a/doc/src/vpr/command_line_usage.rst +++ b/doc/src/vpr/command_line_usage.rst @@ -1270,6 +1270,49 @@ Analytical Placement is generally split into three stages: **Default:** ``0.5`` +.. option:: --appack_max_dist_th { auto | :, } + + Sets the maximum candidate distance thresholds for the logical block types + used by APPack. APPack uses the primitive-level placement produced by the + global placer to cluster primitives together. APPack uses the thresholds + here to ignore primitives which are too far away from the cluster being formed. + + When this option is set to "auto", VPR will select good values for these + thresholds based on the primitives contained within each logical block type. + + Using this option, the user can set the maximum candidate distance threshold + of logical block types to something else. The strings passed in by the user + should be of the form ``:,`` where the regex string is + used to match the name of the logical block type to set, the first float + is a scaling term, and the second float is an offset. The threshold will + be set to max(scale * (W + H), offset), where W and H are the width and height + of the device. This allows the user to specify a threshold based on the + size of the device, while also preventing the number from going below "offset". + When multiple strings are provided, the thresholds are set from left to right, + and any logical block types which have been unset will be set to their "auto" + values. + + For example: + + .. code-block:: none + + --appack_max_dist_th .*:0.1,0 "clb|memory:0,5" + + Would set all logical block types to be 0.1 * (W + H), except for the clb and + memory block, which will be set to a fixed value of 5. + + Another example: + + .. code-block:: none + + --appack_max_dist_th "clb|LAB:0.2,5" + + This will set all of the logical block types to their "auto" thresholds, except + for logical blocks with the name clb/LAB which will be set to 0.2 * (W + H) or + 5 (whichever is larger). + + **Default:** ``auto`` + .. option:: --ap_verbosity Controls the verbosity of the AP flow output. diff --git a/vpr/src/analytical_place/full_legalizer.cpp b/vpr/src/analytical_place/full_legalizer.cpp index 7b7cc9cfb39..369ef53510c 100644 --- a/vpr/src/analytical_place/full_legalizer.cpp +++ b/vpr/src/analytical_place/full_legalizer.cpp @@ -520,6 +520,7 @@ void APPack::legalize(const PartialPlacement& p_placement) { // Run the Packer stage with the flat placement as a hint. try_pack(vpr_setup_.PackerOpts, vpr_setup_.AnalysisOpts, + vpr_setup_.APOpts, arch_, vpr_setup_.PackerRRGraph, prepacker_, diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index b40dd89f18d..807650cd7ec 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -550,6 +550,7 @@ void SetupAPOpts(const t_options& options, apOpts.full_legalizer_type = options.ap_full_legalizer.value(); apOpts.detailed_placer_type = options.ap_detailed_placer.value(); apOpts.ap_timing_tradeoff = options.ap_timing_tradeoff.value(); + apOpts.appack_max_dist_th = options.appack_max_dist_th.value(); apOpts.log_verbosity = options.ap_verbosity.value(); } diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index 6c741c12f6e..f94a04b7225 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -1945,6 +1945,31 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio .default_value("0.5") .show_in(argparse::ShowIn::HELP_ONLY); + ap_grp.add_argument(args.appack_max_dist_th, "--appack_max_dist_th") + .help( + "Sets the maximum candidate distance thresholds for the logical block types" + "used by APPack. APPack uses the primitive-level placement produced by the" + "global placer to cluster primitives together. APPack uses the thresholds" + "here to ignore primitives which are too far away from the cluster being formed." + "\n" + "When this option is set to auto, VPR will select good values for these" + "thresholds based on the primitives contained within each logical block type." + "\n" + "Using this option, the user can set the maximum candidate distance threshold" + "of logical block types to something else. The strings passed in by the user" + "should be of the form :, where the regex string is" + "used to match the name of the logical block type to set, the first float" + "is a scaling term, and the second float is an offset. The threshold will" + "be set to max(scale * (W + H), offset), where W and H are the width and height" + "of the device. This allows the user to specify a threshold based on the" + "size of the device, while also preventing the number from going below offset" + "When multiple strings are provided, the thresholds are set from left to right," + "and any logical block types which have been unset will be set to their auto" + "values.") + .nargs('+') + .default_value({"auto"}) + .show_in(argparse::ShowIn::HELP_ONLY); + ap_grp.add_argument(args.ap_verbosity, "--ap_verbosity") .help( "Controls how verbose the AP flow's log messages will be. Higher " diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h index fc5e4889ad3..3697667015e 100644 --- a/vpr/src/base/read_options.h +++ b/vpr/src/base/read_options.h @@ -102,6 +102,7 @@ struct t_options { argparse::ArgValue ap_partial_legalizer; argparse::ArgValue ap_full_legalizer; argparse::ArgValue ap_detailed_placer; + argparse::ArgValue> appack_max_dist_th; argparse::ArgValue ap_verbosity; argparse::ArgValue ap_timing_tradeoff; diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 0d83e5fc17d..97f8f164635 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -658,7 +658,7 @@ bool vpr_pack(t_vpr_setup& vpr_setup, const t_arch& arch) { vpr_setup.PackerOpts.device_layout, vpr_setup.AnalysisOpts); - return try_pack(vpr_setup.PackerOpts, vpr_setup.AnalysisOpts, + return try_pack(vpr_setup.PackerOpts, vpr_setup.AnalysisOpts, vpr_setup.APOpts, arch, vpr_setup.PackerRRGraph, prepacker, diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 07257e398ba..94a97bc9e61 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1113,6 +1113,9 @@ struct t_placer_opts { * @param ap_timing_tradeoff * A trade-off parameter used to decide how focused the AP flow * should be on optimizing timing over wirelength. + * @param appack_max_dist_th + * Array of string passed by the user to configure the max candidate + * distance thresholds. * @param log_verbosity * The verbosity level of log messages in the AP flow, with higher * values leading to more verbose messages. @@ -1130,6 +1133,8 @@ struct t_ap_opts { float ap_timing_tradeoff; + std::vector appack_max_dist_th; + int log_verbosity; }; diff --git a/vpr/src/pack/appack_context.h b/vpr/src/pack/appack_context.h index 0461f26b320..4235fb1fd95 100644 --- a/vpr/src/pack/appack_context.h +++ b/vpr/src/pack/appack_context.h @@ -8,12 +8,12 @@ #pragma once -#include -#include +#include "appack_max_dist_th_manager.h" #include "device_grid.h" #include "flat_placement_types.h" #include "physical_types.h" #include "vpr_context.h" +#include "vpr_types.h" #include "vpr_utils.h" /** @@ -25,29 +25,10 @@ */ struct t_appack_options { // Constructor for the appack options. - t_appack_options(const FlatPlacementInfo& flat_placement_info, - const DeviceGrid& device_grid) { + t_appack_options(const FlatPlacementInfo& flat_placement_info) { // If the flat placement info is valid, we want to use APPack. // TODO: Should probably check that all the information is valid here. use_appack = flat_placement_info.valid; - - // Set the max candidate distance as being some fraction of the longest - // distance on the device (from the bottom corner to the top corner). - // We also use an offset for the minimum this distance can be to prevent - // small devices from finding candidates. - float max_candidate_distance_scale = 0.1f; - float max_candidate_distance_offset = 15.0f; - // Longest L1 distance on the device. - float longest_distance = device_grid.width() + device_grid.height(); - max_candidate_distance = std::max(max_candidate_distance_scale * longest_distance, - max_candidate_distance_offset); - - // Infer the logical block type in the architecture. This will be used - // for the max candidate distance optimization to use a more aggressive - // distance. - t_logical_block_type_ptr logic_block_type = infer_logic_block_type(device_grid); - if (logic_block_type != nullptr) - logic_block_type_index = logic_block_type->index; } // Whether to use APPack or not. @@ -88,22 +69,6 @@ struct t_appack_options { // Squared scaling factor for the quadratic decay term. static constexpr float quad_fac_sqr = (1.0f - attenuation_th) / (dist_th * dist_th); - // =========== Candidate selection distance ============================ // - // When selecting candidates, what distance from the cluster will we - // consider? Any candidate beyond this distance will not be proposed. - // This is set in the constructor. - // TODO: It may be a good idea to have max different distances for different - // types of molecules / clusters. For example, CLBs vs DSPs - float max_candidate_distance = std::numeric_limits::max(); - - // A scaling applied to the max candidate distance of all clusters that are - // not logic blocks. - static constexpr float max_candidate_distance_non_lb_scale = 3.5f; - - // TODO: This should be an option similar to the target pin utilization - // so we can specify the max distance per block type! - int logic_block_type_index = -1; - // =========== Unrelated clustering ==================================== // // After searching for candidates by connectivity and timing, the user may // turn on unrelated clustering, which will allow molecules which are @@ -144,9 +109,21 @@ struct APPackContext : public Context { /** * @brief Constructor for the APPack context. */ - APPackContext(const FlatPlacementInfo& fplace_info, const DeviceGrid& device_grid) - : appack_options(fplace_info, device_grid) - , flat_placement_info(fplace_info) {} + APPackContext(const FlatPlacementInfo& fplace_info, + const t_ap_opts& ap_opts, + const std::vector logical_block_types, + const DeviceGrid& device_grid) + : appack_options(fplace_info) + , flat_placement_info(fplace_info) { + + // If the flat placement info has been provided, calculate max distance + // thresholds for all logical block types. + if (fplace_info.valid) { + max_distance_threshold_manager.init(ap_opts.appack_max_dist_th, + logical_block_types, + device_grid); + } + } /** * @brief Options used to configure APPack. @@ -157,4 +134,8 @@ struct APPackContext : public Context { * @brief The flat placement information passed into APPack. */ const FlatPlacementInfo& flat_placement_info; + + // When selecting candidates, what distance from the cluster will we + // consider? Any candidate beyond this distance will not be proposed. + APPackMaxDistThManager max_distance_threshold_manager; }; diff --git a/vpr/src/pack/appack_max_dist_th_manager.cpp b/vpr/src/pack/appack_max_dist_th_manager.cpp new file mode 100644 index 00000000000..9f9a39815a7 --- /dev/null +++ b/vpr/src/pack/appack_max_dist_th_manager.cpp @@ -0,0 +1,271 @@ +/** + * @file + * @author Alex Singer + * @date May 2025 + * @breif Definition of the max distance threshold manager class. + */ + +#include "appack_max_dist_th_manager.h" +#include +#include +#include +#include +#include "device_grid.h" +#include "physical_types.h" +#include "physical_types_util.h" +#include "vpr_error.h" +#include "vpr_utils.h" +#include "vtr_assert.h" +#include "vtr_log.h" + +/** + * @brief Helper method to convert a string into a float with error checking. + */ +static float str_to_float_or_error(const std::string& str); + +/** + * @brief Helper method to parse one term of the user-provided max distance + * threshold string. + * + * This method decomposes the user string of the form ":," + * into its three components. + */ +static std::tuple parse_max_dist_th(const std::string& max_dist_th); + +/** + * @brief Recursive helper method to deduce if the given pb_type is or contains + * pb_types which are of the memory class. + * + * TODO: This should be a graph traversal instead of a recursive function. + */ +static bool has_memory_pbs(const t_pb_type* pb_type); + +void APPackMaxDistThManager::init(const std::vector& max_dist_ths, + const std::vector& logical_block_types, + const DeviceGrid& device_grid) { + // Automatically set the max distance thresholds. + auto_set_max_distance_thresholds(logical_block_types, device_grid); + + // If the max distance threshold strings have been set (they are not set to + // auto), set the max distance thresholds based on the user-provided strings. + VTR_ASSERT(!max_dist_ths.empty()); + if (max_dist_ths.size() != 1 || max_dist_ths[0] != "auto") { + set_max_distance_thresholds_from_strings(max_dist_ths, logical_block_types, device_grid); + } + + // Set the initilized flag to true. + is_initialized_ = true; + + // Log the max distance thresholds for each logical block type. This is + // similar to how the input and output pin utilizations are printed. + VTR_LOG("APPack is using max distance thresholds: "); + for (const t_logical_block_type& lb_ty : logical_block_types) { + if (lb_ty.is_empty()) + continue; + VTR_LOG("%s:%g ", + lb_ty.name.c_str(), + get_max_dist_threshold(lb_ty)); + } + VTR_LOG("\n"); +} + +void APPackMaxDistThManager::auto_set_max_distance_thresholds(const std::vector& logical_block_types, + const DeviceGrid& device_grid) { + // Compute the max device distance based on the width and height of the + // device. This is the L1 (manhattan) distance. + float max_device_distance = device_grid.width() + device_grid.height(); + + // Compute the max distance thresholds of the different logical block types. + float default_max_distance_th = std::max(default_max_dist_th_scale_ * max_device_distance, + default_max_dist_th_offset_); + float logic_block_max_distance_th = std::max(logic_block_max_dist_th_scale_ * max_device_distance, + logic_block_max_dist_th_offset_); + float memory_max_distance_th = std::max(memory_max_dist_th_scale_ * max_device_distance, + memory_max_dist_th_offset_); + float io_block_max_distance_th = std::max(io_max_dist_th_scale_ * max_device_distance, + io_max_dist_th_offset_); + + // Set all logical block types to have the default max distance threshold. + logical_block_dist_thresholds_.resize(logical_block_types.size(), default_max_distance_th); + + // Find which (if any) of the logical block types most looks like a CLB block. + t_logical_block_type_ptr logic_block_type = infer_logic_block_type(device_grid); + + // Go through each of the logical block types. + for (const t_logical_block_type& lb_ty : logical_block_types) { + // Skip the empty logical block type. This should not have any blocks. + if (lb_ty.is_empty()) + continue; + + // Find which type(s) this logical block type looks like. + bool has_memory = has_memory_pbs(lb_ty.pb_type); + bool is_logic_block_type = (lb_ty.index == logic_block_type->index); + bool is_io_block = is_io_type(pick_physical_type(&lb_ty)); + + // Update the max distance threshold based on the type. If the logical + // block type looks like many block types at the same time (for example + // a CLB which has memory slices within it), then take the average + // of the max distance thresholds of those types. + float max_distance_th_sum = 0.0f; + unsigned block_category_count = 0; + if (is_logic_block_type) { + max_distance_th_sum += logic_block_max_distance_th; + block_category_count++; + } + if (has_memory) { + max_distance_th_sum += memory_max_distance_th; + block_category_count++; + } + if (is_io_block) { + max_distance_th_sum += io_block_max_distance_th; + block_category_count++; + } + if (block_category_count > 0) { + logical_block_dist_thresholds_[lb_ty.index] = max_distance_th_sum / static_cast(block_category_count); + } + } +} + +static bool has_memory_pbs(const t_pb_type* pb_type) { + if (pb_type == nullptr) + return false; + + // Check if this pb_type is a memory class. If so return true. This acts as + // a base case for the recursion. + if (pb_type->class_type == e_pb_type_class::MEMORY_CLASS) + return true; + + // Go through all modes of this pb_type and check if any of those modes' + // children have memory pb_types, if so return true. + for (int mode_idx = 0; mode_idx < pb_type->num_modes; mode_idx++) { + const t_mode& mode = pb_type->modes[mode_idx]; + for (int child_idx = 0; child_idx < mode.num_pb_type_children; child_idx++) { + if (has_memory_pbs(&mode.pb_type_children[child_idx])) + return true; + } + } + + // If this pb_type is not a memory and its modes do not have memory pbs in + // them, then this pb_type is not a memory. + return false; +} + +void APPackMaxDistThManager::set_max_distance_thresholds_from_strings( + const std::vector& max_dist_ths, + const std::vector& logical_block_types, + const DeviceGrid& device_grid) { + + // Go through each of the user-provided strings. + for (const std::string& max_dist_th : max_dist_ths) { + // If any of them are the word "auto", this was a user error and should + // be flagged. + // TODO: Maybe move this and other semantic checks up to the checker of + // VPR's command line. + if (max_dist_th == "auto") { + VPR_FATAL_ERROR(VPR_ERROR_PACK, + "APPack: Cannot provide both auto and other max distance threshold strings"); + } + + // Parse the string for the regex, scale, and offset. + std::string logical_block_regex_str; + float logical_block_max_dist_th_scale; + float logical_block_max_dist_th_offset; + std::tie(logical_block_regex_str, + logical_block_max_dist_th_scale, + logical_block_max_dist_th_offset) = parse_max_dist_th(max_dist_th); + + // Setup the regex for the logical blocks the user wants to set the + // thresholds for. + std::regex logical_block_regex(logical_block_regex_str); + + // Compute the max distance threshold the user selected. + float max_device_distance = device_grid.width() + device_grid.height(); + float logical_block_max_dist_th = std::max(max_device_distance * logical_block_max_dist_th_scale, + logical_block_max_dist_th_offset); + + // Search through all logical blocks and set the thresholds of any matches + // to the threshold the user selected. + bool found_match = false; + for (const t_logical_block_type& lb_ty : logical_block_types) { + bool is_match = std::regex_match(lb_ty.name, logical_block_regex); + if (!is_match) + continue; + + logical_block_dist_thresholds_[lb_ty.index] = logical_block_max_dist_th; + found_match = true; + } + // If no match is found, send a warning to the user. + if (!found_match) { + VTR_LOG_WARN("Unable to find logical block type for max distance threshold regex string: %s\n", + logical_block_regex_str.c_str()); + } + } +} + +static std::tuple parse_max_dist_th(const std::string& max_dist_th) { + // Verify the format of the string. It must have one and only one colon. + unsigned colon_count = 0; + for (char c : max_dist_th) { + if (c == ':') + colon_count++; + } + if (colon_count != 1) { + VTR_LOG_ERROR("Invalid max distance threshold string: %s\n", + max_dist_th.c_str()); + VPR_FATAL_ERROR(VPR_ERROR_PACK, + "Error when parsing APPack max distance threshold string"); + } + + // Split the string along the colon. + auto del_pos = max_dist_th.find(':'); + std::string logical_block_regex_str = max_dist_th.substr(0, del_pos); + std::string lb_max_dist_th_str = max_dist_th.substr(del_pos + 1, std::string::npos); + + // Split along the comma for the scale/offset. + // Verify that the comma only appears once in the scale/offset string. + unsigned comma_count = 0; + for (char c : lb_max_dist_th_str) { + if (c == ',') + comma_count++; + } + if (comma_count != 1) { + VTR_LOG_ERROR("Invalid max distance threshold string: %s\n", + max_dist_th.c_str()); + VPR_FATAL_ERROR(VPR_ERROR_PACK, + "Error when parsing APPack max distance threshold string"); + } + + // Split the string along the comma. + auto comma_pos = lb_max_dist_th_str.find(','); + std::string lb_max_dist_th_scale_str = lb_max_dist_th_str.substr(0, comma_pos); + std::string lb_max_dist_th_offset_str = lb_max_dist_th_str.substr(comma_pos + 1, std::string::npos); + + // Convert the scale and offset into floats (error checking to be safe). + float lb_max_dist_th_scale = str_to_float_or_error(lb_max_dist_th_scale_str); + float lb_max_dist_th_offset = str_to_float_or_error(lb_max_dist_th_offset_str); + + // Return the results as a tuple. + return std::make_tuple(logical_block_regex_str, lb_max_dist_th_scale, lb_max_dist_th_offset); +} + +static float str_to_float_or_error(const std::string& str) { + float val = -1; + try { + val = std::stof(str); + } catch (const std::invalid_argument& e) { + VTR_LOG_ERROR("Error while parsing max distance threshold value: %s\n" + "Failed with invalid argument: %s\n", + str.c_str(), + e.what()); + } catch (const std::out_of_range& e) { + VTR_LOG_ERROR("Error while parsing max distance threshold value: %s\n" + "Failed with out of range: %s\n", + str.c_str(), + e.what()); + } + if (val < 0.0f) { + VPR_FATAL_ERROR(VPR_ERROR_PACK, + "Error when parsing APPack max distance threshold string"); + } + return val; +} diff --git a/vpr/src/pack/appack_max_dist_th_manager.h b/vpr/src/pack/appack_max_dist_th_manager.h new file mode 100644 index 00000000000..558b224c56b --- /dev/null +++ b/vpr/src/pack/appack_max_dist_th_manager.h @@ -0,0 +1,118 @@ +/** + * @file + * @author Alex Singer + * @date May 2025 + * @brief Declaration of a class that manages the max candidate distance + * thresholding optimization used within APPack. + */ + +#pragma once + +#include +#include +#include "physical_types.h" +#include "vtr_assert.h" + +// Forward declarations. +class DeviceGrid; + +/** + * @brief Manager class which manages parsing and getting the max candidate + * distance thresholds for each of the logical block types in the + * architecture. + * + * The initializer of this class will set the max candidate distance thresholds + * based on the arguments passed by the user. + * + * Within the packer, the get_max_dist_threshold method can be used to get the + * max distance threshold for a given logical block type. + */ +class APPackMaxDistThManager { + // To compute the max distance threshold, we use two numbers to compute it: + // - Scale: This is what fraction of the device the distance should be. + // i.e. the max distance threshold will be scale * (W + H) since + // W+H is the farthes L1 distance possible on the device. + // - Offset: This is the minimum threshold it can have. This prevents small + // devices with small scales having thresholds that are too small. + // The following scales and offsets are set for interesting logical blocks + // when the "auto" selection mode is used. The following numbers were + // empirically found to work well. + + // This is the default scale and offset. Logical blocks that we do not + // recognize as being of the special categories will have this threshold. + static constexpr float default_max_dist_th_scale_ = 0.35f; + static constexpr float default_max_dist_th_offset_ = 15.0f; + + // Logic blocks (such as CLBs and LABs) tend to have more resources on the + // device, thus they have tighter thresholds. This was found to work well. + static constexpr float logic_block_max_dist_th_scale_ = 0.1f; + static constexpr float logic_block_max_dist_th_offset_ = 15.0f; + + // Memory blocks (i.e. blocks that contain pb_types of the memory class) + // seem to have very touchy packing; thus these do not have the max + // threshold to prevent them from creating too many clusters. + static constexpr float memory_max_dist_th_scale_ = 1.0f; + static constexpr float memory_max_dist_th_offset_ = 0.0f; + + // IO blocks tend to have very sparse resources and setting the offset too + // low can create too many blocks. Set this to a higher value. + static constexpr float io_max_dist_th_scale_ = 0.5f; + static constexpr float io_max_dist_th_offset_ = 15.0f; + + public: + APPackMaxDistThManager() = default; + + /** + * @brief Initializer for the manager class. The thresholds for each logical + * block type is selected here. + * + * @param should_initialize + * Whether to compute the thresholds for each logical block or not. This + * is to allow the class to be passed around without AP being enabled. + * @param max_dist_ths + * An array of strings representing the user-defined max distance + * thresholds. This is passed from the command line. + * @param logical_block_types + * An array of all logical block types in the architecture. + * @param device_grid + */ + void init(const std::vector& max_dist_ths, + const std::vector& logical_block_types, + const DeviceGrid& device_grid); + + /** + * @brief Get the max distance threshold of the given lobical block type. + */ + inline float get_max_dist_threshold(const t_logical_block_type& logical_block_ty) const { + VTR_ASSERT_SAFE_MSG(is_initialized_, + "APPackMaxDistThManager has not been initialized, cannot call this method"); + VTR_ASSERT_SAFE_MSG((size_t)logical_block_ty.index < logical_block_dist_thresholds_.size(), + "Logical block type does not have a max distance threshold"); + + return logical_block_dist_thresholds_[logical_block_ty.index]; + } + + private: + /** + * @brief Helper method that initializes the thresholds of all logical + * block types to reasonable numbers based on the characteristics + * of the logical block type. + */ + void auto_set_max_distance_thresholds(const std::vector& logical_block_types, + const DeviceGrid& device_grid); + + /** + * @brief Helper method that sets the thresholds based on the user-provided + * strings. + */ + void set_max_distance_thresholds_from_strings(const std::vector& max_dist_ths, + const std::vector& logical_block_types, + const DeviceGrid& device_grid); + + /// @brief A flag which shows if the thesholds have been computed or not. + bool is_initialized_ = false; + + /// @brief The max distance thresholds of all logical blocks in the architecture. + /// This is initialized in the constructor and accessed during packing. + std::vector logical_block_dist_thresholds_; +}; diff --git a/vpr/src/pack/greedy_candidate_selector.cpp b/vpr/src/pack/greedy_candidate_selector.cpp index 199894b8d23..d4579a45554 100644 --- a/vpr/src/pack/greedy_candidate_selector.cpp +++ b/vpr/src/pack/greedy_candidate_selector.cpp @@ -960,11 +960,7 @@ static void add_molecule_to_pb_stats_candidates(PackMoleculeId molecule_id, // distance. Was found to create too many RAM blocks. if (!cluster_gain_stats.is_memory) { // Get the max dist for this block type. - float max_dist = appack_ctx.appack_options.max_candidate_distance; - // If this cluster is anything but a logic block type, then scale - // up the max distance. - if (cluster_type->index != appack_ctx.appack_options.logic_block_type_index) - max_dist *= appack_ctx.appack_options.max_candidate_distance_non_lb_scale; + float max_dist = appack_ctx.max_distance_threshold_manager.get_max_dist_threshold(*cluster_type); // If the distance from the cluster to the candidate is too large, // do not add this molecule to the list of candidates. diff --git a/vpr/src/pack/pack.cpp b/vpr/src/pack/pack.cpp index 85a21c229e6..57ee96a1a7f 100644 --- a/vpr/src/pack/pack.cpp +++ b/vpr/src/pack/pack.cpp @@ -29,6 +29,7 @@ static bool try_size_device_grid(const t_arch& arch, bool try_pack(const t_packer_opts& packer_opts, const t_analysis_opts& analysis_opts, + const t_ap_opts& ap_opts, const t_arch& arch, std::vector* lb_type_rr_graphs, const Prepacker& prepacker, @@ -126,7 +127,10 @@ bool try_pack(const t_packer_opts& packer_opts, VTR_LOG("Packing with high fanout thresholds: %s\n", high_fanout_thresholds.to_string().c_str()); // Construct the APPack Context. - APPackContext appack_ctx(flat_placement_info, device_ctx.grid); + APPackContext appack_ctx(flat_placement_info, + ap_opts, + device_ctx.logical_block_types, + device_ctx.grid); // Initialize the greedy clusterer. GreedyClusterer clusterer(packer_opts, diff --git a/vpr/src/pack/pack.h b/vpr/src/pack/pack.h index 64189ea4ee9..f484146ac66 100644 --- a/vpr/src/pack/pack.h +++ b/vpr/src/pack/pack.h @@ -9,6 +9,7 @@ class FlatPlacementInfo; class PreClusterTimingManager; class Prepacker; struct t_analysis_opts; +struct t_ap_opts; struct t_arch; struct t_lb_type_rr_node; struct t_packer_opts; @@ -37,6 +38,7 @@ struct t_packer_opts; */ bool try_pack(const t_packer_opts& packer_opts, const t_analysis_opts& analysis_opts, + const t_ap_opts& ap_opts, const t_arch& arch, std::vector* lb_type_rr_graphs, const Prepacker& prepacker,