Skip to content

Add PlacerSetupSlacks interface #1450

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

Closed
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
24 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
da55abf
Merged t_placer_costs and t_placer_prev_inverse_costs and added
Bill-hbrhbr Aug 21, 2020
92c416a
Reduced down the argument list for starting_t, placement_inner_loop, …
Bill-hbrhbr Aug 22, 2020
870eca6
Moved t_placer_costs and t_annealing_state and related routines to pl…
Bill-hbrhbr Aug 22, 2020
a2685c7
Changed major place.cpp data structures from file scope to global sco…
Bill-hbrhbr Aug 23, 2020
cc4488e
Moved timing update routines from place.cpp to place_timing_update.*.…
Bill-hbrhbr Aug 24, 2020
38f25cc
Enchanced documentation for timing_place.*. Moved chanx, chany 2d arr…
Bill-hbrhbr Aug 25, 2020
74d279c
Added documentation for the timing driven routines used in try_swap()…
Bill-hbrhbr Aug 26, 2020
9f18666
Merge branch 'master' into PlacerSetupSlacks
Bill-hbrhbr Aug 26, 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
3 changes: 2 additions & 1 deletion vpr/src/base/vpr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,8 @@ struct t_annealing_sched {
* doPlacement: true if placement is supposed to be done in the CAD flow, false otherwise */
enum e_place_algorithm {
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 each enum constant chooses.
I also think we should PATH_DRIVEN_TIMING_PLACE to CRITICALITY_TIMING_PLACE (would be more clear; PATH_DRIVEN is no longer very relevant as all our timing data comes from timing paths).

BOUNDING_BOX_PLACE,
PATH_TIMING_DRIVEN_PLACE
PATH_TIMING_DRIVEN_PLACE,
SETUP_SLACK_ANALYSIS_PLACE
};

enum e_place_effort_scaling {
Expand Down
676 changes: 496 additions & 180 deletions vpr/src/place/place.cpp

Large diffs are not rendered by default.

174 changes: 126 additions & 48 deletions vpr/src/place/timing_place.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@

#include "timing_info.h"

//Use an incremental approach to updaing criticalities?
//Use an incremental approach to updating criticalities and setup slacks?
constexpr bool INCR_UPDATE_CRITICALITIES = true;
constexpr bool INCR_UPDATE_SETUP_SLACKS = true;

/**************************************/

Expand All @@ -27,58 +28,29 @@ PlacerCriticalities::PlacerCriticalities(const ClusteredNetlist& clb_nlist, cons
, timing_place_crit_(make_net_pins_matrix(clb_nlist_, std::numeric_limits<float>::quiet_NaN())) {
}

/**************************************/
void PlacerCriticalities::update_criticalities(const SetupTimingInfo* timing_info, float crit_exponent) {
/* Performs a 1-to-1 mapping from criticality to timing_place_crit_.
* For every pin on every net (or, equivalently, for every tedge ending
* in that pin), timing_place_crit_ = criticality^(criticality exponent) */
void PlacerCriticalities::update_criticalities(const SetupTimingInfo* timing_info, float crit_exponent, bool recompute) {
//If the criticalities are not updated immediately after each time we call
//timing_info->update(), then timing_info->pins_with_modified_setup_criticality()
//cannot accurately account for all the pins that need to be updated.
//In this case, we pass in recompute=true to update all criticalities from scratch.
//
//If the criticality exponent has changed, we also need to update from scratch.

//Determine what pins need updating
if (INCR_UPDATE_CRITICALITIES) {
cluster_pins_with_modified_criticality_.clear();
if (crit_exponent != last_crit_exponent_) {
//Criticality exponent changed, must re-calculate criticalities for *all* sink pins
for (ClusterNetId net_id : clb_nlist_.nets()) {
for (ClusterPinId pin_id : clb_nlist_.net_sinks(net_id)) {
cluster_pins_with_modified_criticality_.insert(pin_id);
}
}

//Record new criticality exponent
last_crit_exponent_ = crit_exponent;
} else {
//Criticality exponent unchanged
//
//Collect the cluster pins which need to be updated based on the latest timing
//analysis
//
//Note we use the set of pins reported by the *timing_info* as having modified
//criticality, rather than those marked as modified by the timing analyzer.
//Since timing_info uses shifted/relaxed criticality (which depends on max
//required time and worst case slacks), additional nodes may be modified
//when updating the atom pin criticalities.

for (AtomPinId atom_pin : timing_info->pins_with_modified_setup_criticality()) {
ClusterPinId clb_pin = pin_lookup_.connected_clb_pin(atom_pin);

//Some atom pins correspond to connections which are completely
//contained within a cluster, and hence have no corresponding
//clustered pin.
if (!clb_pin) continue;

cluster_pins_with_modified_criticality_.insert(clb_pin);
}
}
if (!recompute && crit_exponent == last_crit_exponent_ && INCR_UPDATE_CRITICALITIES) {
incr_update_criticalities(timing_info);
} else {
//Non-incremental: all pins and nets need updating
for (ClusterNetId net_id : clb_nlist_.nets()) {
for (ClusterPinId pin_id : clb_nlist_.net_sinks(net_id)) {
cluster_pins_with_modified_criticality_.insert(pin_id);
}
}
recompute_criticalities();

//Record new criticality exponent
last_crit_exponent_ = crit_exponent;
}

//Update the effected pins
/* Performs a 1-to-1 mapping from criticality to timing_place_crit_.
* For every pin on every net (or, equivalently, for every tedge ending
* in that pin), timing_place_crit_ = criticality^(criticality exponent) */

// Update the effected pins
for (ClusterPinId clb_pin : cluster_pins_with_modified_criticality_) {
ClusterNetId clb_net = clb_nlist_.pin_net(clb_pin);
int pin_index_in_net = clb_nlist_.pin_net_index(clb_pin);
Expand All @@ -92,6 +64,41 @@ void PlacerCriticalities::update_criticalities(const SetupTimingInfo* timing_inf
}
}

void PlacerCriticalities::incr_update_criticalities(const SetupTimingInfo* timing_info) {
cluster_pins_with_modified_criticality_.clear();

//Collect the cluster pins which need to be updated based on the latest timing
//analysis
//
//Note we use the set of pins reported by the *timing_info* as having modified
//criticality, rather than those marked as modified by the timing analyzer.
//Since timing_info uses shifted/relaxed criticality (which depends on max
//required time and worst case slacks), additional nodes may be modified
//when updating the atom pin criticalities.

for (AtomPinId atom_pin : timing_info->pins_with_modified_setup_criticality()) {
ClusterPinId clb_pin = pin_lookup_.connected_clb_pin(atom_pin);

//Some atom pins correspond to connections which are completely
//contained within a cluster, and hence have no corresponding
//clustered pin.
if (!clb_pin) continue;

cluster_pins_with_modified_criticality_.insert(clb_pin);
}
}

void PlacerCriticalities::recompute_criticalities() {
cluster_pins_with_modified_criticality_.clear();

//Non-incremental: all sink pins need updating
for (ClusterNetId net_id : clb_nlist_.nets()) {
for (ClusterPinId pin_id : clb_nlist_.net_sinks(net_id)) {
cluster_pins_with_modified_criticality_.insert(pin_id);
}
}
}

void PlacerCriticalities::set_criticality(ClusterNetId net_id, int ipin, float val) {
timing_place_crit_[net_id][ipin] = val;
}
Expand All @@ -100,6 +107,77 @@ PlacerCriticalities::pin_range PlacerCriticalities::pins_with_modified_criticali
return vtr::make_range(cluster_pins_with_modified_criticality_);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Are some of these routines rewrites / replacements for routines in place.cpp? I haven't checked line by line but some seem similar.

/**************************************/

/* Allocates space for the timing_place_setup_slacks_ data structure */
PlacerSetupSlacks::PlacerSetupSlacks(const ClusteredNetlist& clb_nlist, const ClusteredPinAtomPinsLookup& netlist_pin_lookup)
: clb_nlist_(clb_nlist)
, pin_lookup_(netlist_pin_lookup)
, timing_place_setup_slacks_(make_net_pins_matrix(clb_nlist_, std::numeric_limits<float>::quiet_NaN())) {
}

void PlacerSetupSlacks::update_setup_slacks(const SetupTimingInfo* timing_info, bool recompute) {
//If the setup slacks are not updated immediately after each time we call
//timing_info->update(), then timing_info->pins_with_modified_setup_slack()
//cannot accurately account for all the pins that need to be updated.
//In this case, we pass in recompute=true to update all setup slacks from scratch.
if (!recompute && INCR_UPDATE_SETUP_SLACKS) {
incr_update_setup_slacks(timing_info);
} else {
recompute_setup_slacks();
}

//Update the effected pins
for (ClusterPinId clb_pin : cluster_pins_with_modified_setup_slack_) {
ClusterNetId clb_net = clb_nlist_.pin_net(clb_pin);
int pin_index_in_net = clb_nlist_.pin_net_index(clb_pin);

float clb_pin_setup_slack = calculate_clb_net_pin_setup_slack(*timing_info, pin_lookup_, clb_pin);

timing_place_setup_slacks_[clb_net][pin_index_in_net] = clb_pin_setup_slack;
}
}

void PlacerSetupSlacks::incr_update_setup_slacks(const SetupTimingInfo* timing_info) {
cluster_pins_with_modified_setup_slack_.clear();

//Collect the cluster pins which need to be updated based on the latest timing analysis
//
//Note we use the set of pins reported by the *timing_info* as having modified
//setup slacks, rather than those marked as modified by the timing analyzer.
for (AtomPinId atom_pin : timing_info->pins_with_modified_setup_slack()) {
ClusterPinId clb_pin = pin_lookup_.connected_clb_pin(atom_pin);

//Some atom pins correspond to connections which are completely
//contained within a cluster, and hence have no corresponding
//clustered pin.
if (!clb_pin) continue;

cluster_pins_with_modified_setup_slack_.insert(clb_pin);
}
}

void PlacerSetupSlacks::recompute_setup_slacks() {
cluster_pins_with_modified_setup_slack_.clear();

//Non-incremental: all sink pins need updating
for (ClusterNetId net_id : clb_nlist_.nets()) {
for (ClusterPinId pin_id : clb_nlist_.net_sinks(net_id)) {
cluster_pins_with_modified_setup_slack_.insert(pin_id);
}
}
}

void PlacerSetupSlacks::set_setup_slack(ClusterNetId net_id, int ipin, float val) {
timing_place_setup_slacks_[net_id][ipin] = val;
}

PlacerSetupSlacks::pin_range PlacerSetupSlacks::pins_with_modified_setup_slack() const {
return vtr::make_range(cluster_pins_with_modified_setup_slack_);
}

/**************************************/

std::unique_ptr<PlaceDelayModel> alloc_lookups_and_criticalities(t_chan_width_dist chan_width_dist,
const t_placer_opts& placer_opts,
const t_router_opts& router_opts,
Expand Down
68 changes: 66 additions & 2 deletions vpr/src/place/timing_place.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ class PlacerCriticalities {
pin_range pins_with_modified_criticality() const;

public: //Modifiers
//Incrementally updates criticalities based on the atom netlist criticalitites provied by
//Updates criticalities based on the atom netlist criticalitites provided by
//timing_info and the provided criticality_exponent.
void update_criticalities(const SetupTimingInfo* timing_info, float criticality_exponent);
void update_criticalities(const SetupTimingInfo* timing_info, float criticality_exponent, bool recompute);

//Override the criticality of a particular connection
void set_criticality(ClusterNetId net, int ipin, float val);
Expand All @@ -81,6 +81,70 @@ class PlacerCriticalities {

//Set of pins with criticaltites modified by last call to update_criticalities()
vtr::vec_id_set<ClusterPinId> cluster_pins_with_modified_criticality_;

//Updates criticalities: incremental V.S. from scratch
void incr_update_criticalities(const SetupTimingInfo* timing_info);
void recompute_criticalities();
};

/* Usage
* =====
* PlacerSetupSlacks returns the clustered netlist connection setup slack used by
* the placer. This also serves to map atom netlist level slack (i.e. on AtomPinIds)
* to the clustered netlist (i.e. ClusterPinIds) used during placement.
*
* Setup slacks are calculated by calling update_setup_slacks(), which will
* update setup slacks based on the atom netlist connection setup slacks provided by
* the passed in SetupTimingInfo. This is done incrementally, based on the modified
* connections/AtomPinIds returned by SetupTimingInfo.
*
* The setup slacks of individual connections can then be queried by calling the
* setup_slack() member function.
*
* It also supports iterating via pins_with_modified_setup_slack() through the
* clustered netlist pins/connections which have had their setup slacks modified by
* the last call to update_setup_slacks().
*/
class PlacerSetupSlacks {
Copy link
Contributor

Choose a reason for hiding this comment

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

Explain that these are raw slacks (can be negative, based on the timing constraint specified by the user or the very difficult automatically set timing constraints if no user-specified one exists).

public: //Types
typedef vtr::vec_id_set<ClusterPinId>::iterator pin_iterator;
typedef vtr::vec_id_set<ClusterNetId>::iterator net_iterator;

typedef vtr::Range<pin_iterator> pin_range;
typedef vtr::Range<net_iterator> net_range;

public: //Lifetime
PlacerSetupSlacks(const ClusteredNetlist& clb_nlist, const ClusteredPinAtomPinsLookup& netlist_pin_lookup);
PlacerSetupSlacks(const PlacerSetupSlacks& clb_nlist) = delete;
PlacerSetupSlacks& operator=(const PlacerSetupSlacks& clb_nlist) = delete;

public: //Accessors
//Returns the setup slack of the specified connection
float setup_slack(ClusterNetId net, int ipin) const { return timing_place_setup_slacks_[net][ipin]; }

//Returns the range of clustered netlist pins (i.e. ClusterPinIds) which were modified
//by the last call to update_setup_slacks()
pin_range pins_with_modified_setup_slack() const;

public: //Modifiers
//Updates setup slacks based on the atom netlist setup slacks provided by timing_info
void update_setup_slacks(const SetupTimingInfo* timing_info, bool recompute);

//Override the setup slack of a particular connection
void set_setup_slack(ClusterNetId net, int ipin, float val);

private: //Data
const ClusteredNetlist& clb_nlist_;
const ClusteredPinAtomPinsLookup& pin_lookup_;

ClbNetPinsMatrix<float> timing_place_setup_slacks_; /* [0..cluster_ctx.clb_nlist.nets().size()-1][1..num_pins-1] */

//Set of pins with criticaltites modified by last call to update_criticalities()
vtr::vec_id_set<ClusterPinId> cluster_pins_with_modified_setup_slack_;

//Updates setup slacks: incremental V.S. from scratch
void incr_update_setup_slacks(const SetupTimingInfo* timing_info);
void recompute_setup_slacks();
};

/* Usage
Expand Down
17 changes: 17 additions & 0 deletions vpr/src/timing/timing_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,23 @@ float calculate_clb_net_pin_criticality(const SetupTimingInfo& timing_info, cons
return clb_pin_crit;
}

//Return the setup slack of a net's pin in the CLB netlist
Copy link
Contributor

Choose a reason for hiding this comment

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

Explain that it assumes the timing analysis is up to date (has already been performed with an update call with the right delays).

float calculate_clb_net_pin_setup_slack(const SetupTimingInfo& timing_info, const ClusteredPinAtomPinsLookup& pin_lookup, ClusterPinId clb_pin) {
//There may be multiple atom netlist pins connected to this CLB pin
float clb_pin_setup_slack = std::numeric_limits<float>::quiet_NaN();

for (const auto atom_pin : pin_lookup.connected_atom_pins(clb_pin)) {
//Take the worst of the atom pin slacks as the CLB pin slack
if (std::isnan(clb_pin_setup_slack)) {
clb_pin_setup_slack = timing_info.setup_pin_slack(atom_pin);
} else {
clb_pin_setup_slack = std::min(clb_pin_setup_slack, timing_info.setup_pin_slack(atom_pin));
}
}

return clb_pin_setup_slack;
}

//Returns the worst (maximum) criticality of the set of slack tags specified. Requires the maximum
//required time and worst slack for all domain pairs represent by the slack tags
//
Expand Down
3 changes: 3 additions & 0 deletions vpr/src/timing/timing_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ class ClusteredPinTimingInvalidator {
//Return the criticality of a net's pin in the CLB netlist
float calculate_clb_net_pin_criticality(const SetupTimingInfo& timing_info, const ClusteredPinAtomPinsLookup& pin_lookup, ClusterPinId clb_pin);

//Return the setup slack of a net's pin in the CLB netlist
float calculate_clb_net_pin_setup_slack(const SetupTimingInfo& timing_info, const ClusteredPinAtomPinsLookup& pin_lookup, ClusterPinId clb_pin);

//Returns the worst (maximum) criticality of the set of slack tags specified. Requires the maximum
//required time and worst slack for all domain pairs represent by the slack tags
//
Expand Down