diff --git a/doc/src/vpr/command_line_usage.rst b/doc/src/vpr/command_line_usage.rst index 7a87605e6d..d064b58623 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 7b7cc9cfb3..369ef53510 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 b40dd89f18..807650cd7e 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 6c741c12f6..f94a04b722 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 fc5e4889ad..3697667015 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 0d83e5fc17..97f8f16463 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 07257e398b..94a97bc9e6 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 0461f26b32..4235fb1fd9 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 0000000000..9f9a39815a --- /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 0000000000..558b224c56 --- /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 199894b8d2..d4579a4555 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 85a21c229e..57ee96a1a7 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 64189ea4ee..f484146ac6 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,