Skip to content

Commit

Permalink
create two files for each placement delay model
Browse files Browse the repository at this point in the history
  • Loading branch information
soheilshahrouz committed Nov 28, 2024
1 parent be8519b commit 47dec5c
Show file tree
Hide file tree
Showing 9 changed files with 554 additions and 530 deletions.
34 changes: 34 additions & 0 deletions vpr/src/place/timing/delay_model/delta_delay_model.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

#include "delta_delay_model.h"

float DeltaDelayModel::delay(const t_physical_tile_loc& from_loc, int /*from_pin*/,
const t_physical_tile_loc& to_loc, int /*to_pin*/) const {
int delta_x = std::abs(from_loc.x - to_loc.x);
int delta_y = std::abs(from_loc.y - to_loc.y);

return delays_[from_loc.layer_num][to_loc.layer_num][delta_x][delta_y];
}

void DeltaDelayModel::dump_echo(std::string filepath) const {
FILE* f = vtr::fopen(filepath.c_str(), "w");
fprintf(f, " ");
for (size_t from_layer_num = 0; from_layer_num < delays_.dim_size(0); ++from_layer_num) {
for (size_t to_layer_num = 0; to_layer_num < delays_.dim_size(1); ++to_layer_num) {
fprintf(f, " %9zu", from_layer_num);
fprintf(f, "\n");
for (size_t dx = 0; dx < delays_.dim_size(2); ++dx) {
fprintf(f, " %9zu", dx);
}
fprintf(f, "\n");
for (size_t dy = 0; dy < delays_.dim_size(3); ++dy) {
fprintf(f, "%9zu", dy);
for (size_t dx = 0; dx < delays_.dim_size(2); ++dx) {
fprintf(f, " %9.2e", delays_[from_layer_num][to_layer_num][dx][dy]);
}
fprintf(f, "\n");
}
}
}
vtr::fclose(f);
}

47 changes: 47 additions & 0 deletions vpr/src/place/timing/delay_model/delta_delay_model.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

#pragma once

#include "place_delay_model.h"

/**
* @class DeltaDelayModel
*
* @brief A simple delay model based on the distance (delta) between block locations.
*/
class DeltaDelayModel : public PlaceDelayModel {
public:
DeltaDelayModel(float min_cross_layer_delay,
bool is_flat)
: cross_layer_delay_(min_cross_layer_delay)
, is_flat_(is_flat) {}

DeltaDelayModel(float min_cross_layer_delay,
vtr::NdMatrix<float, 4> delta_delays,
bool is_flat)
: delays_(std::move(delta_delays))
, cross_layer_delay_(min_cross_layer_delay)
, is_flat_(is_flat) {}

void compute(RouterDelayProfiler& router,
const t_placer_opts& placer_opts,
const t_router_opts& router_opts,
int longest_length) override;

float delay(const t_physical_tile_loc& from_loc, int /*from_pin*/, const t_physical_tile_loc& to_loc, int /*to_pin*/) const override;

void dump_echo(std::string filepath) const override;

void read(const std::string& file) override;
void write(const std::string& file) const override;

const vtr::NdMatrix<float, 4>& delays() const {
return delays_;
}

private:
vtr::NdMatrix<float, 4> delays_; // [0..num_layers-1][0..max_dx][0..max_dy]
float cross_layer_delay_;

/// Indicates whether the router is a two-stage or run-flat
bool is_flat_;
};
262 changes: 262 additions & 0 deletions vpr/src/place/timing/delay_model/override_delay_model.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@

#include "override_delay_model.h"

#ifdef VTR_ENABLE_CAPNPROTO
# include "capnp/serialize.h"
# include "place_delay_model.capnp.h"
# include "ndmatrix_serdes.h"
# include "mmap_file.h"
# include "serdes_utils.h"
#endif // VTR_ENABLE_CAPNPROTO

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

