Skip to content
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
191 changes: 145 additions & 46 deletions vpr/src/analytical_place/analytical_solver.cpp

Large diffs are not rendered by default.

58 changes: 50 additions & 8 deletions vpr/src/analytical_place/analytical_solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,16 @@ class B2BSolver : public AnalyticalSolver {
/// number, the solver will focus more on timing and less on wirelength.
static constexpr double timing_slope_fac_ = 0.75;

/// @brief For most FPGA architectures, the cost of moving horizontally is
/// equivalent to the cost moving vertically (i.e. moving in increasing
/// x-dimension has the same cost as moving the same amount in the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not true for S10 and 7-series (different wiring supplies). Also may not be true for timing in many architectures.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be able to get these cost factors from some Soheil/Amin code in the annealer (they compute prefix sums of wiring supply in each dimension; should be able to ask for total wiring in x or y or z from them.

/// y-dimension). However, for 3D FPGAs, moving between layers is
/// much more expensive than moving in the x or y dimension. We account
/// for this by adding a cost penalty factor to the "z"-dimension.
/// TODO: This cost factor was randomly selected because it felt ok. Should
/// choose a better factor that is chosen empirically.
static constexpr double layer_distance_cost_fac_ = 10.0;

public:
B2BSolver(const APNetlist& ap_netlist,
const DeviceGrid& device_grid,
Expand Down Expand Up @@ -699,15 +709,41 @@ class B2BSolver : public AnalyticalSolver {
void update_linear_system_with_anchors(unsigned iteration);

/**
* @brief Store the x and y solutions in Eigen's vectors into the partial
* placement object.
*
* Note: The x_soln and y_soln may be modified if it is found that the
* solution is imposible (i.e. has negative positions).
* @brief Solves the linear system of equations using the connectivity
* matrix (A), the constant vector (b), and a guess for the solution.
*/
void store_solution_into_placement(Eigen::VectorXd& x_soln,
Eigen::VectorXd& y_soln,
PartialPlacement& p_placement);
Eigen::VectorXd solve_linear_system(Eigen::SparseMatrix<double> &A,
Eigen::VectorXd &b,
Eigen::VectorXd &guess);

/**
* @brief Store the solutions from the linear system into the partial
* placement object for the given dimension.
*
* Note: The dim_soln may be modified if it is found that the solution is
* imposible (e.g. has negative positions).
*
* @param dim_soln
* The solution of the linear system for a given dimension.
* @param block_dim_locs
* The block locations in the partial placement for the dimension.
* @param dim_max_pos
* The maximum position allowed for the dimension. For example, for the
* x-dimension, this would be the width of the device. This is used to
* ensure that the positions do not go off device.
*/
void store_solution_into_placement(Eigen::VectorXd &dim_soln,
vtr::vector<APBlockId, double> &block_dim_locs,
double dim_max_pos);

/**
* @brief Does the FPGA that the AP flow is currently targeting have more
* than one die. Having multiple dies would imply that the solver
* needs to add another dimension to solve for.
*/
inline bool is_multi_die() const {
return device_grid_num_layers_ > 1;
}

// The following are variables used to store the system of equations to be
// solved in the x and y dimensions. The equations are of the form:
Expand All @@ -720,22 +756,28 @@ class B2BSolver : public AnalyticalSolver {
Eigen::SparseMatrix<double> A_sparse_x;
/// @brief The coefficient / connectivity matrix for the y dimension.
Eigen::SparseMatrix<double> A_sparse_y;
/// @brief The coefficient / connectivity matrix for the z dimension (layer dimension).
Eigen::SparseMatrix<double> A_sparse_z;
/// @brief The constant vector in the x dimension.
Eigen::VectorXd b_x;
/// @brief The constant vector in the y dimension.
Eigen::VectorXd b_y;
/// @brief The constant vector in the z dimension (layer dimension).
Eigen::VectorXd b_z;

// The following is the solution of the previous iteration of this solver.
// They are updated at the end of solve() and are used as the starting point
// for the next call to solve.
vtr::vector<APBlockId, double> block_x_locs_solved;
vtr::vector<APBlockId, double> block_y_locs_solved;
vtr::vector<APBlockId, double> block_z_locs_solved;

// The following are the legalized solution coming into the analytical solver
// (other than the first iteration). These are stored to be used as anchor
// blocks during the solver.
vtr::vector<APBlockId, double> block_x_locs_legalized;
vtr::vector<APBlockId, double> block_y_locs_legalized;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want to say that for speed, the various _z values are ignored / not updated or used if a device has only one die.

vtr::vector<APBlockId, double> block_z_locs_legalized;

/// @brief The total number of CG iterations that this solver has performed
/// so far. This can be a useful metric for the amount of work the
Expand Down
8 changes: 5 additions & 3 deletions vpr/src/place/initial_placement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -653,21 +653,23 @@ static t_flat_pl_loc find_centroid_loc_from_flat_placement(const t_pl_macro& pl_
// and save the closest of all regions.
t_flat_pl_loc best_projected_pos = centroid;
float best_distance = std::numeric_limits<float>::max();
VTR_ASSERT_MSG(centroid.layer == 0,
"3D FPGAs not supported for this part of the code yet");
for (const Region& region : head_pr.get_regions()) {
const vtr::Rect<int>& rect = region.get_rect();
// Note: We add 0.999 here since the partition region is in grid
// space, so it treats tile positions as having size 0x0 when
// they really are 1x1.
float proj_x = std::clamp<float>(centroid.x, rect.xmin(), rect.xmax() + 0.999);
float proj_y = std::clamp<float>(centroid.y, rect.ymin(), rect.ymax() + 0.999);
float proj_layer = std::clamp<float>(centroid.layer, region.get_layer_range().first,
region.get_layer_range().second + 0.999);
float dx = std::abs(proj_x - centroid.x);
float dy = std::abs(proj_y - centroid.y);
float dist = dx + dy;
float dlayer = std::abs(proj_layer - centroid.layer);
float dist = dx + dy + dlayer;
if (dist < best_distance) {
best_projected_pos.x = proj_x;
best_projected_pos.y = proj_y;
best_projected_pos.layer = proj_layer;
best_distance = dist;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ circuit_list_add=mm9b.blif
circuit_list_add=styr.blif
circuit_list_add=s953.blif

# Constrain the IOs
# TODO: Should create a unique config file that tests fixed blocks for 3D AP.
# - For now, just add one so we can test the solver effectively.
circuit_constraint_list_add=(mm9a.blif, constraints=../../../../constraints/mm9a_io_constraint.xml)

# Parse info and how to parse
parse_file=vpr_fixed_chan_width.txt

Expand All @@ -42,4 +47,6 @@ script_params_common=-starting_stage vpr -track_memory_usage --analytical_place
script_params_list_add=--ap_analytical_solver identity --ap_partial_legalizer none
# Force unrelated clustering on.
script_params_list_add=--ap_analytical_solver identity --ap_partial_legalizer none --allow_unrelated_clustering on
# Test that the solver will work with 3D
script_params_list_add=--ap_partial_legalizer none --allow_unrelated_clustering on

Loading