Skip to content

Commit da66e10

Browse files
Merge pull request #2870 from AlexandreSinger/feature-appack
[APPack] Added Flat Placement Reconstruction
2 parents ddae365 + 42756cd commit da66e10

23 files changed

+1498
-36
lines changed

vpr/src/base/load_flat_place.cpp

+141
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,37 @@
1010

1111
#include <fstream>
1212
#include <unordered_set>
13+
#include "atom_lookup.h"
1314
#include "atom_netlist.h"
1415
#include "clustered_netlist.h"
1516
#include "FlatPlacementInfo.h"
1617
#include "globals.h"
1718
#include "vpr_context.h"
1819
#include "vpr_error.h"
1920
#include "vpr_types.h"
21+
#include "vtr_assert.h"
2022
#include "vtr_log.h"
23+
#include "vtr_vector_map.h"
24+
#include "vtr_version.h"
25+
26+
/**
27+
* @brief Prints the header for the flat placement file. This includes helpful
28+
* information on how to read the file and when it was generated.
29+
*
30+
* @param fp
31+
* File pointer to the file the cluster is printed to.
32+
*/
33+
static void print_flat_placement_file_header(FILE* fp) {
34+
fprintf(fp, "# Flat Placement File\n");
35+
fprintf(fp, "# Auto-generated by VPR %s\n",
36+
vtr::VERSION);
37+
fprintf(fp, "# Created: %s\n",
38+
vtr::BUILD_TIMESTAMP);
39+
fprintf(fp, "#\n");
40+
fprintf(fp, "# This file prints the following information for each atom in the netlist:\n");
41+
fprintf(fp, "# <atom_name> <x> <y> <layer> <atom_sub_tile> <atom_site_idx> #<clb_blk_id> <atom_pb_type>\n");
42+
fprintf(fp, "\n");
43+
}
2144