float OverrideDelayModel::delay(const t_physical_tile_loc& from_loc, int from_pin, const t_physical_tile_loc& to_loc, int to_pin) const {
// First check to if there is an override delay value
const auto& device_ctx = g_vpr_ctx.device();
const auto& grid = device_ctx.grid;

t_physical_tile_type_ptr from_type_ptr = grid.get_physical_type(from_loc);
t_physical_tile_type_ptr to_type_ptr = grid.get_physical_type(to_loc);

t_override override_key;
override_key.from_type = from_type_ptr->index;
override_key.from_class = from_type_ptr->pin_class[from_pin];
override_key.to_type = to_type_ptr->index;
override_key.to_class = to_type_ptr->pin_class[to_pin];

//Delay overrides may be different for +/- delta so do not use
//an absolute delta for the look-up
override_key.delta_x = to_loc.x - from_loc.x;
override_key.delta_y = to_loc.y - from_loc.y;

float delay_val = std::numeric_limits<float>::quiet_NaN();
auto override_iter = delay_overrides_.find(override_key);
if (override_iter != delay_overrides_.end()) {
//Found an override
delay_val = override_iter->second;
} else {
//Fall back to the base delay model if no override was found
delay_val = base_delay_model_->delay(from_loc, from_pin, to_loc, to_pin);
}

return delay_val;
}

void OverrideDelayModel::set_delay_override(int from_type, int from_class, int to_type, int to_class, int delta_x, int delta_y, float delay_val) {
t_override override_key;
override_key.from_type = from_type;
override_key.from_class = from_class;
override_key.to_type = to_type;
override_key.to_class = to_class;
override_key.delta_x = delta_x;
override_key.delta_y = delta_y;

auto res = delay_overrides_.insert(std::make_pair(override_key, delay_val));
if (!res.second) { //Key already exists
res.first->second = delay_val; //Overwrite existing delay
}
}

void OverrideDelayModel::dump_echo(std::string filepath) const {
base_delay_model_->dump_echo(filepath);

FILE* f = vtr::fopen(filepath.c_str(), "a");

fprintf(f, "\n");
fprintf(f, "# Delay Overrides\n");
auto& device_ctx = g_vpr_ctx.device();
for (auto kv : delay_overrides_) {
auto override_key = kv.first;
float delay_val = kv.second;
fprintf(f, "from_type: %s to_type: %s from_pin_class: %d to_pin_class: %d delta_x: %d delta_y: %d -> delay: %g\n",
device_ctx.physical_tile_types[override_key.from_type].name.c_str(),
device_ctx.physical_tile_types[override_key.to_type].name.c_str(),
override_key.from_class,
override_key.to_class,
override_key.delta_x,
override_key.delta_y,
delay_val);
}

vtr::fclose(f);
}

float OverrideDelayModel::get_delay_override(int from_type, int from_class, int to_type, int to_class, int delta_x, int delta_y) const {
t_override key;
key.from_type = from_type;
key.from_class = from_class;
key.to_type = to_type;
key.to_class = to_class;
key.delta_x = delta_x;
key.delta_y = delta_y;

auto iter = delay_overrides_.find(key);
if (iter == delay_overrides_.end()) {
VPR_THROW(VPR_ERROR_PLACE, "Key not found.");
}
return iter->second;
}

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.
*/
#ifndef VTR_ENABLE_CAPNPROTO

# define DISABLE_ERROR \
"is disable because VTR_ENABLE_CAPNPROTO=OFF." \
"Re-compile with CMake option VTR_ENABLE_CAPNPROTO=ON to enable."

void DeltaDelayModel::read(const std::string& /*file*/) {
VPR_THROW(VPR_ERROR_PLACE, "DeltaDelayModel::read " DISABLE_ERROR);
}

void DeltaDelayModel::write(const std::string& /*file*/) const {
VPR_THROW(VPR_ERROR_PLACE, "DeltaDelayModel::write " DISABLE_ERROR);
}

void OverrideDelayModel::read(const std::string& /*file*/) {
VPR_THROW(VPR_ERROR_PLACE, "OverrideDelayModel::read " DISABLE_ERROR);
}

void OverrideDelayModel::write(const std::string& /*file*/) const {
VPR_THROW(VPR_ERROR_PLACE, "OverrideDelayModel::write " DISABLE_ERROR);
}

#else /* VTR_ENABLE_CAPNPROTO */

static void ToFloat(float* out, const VprFloatEntry::Reader& in) {
// Getting a scalar field is always "get<field name>()".
*out = in.getValue();
}

static void FromFloat(VprFloatEntry::Builder* out, const float& in) {
// Setting a scalar field is always "set<field name>(value)".
out->setValue(in);
}

