Skip to content

Commit 53e90e6

Browse files
[APPack] Added Flat Placement Reconstruction
Added logic to the packer to reconstruct clusters from the flat placement, if one is provided. The packer will fall-back on the original packing algorithm if it runs out of options for candidates to cluster. Added logic to the initial placer to reconstruct the placement of each cluster from the flat placement, if one is provided. It will try to place the cluster at the centroid location of all atoms in a cluster, if it cannot place the cluster there it will fall-back on the original initial placement algorithm. Added a simple testcase to ensure the reading and writing of the flat placement file is working.
1 parent 9761055 commit 53e90e6

23 files changed

+1457
-37
lines changed

vpr/src/base/load_flat_place.cpp

+114
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@
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"
2124

2225
/**
2326
* @brief Prints flat placement file entries for the atoms in one placed
@@ -174,3 +177,114 @@ bool load_flat_placement(t_vpr_setup& vpr_setup, const t_arch& arch) {
174177
return false;
175178
}
176179

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

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 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& 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 before packing and
85+
/// placement.
86+
FlatPlacementInfo flat_placement_info;
8287
};
8388

8489
/**

0 commit comments

Comments
 (0)