Skip to content

Commit 18097d4

Browse files
[APPack] Added read_flat_place Option and Verifier
Added the read_flat_place option to VPR's CLI. This allows the user to pass a flat placement file into the packer. Added code to parse this file into a FlatPlacementInfo object which only verifies that the atom given in the file exists in the atom netlist. Added code in the packer to read in the flat placement and verify that the flat placement is valid for use in the packer.
1 parent c90ac0d commit 18097d4

13 files changed

+373
-5
lines changed

doc/src/vpr/command_line_usage.rst

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,31 @@ 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+
415+
This is used by the packer to better cluster atoms together.
416+
417+
The flat placement file (which often ends in ``.fplace``) is a text file
418+
where each line describes the location of an atom. It has the following
419+
expected syntax:
420+
421+
.. code-block:: none
422+
423+
<atom_name : str> <atom_x_pos : float> <atom_y_pos : float> <atom_sub_tile? : int> <atom_site_idx? : int>
424+
n523 6 8 0 3
425+
n522 6 8 0 5
426+
n520 6 8 0 2
427+
n518 6 8 0 16
428+
429+
The ``sub_tile`` and ``site_idx`` are optional parameters which may be used
430+
as a hint to reconstruct clusters.
431+
432+
.. warning::
433+
434+
This interface is currently experimental and under active development.
435+
411436
.. option:: --write_flat_place <file>
412437

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

vpr/src/base/FlatPlacementInfo.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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+
/// @brief The x-positions of each atom block. Is UNDEFINED_POS if undefined.
30+
vtr::vector<AtomBlockId, float> blk_x_pos;
31+
/// @brief The y-positions of each atom block. Is UNDEFINED_POS if undefined.
32+
vtr::vector<AtomBlockId, float> blk_y_pos;
33+
/// @brief The sub tile location of each atom block. Is UNDEFINED_SUB_TILE
34+
/// if undefined.
35+
vtr::vector<AtomBlockId, int> blk_sub_tile;
36+
/// @brief The flat site idx of each atom block. Is UNDEFINED_SITE_IDX if
37+
/// undefined.
38+
vtr::vector<AtomBlockId, int> blk_site_idx;
39+
40+
/// @brief A flag to signify if this object has been constructed with data
41+
/// or not. This makes it easier to detect if a flat placement exists
42+
/// or not. Is true when a placement has been loaded into this
43+
/// object, false otherwise.
44+
bool valid;
45+
46+
/**
47+
* @brief Default constructor of this class.
48+
*
49+
* Initializes the data structure to invalid so it can be easily checked to
50+
* be uninitialized.
51+
*/
52+
FlatPlacementInfo() : valid(false) {}
53+
54+
/**
55+
* @brief Constructs the flat placement with undefined positions for each
56+
* atom block in the atom netlist.
57+
*
58+
* The valid flag is set to true here, since this structure is now
59+
* initialized with data and can be used.
60+
*
61+
* @param atom_netlist
62+
* The netlist of atom blocks in the circuit.
63+
*/
64+
FlatPlacementInfo(const AtomNetlist& atom_netlist)
65+
: blk_x_pos(atom_netlist.blocks().size(), UNDEFINED_POS),
66+
blk_y_pos(atom_netlist.blocks().size(), UNDEFINED_POS),
67+
blk_sub_tile(atom_netlist.blocks().size(), UNDEFINED_SUB_TILE),
68+
blk_site_idx(atom_netlist.blocks().size(), UNDEFINED_SITE_IDX),
69+
valid(true) {}
70+
};
71+

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: 83 additions & 0 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
@@ -77,6 +82,84 @@ void write_flat_placement(const char* flat_place_file_path,
7782
fclose(fp);
7883
}
7984

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

vpr/src/pack/pack.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
#include <unordered_set>
21

2+
#include "pack.h"
3+
4+
#include <unordered_set>
5+
#include "FlatPlacementInfo.h"
36
#include "SetupGrid.h"
47
#include "attraction_groups.h"
58
#include "cluster_legalizer.h"
69
#include "cluster_util.h"
710
#include "constraints_report.h"
811
#include "globals.h"
912
#include "greedy_clusterer.h"
10-
#include "pack.h"
1113
#include "prepack.h"
14+
#include "verify_flat_placement.h"
1215
#include "vpr_context.h"
1316
#include "vpr_error.h"
1417
#include "vpr_types.h"
@@ -26,7 +29,8 @@ bool try_pack(t_packer_opts* packer_opts,
2629
const t_model* user_models,
2730
const t_model* library_models,
2831
float interc_delay,
29-
std::vector<t_lb_type_rr_node>* lb_type_rr_graphs) {
32+
std::vector<t_lb_type_rr_node>* lb_type_rr_graphs,
33+
const FlatPlacementInfo& flat_placement_info) {
3034
const AtomContext& atom_ctx = g_vpr_ctx.atom();
3135
const DeviceContext& device_ctx = g_vpr_ctx.device();
3236
// The clusterer modifies the device context by increasing the size of the
@@ -69,6 +73,24 @@ bool try_pack(t_packer_opts* packer_opts,
6973
VTR_LOG("%d attraction groups were created during prepacking.\n", attraction_groups.num_attraction_groups());
7074
VTR_LOG("Finish prepacking.\n");
7175

76+
// Verify that the Flat Placement is valid for packing.
77+
if (flat_placement_info.valid) {
78+
unsigned num_errors = verify_flat_placement_for_packing(flat_placement_info,
79+
atom_ctx.nlist,
80+
prepacker);
81+
if (num_errors == 0) {
82+
VTR_LOG("Completed flat placement consistency check successfully.\n");
83+
} else {
84+
// TODO: In the future, we can just erase the flat placement and
85+
// continue. It depends on what we want to happen if the
86+
// flat placement is not valid.
87+
VPR_ERROR(VPR_ERROR_PACK,
88+
"%u errors found while performing flat placement "
89+
"consistency check. Aborting program.\n",
90+
num_errors);
91+
}
92+
}
93+
7294
if (packer_opts->auto_compute_inter_cluster_net_delay) {
7395
packer_opts->inter_cluster_net_delay = interc_delay;
7496
VTR_LOG("Using inter-cluster delay: %g\n", packer_opts->inter_cluster_net_delay);

0 commit comments

Comments
 (0)