void DeltaDelayModel::read(const std::string& file) {
// MmapFile object creates an mmap of the specified path, and will munmap
// when the object leaves scope.
MmapFile f(file);

/* Increase reader limit to 1G words to allow for large files. */
::capnp::ReaderOptions opts = default_large_capnp_opts();

// FlatArrayMessageReader is used to read the message from the data array
// provided by MmapFile.
::capnp::FlatArrayMessageReader reader(f.getData(), opts);

// When reading capnproto files the Reader object to use is named
// <schema name>::Reader.
//
// Initially this object is an empty VprDeltaDelayModel.
VprDeltaDelayModel::Reader model;

// The reader.getRoot performs a cast from the generic capnproto to fit
// with the specified schema.
//
// Note that capnproto does not validate that the incoming data matches the
// schema. If this property is required, some form of check would be
// required.
model = reader.getRoot<VprDeltaDelayModel>();

// ToNdMatrix is a generic function for converting a Matrix capnproto
// to a vtr::NdMatrix.
//
// The use must supply the matrix dimension (2 in this case), the source
// capnproto type (VprFloatEntry),
// target C++ type (flat), and a function to convert from the source capnproto
// type to the target C++ type (ToFloat).
//
// The second argument should be of type Matrix<X>::Reader where X is the
// capnproto element type.
ToNdMatrix<4, VprFloatEntry, float>(&delays_, model.getDelays(), ToFloat);
}

void DeltaDelayModel::write(const std::string& file) const {
// MallocMessageBuilder object is the generate capnproto message builder,
// using malloc for buffer allocation.
::capnp::MallocMessageBuilder builder;

// initRoot<X> returns a X::Builder object that can be used to set the
// fields in the message.
auto model = builder.initRoot<VprDeltaDelayModel>();

// FromNdMatrix is a generic function for converting a vtr::NdMatrix to a
// Matrix message. It is the mirror function of ToNdMatrix described in
// read above.
auto delay_values = model.getDelays();
FromNdMatrix<4, VprFloatEntry, float>(&delay_values, delays_, FromFloat);

// writeMessageToFile writes message to the specified file.
writeMessageToFile(file, &builder);
}

void OverrideDelayModel::read(const std::string& file) {
MmapFile f(file);

/* Increase reader limit to 1G words to allow for large files. */
::capnp::ReaderOptions opts = default_large_capnp_opts();
::capnp::FlatArrayMessageReader reader(f.getData(), opts);

vtr::NdMatrix<float, 4> delays;
auto model = reader.getRoot<VprOverrideDelayModel>();
ToNdMatrix<4, VprFloatEntry, float>(&delays, model.getDelays(), ToFloat);

base_delay_model_ = std::make_unique<DeltaDelayModel>(cross_layer_delay_, delays, is_flat_);

// Reading non-scalar capnproto fields is roughly equivilant to using
// a std::vector of the field type. Actual type is capnp::List<X>::Reader.
auto overrides = model.getDelayOverrides();
std::vector<std::pair<t_override, float> > overrides_arr(overrides.size());
for (size_t i = 0; i < overrides.size(); ++i) {
const auto& elem = overrides[i];
overrides_arr[i].first.from_type = elem.getFromType();
overrides_arr[i].first.to_type = elem.getToType();
overrides_arr[i].first.from_class = elem.getFromClass();
overrides_arr[i].first.to_class = elem.getToClass();
overrides_arr[i].first.delta_x = elem.getDeltaX();
overrides_arr[i].first.delta_y = elem.getDeltaY();

overrides_arr[i].second = elem.getDelay();
}

delay_overrides_ = vtr::make_flat_map2(std::move(overrides_arr));
}

void OverrideDelayModel::write(const std::string& file) const {
::capnp::MallocMessageBuilder builder;
auto model = builder.initRoot<VprOverrideDelayModel>();

auto delays = model.getDelays();
FromNdMatrix<4, VprFloatEntry, float>(&delays, base_delay_model_->delays(), FromFloat);

// Non-scalar capnproto fields should be first initialized with
// init<field name>(count), and then accessed from the returned
// std::vector-like Builder object (specifically capnp::List<X>::Builder).
auto overrides = model.initDelayOverrides(delay_overrides_.size());
auto dst_iter = overrides.begin();
for (const auto& src : delay_overrides_) {
auto elem = *dst_iter++;
elem.setFromType(src.first.from_type);
elem.setToType(src.first.to_type);
elem.setFromClass(src.first.from_class);
elem.setToClass(src.first.to_class);
elem.setDeltaX(src.first.delta_x);
elem.setDeltaY(src.first.delta_y);

elem.setDelay(src.second);
}

writeMessageToFile(file, &builder);
}

#endif
Loading

0 comments on commit 47dec5c

Please sign in to comment.