Skip to content
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

Improving Unrelated Clustering Feature in VPR #2237

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
18 changes: 16 additions & 2 deletions doc/src/vpr/command_line_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -471,16 +471,30 @@ For people not working on CAD, you can probably leave all the options to their d

**Default**: ``on``

.. option:: --allow_unrelated_clustering {on | off | auto}
.. option:: --allow_unrelated_clustering {on | off | auto | <string>:{on|off|auto}}

Controls whether primitives with no attraction to a cluster may be packed into it.

Unrelated clustering can increase packing density (decreasing the number of blocks required to implement the circuit), but can significantly impact routability.

* ``auto`` Dynamically enabled/disabled (based on density).

* ``on`` Unrelated clustering enabled.

* ``off`` Unrelated clustering disabled.

When set to ``auto`` VPR automatically decides whether to enable unrelated clustring based on the targetted device and achieved packing density.
* ``<string>:{on|off|auto}`` Specify the unrelated clustering status for a specific block type.

**Default**: ``auto``

This option can also take multiple space-separated values.

For example::

--allow_unrelated_clustering auto io:on

would turn on unrelated clustering for io blocks and dynamically determine enable/disable unrelated clustering for all other blocks.

.. option:: --alpha_clustering <float>

A parameter that weights the optimization of timing vs area.
Expand Down
11 changes: 1 addition & 10 deletions vpr/src/base/ShowSetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -730,16 +730,7 @@ static void ShowAnalysisOpts(const t_analysis_opts& AnalysisOpts) {
}

static void ShowPackerOpts(const t_packer_opts& PackerOpts) {
VTR_LOG("PackerOpts.allow_unrelated_clustering: ");
if (PackerOpts.allow_unrelated_clustering == e_unrelated_clustering::ON) {
VTR_LOG("true\n");
} else if (PackerOpts.allow_unrelated_clustering == e_unrelated_clustering::OFF) {
VTR_LOG("false\n");
} else if (PackerOpts.allow_unrelated_clustering == e_unrelated_clustering::AUTO) {
VTR_LOG("auto\n");
} else {
VPR_FATAL_ERROR(VPR_ERROR_UNKNOWN, "Unknown packer allow_unrelated_clustering\n");
}
VTR_LOG("PackerOpts.allow_unrelated_clustering: %s\n", vtr::join(PackerOpts.allow_unrelated_clustering, " ").c_str());
VTR_LOG("PackerOpts.alpha_clustering: %f\n", PackerOpts.alpha);
VTR_LOG("PackerOpts.beta_clustering: %f\n", PackerOpts.beta);
VTR_LOG("PackerOpts.cluster_seed_type: ");
Expand Down
88 changes: 16 additions & 72 deletions vpr/src/base/read_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include "vtr_log.h"
#include "vtr_util.h"
#include "vtr_path.h"
#include <string>

using argparse::ConvertedValue;
using argparse::Provenance;
Expand Down Expand Up @@ -648,44 +647,6 @@ struct ParseClockModeling {
}
};

struct ParseUnrelatedClustering {
ConvertedValue<e_unrelated_clustering> from_str(std::string str) {
ConvertedValue<e_unrelated_clustering> conv_value;
if (str == "on")
conv_value.set_value(e_unrelated_clustering::ON);
else if (str == "off")
conv_value.set_value(e_unrelated_clustering::OFF);
else if (str == "auto")
conv_value.set_value(e_unrelated_clustering::AUTO);
else {
std::stringstream msg;
msg << "Invalid conversion from '"
<< str
<< "' to e_unrelated_clustering (expected one of: "
<< argparse::join(default_choices(), ", ") << ")";
conv_value.set_error(msg.str());
}
return conv_value;
}

ConvertedValue<std::string> to_str(e_unrelated_clustering val) {
ConvertedValue<std::string> conv_value;
if (val == e_unrelated_clustering::ON)
conv_value.set_value("on");
else if (val == e_unrelated_clustering::OFF)
conv_value.set_value("off");
else {
VTR_ASSERT(val == e_unrelated_clustering::AUTO);
conv_value.set_value("auto");
}
return conv_value;
}

std::vector<std::string> default_choices() {
return {"on", "off", "auto"};
}
};

