vpr: Add --balance_block_type_utilization option
This option controls whether the clusterer attempts to balance resource
utilization across different block types which can implement the same
primitive. Default is 'on' which matches previous behaviour.
diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp
index caad775..3769895 100644
--- a/vpr/src/base/SetupVPR.cpp
+++ b/vpr/src/base/SetupVPR.cpp
@@ -425,6 +425,7 @@
PackerOpts->beta = Options.beta_clustering;
PackerOpts->pack_verbosity = Options.pack_verbosity;
PackerOpts->enable_pin_feasibility_filter = Options.enable_clustering_pin_feasibility_filter;
+ PackerOpts->balance_block_type_utilization = Options.balance_block_type_utilization;
PackerOpts->target_external_pin_util = Options.target_external_pin_util;
PackerOpts->target_device_utilization = Options.target_device_utilization;
diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp
index 9c5cab4..1029d2b 100644
--- a/vpr/src/base/read_options.cpp
+++ b/vpr/src/base/read_options.cpp
@@ -943,6 +943,12 @@
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);
+ pack_grp.add_argument<bool,ParseOnOff>(args.balance_block_type_utilization, "--balance_block_type_utilization")
+ .help("If enabled, when a primitive can potentially be mapped to multiple block types the packer will "
+ "pick the block type which (currently) has lower utilization.")
+ .default_value("on")
+ .show_in(argparse::ShowIn::HELP_ONLY);
+
pack_grp.add_argument(args.target_external_pin_util, "--target_ext_pin_util")
.help("Sets the external pin utilization target during clustering.\n"
"Value Ranges: [1.0, 0.0]\n"
diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h
index b43fd35..76b2268 100644
--- a/vpr/src/base/read_options.h
+++ b/vpr/src/base/read_options.h
@@ -69,6 +69,7 @@
argparse::ArgValue<bool> timing_driven_clustering;
argparse::ArgValue<e_cluster_seed> cluster_seed_type;
argparse::ArgValue<bool> enable_clustering_pin_feasibility_filter;
+ argparse::ArgValue<bool> balance_block_type_utilization;
argparse::ArgValue<std::vector<std::string>> target_external_pin_util;
argparse::ArgValue<int> pack_verbosity;
diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h
index e309ab5..de0a4cd 100644
--- a/vpr/src/base/vpr_types.h
+++ b/vpr/src/base/vpr_types.h
@@ -667,6 +667,7 @@
bool connection_driven;
int pack_verbosity;
bool enable_pin_feasibility_filter;
+ bool balance_block_type_utilization;
std::vector<std::string> target_external_pin_util;
e_stage_action doPacking;
enum e_packer_algorithm packer_algorithm;
diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp
index 59e1731..957ac4a 100644
--- a/vpr/src/pack/cluster.cpp
+++ b/vpr/src/pack/cluster.cpp
@@ -241,7 +241,8 @@
ClusteredNetlist *clb_nlist,
const std::map<const t_model*,std::vector<t_type_ptr>>& primitive_candidate_block_types,
int verbosity,
- bool enable_pin_feasibility_filter);
+ bool enable_pin_feasibility_filter,
+ bool balance_block_type_utilization);
static t_pack_molecule* get_highest_gain_molecule(
t_pb *cur_pb,
@@ -505,7 +506,8 @@
detailed_routing_stage, &cluster_ctx.clb_nlist,
primitive_candidate_block_types,
packer_opts.pack_verbosity,
- packer_opts.enable_pin_feasibility_filter);
+ packer_opts.enable_pin_feasibility_filter,
+ packer_opts.balance_block_type_utilization);
if (packer_opts.pack_verbosity > 1 && packer_opts.pack_verbosity < 3) {
VTR_LOG("Complex block %d: %s, type: %s ",
@@ -1855,7 +1857,8 @@
ClusteredNetlist *clb_nlist,
const std::map<const t_model*,std::vector<t_type_ptr>>& primitive_candidate_block_types,
int verbosity,
- bool enable_pin_feasibility_filter) {
+ bool enable_pin_feasibility_filter,
+ bool balance_block_type_utilization) {
/* Given a starting seed block, start_new_cluster determines the next cluster type to use
It expands the FPGA if it cannot find a legal cluster for the atom block
*/
@@ -1872,19 +1875,21 @@
VTR_ASSERT(itr != primitive_candidate_block_types.end());
std::vector<t_type_ptr> candidate_types = itr->second;
- //We sort the candidate types in ascending order by their current utilization.
- //This means that the packer will prefer to use types with lower utilization.
- //This is a naive approach to try balancing utilization when multiple types can
- //support the same primitive(s).
- std::sort(candidate_types.begin(), candidate_types.end(),
- [&](t_type_ptr lhs, t_type_ptr rhs) {
- float lhs_util = float(num_used_type_instances[lhs]) / device_ctx.grid.num_instances(lhs);
- float rhs_util = float(num_used_type_instances[rhs]) / device_ctx.grid.num_instances(rhs);
+ if (balance_block_type_utilization) {
+ //We sort the candidate types in ascending order by their current utilization.
+ //This means that the packer will prefer to use types with lower utilization.
+ //This is a naive approach to try balancing utilization when multiple types can
+ //support the same primitive(s).
+ std::sort(candidate_types.begin(), candidate_types.end(),
+ [&](t_type_ptr lhs, t_type_ptr rhs) {
+ float lhs_util = float(num_used_type_instances[lhs]) / device_ctx.grid.num_instances(lhs);
+ float rhs_util = float(num_used_type_instances[rhs]) / device_ctx.grid.num_instances(rhs);
- //Lower util first
- return lhs_util < rhs_util;
- }
- );
+ //Lower util first
+ return lhs_util < rhs_util;
+ }
+ );
+ }
if (verbosity > 2) {