Skip to content

[APPack] Iterative Re-Packing #3171

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions vpr/src/analytical_place/flat_placement_density_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,20 @@ static PrimitiveVector calc_bin_underfill(const PrimitiveVector& bin_utilization
* The command-line arguments provided by the user.
* @param physical_tile_types
* A vector of all physical tile types in the architecture.
* @param device_grid
* The current physical device grid of the FPGA.
*/
static std::vector<float> get_physical_type_target_densities(const std::vector<std::string>& target_density_arg_strs,
const std::vector<t_physical_tile_type>& physical_tile_types) {
const std::vector<t_physical_tile_type>& physical_tile_types,
const DeviceGrid& device_grid) {
// Get the target densisty of each physical block type.
// TODO: Create auto feature to automatically select target densities based
// on properties of the architecture. Need to sweep to find reasonable
// values.
std::vector<float> phy_ty_target_density(physical_tile_types.size(), 1.0f);

// By default (auto), make the CLB target density 80%, leaving the other
// blocks at 100%.
t_logical_block_type_ptr logic_block_type = infer_logic_block_type(device_grid);
phy_ty_target_density[logic_block_type->index] = 0.8f;

// Set to auto if no user args are provided.
if (target_density_arg_strs.size() == 0)
return phy_ty_target_density;
Expand Down Expand Up @@ -123,7 +128,8 @@ FlatPlacementDensityManager::FlatPlacementDensityManager(const APNetlist& ap_net

// Get the target densisty of each physical block type.
std::vector<float> phy_ty_target_densities = get_physical_type_target_densities(target_density_arg_strs,
physical_tile_types);
physical_tile_types,
device_grid);
VTR_LOG("Partial legalizer is using target densities:");
for (const t_physical_tile_type& phy_ty : physical_tile_types) {
VTR_LOG(" %s:%.1f", phy_ty.name.c_str(), phy_ty_target_densities[phy_ty.index]);
Expand Down
31 changes: 31 additions & 0 deletions vpr/src/base/flat_placement_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
* @brief Utility methods for working with flat placements.
*/

#include <algorithm>
#include <cstdlib>
#include "device_grid.h"
#include "flat_placement_types.h"
#include "physical_types.h"

/**
* @brief Returns the manhattan distance (L1 distance) between two flat
Expand All @@ -17,3 +20,31 @@ inline float get_manhattan_distance(const t_flat_pl_loc& loc_a,
const t_flat_pl_loc& loc_b) {
return std::abs(loc_a.x - loc_b.x) + std::abs(loc_a.y - loc_b.y) + std::abs(loc_a.layer - loc_b.layer);
}

/**
* @brief Returns the L1 distance something at the given flat location would
* need to move to be within the bounds of a tile at the given tile loc.
*/
inline float get_manhattan_distance_to_tile(const t_flat_pl_loc& src_flat_loc,
const t_physical_tile_loc& tile_loc,
const DeviceGrid& device_grid) {
// Get the bounds of the tile.
// Note: The get_tile_bb function will not work in this case since it
// subtracts 1 from the width and height.
auto tile_type = device_grid.get_physical_type(tile_loc);
float tile_xmin = tile_loc.x - device_grid.get_width_offset(tile_loc);
float tile_xmax = tile_xmin + tile_type->width;
float tile_ymin = tile_loc.y - device_grid.get_height_offset(tile_loc);
float tile_ymax = tile_ymin + tile_type->height;

// Get the closest point in the bounding box (including the edges) to
// the src_flat_loc. To do this, we project the point in L1 space.
float proj_x = std::clamp(src_flat_loc.x, tile_xmin, tile_xmax);
float proj_y = std::clamp(src_flat_loc.y, tile_ymin, tile_ymax);

// Then compute the L1 distance from the src_flat_loc to the projected
// position. This will be the minimum distance this point needs to move.
float dx = std::abs(proj_x - src_flat_loc.x);
float dy = std::abs(proj_y - src_flat_loc.y);
return dx + dy;
}
25 changes: 21 additions & 4 deletions vpr/src/pack/appack_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ struct t_appack_options {
// Distance threshold which decides when to use quadratic decay or inverted
// sqrt decay. If the distance is less than this threshold, quadratic decay
// is used. Inverted sqrt is used otherwise.
static constexpr float dist_th = 1.75f;
static constexpr float dist_th = 2.0f;
// Attenuation value at the threshold.
static constexpr float attenuation_th = 0.35f;
static constexpr float attenuation_th = 0.25f;

// Using the distance threshold and the attenuation value at that point, we
// can compute the other two terms. This is to keep the attenuation function
Expand All @@ -82,7 +82,9 @@ struct t_appack_options {
// search within the cluster's tile. Setting this to a higher number would
// allow APPack to search farther away; but may bring in molecules which
// do not "want" to be in the cluster.
static constexpr float max_unrelated_tile_distance = 5.0f;
//
// [block_type_index] -> unrelated_tile_distance
std::vector<float> max_unrelated_tile_distance;

// Unrelated clustering occurs after all other candidate selection methods
// have failed. This parameter sets how many time we will attempt unrelated
Expand All @@ -93,7 +95,13 @@ struct t_appack_options {
// NOTE: A similar option exists in the candidate selector class. This was
// duplicated since it is very likely that APPack would need a
// different value for this option than the non-APPack flow.
static constexpr int max_unrelated_clustering_attempts = 10;
//
// [block_type_index] -> max_unrelated_attempts
std::vector<int> max_unrelated_clustering_attempts;
// By default, we perform 10 unrelated clustering attempts. This is used
// to aggresivly resolve density while adhering to the GP solution as much
// as possible.
static constexpr int default_max_unrelated_clustering_attempts = 10;

// TODO: Investigate adding flat placement info to seed selection.
};
Expand Down Expand Up @@ -122,6 +130,15 @@ struct APPackContext : public Context {
logical_block_types,
device_grid);
}

// By default, when unrelated clustering is on, search for unrelated molecules
// that are within 1 tile from the centroid of the cluster.
// NOTE: Molecules within the same tile as the centroid are considered to have
// 0 distance. The distance is computed relative to the bounds of the
// tile containing the centroid.
appack_options.max_unrelated_tile_distance.resize(logical_block_types.size(), 1.0);
appack_options.max_unrelated_clustering_attempts.resize(logical_block_types.size(),
appack_options.default_max_unrelated_clustering_attempts);
}

/**
Expand Down
23 changes: 11 additions & 12 deletions vpr/src/pack/appack_max_dist_th_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,18 @@ static bool has_memory_pbs(const t_pb_type* pb_type);
void APPackMaxDistThManager::init(const std::vector<std::string>& max_dist_ths,
const std::vector<t_logical_block_type>& 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.
max_distance_on_device_ = device_grid.width() + device_grid.height();

// 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_max_distance_thresholds_from_strings(max_dist_ths, logical_block_types);
}

// Set the initilized flag to true.
Expand All @@ -57,18 +61,15 @@ void APPackMaxDistThManager::init(const std::vector<std::string>& max_dist_ths,

void APPackMaxDistThManager::auto_set_max_distance_thresholds(const std::vector<t_logical_block_type>& 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,
float default_max_distance_th = std::max(default_max_dist_th_scale_ * max_distance_on_device_,
default_max_dist_th_offset_);
float logic_block_max_distance_th = std::max(logic_block_max_dist_th_scale_ * max_device_distance,
float logic_block_max_distance_th = std::max(logic_block_max_dist_th_scale_ * max_distance_on_device_,
logic_block_max_dist_th_offset_);
float memory_max_distance_th = std::max(memory_max_dist_th_scale_ * max_device_distance,
float memory_max_distance_th = std::max(memory_max_dist_th_scale_ * max_distance_on_device_,
memory_max_dist_th_offset_);
float io_block_max_distance_th = std::max(io_max_dist_th_scale_ * max_device_distance,
float io_block_max_distance_th = std::max(io_max_dist_th_scale_ * max_distance_on_device_,
io_max_dist_th_offset_);

// Set all logical block types to have the default max distance threshold.
Expand Down Expand Up @@ -138,8 +139,7 @@ static bool has_memory_pbs(const t_pb_type* pb_type) {

void APPackMaxDistThManager::set_max_distance_thresholds_from_strings(
const std::vector<std::string>& max_dist_ths,
const std::vector<t_logical_block_type>& logical_block_types,
const DeviceGrid& device_grid) {
const std::vector<t_logical_block_type>& logical_block_types) {

std::vector<std::string> lb_type_names;
std::unordered_map<std::string, int> lb_type_name_to_index;
Expand Down Expand Up @@ -167,8 +167,7 @@ void APPackMaxDistThManager::set_max_distance_thresholds_from_strings(
}

// 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,
float logical_block_max_dist_th = std::max(max_distance_on_device_ * logical_block_max_dist_th_scale,
logical_block_max_dist_th_offset);

int lb_ty_index = lb_type_name_to_index[lb_name];
Expand Down
41 changes: 35 additions & 6 deletions vpr/src/pack/appack_max_dist_th_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ class APPackMaxDistThManager {

// 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;
static constexpr float default_max_dist_th_scale_ = 0.1f;
static constexpr float default_max_dist_th_offset_ = 10.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_scale_ = 0.06f;
static constexpr float logic_block_max_dist_th_offset_ = 15.0f;

// Memory blocks (i.e. blocks that contain pb_types of the memory class)
Expand Down Expand Up @@ -80,7 +80,7 @@ class APPackMaxDistThManager {
const DeviceGrid& device_grid);

/**
* @brief Get the max distance threshold of the given lobical block type.
* @brief Get the max distance threshold of the given logical block type.
*/
inline float get_max_dist_threshold(const t_logical_block_type& logical_block_ty) const {
VTR_ASSERT_SAFE_MSG(is_initialized_,
Expand All @@ -91,6 +91,31 @@ class APPackMaxDistThManager {
return logical_block_dist_thresholds_[logical_block_ty.index];
}

/**
* @brief Get the maximum distance possible on the device. This is the
* manhattan distance from the bottom-left corner of the device to
* the top-right.
*/
inline float get_max_device_distance() const {
VTR_ASSERT_SAFE_MSG(is_initialized_,
"APPackMaxDistThManager has not been initialized, cannot call this method");

return max_distance_on_device_;
}

/**
* @brief Set the max distance threshold of the given logical block type.
*/
inline void set_max_dist_threshold(const t_logical_block_type& logical_block_ty,
float new_threshold) {
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");

logical_block_dist_thresholds_[logical_block_ty.index] = new_threshold;
}

private:
/**
* @brief Helper method that initializes the thresholds of all logical
Expand All @@ -105,13 +130,17 @@ class APPackMaxDistThManager {
* strings.
*/
void set_max_distance_thresholds_from_strings(const std::vector<std::string>& max_dist_ths,
const std::vector<t_logical_block_type>& logical_block_types,
const DeviceGrid& device_grid);
const std::vector<t_logical_block_type>& logical_block_types);

/// @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<float> logical_block_dist_thresholds_;

/// @brief This is the maximum minhattan distance possible on the device. This
/// is the distance of traveling from the bottom-left corner of the device
/// to the top right.
float max_distance_on_device_;
};
Loading