Skip to content

Commit

Permalink
Merge pull request #2870 from AlexandreSinger/feature-appack
Browse files Browse the repository at this point in the history
[APPack] Added Flat Placement Reconstruction
  • Loading branch information
AlexandreSinger authored Jan 28, 2025
2 parents ddae365 + 42756cd commit da66e10
Show file tree
Hide file tree
Showing 23 changed files with 1,498 additions and 36 deletions.
141 changes: 141 additions & 0 deletions vpr/src/base/load_flat_place.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,37 @@

#include <fstream>
#include <unordered_set>
#include "atom_lookup.h"
#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_assert.h"
#include "vtr_log.h"
#include "vtr_vector_map.h"
#include "vtr_version.h"

/**
* @brief Prints the header for the flat placement file. This includes helpful
* information on how to read the file and when it was generated.
*
* @param fp
* File pointer to the file the cluster is printed to.
*/
static void print_flat_placement_file_header(FILE* fp) {
fprintf(fp, "# Flat Placement File\n");
fprintf(fp, "# Auto-generated by VPR %s\n",
vtr::VERSION);
fprintf(fp, "# Created: %s\n",
vtr::BUILD_TIMESTAMP);
fprintf(fp, "#\n");
fprintf(fp, "# This file prints the following information for each atom in the netlist:\n");
fprintf(fp, "# <atom_name> <x> <y> <layer> <atom_sub_tile> <atom_site_idx> #<clb_blk_id> <atom_pb_type>\n");
fprintf(fp, "\n");
}

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

// Add a header to the flat placement file.
print_flat_placement_file_header(fp);

