Skip to content

Commit

Permalink
[APPack] Added Layer to Flat Placement
Browse files Browse the repository at this point in the history
As per Vaughn's suggestions, added layer to the flat placement file
specification to make it easier to upgrade to 3D FPGAs in the future.

Fixed some small documentation issues.
  • Loading branch information
AlexandreSinger committed Jan 20, 2025
1 parent 18097d4 commit d3967a6
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 27 deletions.
39 changes: 29 additions & 10 deletions doc/src/vpr/command_line_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -411,23 +411,42 @@ Use the options below to override this default naming behaviour.
.. option:: --read_flat_place <file>

Reads a file containing the locations of each atom on the FPGA.

This is used by the packer to better cluster atoms together.

The flat placement file (which often ends in ``.fplace``) is a text file
where each line describes the location of an atom. It has the following
expected syntax:
where each line describes the location of an atom. Each line in the flat
placement file should have the following syntax:

.. code-block:: none
<atom_name : str> <atom_x_pos : float> <atom_y_pos : float> <atom_sub_tile? : int> <atom_site_idx? : int>
n523 6 8 0 3
n522 6 8 0 5
n520 6 8 0 2
n518 6 8 0 16
<atom_name : str> <x : float> <y : float> <layer : float> <atom_sub_tile : int> <atom_site_idx? : int>
For example:

.. code-block:: none
The ``sub_tile`` and ``site_idx`` are optional parameters which may be used
as a hint to reconstruct clusters.
n523 6 8 0 0 3
n522 6 8 0 0 5
n520 6 8 0 0 2
n518 6 8 0 0 16
The position of the atom on the FPGA is given by 3 floating point values
(``x``, ``y``, ``layer``). We allow for the positions of atom to be not
quite legal (ok to be off-grid) since this flat placement will be fed into
the packer and placer, which will snap the positions to grid locations. By
allowing for off-grid positions, the packer can better trade-off where to
move atom blocks if they cannot be placed at the given position.
For 2D FPGA architectures, the ``layer`` should be 0.

The ``sub_tile`` is a clustered placement construct: which cluster-level
location at a given (x, y, layer) should these atoms go at (relevant when
multiple clusters can be stacked there). A sub-tile of -1 may be used when
the sub-tile of an atom is unkown (allowing the packing algorithm to choose
any sub-tile at the given (x, y, layer) location).

The ``site_idx`` is an optional index into a linearized list of primitive
locations within a cluster-level block which may be used as a hint to
reconstruct clusters.

.. warning::