struct ParseBalanceBlockTypeUtil {
ConvertedValue<e_balance_block_type_util> from_str(std::string str) {
ConvertedValue<e_balance_block_type_util> conv_value;
Expand Down Expand Up @@ -1629,14 +1590,24 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);

pack_grp.add_argument<e_unrelated_clustering, ParseUnrelatedClustering>(args.allow_unrelated_clustering, "--allow_unrelated_clustering")
pack_grp.add_argument(args.allow_unrelated_clustering, "--allow_unrelated_clustering")
.help(
"Controls whether primitives with no attraction to a cluster can be packed into it.\n"
"Turning unrelated clustering on can increase packing density (fewer blocks are used), but at the cost of worse routability.\n"
" * on : Unrelated clustering enabled\n"
" * off : Unrelated clustering disabled\n"
" * auto: Dynamically enabled/disabled (based on density)\n")
.default_value("auto")
"This option can take multiple specifications in several\n"
"formats:\n"
"* auto (i.e. 'auto'): Dynamically enabled/disabled (based on density)\n"
"* on : Unrelated clustering enabled\n"
"* off : Unrelated clustering disabled\n"
"* Specified for a certain block type: (e.g. 'clb:on')\n"
"These can be used in combination. For example:\n"
" '--allow_unrelated_clustering auto io:on'\n"
"would turn on unrelated clustering for io blocks and\n"
"dynamically determine enable/disable unrelated clustering,\n"
"for all other blocks.\n")

.nargs('+')
.default_value({"auto"})
.show_in(argparse::ShowIn::HELP_ONLY);

pack_grp.add_argument(args.alpha_clustering, "--alpha_clustering")
Expand Down Expand Up @@ -1773,19 +1744,6 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);

pack_grp.add_argument(args.pack_num_moves, "--pack_num_moves")
.help(
"The number of moves that can be tried in packing stage")
.default_value("100000")
.show_in(argparse::ShowIn::HELP_ONLY);

pack_grp.add_argument(args.pack_move_type, "--pack_move_type")
.help(
"The move type used in packing."
"The available values are: randomSwap, semiDirectedSwap, semiDirectedSameTypeSwap")
.default_value("semiDirectedSwap")
.show_in(argparse::ShowIn::HELP_ONLY);

auto& place_grp = parser.add_argument_group("placement options");

place_grp.add_argument(args.Seed, "--seed")
Expand Down Expand Up @@ -2014,8 +1972,7 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
place_grp.add_argument(args.place_reward_fun, "--place_reward_fun")
.help(
"The reward function used by placement RL agent."
"The available values are: basic, nonPenalizing_basic, runtime_aware, WLbiased_runtime_aware"
"The latter two are only available for timing-driven placement.")
"The available values are: basic, nonPenalizing_basic, runtime_aware, WLbiased_runtime_aware")
.default_value("WLbiased_runtime_aware")
.show_in(argparse::ShowIn::HELP_ONLY);

Expand Down Expand Up @@ -2764,19 +2721,6 @@ void set_conditional_defaults(t_options& args) {
}
}

// Check for correct options combinations
// If you are running WLdriven placement, the RL reward function should be
// either basic or nonPenalizing basic
if (args.RL_agent_placement && (args.PlaceAlgorithm == BOUNDING_BOX_PLACE || !args.timing_analysis)) {
if (args.place_reward_fun.value() != "basic" && args.place_reward_fun.value() != "nonPenalizing_basic") {
VTR_LOG_WARN(
"To use RLPlace for WLdriven placements, the reward function should be basic or nonPenalizing_basic.\n"
"you can specify the reward function using --place_reward_fun.\n"
"Setting the placement reward function to \"basic\"\n");
args.place_reward_fun.set("basic", Provenance::INFERRED);
}
}

