Skip to content

Commit

Permalink
Merge pull request verilog-to-routing#2861 from AlexandreSinger/featu…
Browse files Browse the repository at this point in the history
…re-read-flat-place

[APPack] Added read_flat_place Option and Verifier
  • Loading branch information
vaughnbetz authored Jan 20, 2025
2 parents c90ac0d + d3967a6 commit 801dc62
Show file tree
Hide file tree
Showing 13 changed files with 439 additions and 7 deletions.
44 changes: 44 additions & 0 deletions doc/src/vpr/command_line_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,50 @@ Use the options below to override this default naming behaviour.

Prefix for output files

.. 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. Each line in the flat
placement file should have the following syntax:

.. code-block:: none
<atom_name : str> <x : float> <y : float> <layer : float> <atom_sub_tile : int> <atom_site_idx? : int>
For example:

.. code-block:: none
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::

This interface is currently experimental and under active development.

.. option:: --write_flat_place <file>

Writes the post-placement locations of each atom into a flat placement file.
Expand Down
84 changes: 84 additions & 0 deletions vpr/src/base/FlatPlacementInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* @file
* @author Alex Singer
* @date January 2025
* @brief Declaration of the FlatPlacementInfo object, which is used to store
* flat placement information used by the packer.
*/

#pragma once

#include "atom_netlist.h"
#include "vtr_vector.h"

/**
* @brief Flat placement storage class.
*
* This stores placement information for each atom in the netlist. It contains
* any information that may be used by the packer to better create clusters.
*/
class FlatPlacementInfo {
public:
/// @brief Identifier for an undefined position.
static constexpr float UNDEFINED_POS = -1.f;
/// @brief Identifier for an undefined sub tile.
static constexpr int UNDEFINED_SUB_TILE = -1;
/// @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. 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
/// or not. This makes it easier to detect if a flat placement exists
/// or not. Is true when a placement has been loaded into this
/// object, false otherwise.
bool valid;

/**
* @brief Default constructor of this class.
*
* Initializes the data structure to invalid so it can be easily checked to
* be uninitialized.
*/
FlatPlacementInfo() : valid(false) {}

/**
* @brief Constructs the flat placement with undefined positions for each
* atom block in the atom netlist.
*
* The valid flag is set to true here, since this structure is now
* initialized with data and can be used.
*
* @param atom_netlist
* The netlist of atom blocks in the circuit.
*/
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) {}
};

