Skip to content

Commit

Permalink
add comments and subroutines
Browse files Browse the repository at this point in the history
  • Loading branch information
soheilshahrouz committed May 22, 2024
1 parent 8338c90 commit 80dcdeb
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 74 deletions.
3 changes: 3 additions & 0 deletions vpr/src/base/vpr_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,9 @@ struct ClusteringHelperContext : public Context {
// unordered_set for faster insertion/deletion during the iterative improvement process of packing
vtr::vector<ClusterBlockId, std::unordered_set<AtomBlockId>> atoms_lookup;

/** Stores the NoC group ID of each atom block. Atom blocks that belong
* to different NoC groups can't be clustered with each other into the
* same clustered block.*/
vtr::vector<AtomBlockId, NocGroupId> atom_noc_grp_id;

~ClusteringHelperContext() {
Expand Down
2 changes: 1 addition & 1 deletion vpr/src/base/vpr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1501,7 +1501,7 @@ struct t_noc_opts {
double noc_latency_constraints_weighting; ///<controls the significance of meeting the traffic flow constraints range:[0-inf)
double noc_latency_weighting; ///<controls the significance of the traffic flow latencies relative to the other NoC placement costs range:[0-inf)
double noc_congestion_weighting; ///<controls the significance of the link congestions relative to the other NoC placement costs range:[0-inf)
double noc_centroid_weight;
double noc_centroid_weight; ///<controls how much the centroid location is adjusted towards NoC routers in NoC-biased centroid move:[0, 1]
int noc_swap_percentage; ///<controls the number of NoC router block swap attempts relative to the total number of swaps attempted by the placer range:[0-100]
std::string noc_placement_file_name; ///<is the name of the output file that contains the NoC placement information
};
Expand Down
1 change: 1 addition & 0 deletions vpr/src/noc/noc_data_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct noc_traffic_flow_id_tag;
/** Datatype to index traffic flows within the application */
typedef vtr::StrongId<noc_traffic_flow_id_tag, int> NocTrafficFlowId;

/** Data type to index NoC groups. */
struct noc_group_id_tag;
typedef vtr::StrongId<noc_group_id_tag, int> NocGroupId;

Expand Down
9 changes: 7 additions & 2 deletions vpr/src/pack/cluster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
* t_pb:
* Represents a clustered instance of a t_pb_graph_node containing netlist primitives
*
* t_pb_type and t_pb_graph_node (and related types) describe the targetted FPGA architecture, while t_pb represents
* t_pb_type and t_pb_graph_node (and related types) describe the targeted FPGA architecture, while t_pb represents
* the actual clustering of the user netlist.
*
* For example:
Expand Down Expand Up @@ -82,7 +82,7 @@
* cluster until a nullptr is returned. So, the number of repeated molecules is changed from 1 to 500,
* effectively making the clusterer pack a cluster until a nullptr is returned.
*/
#define ATTRACTION_GROUPS_MAX_REPEATED_MOLECULES 500
static constexpr int ATTRACTION_GROUPS_MAX_REPEATED_MOLECULES = 500;

std::map<t_logical_block_type_ptr, size_t> do_clustering(const t_packer_opts& packer_opts,
const t_analysis_opts& analysis_opts,
Expand Down Expand Up @@ -243,6 +243,11 @@ std::map<t_logical_block_type_ptr, size_t> do_clustering(const t_packer_opts& pa
* Since some of the primitives might fail legality, this structure temporarily
* stores PartitionRegion information while the cluster is packed*/
PartitionRegion temp_cluster_pr;
/*
* Stores the cluster's NoC group ID as more primitives are added to it.
* This is used to check if a candidate primitive is in the same NoC group
* as the atom blocks that have already been added to the primitive.
*/
NocGroupId temp_cluster_noc_grp_id = NocGroupId::INVALID();

start_new_cluster(helper_ctx.cluster_placement_stats, helper_ctx.primitives_list,
Expand Down
8 changes: 8 additions & 0 deletions vpr/src/pack/noc_aware_cluster_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ void update_noc_reachability_partitions(const std::vector<AtomBlockId>& noc_atom

int noc_grp_id_cnt = 0;

/*
* Assume that the atom netlist is represented as an undirected graph
* with all high fanout nets removed. In this graph, we want to find all
* connected components that include at least one NoC router. We start a
* BFS from each NoC router and traverse all nets below the high_fanout_threshold,
* and mark each atom block with a NoC group ID.
*/

for (auto noc_atom_id : noc_atoms) {
// check if this NoC router has already been visited
if (atom_visited[noc_atom_id]) {
Expand Down
31 changes: 30 additions & 1 deletion vpr/src/pack/noc_aware_cluster_util.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,42 @@

#ifndef VTR_NOC_AWARE_CLUSTER_UTIL_H
#define VTR_NOC_AWARE_CLUSTER_UTIL_H

/**
* @file This file includes helper functions used to find NoC groups
* in the atom netlist and assign NoC group IDs to atom blocks.
*
* A NoC group is a set of atom blocks that are reachable from a NoC router
* through low fanout nets. During packing, atom blocks that belong to two different
* NoC group IDs cannot be packed with each other into the same clustered block.
* This prevents atom blocks that belong to two separate NoC-attached modules from
* being packed with each other, and helps with more localized placement of NoC-attached
* modules around their corresponding NoC routers.
*
* For more details refer to the following paper:
* The Road Less Traveled: Congestion-Aware NoC Placement and Packet Routing for FPGAs
*/

#include <vector>

#include "vpr_types.h"

/**
* @brief Iterates over all atom blocks and check whether
* their blif model is the same as a NoC routers.
*
* @return The atom block IDs of the NoC router blocks in the netlist.
*/
std::vector<AtomBlockId> find_noc_router_atoms();


/**
* @brief Runs BFS starting from NoC routers to find all connected
* components that include a NoC router. Each connected component
* containing a NoC router is marked as a NoC group. The NoC group ID
* for each atom block is updated in the global state.
*
* @param noc_atoms The atom block IDs of the NoC router blocks in the netlist.
*/
void update_noc_reachability_partitions(const std::vector<AtomBlockId>& noc_atoms);

#endif
145 changes: 75 additions & 70 deletions vpr/src/place/centroid_move_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,88 @@ CentroidMoveGenerator::CentroidMoveGenerator(float noc_attraction_weight, size_t
, noc_attraction_enabled_(true) {
VTR_ASSERT(noc_attraction_weight > 0.0 && noc_attraction_weight <= 1.0);

const auto& cluster_ctx = g_vpr_ctx.clustering();
const auto& noc_ctx = g_vpr_ctx.noc();

// check if static member variables are already initialized
if (!noc_group_clusters_.empty() && !noc_group_routers_.empty() &&
!cluster_to_noc_grp_.empty() && !noc_router_to_noc_group_.empty()) {
return;
} else {
initialize_noc_groups(high_fanout_net);
}
}

e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected,
t_propose_action& proposed_action,
float rlim,
const t_placer_opts& placer_opts,
const PlacerCriticalities* /*criticalities*/) {
// Find a movable block based on blk_type
ClusterBlockId b_from = propose_block_to_move(placer_opts,
proposed_action.logical_blk_type_index,
false,
nullptr,
nullptr);

VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug,
"Centroid Move Choose Block %d - rlim %f\n",
size_t(b_from),
rlim);

if (!b_from) { //No movable block found
VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug,
"\tNo movable block found\n");
return e_create_move::ABORT;
}

const auto& device_ctx = g_vpr_ctx.device();
const auto& place_ctx = g_vpr_ctx.placement();
const auto& cluster_ctx = g_vpr_ctx.clustering();
auto& place_move_ctx = g_placer_ctx.mutable_move();

t_pl_loc from = place_ctx.block_locs[b_from].loc;
auto cluster_from_type = cluster_ctx.clb_nlist.block_type(b_from);
auto grid_from_type = device_ctx.grid.get_physical_type({from.x, from.y, from.layer});
VTR_ASSERT(is_tile_compatible(grid_from_type, cluster_from_type));

t_range_limiters range_limiters{rlim,
place_move_ctx.first_rlim,
placer_opts.place_dm_rlim};

t_pl_loc to, centroid;

/* Calculate the centroid location*/
calculate_centroid_loc(b_from, false, centroid, nullptr, noc_attraction_enabled_, noc_attraction_w_);

// Centroid location is not necessarily a valid location, and the downstream location expect a valid
// layer for "to" location. So if the layer is not valid, we set it to the same layer as from loc.
to.layer = (centroid.layer < 0) ? from.layer : centroid.layer;
/* Find a location near the weighted centroid_loc */
if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to, b_from)) {
return e_create_move::ABORT;
}

e_create_move create_move = ::create_move(blocks_affected, b_from, to);

//Check that all the blocks affected by the move would still be in a legal floorplan region after the swap
if (!floorplan_legal(blocks_affected)) {
return e_create_move::ABORT;
}

return create_move;
}

const std::vector<ClusterBlockId>& CentroidMoveGenerator::get_noc_group_routers(NocGroupId noc_grp_id) {
return CentroidMoveGenerator::noc_group_routers_[noc_grp_id];
}

NocGroupId CentroidMoveGenerator::get_cluster_noc_group(ClusterBlockId blk_id) {
return CentroidMoveGenerator::cluster_to_noc_grp_[blk_id];
}

void CentroidMoveGenerator::initialize_noc_groups(size_t high_fanout_net) {
const auto& cluster_ctx = g_vpr_ctx.clustering();
const auto& noc_ctx = g_vpr_ctx.noc();

noc_group_clusters_.clear();
noc_group_routers_.clear();
cluster_to_noc_grp_.clear();
Expand Down Expand Up @@ -127,71 +200,3 @@ CentroidMoveGenerator::CentroidMoveGenerator(float noc_attraction_weight, size_t
}
}
}

e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected,
t_propose_action& proposed_action,
float rlim,
const t_placer_opts& placer_opts,
const PlacerCriticalities* /*criticalities*/) {
// Find a movable block based on blk_type
ClusterBlockId b_from = propose_block_to_move(placer_opts,
proposed_action.logical_blk_type_index,
false,
nullptr,
nullptr);

VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug,
"Centroid Move Choose Block %d - rlim %f\n",
size_t(b_from),
rlim);

if (!b_from) { //No movable block found
VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug,
"\tNo movable block found\n");
return e_create_move::ABORT;
}

const auto& device_ctx = g_vpr_ctx.device();
const auto& place_ctx = g_vpr_ctx.placement();
const auto& cluster_ctx = g_vpr_ctx.clustering();
auto& place_move_ctx = g_placer_ctx.mutable_move();

t_pl_loc from = place_ctx.block_locs[b_from].loc;
auto cluster_from_type = cluster_ctx.clb_nlist.block_type(b_from);
auto grid_from_type = device_ctx.grid.get_physical_type({from.x, from.y, from.layer});
VTR_ASSERT(is_tile_compatible(grid_from_type, cluster_from_type));

t_range_limiters range_limiters{rlim,
place_move_ctx.first_rlim,
placer_opts.place_dm_rlim};

t_pl_loc to, centroid;

/* Calculate the centroid location*/
calculate_centroid_loc(b_from, false, centroid, nullptr, noc_attraction_enabled_, noc_attraction_w_);

// Centroid location is not necessarily a valid location, and the downstream location expect a valid
// layer for "to" location. So if the layer is not valid, we set it to the same layer as from loc.
to.layer = (centroid.layer < 0) ? from.layer : centroid.layer;
/* Find a location near the weighted centroid_loc */
if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to, b_from)) {
return e_create_move::ABORT;
}