//Which placement algorithm to use during placement quench?
if (args.PlaceQuenchAlgorithm.provenance() != Provenance::SPECIFIED) {
args.PlaceQuenchAlgorithm.set(args.PlaceAlgorithm, Provenance::INFERRED);
Expand Down
2 changes: 1 addition & 1 deletion vpr/src/base/read_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ struct t_options {

/* Clustering options */
argparse::ArgValue<bool> connection_driven_clustering;
argparse::ArgValue<e_unrelated_clustering> allow_unrelated_clustering;
argparse::ArgValue<std::vector<std::string>> allow_unrelated_clustering;
argparse::ArgValue<float> alpha_clustering;
argparse::ArgValue<float> beta_clustering;
argparse::ArgValue<bool> timing_driven_clustering;
Expand Down
29 changes: 29 additions & 0 deletions vpr/src/base/vpr_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,35 @@ void t_ext_pin_util_targets::set_default_pin_util(t_ext_pin_util default_target)
defaults_ = default_target;
}

t_allow_unrelated_clustering::t_allow_unrelated_clustering(enum e_unrel_clust_stat default_stat, enum e_unrel_clust_mode default_mode) {
default_.first = default_stat;
default_.second = default_mode;
}
enum e_unrel_clust_stat t_allow_unrelated_clustering::get_block_status(std::string block_type_name) const {
auto itr = overrides_.find(block_type_name);
if (itr != overrides_.end()) {
std::pair<enum e_unrel_clust_stat, enum e_unrel_clust_mode> status = itr->second;
return status.first;
}
return default_.first;
}

enum e_unrel_clust_mode t_allow_unrelated_clustering::get_block_mode(std::string block_type_name) const {
auto itr = overrides_.find(block_type_name);
if (itr != overrides_.end()) {
std::pair<enum e_unrel_clust_stat, enum e_unrel_clust_mode> status = itr->second;
return status.second;
}
return default_.second;
}

void t_allow_unrelated_clustering::set_block_status(std::string block_type_name, std::pair<enum e_unrel_clust_stat, enum e_unrel_clust_mode> status) {
overrides_[block_type_name] = status;
}
void t_allow_unrelated_clustering::set_default_status(std::pair<enum e_unrel_clust_stat, enum e_unrel_clust_mode> status) {
default_ = status;
}

t_pack_high_fanout_thresholds::t_pack_high_fanout_thresholds(int threshold)
: default_(threshold) {}

Expand Down
48 changes: 44 additions & 4 deletions vpr/src/base/vpr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,14 @@ enum class e_const_gen_inference {
COMB_SEQ ///<Both combinational and sequential constant generator inference
};

enum class e_unrelated_clustering {
enum class e_unrel_clust_stat {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment usage / meaning

OFF,
ON,
AUTO
ON
};

enum class e_unrel_clust_mode {
FIXED, ///<Unrelated clustering status is given by the user and cannot be updated
AUTO ///<Unrelated clustering status can be updated by VPR throughout the packing flow
};

enum class e_balance_block_type_util {
Expand Down Expand Up @@ -208,6 +212,42 @@ class t_ext_pin_util_targets {
std::map<std::string, t_ext_pin_util> overrides_;
};

class t_allow_unrelated_clustering {
public:
t_allow_unrelated_clustering() = default;
t_allow_unrelated_clustering(enum e_unrel_clust_stat status, enum e_unrel_clust_mode mode);
/**
* @brief Returns the unrelated clustering status for the specified block type
*/
enum e_unrel_clust_stat get_block_status(std::string block_type_name) const;
/**
* @brief Returns the unrelated clustering mode for the specified block type
*/
enum e_unrel_clust_mode get_block_mode(std::string block_type_name) const;

public:
/**
* @brief Sets the unrelated clustering status for the specified block type
*
* The unrelated clustering status is represented as a pair of booleans.
* The first boolean incidcates whether unrelated clustering is turned on or off.
* The second variable indicates whether the status of the variable is provided
* by the user(bool = false) or user let it to be automatically determined by VPR(bool = ture).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ture -> true

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using @param in this description and being more precise (not pair of booleans; instead it is a pair of status control variables) would be good here

* If provided by the user, the status cannot be overriden later, otherwise
* it can be adjusted by VPR throughout the flow as necessary.
*/
void set_block_status(std::string block_type_name, std::pair<enum e_unrel_clust_stat, enum e_unrel_clust_mode> status);
/**
* @brief Sets the default value for unrelated clustering status
*
*/
void set_default_status(std::pair<enum e_unrel_clust_stat, enum e_unrel_clust_mode> status);

private:
std::pair<enum e_unrel_clust_stat, enum e_unrel_clust_mode> default_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment what these are: default value for all block types, and overrides by block_type name for specific types. Each says whether unrelated cluster is on or off, and if it was set to that state by the user or automatic vpr behaviour.

std::map<std::string, std::pair<enum e_unrel_clust_stat, enum e_unrel_clust_mode>> overrides_;
};

class t_pack_high_fanout_thresholds {
public:
t_pack_high_fanout_thresholds() = default;
Expand Down Expand Up @@ -840,7 +880,7 @@ struct t_packer_opts {
float inter_cluster_net_delay;
float target_device_utilization;
bool auto_compute_inter_cluster_net_delay;
e_unrelated_clustering allow_unrelated_clustering;
std::vector<std::string> allow_unrelated_clustering;
bool connection_driven;
int pack_verbosity;
bool enable_pin_feasibility_filter;
Expand Down
11 changes: 8 additions & 3 deletions vpr/src/pack/cluster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ std::map<t_logical_block_type_ptr, size_t> do_clustering(const t_packer_opts& pa
int num_models,
const std::unordered_set<AtomNetId>& is_clock,
const std::unordered_map<AtomBlockId, t_pb_graph_node*>& expected_lowest_cost_pb_gnode,
bool allow_unrelated_clustering,
t_allow_unrelated_clustering allow_unrelated_clustering,
bool balance_block_type_utilization,
std::vector<t_lb_type_rr_node>* lb_type_rr_graphs,
const t_ext_pin_util_targets& ext_pin_util_targets,
Expand Down Expand Up @@ -300,11 +300,16 @@ std::map<t_logical_block_type_ptr, size_t> do_clustering(const t_packer_opts& pa
/*it doesn't make sense to do a timing analysis here since there*
*is only one atom block clustered it would not change anything */
}
bool allow_unrel_clust_cur_blk = false;
if (allow_unrelated_clustering.get_block_status(cluster_ctx.clb_nlist.block_type(clb_index)->name) == e_unrel_clust_stat::ON) {
allow_unrel_clust_cur_blk = true;
}

cur_cluster_placement_stats_ptr = &(helper_ctx.cluster_placement_stats[cluster_ctx.clb_nlist.block_type(clb_index)->index]);
cluster_stats.num_unrelated_clustering_attempts = 0;
next_molecule = get_molecule_for_cluster(cluster_ctx.clb_nlist.block_pb(clb_index),
attraction_groups,
allow_unrelated_clustering,
allow_unrel_clust_cur_blk,
packer_opts.prioritize_transitive_connectivity,
packer_opts.transitive_fanout_threshold,
packer_opts.feasible_block_array_size,
Expand Down Expand Up @@ -351,7 +356,7 @@ std::map<t_logical_block_type_ptr, size_t> do_clustering(const t_packer_opts& pa
detailed_routing_stage,
attraction_groups,
clb_inter_blk_nets,
allow_unrelated_clustering,
allow_unrel_clust_cur_blk,
high_fanout_threshold,
is_clock,
timing_info,
Expand Down
2 changes: 1 addition & 1 deletion vpr/src/pack/cluster.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ std::map<t_logical_block_type_ptr, size_t> do_clustering(const t_packer_opts& pa
int num_models,
const std::unordered_set<AtomNetId>& is_clock,
const std::unordered_map<AtomBlockId, t_pb_graph_node*>& expected_lowest_cost_pb_gnode,
bool allow_unrelated_clustering,
t_allow_unrelated_clustering allow_unrelated_clustering,
bool balance_block_type_utilization,
std::vector<t_lb_type_rr_node>* lb_type_rr_graphs,
const t_ext_pin_util_targets& ext_pin_util_targets,
Expand Down
Loading