Skip to content

Commit 801dc62

Browse files
authored
Merge pull request #2861 from AlexandreSinger/feature-read-flat-place
[APPack] Added read_flat_place Option and Verifier
2 parents c90ac0d + d3967a6 commit 801dc62

13 files changed

+439
-7
lines changed

doc/src/vpr/command_line_usage.rst

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,50 @@ Use the options below to override this default naming behaviour.
408408

409409
Prefix for output files
410410

411+
.. option:: --read_flat_place <file>
412+
413+
Reads a file containing the locations of each atom on the FPGA.
414+
This is used by the packer to better cluster atoms together.
415+
416+
The flat placement file (which often ends in ``.fplace``) is a text file
417+
where each line describes the location of an atom. Each line in the flat
418+
placement file should have the following syntax:
419+
420+
.. code-block:: none
421+
422+
<atom_name : str> <x : float> <y : float> <layer : float> <atom_sub_tile : int> <atom_site_idx? : int>
423+
424+
For example:
425+
426+
.. code-block:: none
427+
428+
n523 6 8 0 0 3
429+
n522 6 8 0 0 5
430+
n520 6 8 0 0 2
431+
n518 6 8 0 0 16
432+
433+
The position of the atom on the FPGA is given by 3 floating point values
434+
(``x``, ``y``, ``layer``). We allow for the positions of atom to be not
435+
quite legal (ok to be off-grid) since this flat placement will be fed into
436+
the packer and placer, which will snap the positions to grid locations. By
437+
allowing for off-grid positions, the packer can better trade-off where to
438+
move atom blocks if they cannot be placed at the given position.
439+
For 2D FPGA architectures, the ``layer`` should be 0.
440+
441+
The ``sub_tile`` is a clustered placement construct: which cluster-level
442+
location at a given (x, y, layer) should these atoms go at (relevant when
443+
multiple clusters can be stacked there). A sub-tile of -1 may be used when
444+
the sub-tile of an atom is unkown (allowing the packing algorithm to choose
445+
any sub-tile at the given (x, y, layer) location).
446+
447+
The ``site_idx`` is an optional index into a linearized list of primitive
448+
locations within a cluster-level block which may be used as a hint to
449+
reconstruct clusters.
450+
451+
.. warning::
452+
453+
This interface is currently experimental and under active development.
454+
411455
.. option:: --write_flat_place <file>
412456

413457
Writes the post-placement locations of each atom into a flat placement file.