e_create_move create_move = ::create_move(blocks_affected, b_from, to);

//Check that all the blocks affected by the move would still be in a legal floorplan region after the swap
if (!floorplan_legal(blocks_affected)) {
return e_create_move::ABORT;
}

return create_move;
}

const std::vector<ClusterBlockId>& CentroidMoveGenerator::get_noc_group_routers(NocGroupId noc_grp_id) {
return CentroidMoveGenerator::noc_group_routers_[noc_grp_id];
}

NocGroupId CentroidMoveGenerator::get_cluster_noc_group(ClusterBlockId blk_id) {
return CentroidMoveGenerator::cluster_to_noc_grp_[blk_id];
}
10 changes: 10 additions & 0 deletions vpr/src/place/centroid_move_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ class CentroidMoveGenerator : public MoveGenerator {

/** Specifies the NoC group for each NoC router*/
static std::map<ClusterBlockId, NocGroupId> noc_router_to_noc_group_;

/**
* @brief This function forms NoC groups by finding connected components
* in the graph representing the clustered netlist. When finding connected
* components, none of the nets whose fanout is larger than high_fanout_net
* are traversed.
* @param high_fanout_net All nets with a fanout larger than this number are
* ignored when forming NoC groups.
*/
static void initialize_noc_groups(size_t high_fanout_net);
};

#endif

0 comments on commit 80dcdeb

Please sign in to comment.