Skip to content

[APPack] Added Flat Placement Reconstruction #2870

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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