Skip to content

Refactor place.cpp Part I #1529

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 3 commits into from
Sep 11, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
590 changes: 58 additions & 532 deletions vpr/src/place/place.cpp

Large diffs are not rendered by default.

107 changes: 92 additions & 15 deletions vpr/src/place/place_delay_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "vtr_math.h"
#include "vpr_error.h"

#include "placer_globals.h"

#ifdef VTR_ENABLE_CAPNPROTO
# include "capnp/serialize.h"
# include "place_delay_model.capnp.h"
Expand All @@ -18,10 +20,7 @@
# include "serdes_utils.h"
#endif /* VTR_ENABLE_CAPNPROTO */

/*
* DeltaDelayModel
*/

///@brief DeltaDelayModel methods.
float DeltaDelayModel::delay(int from_x, int from_y, int /*from_pin*/, int to_x, int to_y, int /*to_pin*/) const {
int delta_x = std::abs(from_x - to_x);
int delta_y = std::abs(from_y - to_y);
Expand All @@ -46,9 +45,11 @@ void DeltaDelayModel::dump_echo(std::string filepath) const {
vtr::fclose(f);
}

/*
* OverrideDelayModel
*/
const DeltaDelayModel* OverrideDelayModel::base_delay_model() const {
return base_delay_model_.get();
}

///@brief OverrideDelayModel methods.
float OverrideDelayModel::delay(int from_x, int from_y, int from_pin, int to_x, int to_y, int to_pin) const {
//First check to if there is an override delay value
auto& device_ctx = g_vpr_ctx.device();
Expand Down Expand Up @@ -136,18 +137,14 @@ float OverrideDelayModel::get_delay_override(int from_type, int from_class, int
return iter->second;
}

const DeltaDelayModel* OverrideDelayModel::base_delay_model() const {
return base_delay_model_.get();
}

void OverrideDelayModel::set_base_delay_model(std::unique_ptr<DeltaDelayModel> base_delay_model_obj) {
base_delay_model_ = std::move(base_delay_model_obj);
}

// When writing capnp targetted serialization, always allow compilation when
// VTR_ENABLE_CAPNPROTO=OFF. Generally this means throwing an exception
// instead.
//
/**
* When writing capnp targetted serialization, always allow compilation when
* VTR_ENABLE_CAPNPROTO=OFF. Generally this means throwing an exception instead.
*/
#ifndef VTR_ENABLE_CAPNPROTO

# define DISABLE_ERROR \
Expand Down Expand Up @@ -300,3 +297,83 @@ void OverrideDelayModel::write(const std::string& file) const {
}

#endif

///@brief Initialize the placer delay model.
std::unique_ptr<PlaceDelayModel> alloc_lookups_and_delay_model(t_chan_width_dist chan_width_dist,
const t_placer_opts& placer_opts,
const t_router_opts& router_opts,
t_det_routing_arch* det_routing_arch,
std::vector<t_segment_inf>& segment_inf,
const t_direct_inf* directs,
const int num_directs) {
return compute_place_delay_model(placer_opts, router_opts, det_routing_arch, segment_inf,
chan_width_dist, directs, num_directs);
}

/**
* @brief Returns the delay of one point to point connection.
*
* Only estimate delay for signals routed through the inter-block routing network.
* TODO: Do how should we compute the delay for globals. "Global signals are assumed to have zero delay."
*/
float comp_td_single_connection_delay(const PlaceDelayModel* delay_model, ClusterNetId net_id, int ipin) {
auto& cluster_ctx = g_vpr_ctx.clustering();
auto& place_ctx = g_vpr_ctx.placement();

float delay_source_to_sink = 0.;

if (!cluster_ctx.clb_nlist.net_is_ignored(net_id)) {
ClusterPinId source_pin = cluster_ctx.clb_nlist.net_driver(net_id);
ClusterPinId sink_pin = cluster_ctx.clb_nlist.net_pin(net_id, ipin);

ClusterBlockId source_block = cluster_ctx.clb_nlist.pin_block(source_pin);
ClusterBlockId sink_block = cluster_ctx.clb_nlist.pin_block(sink_pin);

int source_block_ipin = cluster_ctx.clb_nlist.pin_logical_index(source_pin);
int sink_block_ipin = cluster_ctx.clb_nlist.pin_logical_index(sink_pin);

int source_x = place_ctx.block_locs[source_block].loc.x;
int source_y = place_ctx.block_locs[source_block].loc.y;
int sink_x = place_ctx.block_locs[sink_block].loc.x;
int sink_y = place_ctx.block_locs[sink_block].loc.y;

/**
* This heuristic only considers delta_x and delta_y, a much better
* heuristic would be to to create a more comprehensive lookup table.
*
* In particular this approach does not accurately capture the effect
* of fast carry-chain connections.
*/
delay_source_to_sink = delay_model->delay(source_x,
source_y,
source_block_ipin,
sink_x,
sink_y,
sink_block_ipin);
if (delay_source_to_sink < 0) {
VPR_ERROR(VPR_ERROR_PLACE,
"in comp_td_single_connection_delay: Bad delay_source_to_sink value %g from %s (at %d,%d) to %s (at %d,%d)\n"
"in comp_td_single_connection_delay: Delay is less than 0\n",
block_type_pin_index_to_name(physical_tile_type(source_block), source_block_ipin).c_str(),
source_x, source_y,
block_type_pin_index_to_name(physical_tile_type(sink_block), sink_block_ipin).c_str(),
sink_x, sink_y,
delay_source_to_sink);
}
}

return (delay_source_to_sink);
}

///@brief Recompute all point to point delays, updating `connection_delay` matrix.
void comp_td_connection_delays(const PlaceDelayModel* delay_model) {
const auto& cluster_ctx = g_vpr_ctx.clustering();
auto& p_timing_ctx = g_placer_ctx.mutable_timing();
auto& connection_delay = p_timing_ctx.connection_delay;

for (auto net_id : cluster_ctx.clb_nlist.nets()) {
for (size_t ipin = 1; ipin < cluster_ctx.clb_nlist.net_pins(net_id).size(); ++ipin) {
connection_delay[net_id][ipin] = comp_td_single_connection_delay(delay_model, net_id, ipin);
}
}
}
77 changes: 55 additions & 22 deletions vpr/src/place/place_delay_model.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef PLACE_DELAY_MODEL_H
#define PLACE_DELAY_MODEL_H
/**
* @file place_delay_model.h
* @brief This file contains all the class and function declarations related to
* the placer delay model. For implementations, see place_delay_model.cpp.
*/

#pragma once
#include "vtr_ndmatrix.h"
#include "vtr_flat_map.h"
#include "vpr_types.h"
Expand All @@ -20,38 +24,63 @@
# define ALWAYS_INLINE inline
#endif

//Abstract interface to a placement delay model
///@brief Forward declarations.
class PlaceDelayModel;

///@brief Initialize the placer delay model.
std::unique_ptr<PlaceDelayModel> alloc_lookups_and_delay_model(t_chan_width_dist chan_width_dist,
const t_placer_opts& place_opts,
const t_router_opts& router_opts,
t_det_routing_arch* det_routing_arch,
std::vector<t_segment_inf>& segment_inf,
const t_direct_inf* directs,
const int num_directs);

///@brief Returns the delay of one point to point connection.
float comp_td_single_connection_delay(const PlaceDelayModel* delay_model, ClusterNetId net_id, int ipin);

///@brief Recompute all point to point delays, updating `connection_delay` matrix.
void comp_td_connection_delays(const PlaceDelayModel* delay_model);

///@brief Abstract interface to a placement delay model.
class PlaceDelayModel {
public:
virtual ~PlaceDelayModel() = default;

// Computes place delay model.
///@brief Computes place delay model.
virtual void compute(
RouterDelayProfiler& route_profiler,
const t_placer_opts& placer_opts,
const t_router_opts& router_opts,
int longest_length)
= 0;

//Returns the delay estimate between the specified block pins
//
// Either compute or read methods must be invoked before invoking
// delay.
/**
* @brief Returns the delay estimate between the specified block pins.
*
* Either compute or read methods must be invoked before invoking delay.
*/
virtual float delay(int from_x, int from_y, int from_pin, int to_x, int to_y, int to_pin) const = 0;

//Dumps the delay model to an echo file
///@brief Dumps the delay model to an echo file.
virtual void dump_echo(std::string filename) const = 0;

// Write place delay model to specified file.
// May be unimplemented, in which case method should throw an exception.
/**
* @brief Write place delay model to specified file.
*
* May be unimplemented, in which case method should throw an exception.
*/
virtual void write(const std::string& file) const = 0;

// Read place delay model from specified file.
// May be unimplemented, in which case method should throw an exception.
/**
* @brief Read place delay model from specified file.
*
* May be unimplemented, in which case method should throw an exception.
*/
virtual void read(const std::string& file) = 0;
};

//A simple delay model based on the distance (delta) between block locations
///@brief A simple delay model based on the distance (delta) between block locations.
class DeltaDelayModel : public PlaceDelayModel {
public:
DeltaDelayModel() {}
Expand Down Expand Up @@ -109,10 +138,13 @@ class OverrideDelayModel : public PlaceDelayModel {
short delta_x;
short delta_y;

//A combination of ALWAYS_INLINE attribute and std::lexicographical_compare
//is required for operator< to be inlined by compiler.
//Proper inlining of the function reduces place time by around 5%.
//For more information: https://github.com/verilog-to-routing/vtr-verilog-to-routing/issues/1225
/**
* A combination of ALWAYS_INLINE attribute and std::lexicographical_compare
* is required for operator< to be inlined by compiler. Proper inlining of the
* function reduces place time by around 5%.
*
* For more information: https://github.com/verilog-to-routing/vtr-verilog-to-routing/issues/1225
*/
friend ALWAYS_INLINE bool operator<(const t_override& lhs, const t_override& rhs) {
const short* left = reinterpret_cast<const short*>(&lhs);
const short* right = reinterpret_cast<const short*>(&rhs);
Expand All @@ -123,8 +155,11 @@ class OverrideDelayModel : public PlaceDelayModel {

vtr::flat_map2<t_override, float> delay_overrides_;

//operator< treats memory layout of t_override as an array of short
//this requires all members of t_override are shorts and there is no padding between members of t_override
/**
* operator< treats memory layout of t_override as an array of short.
* This requires all members of t_override are shorts and there is no
* padding between members of t_override.
*/
static_assert(sizeof(t_override) == sizeof(t_override::from_type) + sizeof(t_override::to_type) + sizeof(t_override::from_class) + sizeof(t_override::to_class) + sizeof(t_override::delta_x) + sizeof(t_override::delta_y), "Expect t_override to have a memory layout equivalent to an array of short (no padding)");
static_assert(sizeof(t_override::from_type) == sizeof(short), "Expect all t_override data members to be shorts");
static_assert(sizeof(t_override::to_type) == sizeof(short), "Expect all t_override data members to be shorts");
Expand All @@ -133,5 +168,3 @@ class OverrideDelayModel : public PlaceDelayModel {
static_assert(sizeof(t_override::delta_x) == sizeof(short), "Expect all t_override data members to be shorts");
static_assert(sizeof(t_override::delta_y) == sizeof(short), "Expect all t_override data members to be shorts");
};

#endif
Loading