// For each cluster, write out the atoms in the cluster at this cluster's
// location.
for (ClusterBlockId iblk : cluster_netlist.blocks()) {
Expand Down Expand Up @@ -174,3 +200,118 @@ bool load_flat_placement(t_vpr_setup& vpr_setup, const t_arch& arch) {
return false;
}

void log_flat_placement_reconstruction_info(
const FlatPlacementInfo& flat_placement_info,
const vtr::vector_map<ClusterBlockId, t_block_loc>& block_locs,
const vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>>& atoms_lookup,
const AtomLookup& cluster_of_atom_lookup,
const AtomNetlist& atom_netlist,
const ClusteredNetlist& clustered_netlist) {
// Go through each cluster and see how many clusters have atoms that
// do not belong (cluster is imperfect).
unsigned num_imperfect_clusters = 0;
for (ClusterBlockId clb_blk_id : clustered_netlist.blocks()) {
// Get the centroid of the cluster
const auto& clb_atoms = atoms_lookup[clb_blk_id];
float centroid_x = 0.f;
float centroid_y = 0.f;
float centroid_layer = 0.f;
float centroid_sub_tile = 0.f;
for (AtomBlockId atom_blk_id : clb_atoms) {
// TODO: Currently only handle the case when all of the position
// data is provided. This can be extended,
VTR_ASSERT(flat_placement_info.blk_x_pos[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS);
VTR_ASSERT(flat_placement_info.blk_y_pos[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS);
VTR_ASSERT(flat_placement_info.blk_layer[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS);
VTR_ASSERT(flat_placement_info.blk_sub_tile[atom_blk_id] != FlatPlacementInfo::UNDEFINED_SUB_TILE);

centroid_x += flat_placement_info.blk_x_pos[atom_blk_id];
centroid_y += flat_placement_info.blk_y_pos[atom_blk_id];
centroid_layer += flat_placement_info.blk_layer[atom_blk_id];
centroid_sub_tile += flat_placement_info.blk_sub_tile[atom_blk_id];
}
centroid_x /= static_cast<float>(clb_atoms.size());
centroid_y /= static_cast<float>(clb_atoms.size());
centroid_layer /= static_cast<float>(clb_atoms.size());
centroid_sub_tile /= static_cast<float>(clb_atoms.size());
// Check if every atom in the cluster is within 0.5 units of the
// centroid.
for (AtomBlockId atom_blk_id : clb_atoms) {
// If the atom's flat placement more than half a block in any
// direction from the flat placement centroid, then it does not
// want to be in this cluster.
// FIXME: This should take into account large blocks somehow, just
// being 0.5 tiles away may not be sufficient.
if (std::abs(centroid_x - flat_placement_info.blk_x_pos[atom_blk_id]) > 0.5f ||
std::abs(centroid_y - flat_placement_info.blk_y_pos[atom_blk_id]) > 0.5f ||
std::abs(centroid_layer - flat_placement_info.blk_layer[atom_blk_id]) > 0.5f ||
std::abs(centroid_sub_tile - flat_placement_info.blk_sub_tile[atom_blk_id]) > 0.5f) {
num_imperfect_clusters++;
break;
}
}
}
// Go through each atom and compute how much it has displaced and count
// how many have been displaced beyond some threshold.
constexpr float disp_threashold = 0.5f;
float total_disp = 0;
unsigned num_atoms_missplaced = 0;
for (AtomBlockId atom_blk_id : atom_netlist.blocks()) {
// TODO: Currently only handle the case when all of the position
// data is provided. This can be extended,
VTR_ASSERT(flat_placement_info.blk_x_pos[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS);
VTR_ASSERT(flat_placement_info.blk_y_pos[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS);
VTR_ASSERT(flat_placement_info.blk_layer[atom_blk_id] != FlatPlacementInfo::UNDEFINED_POS);
VTR_ASSERT(flat_placement_info.blk_sub_tile[atom_blk_id] != FlatPlacementInfo::UNDEFINED_SUB_TILE);

// Get the (x, y, layer) position of the block.
int blk_x = flat_placement_info.blk_x_pos[atom_blk_id];
int blk_y = flat_placement_info.blk_y_pos[atom_blk_id];
int blk_layer = flat_placement_info.blk_layer[atom_blk_id];

// Get the (x, y, layer) position of the cluster that contains this block.
ClusterBlockId atom_clb_id = cluster_of_atom_lookup.atom_clb(atom_blk_id);
const t_block_loc& clb_loc = block_locs[atom_clb_id];

// Compute the distance between these two positions.
// FIXME: This will overreport large blocks. This should really be
// the distance outside of the tile you want to be placed in.
float dx = blk_x - clb_loc.loc.x;
float dy = blk_y - clb_loc.loc.y;
float dlayer = blk_layer - clb_loc.loc.layer;
float dist = std::sqrt((dx * dx) + (dy * dy) + (dlayer * dlayer));

// Accumulate into the total displacement.
total_disp += dist;

// Check if this block has been displaced beyond the threshold.
if (dist >= disp_threashold) {
num_atoms_missplaced++;
}

// TODO: Make this debug option of higher verbosity. Helpful for
// debugging flat placement reconstruction.
/*
VTR_LOG("%s %d %d %d %d\n",
g_vpr_ctx.atom().nlist.block_name(atom_blk_id).c_str(),
clb_loc.loc.x,
clb_loc.loc.y,
clb_loc.loc.layer,
clb_loc.loc.sub_tile);
*/
}

// Log the flat placement reconstruction info.
size_t num_atoms = atom_netlist.blocks().size();
size_t num_clusters = clustered_netlist.blocks().size();
VTR_LOG("Flat Placement Reconstruction Info:\n");
VTR_LOG("\tPercent of clusters with reconstruction errors: %f\n",
static_cast<float>(num_imperfect_clusters) / static_cast<float>(num_clusters));
VTR_LOG("\tTotal displacement of initial placement from flat placement: %f\n",
total_disp);
VTR_LOG("\tAverage atom displacement of initial placement from flat placement: %f\n",
total_disp / static_cast<float>(num_atoms));
VTR_LOG("\tPercent of atoms misplaced from the flat placement: %f\n",
static_cast<float>(num_atoms_missplaced) / static_cast<float>(num_atoms));
}

27 changes: 27 additions & 0 deletions vpr/src/base/load_flat_place.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

// Forward declarations
class AtomBlockId;
class AtomLookup;
class AtomNetlist;
class ClusterBlockId;
class ClusteredNetlist;
Expand Down Expand Up @@ -61,3 +62,29 @@ FlatPlacementInfo read_flat_placement(const std::string& read_flat_place_file_pa
*/
bool load_flat_placement(t_vpr_setup& vpr_setup, const t_arch& arch);

/**
* @brief Logs information on the quality of the clustering and placement
* reconstruction of the given flat placement.
*
* @param flat_placement_info
* The flat placement to log,
* @param block_locs
* The location of each cluster in the netlist.
* @param atoms_lookup
* A lookup between each cluster and the atoms it contains.
* @param cluster_of_atom_lookup
* A lookup between each atom and the cluster that contains it.
* @param atom_netlist
* The netlist of atoms the flat placement was over.
* @param clustered_netlist
* The clustered netlist that the flat placement was used to
* generate.
*/
void log_flat_placement_reconstruction_info(
const FlatPlacementInfo& flat_placement_info,
const vtr::vector_map<ClusterBlockId, t_block_loc>& block_locs,
const vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>>& atoms_lookup,
const AtomLookup& cluster_of_atom_lookup,
const AtomNetlist& atom_netlist,
const ClusteredNetlist& clustered_netlist);

3 changes: 3 additions & 0 deletions vpr/src/base/place_and_route.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <cmath>
#include <algorithm>

#include "FlatPlacementInfo.h"
#include "vtr_assert.h"
#include "vtr_log.h"

Expand Down Expand Up @@ -173,6 +174,7 @@ int binary_search_place_and_route(const Netlist<>& placement_net_list,
det_routing_arch,
segment_inf,
arch->directs,
FlatPlacementInfo(), // Pass empty flat placement info.
/*is_flat=*/false);
}
success = route(router_net_list,
Expand Down Expand Up @@ -311,6 +313,7 @@ int binary_search_place_and_route(const Netlist<>& placement_net_list,
try_place(placement_net_list, placer_opts, router_opts, analysis_opts, noc_opts,
arch->Chans, det_routing_arch, segment_inf,
arch->directs,
FlatPlacementInfo(), // Pass empty flat placement info.
/*is_flat=*/false);
}

Expand Down
21 changes: 16 additions & 5 deletions vpr/src/base/vpr_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -688,18 +688,19 @@ 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(
// Read in the flat placement if a flat placement file is provided and it
// has not been loaded already.
if (!vpr_setup.FileNameOpts.read_flat_place_file.empty() &&
!g_vpr_ctx.atom().flat_placement_info.valid) {
g_vpr_ctx.mutable_atom().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, flat_placement_info);
vpr_setup.PackerRRGraph, g_vpr_ctx.atom().flat_placement_info);
}

void vpr_load_packing(t_vpr_setup& vpr_setup, const t_arch& arch) {
Expand Down Expand Up @@ -849,6 +850,15 @@ void vpr_place(const Netlist<>& net_list, t_vpr_setup& vpr_setup, const t_arch&
is_flat);
}

// Read in the flat placement if a flat placement file is provided and it
// has not been loaded already.
if (!vpr_setup.FileNameOpts.read_flat_place_file.empty() &&
!g_vpr_ctx.atom().flat_placement_info.valid) {
g_vpr_ctx.mutable_atom().flat_placement_info = read_flat_placement(
vpr_setup.FileNameOpts.read_flat_place_file,
g_vpr_ctx.atom().nlist);
}

try_place(net_list,
vpr_setup.PlacerOpts,
vpr_setup.RouterOpts,
Expand All @@ -858,6 +868,7 @@ void vpr_place(const Netlist<>& net_list, t_vpr_setup& vpr_setup, const t_arch&
&vpr_setup.RoutingArch,
vpr_setup.Segments,
arch.directs,
g_vpr_ctx.atom().flat_placement_info,
is_flat);

auto& filename_opts = vpr_setup.FileNameOpts;
Expand Down
5 changes: 5 additions & 0 deletions vpr/src/base/vpr_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <vector>
#include <mutex>

#include "FlatPlacementInfo.h"
#include "prepack.h"
#include "vpr_types.h"
#include "vtr_ndmatrix.h"
Expand Down Expand Up @@ -79,6 +80,10 @@ struct AtomContext : public Context {

/// @brief Mappings to/from the Atom Netlist to physically described .blif models
AtomLookup lookup;

/// @brief Placement information on each atom known (from a file or another
/// algorithm) before packing and the cluster-level placement.
FlatPlacementInfo flat_placement_info;
};

/**
Expand Down
Loading

0 comments on commit da66e10

Please sign in to comment.