vpr/src/base/FlatPlacementInfo.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* @file
3+
* @author Alex Singer
4+
* @date January 2025
5+
* @brief Declaration of the FlatPlacementInfo object, which is used to store
6+
* flat placement information used by the packer.
7+
*/
8+
9+
#pragma once
10+
11+
#include "atom_netlist.h"
12+
#include "vtr_vector.h"
13+
14+
/**
15+
* @brief Flat placement storage class.
16+
*
17+
* This stores placement information for each atom in the netlist. It contains
18+
* any information that may be used by the packer to better create clusters.
19+
*/
20+
class FlatPlacementInfo {
21+
public:
22+
/// @brief Identifier for an undefined position.
23+
static constexpr float UNDEFINED_POS = -1.f;
24+
/// @brief Identifier for an undefined sub tile.
25+
static constexpr int UNDEFINED_SUB_TILE = -1;
26+
/// @brief Identifier for an undefined site idx.
27+
static constexpr int UNDEFINED_SITE_IDX = -1;
28+
29+
// The following three floating point numbers describe the flat position of
30+
// an atom block. These are floats instead of integers to allow for flat
31+
// placements which are not quite legal (ok to be off-grid). This allows
32+
// the flat placement to encode information about where atom blocks would
33+
// want to go if they cannot be placed at the grid position they are at.
34+
// (for example, a block placed at (0.9, 0.9) wants to be at tile (0, 0),
35+
// but if thats not possible it would prefer (1, 1) over anything else.
36+
37+
/// @brief The x-positions of each atom block. Is UNDEFINED_POS if undefined.
38+
vtr::vector<AtomBlockId, float> blk_x_pos;
39+
/// @brief The y-positions of each atom block. Is UNDEFINED_POS if undefined.
40+
vtr::vector<AtomBlockId, float> blk_y_pos;
41+
/// @brief The layer of each atom block. Is UNDEFINED_POS if undefined.
42+
vtr::vector<AtomBlockId, float> blk_layer;
43+
44+
/// @brief The sub tile location of each atom block. Is UNDEFINED_SUB_TILE
45+
/// if undefined.
46+
vtr::vector<AtomBlockId, int> blk_sub_tile;
47+
/// @brief The flat site idx of each atom block. This is an optional index
48+
/// into a linearized list of primitive locations within a cluster-
49+
/// level block. Is UNDEFINED_SITE_IDX if undefined.
50+
vtr::vector<AtomBlockId, int> blk_site_idx;
51+
52+
/// @brief A flag to signify if this object has been constructed with data
53+
/// or not. This makes it easier to detect if a flat placement exists
54+
/// or not. Is true when a placement has been loaded into this
55+
/// object, false otherwise.
56+
bool valid;
57+
58+
/**
59+
* @brief Default constructor of this class.
60+
*
61+
* Initializes the data structure to invalid so it can be easily checked to
62+
* be uninitialized.
63+
*/
64+
FlatPlacementInfo() : valid(false) {}
65+
66+
/**
67+
* @brief Constructs the flat placement with undefined positions for each
68+
* atom block in the atom netlist.
69+
*
70+
* The valid flag is set to true here, since this structure is now
71+
* initialized with data and can be used.
72+
*
73+
* @param atom_netlist
74+
* The netlist of atom blocks in the circuit.
75+
*/
76+
FlatPlacementInfo(const AtomNetlist& atom_netlist)
77+
: blk_x_pos(atom_netlist.blocks().size(), UNDEFINED_POS),
78+
blk_y_pos(atom_netlist.blocks().size(), UNDEFINED_POS),
79+
blk_layer(atom_netlist.blocks().size(), UNDEFINED_POS),
80+
blk_sub_tile(atom_netlist.blocks().size(), UNDEFINED_SUB_TILE),
81+
blk_site_idx(atom_netlist.blocks().size(), UNDEFINED_SITE_IDX),
82+
valid(true) {}
83+
};
84+