2245
/**
2346
* @brief Prints flat placement file entries for the atoms in one placed
@@ -73,6 +96,9 @@ void write_flat_placement(const char* flat_place_file_path,
7396
// Create a file in write mode for the flat placement.
7497
FILE* fp = fopen(flat_place_file_path, "w");
7598

99+
// Add a header to the flat placement file.
100+
print_flat_placement_file_header(fp);
101+
76102
// For each cluster, write out the atoms in the cluster at this cluster's
77103
// location.
78104
for (ClusterBlockId iblk : cluster_netlist.blocks()) {
@@ -174,3 +200,118 @@ bool load_flat_placement(t_vpr_setup& vpr_setup, const t_arch& arch) {
174200
return false;
175201
}
176202

203+
void log_flat_placement_reconstruction_info(
204+
const FlatPlacementInfo& flat_placement_info,
205+
const vtr::vector_map<ClusterBlockId, t_block_loc>& block_locs,
206+
const vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>>& atoms_lookup,
207+
const AtomLookup& cluster_of_atom_lookup,
208+
const AtomNetlist& atom_netlist,
209+
const ClusteredNetlist& clustered_netlist) {
210+
// Go through each cluster and see how many clusters have atoms that
211+
// do not belong (cluster is imperfect).
212+
unsigned num_imperfect_clusters = 0;
213+
for (ClusterBlockId clb_blk_id : clustered_netlist.blocks()) {
214+
// Get the centroid of the cluster
215+
const auto& clb_atoms = atoms_lookup[clb_blk_id];
216+
float centroid_x = 0.f;
217+
float centroid_y = 0.f;
218+
float centroid_layer = 0.f;
219+
float centroid_sub_tile = 0.f;
220+
for (AtomBlockId atom_blk_id : clb_atoms) {
221+
// TODO: Currently only handle the case when all of the position
222+
// data is provided. This can be extended,
223+
VTR_ASSERT(flat_placement_info.blk_x_pos[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS);
224+
VTR_ASSERT(flat_placement_info.blk_y_pos[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS);
225+
VTR_ASSERT(flat_placement_info.blk_layer[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS);
226+
VTR_ASSERT(flat_placement_info.blk_sub_tile[atom_blk_id] != FlatPlacementInfo::UNDEFINED_SUB_TILE);
227+
228+
centroid_x += flat_placement_info.blk_x_pos[atom_blk_id];
229+
centroid_y += flat_placement_info.blk_y_pos[atom_blk_id];
230+
centroid_layer += flat_placement_info.blk_layer[atom_blk_id];
231+
centroid_sub_tile += flat_placement_info.blk_sub_tile[atom_blk_id];
232+
}
233+
centroid_x /= static_cast<float>(clb_atoms.size());
234+
centroid_y /= static_cast<float>(clb_atoms.size());
235+
centroid_layer /= static_cast<float>(clb_atoms.size());
236+
centroid_sub_tile /= static_cast<float>(clb_atoms.size());
237+
// Check if every atom in the cluster is within 0.5 units of the
238+
// centroid.
239+
for (AtomBlockId atom_blk_id : clb_atoms) {
240+
// If the atom's flat placement more than half a block in any
241+
// direction from the flat placement centroid, then it does not
242+
// want to be in this cluster.
243+
// FIXME: This should take into account large blocks somehow, just
244+
// being 0.5 tiles away may not be sufficient.
245+
if (std::abs(centroid_x - flat_placement_info.blk_x_pos[atom_blk_id]) > 0.5f ||
246+
std::abs(centroid_y - flat_placement_info.blk_y_pos[atom_blk_id]) > 0.5f ||
247+
std::abs(centroid_layer - flat_placement_info.blk_layer[atom_blk_id]) > 0.5f ||
248+
std::abs(centroid_sub_tile - flat_placement_info.blk_sub_tile[atom_blk_id]) > 0.5f) {
249+
num_imperfect_clusters++;
250+
break;
251+
}
252+
}
253+
}
254+
// Go through each atom and compute how much it has displaced and count
255+
// how many have been displaced beyond some threshold.
256+
constexpr float disp_threashold = 0.5f;
257+
float total_disp = 0;
258+
unsigned num_atoms_missplaced = 0;
259+
for (AtomBlockId atom_blk_id : atom_netlist.blocks()) {
260+
// TODO: Currently only handle the case when all of the position
261+
// data is provided. This can be extended,
262+
VTR_ASSERT(flat_placement_info.blk_x_pos[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS);
263+
VTR_ASSERT(flat_placement_info.blk_y_pos[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS);
264+
VTR_ASSERT(flat_placement_info.blk_layer[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS);
265+
VTR_ASSERT(flat_placement_info.blk_sub_tile[atom_blk_id] != FlatPlacementInfo::UNDEFINED_SUB_TILE);
266+
267+
// Get the (x, y, layer) position of the block.
268+
int blk_x = flat_placement_info.blk_x_pos[atom_blk_id];
269+
int blk_y = flat_placement_info.blk_y_pos[atom_blk_id];
270+
int blk_layer = flat_placement_info.blk_layer[atom_blk_id];
271+
272+
// Get the (x, y, layer) position of the cluster that contains this block.
273+
ClusterBlockId atom_clb_id = cluster_of_atom_lookup.atom_clb(atom_blk_id);
274+
const t_block_loc& clb_loc = block_locs[atom_clb_id];
275+
276+
// Compute the distance between these two positions.
277+
// FIXME: This will overreport large blocks. This should really be
278+
// the distance outside of the tile you want to be placed in.
279+
float dx = blk_x - clb_loc.loc.x;
280+
float dy = blk_y - clb_loc.loc.y;
281+
float dlayer = blk_layer - clb_loc.loc.layer;
282+
float dist = std::sqrt((dx * dx) + (dy * dy) + (dlayer * dlayer));
283+
284+
// Accumulate into the total displacement.
285+
total_disp += dist;
286+
287+
// Check if this block has been displaced beyond the threshold.
288+
if (dist >= disp_threashold) {
289+
num_atoms_missplaced++;
290+
}
291+
292+
// TODO: Make this debug option of higher verbosity. Helpful for
293+
// debugging flat placement reconstruction.
294+
/*
295+
VTR_LOG("%s %d %d %d %d\n",
296+
g_vpr_ctx.atom().nlist.block_name(atom_blk_id).c_str(),
297+
clb_loc.loc.x,
298+
clb_loc.loc.y,
299+
clb_loc.loc.layer,
300+
clb_loc.loc.sub_tile);
301+
*/
302+
}
303+
304+
// Log the flat placement reconstruction info.
305+
size_t num_atoms = atom_netlist.blocks().size();
306+
size_t num_clusters = clustered_netlist.blocks().size();
307+
VTR_LOG("Flat Placement Reconstruction Info:\n");
308+
VTR_LOG("\tPercent of clusters with reconstruction errors: %f\n",
309+
static_cast<float>(num_imperfect_clusters) / static_cast<float>(num_clusters));
310+
VTR_LOG("\tTotal displacement of initial placement from flat placement: %f\n",
311+
total_disp);
312+
VTR_LOG("\tAverage atom displacement of initial placement from flat placement: %f\n",
313+
total_disp / static_cast<float>(num_atoms));
314+
VTR_LOG("\tPercent of atoms misplaced from the flat placement: %f\n",
315+
static_cast<float>(num_atoms_missplaced) / static_cast<float>(num_atoms));
316+
}
317+

vpr/src/base/load_flat_place.h

