Skip to content

Add raw setup slack analysis to placement quench #1501

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 28 commits into from
Sep 9, 2020
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f4ea4a1
Added interface for mapping between CLB pins and setup slacks. Refact…
Bill-hbrhbr Jul 23, 2020
c024603
Refactored criticalities update in place.cpp and added setup slacks u…
Bill-hbrhbr Jul 23, 2020
cb6e9a6
Fixe up format and compilation errors
Bill-hbrhbr Jul 23, 2020
63db2e1
Merged 3 update routines into 1 single routine
Bill-hbrhbr Jul 31, 2020
aa7b233
Resolve merge conflicts
Bill-hbrhbr Jul 31, 2020
e8f73c6
Resolve more merge conflicts
Bill-hbrhbr Jul 31, 2020
d80de58
Changed crit_exponent to first_crit_exponent/state.crit_exponent
Bill-hbrhbr Jul 31, 2020
831df44
Created a setup slack matrix that copies data from the PlacerSetupSla…
Bill-hbrhbr Aug 6, 2020
d329911
Provided more complete explanation for the record_setup_slacks routine.
Bill-hbrhbr Aug 6, 2020
225870e
Added placement snapshot functions that facilitates the reversion of …
Bill-hbrhbr Aug 6, 2020
9056301
Merge the master branch into PlacerSetupSlacks (updating vtr flow
Bill-hbrhbr Aug 6, 2020
0e01ed7
Implemented do_setup_slack_cost_analysis: softmax of negative slacks
Bill-hbrhbr Aug 6, 2020
2e212dc
Added single move reversion for setup slack analysis(rather than taki…
Bill-hbrhbr Aug 11, 2020
96e65ba
Corrected the timing update and reversion of setup slack analysis dur…
Bill-hbrhbr Aug 14, 2020
112bde5
Moved four boolean global variables controlling the timing update int…
Bill-hbrhbr Aug 14, 2020
29b55a3
Added vpr option --place_quench_metric to turn on/off setup slack ana…
Bill-hbrhbr Aug 20, 2020
f641b66
Added the option --place_quench_metric to VPR documentation on VPR co…
Bill-hbrhbr Aug 28, 2020
d88a38d
Moved timing_update_mode boolean variables into PlacerSetupSlacks and…
Bill-hbrhbr Aug 28, 2020
df9db48
Removed quench metric option.
Bill-hbrhbr Sep 1, 2020
9b01e1f
Changed PATH_TIMING_DRIVEN_PLACE to CRITICALITY_TIMING_PLACE, and SET…
Bill-hbrhbr Sep 1, 2020
e0b70c4
Changed e_place_algorithm to t_place_algorithm, a wrapper class that …
Bill-hbrhbr Sep 1, 2020
cd79ff5
Added --place_quench_algorithm option to VPR options. Specifies the p…
Bill-hbrhbr Sep 1, 2020
dd2cfe2
Utilized the is_timing_driven() method provided by the t_place_algori…
Bill-hbrhbr Sep 1, 2020
270d1ef
Added regression test strong_place_quench_slack to check if running S…
Bill-hbrhbr Sep 1, 2020
23e8782
Fixed slack cost routine bug and updated golden results. Added code d…
Bill-hbrhbr Sep 4, 2020
f6e809e
Code review update: enhance more documentations. Added function level…
Bill-hbrhbr Sep 6, 2020
e3d7d65
Removed find_affected_sink_pins() to eliminate the placer runtime inc…
Bill-hbrhbr Sep 8, 2020
06c9cf6
Merge branch 'master' into QuenchSlackDraft
Bill-hbrhbr Sep 8, 2020
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
16 changes: 12 additions & 4 deletions doc/src/vpr/command_line_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -700,16 +700,24 @@ If any of init_t, exit_t or alpha_t is specified, the user schedule, with a fixe

**Default:** ``not_locked``.

.. option:: --place_algorithm {bounding_box | path_timing_driven}
.. option:: --place_algorithm {bounding_box | criticality_timing | slack_timing}

Controls the algorithm used by the placer.

``bounding_box`` focuses purely on minimizing the bounding box wirelength of the circuit.
``bounding_box`` Focuses purely on minimizing the bounding box wirelength of the circuit. Turns off timing analysis if specified.

``path_timing_driven`` focuses on minimizing both wirelength and the critical path delay.
``criticality_timing`` Focuses on minimizing both the wirelength and the connection timing costs (criticality * delay).

``slack_timing`` Focuses on improving the circuit slack values to reduce critical path delay.

**Default:** ``path_timing_driven``
**Default:** ``criticality_timing``

.. option:: --place_quench_algorithm {bounding_box | criticality_timing | slack_timing}

Controls the algorithm used by the placer during placement quench.
The algorithm options have identical functionality as the ones used by the option ``--place_algorithm``.

**Default:** ``criticality_timing``

.. option:: --place_chan_width <int>

Expand Down
4 changes: 2 additions & 2 deletions vpr/src/base/CheckSetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void CheckSetup(const t_packer_opts& PackerOpts,
}

if ((GLOBAL == RouterOpts.route_type)
&& (BOUNDING_BOX_PLACE != PlacerOpts.place_algorithm)) {
&& (PlacerOpts.place_algorithm.is_timing_driven())) {
/* Works, but very weird. Can't optimize timing well, since you're
* not doing proper architecture delay modelling. */
VTR_LOG_WARN(
Expand All @@ -32,7 +32,7 @@ void CheckSetup(const t_packer_opts& PackerOpts,
}

if ((false == Timing.timing_analysis_enabled)
&& (PlacerOpts.place_algorithm == PATH_TIMING_DRIVEN_PLACE)) {
&& (PlacerOpts.place_algorithm.is_timing_driven())) {
/* May work, not tested */
VPR_FATAL_ERROR(VPR_ERROR_OTHER,
"Timing analysis must be enabled for timing-driven placement.\n");
Expand Down
1 change: 1 addition & 0 deletions vpr/src/base/SetupVPR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,7 @@ static void SetupPlacerOpts(const t_options& Options, t_placer_opts* PlacerOpts)
PlacerOpts->td_place_exp_last = Options.place_exp_last;

PlacerOpts->place_algorithm = Options.PlaceAlgorithm;
PlacerOpts->place_quench_algorithm = Options.PlaceQuenchAlgorithm;

PlacerOpts->constraints_file = Options.constraints_file;

Expand Down
11 changes: 7 additions & 4 deletions vpr/src/base/ShowSetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,12 +499,15 @@ static void ShowPlacerOpts(const t_placer_opts& PlacerOpts,
if ((PLACE_ONCE == PlacerOpts.place_freq)
|| (PLACE_ALWAYS == PlacerOpts.place_freq)) {
VTR_LOG("PlacerOpts.place_algorithm: ");
switch (PlacerOpts.place_algorithm) {
switch (PlacerOpts.place_algorithm.get()) {
case BOUNDING_BOX_PLACE:
VTR_LOG("BOUNDING_BOX_PLACE\n");
break;
case PATH_TIMING_DRIVEN_PLACE:
VTR_LOG("PATH_TIMING_DRIVEN_PLACE\n");
case CRITICALITY_TIMING_PLACE:
VTR_LOG("CRITICALITY_TIMING_PLACE\n");
break;
case SLACK_TIMING_PLACE:
VTR_LOG("SLACK_TIMING_PLACE\n");
break;
default:
VTR_LOG_ERROR("Unknown placement algorithm\n");
Expand Down Expand Up @@ -533,7 +536,7 @@ static void ShowPlacerOpts(const t_placer_opts& PlacerOpts,

VTR_LOG("PlacerOpts.place_chan_width: %d\n", PlacerOpts.place_chan_width);

if (PATH_TIMING_DRIVEN_PLACE == PlacerOpts.place_algorithm) {
if (PlacerOpts.place_algorithm.is_timing_driven()) {
VTR_LOG("PlacerOpts.inner_loop_recompute_divider: %d\n", PlacerOpts.inner_loop_recompute_divider);
VTR_LOG("PlacerOpts.recompute_crit_iter: %d\n", PlacerOpts.recompute_crit_iter);
VTR_LOG("PlacerOpts.timing_tradeoff: %f\n", PlacerOpts.timing_tradeoff);
Expand Down
51 changes: 37 additions & 14 deletions vpr/src/base/read_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,31 +350,35 @@ struct ParsePlaceDeltaDelayAlgorithm {
struct ParsePlaceAlgorithm {
ConvertedValue<e_place_algorithm> from_str(std::string str) {
ConvertedValue<e_place_algorithm> conv_value;
if (str == "bounding_box")
if (str == "bounding_box") {
conv_value.set_value(BOUNDING_BOX_PLACE);
else if (str == "path_timing_driven")
conv_value.set_value(PATH_TIMING_DRIVEN_PLACE);
else {
} else if (str == "criticality_timing") {
conv_value.set_value(CRITICALITY_TIMING_PLACE);
} else if (str == "slack_timing") {
conv_value.set_value(SLACK_TIMING_PLACE);
} else {
std::stringstream msg;
msg << "Invalid conversion from '" << str << "' to e_router_algorithm (expected one of: " << argparse::join(default_choices(), ", ") << ")";
msg << "Invalid conversion from '" << str << "' to e_place_algorithm (expected one of: " << argparse::join(default_choices(), ", ") << ")";
conv_value.set_error(msg.str());
}
return conv_value;
}

ConvertedValue<std::string> to_str(e_place_algorithm val) {
ConvertedValue<std::string> conv_value;
if (val == BOUNDING_BOX_PLACE)
if (val == BOUNDING_BOX_PLACE) {
conv_value.set_value("bounding_box");
else {
VTR_ASSERT(val == PATH_TIMING_DRIVEN_PLACE);
conv_value.set_value("path_timing_driven");
} else if (val == CRITICALITY_TIMING_PLACE) {
conv_value.set_value("criticality_timing");
} else {
VTR_ASSERT(val == SLACK_TIMING_PLACE);
conv_value.set_value("slack_timing");
}
return conv_value;
}

std::vector<std::string> default_choices() {
return {"bounding_box", "path_timing_driven"};
return {"bounding_box", "criticality_timing", "slack_timing"};
}
};

Expand Down Expand Up @@ -1679,9 +1683,23 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
.show_in(argparse::ShowIn::HELP_ONLY);

place_grp.add_argument<e_place_algorithm, ParsePlaceAlgorithm>(args.PlaceAlgorithm, "--place_algorithm")
.help("Controls which placement algorithm is used")
.default_value("path_timing_driven")
.choices({"bounding_box", "path_timing_driven"})
.help(
"Controls which placement algorithm is used. Valid options:\n"
" * bounding_box: Focuses purely on minimizing the bounding box wirelength of the circuit. Turns off timing analysis if specified.\n"
" * criticality_timing: Focuses on minimizing both the wirelength and the connection timing costs (criticality * delay).\n"
" * slack_timing: Focuses on improving the circuit slack values to reduce critical path delay.\n")
.default_value("criticality_timing")
.choices({"bounding_box", "criticality_timing", "slack_timing"})
.show_in(argparse::ShowIn::HELP_ONLY);

place_grp.add_argument<e_place_algorithm, ParsePlaceAlgorithm>(args.PlaceQuenchAlgorithm, "--place_quench_algorithm")
.help(
"Controls which placement algorithm is used during placement quench. Valid options:\n"
" * bounding_box: Focuses purely on minimizing the bounding box wirelength of the circuit. Turns off timing analysis if specified.\n"
" * criticality_timing: Focuses on minimizing both the wirelength and the connection timing costs (criticality * delay).\n"
" * slack_timing: Focuses on improving the circuit slack values to reduce critical path delay.\n")
.default_value("criticality_timing")
.choices({"bounding_box", "criticality_timing", "slack_timing"})
.show_in(argparse::ShowIn::HELP_ONLY);

place_grp.add_argument(args.PlaceChanWidth, "--place_chan_width")
Expand Down Expand Up @@ -2306,12 +2324,17 @@ void set_conditional_defaults(t_options& args) {
//Which placement algorithm to use?
if (args.PlaceAlgorithm.provenance() != Provenance::SPECIFIED) {
if (args.timing_analysis) {
args.PlaceAlgorithm.set(PATH_TIMING_DRIVEN_PLACE, Provenance::INFERRED);
args.PlaceAlgorithm.set(CRITICALITY_TIMING_PLACE, Provenance::INFERRED);
} else {
args.PlaceAlgorithm.set(BOUNDING_BOX_PLACE, Provenance::INFERRED);
}
}

//Which placement algorithm to use during placement quench?
if (args.PlaceQuenchAlgorithm.provenance() != Provenance::SPECIFIED) {
args.PlaceQuenchAlgorithm.set(args.PlaceAlgorithm, Provenance::INFERRED);
}

//Place chan width follows Route chan width if unspecified
if (args.PlaceChanWidth.provenance() != Provenance::SPECIFIED && args.RouteChanWidth.provenance() == Provenance::SPECIFIED) {
args.PlaceChanWidth.set(args.RouteChanWidth.value(), Provenance::INFERRED);
Expand Down
1 change: 1 addition & 0 deletions vpr/src/base/read_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ struct t_options {
argparse::ArgValue<float> PlaceSuccessTarget;
argparse::ArgValue<sched_type> anneal_sched_type;
argparse::ArgValue<e_place_algorithm> PlaceAlgorithm;
argparse::ArgValue<e_place_algorithm> PlaceQuenchAlgorithm;
argparse::ArgValue<e_pad_loc_type> pad_loc_type;
argparse::ArgValue<int> PlaceChanWidth;
argparse::ArgValue<float> place_rlim_escape_fraction;
Expand Down
135 changes: 113 additions & 22 deletions vpr/src/base/vpr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -829,36 +829,84 @@ struct t_annealing_sched {
float success_target;
};

/* Various options for the placer. *
* place_algorithm: BOUNDING_BOX_PLACE or PATH_TIMING_DRIVEN_PLACE *
* timing_tradeoff: When TIMING_DRIVEN_PLACE mode, what is the tradeoff *
* timing driven and BOUNDING_BOX_PLACE. *
* place_cost_exp: Power to which denominator is raised for linear_cong. *
* place_chan_width: The channel width assumed if only one placement is *
* performed. *
* pad_loc_type: Are pins free to move during placement or fixed randomly. *
* constraints_file: File used to lock block locations during placement. *
* place_freq: Should the placement be skipped, done once, or done for each *
* channel width in the binary search. *
* recompute_crit_iter: how many temperature stages pass before we recompute *
* criticalities based on average point to point delay *
* inner_loop_crit_divider: (move_lim/inner_loop_crit_divider) determines how*
* many inner_loop iterations pass before a recompute of *
* criticalities is done. *
* td_place_exp_first: exponent that is used on the timing_driven criticlity *
* it is the value that the exponent starts at. *
* td_place_exp_last: value that the criticality exponent will be at the end *
* doPlacement: true if placement is supposed to be done in the CAD flow, false otherwise */
/******************************************************************
* Placer data types
*******************************************************************/

/**
* @brief Types of placement algorithms used in the placer.
*
* @param BOUNDING_BOX_PLACE
* Focuses purely on minimizing the bounding
* box wirelength of the circuit.
* @param CRITICALITY_TIMING_PLACE
* Focuses on minimizing both the wirelength and the
* connection timing costs (criticality * delay).
* @param SLACK_TIMING_PLACE
* Focuses on improving the circuit slack values
* to reduce critical path delay.
*
* The default is to use CRITICALITY_TIMING_PLACE. BOUNDING_BOX_PLACE
* is used when there is no timing information available (wiring only).
* SLACK_TIMING_PLACE is mainly feasible during placement quench.
*/
enum e_place_algorithm {
BOUNDING_BOX_PLACE,
PATH_TIMING_DRIVEN_PLACE
CRITICALITY_TIMING_PLACE,
SLACK_TIMING_PLACE
};

/**
* @brief Provides a wrapper around enum e_place_algorithm.
*
* Supports the method isTimingDriven(), which allows flexible updates
* to the placer algorithms if more timing driven placement strategies
* are added in tht future. This method is used across various placement
* setup files, and it can be useful for major placer routines as well.
*
* More methods can be added to this class if the placement strategies
* will be further divided into more categories the future.
*
* Also supports assignments and comparisons between t_place_algorithm
* and e_place_algorithm so as not to break down previous codes.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the justification for this over the following?

bool is_timing_driven(e_place_algorithm algo) {
  return algo == CRITICALITY_TIMING_PLACE || algo == SLACK_TIMING_PLACE; 
}

What methods do you propose should be added to this class? Do they improve the current code? If so, please add them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. The timing driven check is performed in several places other than place.cpp. So I incorporated this check into placer_opts.
  2. There might be future categorizations of placement algorithms/strategies. Currently, there are only two categories (timing and no timing). Having this class will make it easier to describe and implement new categorizations in the future. If you don't think this is necessary, I'll revert the change.

class t_place_algorithm {
public:
//Constructors
t_place_algorithm() = default;
t_place_algorithm(e_place_algorithm _algo)
: algo(_algo) {}
~t_place_algorithm() = default;

//Assignment operators
void operator=(const t_place_algorithm& rhs) { algo = rhs.algo; }
void operator=(e_place_algorithm rhs) { algo = rhs; }

//Equality operators
bool operator==(const t_place_algorithm& rhs) const { return algo == rhs.algo; }
bool operator==(e_place_algorithm rhs) const { return algo == rhs; }
bool operator!=(const t_place_algorithm& rhs) const { return algo != rhs.algo; }
bool operator!=(e_place_algorithm rhs) const { return algo != rhs; }

///@brief Check if the algorithm belongs to the timing driven category.
inline bool is_timing_driven() const {
return algo == CRITICALITY_TIMING_PLACE || algo == SLACK_TIMING_PLACE;
}

///@brief Accessor: returns the underlying e_place_algorithm enum value.
e_place_algorithm get() const { return algo; }

private:
///@brief The underlying algorithm. Default set to CRITICALITY_TIMING_PLACE.
e_place_algorithm algo = e_place_algorithm::CRITICALITY_TIMING_PLACE;
};

enum e_pad_loc_type {
FREE,
RANDOM
};

///@brief Used to calculate the inner placer loop's block swapping limit move_lim.
enum e_place_effort_scaling {
CIRCUIT, ///<Effort scales based on circuit size only
DEVICE_CIRCUIT ///<Effort scales based on both circuit and device size
Expand Down Expand Up @@ -889,8 +937,51 @@ enum class e_place_delta_delay_algorithm {
DIJKSTRA_EXPANSION,
};

/**
* @brief Various options for the placer.
*
* @param place_algorithm
* Controls which placement algorithm is used.
* @param place_quench_algorithm
* Controls which placement algorithm is used
* during placement quench.
* @param timing_tradeoff
* When in CRITICALITY_TIMING_PLACE mode, what is the
* tradeoff between timing and wiring costs.
* @param place_cost_exp
* Power to which denominator is raised for linear_cong.
* @param place_chan_width
* The channel width assumed if only one placement is performed.
* @param pad_loc_type
* Are pins FREE, fixed randomly, or fixed from a file.
* @param block_loc_type
* Are blocks fixed from a file.
* @param constraints_file
* File to read block locations from if block_loc_type is LOCKED.
* @param pad_loc_file
* File to read pad locations from if pad_loc_type is USER.
* @param place_freq
* Should the placement be skipped, done once, or done
* for each channel width in the binary search.
* @param recompute_crit_iter
* How many temperature stages pass before we recompute
* criticalities based on average point to point delay.
* @param inner_loop_crit_divider
* (move_lim/inner_loop_crit_divider) determines how
* many inner_loop iterations pass before a recompute
* of criticalities is done.
* @param td_place_exp_first
* Exponent that is used in the CRITICALITY_TIMING_PLACE
* mode. It is the value that the crit_exponent starts at.
* @param td_place_exp_last
* Value that the criticality exponent will be at the end.
* @param doPlacement
* True if placement is supposed to be done in the CAD flow.
* False if otherwise.
*/
struct t_placer_opts {
enum e_place_algorithm place_algorithm;
t_place_algorithm place_algorithm;
t_place_algorithm place_quench_algorithm;
float timing_tradeoff;
float place_cost_exp;
int place_chan_width;
Expand Down
Loading