1 change: 1 addition & 0 deletions vpr/src/base/SetupVPR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ void SetupVPR(const t_options* options,
fileNameOpts->read_vpr_constraints_file = options->read_vpr_constraints_file;
fileNameOpts->write_vpr_constraints_file = options->write_vpr_constraints_file;
fileNameOpts->write_constraints_file = options->write_constraints_file;
fileNameOpts->read_flat_place_file = options->read_flat_place_file;
fileNameOpts->write_flat_place_file = options->write_flat_place_file;
fileNameOpts->write_block_usage = options->write_block_usage;

Expand Down
90 changes: 88 additions & 2 deletions vpr/src/base/load_flat_place.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@

#include "load_flat_place.h"

#include <fstream>
#include <unordered_set>
#include "atom_netlist.h"
#include "clustered_netlist.h"
#include "FlatPlacementInfo.h"
#include "globals.h"
#include "vpr_context.h"
#include "vpr_error.h"
#include "vpr_types.h"
#include "vtr_log.h"

/**
* @brief Prints flat placement file entries for the atoms in one placed
Expand Down Expand Up @@ -45,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 @@ -77,6 +83,86 @@ void write_flat_placement(const char* flat_place_file_path,
fclose(fp);
}

FlatPlacementInfo read_flat_placement(const std::string& read_flat_place_file_path,
const AtomNetlist& atom_netlist) {
// Try to open the file, crash if we cannot open the file.
std::ifstream flat_place_file(read_flat_place_file_path);
if (!flat_place_file.is_open()) {
VPR_ERROR(VPR_ERROR_OTHER, "Unable to open flat placement file: %s\n",
read_flat_place_file_path.c_str());
}

// Create a FlatPlacementInfo object to hold the flat placement.
FlatPlacementInfo flat_placement_info(atom_netlist);

// Read each line of the flat placement file.
unsigned line_num = 0;
std::string line;
while (std::getline(flat_place_file, line)) {
// Split the line into tokens (using spaces, tabs, etc. as delimiters).
std::vector<std::string> tokens = vtr::split(line);
// Skip empty lines
if (tokens.empty())
continue;
// Skip lines that are only comments.
if (tokens[0][0] == '#')
continue;
// Skip lines with too few arguments.
// Required arguments:
// - Atom name
// - Atom x-pos
// - Atom y-pos
// - 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> <x> <y> <layer> <sub_tile>\n",
line_num);
continue;
}

// Get the atom name, which should be the first argument.
AtomBlockId atom_blk_id = atom_netlist.find_block(tokens[0]);
if (!atom_blk_id.is_valid()) {
VTR_LOG_WARN("Flat placement file, line %d atom name does not match "
"any atoms in the atom netlist.\n",
line_num);
continue;
}

// Check if this atom already has a flat placement
// Using the x_pos and y_pos as identifiers.
if (flat_placement_info.blk_x_pos[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS ||
flat_placement_info.blk_y_pos[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS) {
VTR_LOG_WARN("Flat placement file, line %d, atom %s has multiple "
"placement definitions in the flat placement file.\n",
line_num, atom_netlist.block_name(atom_blk_id).c_str());
continue;
}

// 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]);

// 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() >= 6 && tokens[5][0] != '#')
flat_placement_info.blk_site_idx[atom_blk_id] = vtr::atoi(tokens[5]);

// Ignore any further tokens.

line_num++;
}

// Return the flat placement info loaded from the file.
return flat_placement_info;
}

/* ingests and legalizes a flat placement file */
bool load_flat_placement(t_vpr_setup& vpr_setup, const t_arch& arch) {
VTR_LOG("load_flat_placement(); when implemented, this function:");
Expand Down
16 changes: 16 additions & 0 deletions vpr/src/base/load_flat_place.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@

#pragma once

#include <string>
#include <unordered_set>
#include "vtr_vector_map.h"
#include "vtr_vector.h"

// Forward declarations
class AtomBlockId;
class AtomNetlist;
class ClusterBlockId;
class ClusteredNetlist;
class FlatPlacementInfo;
class Prepacker;
struct t_arch;
struct t_block_loc;
struct t_vpr_setup;
Expand All @@ -40,6 +44,18 @@ void write_flat_placement(const char* flat_place_file_path,
const vtr::vector_map<ClusterBlockId, t_block_loc> &block_locs,
const vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>>& atoms_lookup);

/**
* @brief Reads a flat placement file generated from a previous run of VTR or
* externally generated.
*
* @param read_flat_place_file_path
* Path to the file to read the flat placement from.
* @param atom_netlist
* The netlist of atom blocks in the circuit.
*/
FlatPlacementInfo read_flat_placement(const std::string& read_flat_place_file_path,
const AtomNetlist& atom_netlist);

/**
* @brief A function that loads and legalizes a flat placement file
*/
Expand Down
5 changes: 5 additions & 0 deletions vpr/src/base/read_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1652,6 +1652,11 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio
.default_value("fix_clusters.out")
.show_in(argparse::ShowIn::HELP_ONLY);

file_grp.add_argument(args.read_flat_place_file, "--read_flat_place")
.help(
"Reads VPR's (or reconstructed external) placement solution in flat placement file format; this file lists cluster and intra-cluster placement coordinates for each atom and can be used to reconstruct a clustering and placement solution.")
.show_in(argparse::ShowIn::HELP_ONLY);

file_grp.add_argument(args.write_flat_place_file, "--write_flat_place")
.help(
"VPR's (or reconstructed external) placement solution in flat placement file format; this file lists cluster and intra-cluster placement coordinates for each atom and can be used to reconstruct a clustering and placement solution.")
Expand Down
1 change: 1 addition & 0 deletions vpr/src/base/read_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct t_options {
argparse::ArgValue<std::string> read_vpr_constraints_file;
argparse::ArgValue<std::string> write_vpr_constraints_file;
argparse::ArgValue<std::string> write_constraints_file;
argparse::ArgValue<std::string> read_flat_place_file;
argparse::ArgValue<std::string> write_flat_place_file;

argparse::ArgValue<std::string> write_placement_delay_lookup;
Expand Down
11 changes: 10 additions & 1 deletion vpr/src/base/vpr_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <cstring>
#include <cmath>

#include "FlatPlacementInfo.h"
#include "cluster_util.h"
#include "verify_placement.h"
#include "vpr_context.h"
Expand Down Expand Up @@ -687,10 +688,18 @@ bool vpr_pack(t_vpr_setup& vpr_setup, const t_arch& arch) {
+ wtoi_switch_del); /* multiply by 4 to get a more conservative estimate */
}

// Read in the flat placement if a flat placement file is provided.
FlatPlacementInfo flat_placement_info;
if (!vpr_setup.FileNameOpts.read_flat_place_file.empty()) {
flat_placement_info = read_flat_placement(
vpr_setup.FileNameOpts.read_flat_place_file,
g_vpr_ctx.atom().nlist);
}

return try_pack(&vpr_setup.PackerOpts, &vpr_setup.AnalysisOpts,
&arch, vpr_setup.user_models,
vpr_setup.library_models, inter_cluster_delay,
vpr_setup.PackerRRGraph);
vpr_setup.PackerRRGraph, flat_placement_info);
}

void vpr_load_packing(t_vpr_setup& vpr_setup, const t_arch& arch) {
Expand Down
1 change: 1 addition & 0 deletions vpr/src/base/vpr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,7 @@ struct t_file_name_opts {
std::string read_vpr_constraints_file;
std::string write_vpr_constraints_file;
std::string write_constraints_file;
std::string read_flat_place_file;
std::string write_flat_place_file;
std::string write_block_usage;
bool verify_file_digests;
Expand Down
Loading

0 comments on commit 801dc62

Please sign in to comment.