+27
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
// Forward declarations
1919
class AtomBlockId;
20+
class AtomLookup;
2021
class AtomNetlist;
2122
class ClusterBlockId;
2223
class ClusteredNetlist;
@@ -61,3 +62,29 @@ FlatPlacementInfo read_flat_placement(const std::string& read_flat_place_file_pa
6162
*/
6263
bool load_flat_placement(t_vpr_setup& vpr_setup, const t_arch& arch);
6364

65+
/**
66+
* @brief Logs information on the quality of the clustering and placement
67+
* reconstruction of the given flat placement.
68+
*
69+
* @param flat_placement_info
70+
* The flat placement to log,
71+
* @param block_locs
72+
* The location of each cluster in the netlist.
73+
* @param atoms_lookup
74+
* A lookup between each cluster and the atoms it contains.
75+
* @param cluster_of_atom_lookup
76+
* A lookup between each atom and the cluster that contains it.
77+
* @param atom_netlist
78+
* The netlist of atoms the flat placement was over.
79+
* @param clustered_netlist
80+
* The clustered netlist that the flat placement was used to
81+
* generate.
82+
*/
83+
void log_flat_placement_reconstruction_info(
84+
const FlatPlacementInfo& flat_placement_info,
85+
const vtr::vector_map<ClusterBlockId, t_block_loc>& block_locs,
86+
const vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>>& atoms_lookup,
87+
const AtomLookup& cluster_of_atom_lookup,
88+
const AtomNetlist& atom_netlist,
89+
const ClusteredNetlist& clustered_netlist);
90+

vpr/src/base/place_and_route.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <cmath>
55
#include <algorithm>
66

7+
#include "FlatPlacementInfo.h"
78
#include "vtr_assert.h"
89
#include "vtr_log.h"
910

@@ -173,6 +174,7 @@ int binary_search_place_and_route(const Netlist<>& placement_net_list,
173174
det_routing_arch,
174175
segment_inf,
175176
arch->directs,
177+
FlatPlacementInfo(), // Pass empty flat placement info.
176178
/*is_flat=*/false);
177179
}
178180
success = route(router_net_list,
@@ -311,6 +313,7 @@ int binary_search_place_and_route(const Netlist<>& placement_net_list,
311313
try_place(placement_net_list, placer_opts, router_opts, analysis_opts, noc_opts,
312314
arch->Chans, det_routing_arch, segment_inf,
313315
arch->directs,
316+
FlatPlacementInfo(), // Pass empty flat placement info.
314317
/*is_flat=*/false);
315318
}
316319

vpr/src/base/vpr_api.cpp

+16-5
Original file line numberDiff line numberDiff line change
@@ -688,18 +688,19 @@ bool vpr_pack(t_vpr_setup& vpr_setup, const t_arch& arch) {
688688
+ wtoi_switch_del); /* multiply by 4 to get a more conservative estimate */
689689
}
690690

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(
691+
// Read in the flat placement if a flat placement file is provided and it
692+
// has not been loaded already.
693+
if (!vpr_setup.FileNameOpts.read_flat_place_file.empty() &&
694+
!g_vpr_ctx.atom().flat_placement_info.valid) {
695+
g_vpr_ctx.mutable_atom().flat_placement_info = read_flat_placement(
695696
vpr_setup.FileNameOpts.read_flat_place_file,
696697
g_vpr_ctx.atom().nlist);
697698
}
698699

699700
return try_pack(&vpr_setup.PackerOpts, &vpr_setup.AnalysisOpts,
700701
&arch, vpr_setup.user_models,
701702
vpr_setup.library_models, inter_cluster_delay,
702-
vpr_setup.PackerRRGraph, flat_placement_info);
703+
vpr_setup.PackerRRGraph, g_vpr_ctx.atom().flat_placement_info);
703704
}
704705

705706
void vpr_load_packing(t_vpr_setup& vpr_setup, const t_arch& arch) {
@@ -849,6 +850,15 @@ void vpr_place(const Netlist<>& net_list, t_vpr_setup& vpr_setup, const t_arch&
849850
is_flat);
850851
}
851852

853+
// Read in the flat placement if a flat placement file is provided and it
854+
// has not been loaded already.
855+
if (!vpr_setup.FileNameOpts.read_flat_place_file.empty() &&
856+
!g_vpr_ctx.atom().flat_placement_info.valid) {
857+
g_vpr_ctx.mutable_atom().flat_placement_info = read_flat_placement(
858+
vpr_setup.FileNameOpts.read_flat_place_file,
859+
g_vpr_ctx.atom().nlist);
860+
}
861+
852862
try_place(net_list,
853863
vpr_setup.PlacerOpts,
854864
vpr_setup.RouterOpts,
@@ -858,6 +868,7 @@ void vpr_place(const Netlist<>& net_list, t_vpr_setup& vpr_setup, const t_arch&
858868
&vpr_setup.RoutingArch,
859869
vpr_setup.Segments,
860870
arch.directs,
871+
g_vpr_ctx.atom().flat_placement_info,
861872
is_flat);
862873

863874
auto& filename_opts = vpr_setup.FileNameOpts;

vpr/src/base/vpr_context.h

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <vector>
66
#include <mutex>
77

8+
#include "FlatPlacementInfo.h"
89
#include "prepack.h"
910
#include "vpr_types.h"
1011
#include "vtr_ndmatrix.h"
@@ -79,6 +80,10 @@ struct AtomContext : public Context {
7980

8081
/// @brief Mappings to/from the Atom Netlist to physically described .blif models
8182
AtomLookup lookup;
83+
84+
/// @brief Placement information on each atom known (from a file or another
85+
/// algorithm) before packing and the cluster-level placement.
86+
FlatPlacementInfo flat_placement_info;
8287
};
8388

8489
/**

0 commit comments

Comments
 (0)