Expand Down
17 changes: 15 additions & 2 deletions vpr/src/base/FlatPlacementInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,27 @@ class FlatPlacementInfo {
/// @brief Identifier for an undefined site idx.
static constexpr int UNDEFINED_SITE_IDX = -1;

// The following three floating point numbers describe the flat position of
// an atom block. These are floats instead of integers to allow for flat
// placements which are not quite legal (ok to be off-grid). This allows
// the flat placement to encode information about where atom blocks would
// want to go if they cannot be placed at the grid position they are at.
// (for example, a block placed at (0.9, 0.9) wants to be at tile (0, 0),
// but if thats not possible it would prefer (1, 1) over anything else.

/// @brief The x-positions of each atom block. Is UNDEFINED_POS if undefined.
vtr::vector<AtomBlockId, float> blk_x_pos;
/// @brief The y-positions of each atom block. Is UNDEFINED_POS if undefined.
vtr::vector<AtomBlockId, float> blk_y_pos;
/// @brief The layer of each atom block. Is UNDEFINED_POS if undefined.
vtr::vector<AtomBlockId, float> blk_layer;

/// @brief The sub tile location of each atom block. Is UNDEFINED_SUB_TILE
/// if undefined.
vtr::vector<AtomBlockId, int> blk_sub_tile;
/// @brief The flat site idx of each atom block. Is UNDEFINED_SITE_IDX if
/// undefined.
/// @brief The flat site idx of each atom block. This is an optional index
/// into a linearized list of primitive locations within a cluster-
/// level block. Is UNDEFINED_SITE_IDX if undefined.
vtr::vector<AtomBlockId, int> blk_site_idx;

/// @brief A flag to signify if this object has been constructed with data
Expand Down Expand Up @@ -64,6 +76,7 @@ class FlatPlacementInfo {
FlatPlacementInfo(const AtomNetlist& atom_netlist)
: blk_x_pos(atom_netlist.blocks().size(), UNDEFINED_POS),
blk_y_pos(atom_netlist.blocks().size(), UNDEFINED_POS),
blk_layer(atom_netlist.blocks().size(), UNDEFINED_POS),
blk_sub_tile(atom_netlist.blocks().size(), UNDEFINED_SUB_TILE),
blk_site_idx(atom_netlist.blocks().size(), UNDEFINED_SITE_IDX),
valid(true) {}
Expand Down
27 changes: 15 additions & 12 deletions vpr/src/base/load_flat_place.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ static void print_flat_cluster(FILE* fp,
t_pb_graph_node* atom_pbgn = atom_ctx.lookup.atom_pb(atom)->pb_graph_node;

// Print the flat placement information for this atom.
fprintf(fp, "%s %d %d %d %d #%zu %s\n",
fprintf(fp, "%s %d %d %d %d %d #%zu %s\n",
atom_ctx.nlist.block_name(atom).c_str(),
blk_loc.x, blk_loc.y, blk_loc.sub_tile,
blk_loc.x, blk_loc.y, blk_loc.layer,
blk_loc.sub_tile,
atom_pbgn->flat_site_index,
static_cast<size_t>(blk_id),
atom_pbgn->pb_type->name);
Expand Down Expand Up @@ -111,9 +112,11 @@ FlatPlacementInfo read_flat_placement(const std::string& read_flat_place_file_pa
// - Atom name
// - Atom x-pos
// - Atom y-pos
if (tokens.size() < 3) {
// - Atom layer
// - Atom sub-tile
if (tokens.size() < 5) {
VTR_LOG_WARN("Flat placement file, line %d has too few arguments. "
"Requires at least: <atom_name> <atom_x_pos> <atom_y_pos>\n",
"Requires at least: <atom_name> <x> <y> <layer> <sub_tile>\n",
line_num);
continue;
}
Expand All @@ -137,19 +140,19 @@ FlatPlacementInfo read_flat_placement(const std::string& read_flat_place_file_pa
continue;
}

// Get the x and y position of the atom. These functions have error
// checking built in. We parse x and y as floats to allow for reading
// in more global atom positions.
// Get the (x, y, layer) position of the atom. These functions have
// error checking built in. We parse these as floats to allow for
// reading in more global atom positions.
flat_placement_info.blk_x_pos[atom_blk_id] = vtr::atof(tokens[1]);
flat_placement_info.blk_y_pos[atom_blk_id] = vtr::atof(tokens[2]);
flat_placement_info.blk_layer[atom_blk_id] = vtr::atof(tokens[3]);

// If a sub-tile is given, parse the sub-tile as an integer.
if (tokens.size() >= 4 && tokens[3][0] != '#')
flat_placement_info.blk_sub_tile[atom_blk_id] = vtr::atoi(tokens[3]);
// Parse the sub-tile as an integer.
flat_placement_info.blk_sub_tile[atom_blk_id] = vtr::atoi(tokens[4]);

// If a site index is given, parse the site index as an integer.
if (tokens.size() >= 5 && tokens[4][0] != '#')
flat_placement_info.blk_site_idx[atom_blk_id] = vtr::atoi(tokens[4]);
if (tokens.size() >= 6 && tokens[5][0] != '#')
flat_placement_info.blk_site_idx[atom_blk_id] = vtr::atoi(tokens[5]);

// Ignore any further tokens.

Expand Down
22 changes: 22 additions & 0 deletions vpr/src/pack/pack.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,28 @@ struct t_lb_type_rr_node;
struct t_model;
struct t_packer_opts;

/**
* @brief Try to pack the atom netlist into legal clusters on the given
* architecture. Will return true if successful, false otherwise.
*
* @param packer_opts
* Options passed by the user to configure the packing algorithm.
* @param analysis_opts
* Options passed by the user to configure how analysis is
* performed in the packer.
* @param arch
* A pointer to the architecture to create clusters for.
* @param user_models
* A list of architecture models provided by the architecture file.
* @param library_models
* A list of architecture models provided by the library.
* @param interc_delay
* @param lb_type_rr_graphs
* @param flat_placement_info
* Flat (primitive-level) placement information that may be
* provided by the user as a hint for packing. Will be invalid if
* there is no flat placement information provided.
*/
bool try_pack(t_packer_opts* packer_opts,
const t_analysis_opts* analysis_opts,
const t_arch* arch,
Expand Down
13 changes: 10 additions & 3 deletions vpr/src/pack/verify_flat_placement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ unsigned verify_flat_placement_for_packing(const FlatPlacementInfo& flat_placeme
// for each piece of information.
if (flat_placement_info.blk_x_pos.size() != atom_netlist.blocks().size() ||
flat_placement_info.blk_y_pos.size() != atom_netlist.blocks().size() ||
flat_placement_info.blk_layer.size() != atom_netlist.blocks().size() ||
flat_placement_info.blk_sub_tile.size() != atom_netlist.blocks().size() ||
flat_placement_info.blk_site_idx.size() != atom_netlist.blocks().size()) {
VTR_LOG_ERROR(
Expand All @@ -26,14 +27,14 @@ unsigned verify_flat_placement_for_packing(const FlatPlacementInfo& flat_placeme
return num_errors;
}

// 1. Verify that every atom has an x and y position on the device. This is
// the only information we require for the flat placement during packing.
// 1. Verify that every atom has an (x, y, layer) position on the device.
//
// TODO: In the future, we may be able to allow some blocks to have
// undefined positions.
for (AtomBlockId blk_id : atom_netlist.blocks()) {
if (flat_placement_info.blk_x_pos[blk_id] == FlatPlacementInfo::UNDEFINED_POS ||
flat_placement_info.blk_y_pos[blk_id] == FlatPlacementInfo::UNDEFINED_POS) {
flat_placement_info.blk_y_pos[blk_id] == FlatPlacementInfo::UNDEFINED_POS ||
flat_placement_info.blk_layer[blk_id] == FlatPlacementInfo::UNDEFINED_POS) {
VTR_LOG_ERROR(
"Atom block %s has an undefined position in the flat placement.\n",
atom_netlist.block_name(blk_id).c_str());
Expand All @@ -49,10 +50,12 @@ unsigned verify_flat_placement_for_packing(const FlatPlacementInfo& flat_placeme
for (AtomBlockId blk_id : atom_netlist.blocks()) {
float blk_x_pos = flat_placement_info.blk_x_pos[blk_id];
float blk_y_pos = flat_placement_info.blk_y_pos[blk_id];
float blk_layer = flat_placement_info.blk_layer[blk_id];
int blk_sub_tile = flat_placement_info.blk_sub_tile[blk_id];
int blk_site_idx = flat_placement_info.blk_site_idx[blk_id];
if ((blk_x_pos < 0.f && blk_x_pos != FlatPlacementInfo::UNDEFINED_POS) ||
(blk_y_pos < 0.f && blk_y_pos != FlatPlacementInfo::UNDEFINED_POS) ||
(blk_layer < 0.f && blk_layer != FlatPlacementInfo::UNDEFINED_POS) ||
(blk_sub_tile < 0 && blk_sub_tile != FlatPlacementInfo::UNDEFINED_SUB_TILE) ||
(blk_site_idx < 0 && blk_site_idx != FlatPlacementInfo::UNDEFINED_SITE_IDX)) {
VTR_LOG_ERROR(
Expand All @@ -71,12 +74,14 @@ unsigned verify_flat_placement_for_packing(const FlatPlacementInfo& flat_placeme
AtomBlockId root_blk_id = mol->atom_block_ids[mol->root];
float root_pos_x = flat_placement_info.blk_x_pos[root_blk_id];
float root_pos_y = flat_placement_info.blk_y_pos[root_blk_id];
float root_layer = flat_placement_info.blk_layer[root_blk_id];
int root_sub_tile = flat_placement_info.blk_sub_tile[root_blk_id];
for (AtomBlockId mol_blk_id : mol->atom_block_ids) {
if (!mol_blk_id.is_valid())
continue;
if (flat_placement_info.blk_x_pos[mol_blk_id] != root_pos_x ||
flat_placement_info.blk_y_pos[mol_blk_id] != root_pos_y ||
flat_placement_info.blk_layer[mol_blk_id] != root_layer ||
flat_placement_info.blk_sub_tile[mol_blk_id] != root_sub_tile) {
VTR_LOG_ERROR(
"Molecule with root atom block %s contains atom block %s "
Expand All @@ -89,6 +94,8 @@ unsigned verify_flat_placement_for_packing(const FlatPlacementInfo& flat_placeme
}
}

// TODO: May want to verify that the layer is all 0 in the case of 2D FPGAs.

return num_errors;
}

0 comments on commit d3967a6

Please sign in to comment.