vpr/src/base/SetupVPR.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ void SetupVPR(const t_options* options,
132132
fileNameOpts->read_vpr_constraints_file = options->read_vpr_constraints_file;
133133
fileNameOpts->write_vpr_constraints_file = options->write_vpr_constraints_file;
134134
fileNameOpts->write_constraints_file = options->write_constraints_file;
135+
fileNameOpts->read_flat_place_file = options->read_flat_place_file;
135136
fileNameOpts->write_flat_place_file = options->write_flat_place_file;
136137
fileNameOpts->write_block_usage = options->write_block_usage;
137138

vpr/src/base/load_flat_place.cpp

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@
88

99
#include "load_flat_place.h"
1010

11+
#include <fstream>
1112
#include <unordered_set>
13+
#include "atom_netlist.h"
1214
#include "clustered_netlist.h"
15+
#include "FlatPlacementInfo.h"
1316
#include "globals.h"
1417
#include "vpr_context.h"
18+
#include "vpr_error.h"
1519
#include "vpr_types.h"
20+
#include "vtr_log.h"
1621

1722
/**
1823
* @brief Prints flat placement file entries for the atoms in one placed
@@ -45,9 +50,10 @@ static void print_flat_cluster(FILE* fp,
4550
t_pb_graph_node* atom_pbgn = atom_ctx.lookup.atom_pb(atom)->pb_graph_node;
4651

4752
// Print the flat placement information for this atom.
48-
fprintf(fp, "%s %d %d %d %d #%zu %s\n",
53+
fprintf(fp, "%s %d %d %d %d %d #%zu %s\n",
4954
atom_ctx.nlist.block_name(atom).c_str(),
50-
blk_loc.x, blk_loc.y, blk_loc.sub_tile,
55+
blk_loc.x, blk_loc.y, blk_loc.layer,
56+
blk_loc.sub_tile,
5157
atom_pbgn->flat_site_index,
5258
static_cast<size_t>(blk_id),
5359
atom_pbgn->pb_type->name);
@@ -77,6 +83,86 @@ void write_flat_placement(const char* flat_place_file_path,
7783
fclose(fp);
7884
}
7985

86+
FlatPlacementInfo read_flat_placement(const std::string& read_flat_place_file_path,
87+
const AtomNetlist& atom_netlist) {
88+
// Try to open the file, crash if we cannot open the file.
89+
std::ifstream flat_place_file(read_flat_place_file_path);
90+
if (!flat_place_file.is_open()) {
91+
VPR_ERROR(VPR_ERROR_OTHER, "Unable to open flat placement file: %s\n",
92+
read_flat_place_file_path.c_str());
93+
}
94+
95+
// Create a FlatPlacementInfo object to hold the flat placement.
96+
FlatPlacementInfo flat_placement_info(atom_netlist);
97+
98+
// Read each line of the flat placement file.
99+
unsigned line_num = 0;
100+
std::string line;
101+
while (std::getline(flat_place_file, line)) {
102+
// Split the line into tokens (using spaces, tabs, etc. as delimiters).
103+
std::vector<std::string> tokens = vtr::split(line);
104+
// Skip empty lines
105+
if (tokens.empty())
106+
continue;
107+
// Skip lines that are only comments.
108+
if (tokens[0][0] == '#')
109+
continue;
110+
// Skip lines with too few arguments.
111+
// Required arguments:
112+
// - Atom name
113+
// - Atom x-pos
114+
// - Atom y-pos
115+
// - Atom layer
116+
// - Atom sub-tile
117+
if (tokens.size() < 5) {
118+
VTR_LOG_WARN("Flat placement file, line %d has too few arguments. "
119+
"Requires at least: <atom_name> <x> <y> <layer> <sub_tile>\n",
120+
line_num);
121+
continue;
122+
}
123+
124+
// Get the atom name, which should be the first argument.
125+
AtomBlockId atom_blk_id = atom_netlist.find_block(tokens[0]);
126+
if (!atom_blk_id.is_valid()) {
127+
VTR_LOG_WARN("Flat placement file, line %d atom name does not match "
128+
"any atoms in the atom netlist.\n",
129+
line_num);
130+
continue;
131+
}
132+
133+
// Check if this atom already has a flat placement
134+
// Using the x_pos and y_pos as identifiers.
135+
if (flat_placement_info.blk_x_pos[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS ||
136+
flat_placement_info.blk_y_pos[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS) {
137+
VTR_LOG_WARN("Flat placement file, line %d, atom %s has multiple "
138+
"placement definitions in the flat placement file.\n",
139+
line_num, atom_netlist.block_name(atom_blk_id).c_str());
140+
continue;
141+
}
142+
143+
// Get the (x, y, layer) position of the atom. These functions have
144+
// error checking built in. We parse these as floats to allow for
145+
// reading in more global atom positions.
146+
flat_placement_info.blk_x_pos[atom_blk_id] = vtr::atof(tokens[1]);
147+
flat_placement_info.blk_y_pos[atom_blk_id] = vtr::atof(tokens[2]);
148+
flat_placement_info.blk_layer[atom_blk_id] = vtr::atof(tokens[3]);
149+
150+
// Parse the sub-tile as an integer.
151+
flat_placement_info.blk_sub_tile[atom_blk_id] = vtr::atoi(tokens[4]);
152+
153+
// If a site index is given, parse the site index as an integer.
154+
if (tokens.size() >= 6 && tokens[5][0] != '#')
155+
flat_placement_info.blk_site_idx[atom_blk_id] = vtr::atoi(tokens[5]);
156+
157+
// Ignore any further tokens.
158+
159+
line_num++;
160+
}
161+
162+
// Return the flat placement info loaded from the file.
163+
return flat_placement_info;
164+
}
165+
80166
/* ingests and legalizes a flat placement file */
81167
bool load_flat_placement(t_vpr_setup& vpr_setup, const t_arch& arch) {
82168
VTR_LOG("load_flat_placement(); when implemented, this function:");

vpr/src/base/load_flat_place.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,18 @@
1010

1111
#pragma once
1212

13+
#include <string>
1314
#include <unordered_set>
1415
#include "vtr_vector_map.h"
1516
#include "vtr_vector.h"
1617

1718
// Forward declarations
1819
class AtomBlockId;
20+
class AtomNetlist;
1921
class ClusterBlockId;
2022
class ClusteredNetlist;
23+
class FlatPlacementInfo;
24+
class Prepacker;
2125
struct t_arch;
2226
struct t_block_loc;
2327
struct t_vpr_setup;
@@ -40,6 +44,18 @@ void write_flat_placement(const char* flat_place_file_path,
4044
const vtr::vector_map<ClusterBlockId, t_block_loc> &block_locs,
4145
const vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>>& atoms_lookup);
4246

47+
/**
48+
* @brief Reads a flat placement file generated from a previous run of VTR or
49+
* externally generated.
50+
*
51+
* @param read_flat_place_file_path
52+
* Path to the file to read the flat placement from.
53+
* @param atom_netlist
54+
* The netlist of atom blocks in the circuit.
55+
*/
56+
FlatPlacementInfo read_flat_placement(const std::string& read_flat_place_file_path,
57+
const AtomNetlist& atom_netlist);
58+
4359
/**
4460
* @brief A function that loads and legalizes a flat placement file
4561
*/

vpr/src/base/read_options.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,6 +1652,11 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio
16521652
.default_value("fix_clusters.out")
16531653
.show_in(argparse::ShowIn::HELP_ONLY);
16541654

1655+
file_grp.add_argument(args.read_flat_place_file, "--read_flat_place")
1656+
.help(
1657+
"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.")
1658+
.show_in(argparse::ShowIn::HELP_ONLY);
1659+
16551660
file_grp.add_argument(args.write_flat_place_file, "--write_flat_place")
16561661
.help(
16571662
"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.")

vpr/src/base/read_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct t_options {
3333
argparse::ArgValue<std::string> read_vpr_constraints_file;
3434
argparse::ArgValue<std::string> write_vpr_constraints_file;
3535
argparse::ArgValue<std::string> write_constraints_file;
36+
argparse::ArgValue<std::string> read_flat_place_file;
3637
argparse::ArgValue<std::string> write_flat_place_file;
3738

3839
argparse::ArgValue<std::string> write_placement_delay_lookup;

vpr/src/base/vpr_api.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <cstring>
1616
#include <cmath>
1717

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

691+
// Read in the flat placement if a flat placement file is provided.
692+
FlatPlacementInfo flat_placement_info;
693+
if (!vpr_setup.FileNameOpts.read_flat_place_file.empty()) {
694+
flat_placement_info = read_flat_placement(
695+
vpr_setup.FileNameOpts.read_flat_place_file,
696+
g_vpr_ctx.atom().nlist);
697+
}
698+
690699
return try_pack(&vpr_setup.PackerOpts, &vpr_setup.AnalysisOpts,
691700
&arch, vpr_setup.user_models,
692701
vpr_setup.library_models, inter_cluster_delay,
693-
vpr_setup.PackerRRGraph);
702+
vpr_setup.PackerRRGraph, flat_placement_info);
694703
}
695704

696705
void vpr_load_packing(t_vpr_setup& vpr_setup, const t_arch& arch) {

vpr/src/base/vpr_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@ struct t_file_name_opts {
755755
std::string read_vpr_constraints_file;
756756
std::string write_vpr_constraints_file;
757757
std::string write_constraints_file;
758+
std::string read_flat_place_file;
758759
std::string write_flat_place_file;
759760
std::string write_block_usage;
760761
bool verify_file_digests;

0 commit comments

Comments
 (0)