timing graph for circuit models are working

This commit is contained in:
tangxifan 2019-08-10 13:03:24 -06:00
parent c004699a14
commit fbdab32a2d
6 changed files with 269 additions and 22 deletions

View File

@ -373,6 +373,29 @@ CircuitModelId CircuitLibrary::default_circuit_model(const enum e_spice_model_ty
return circuit_model_lookup_[size_t(type)].front();
}
/************************************************************************
* Public Accessors: Timing graph
***********************************************************************/
/* Given the source and sink port information, find the edge connecting the two ports */
CircuitEdgeId CircuitLibrary::edge(const CircuitModelId& circuit_model_id,
const CircuitPortId& from_port, const size_t from_pin,
const CircuitPortId& to_port, const size_t to_pin) {
/* validate the circuit_pin_id */
VTR_ASSERT_SAFE(valid_circuit_pin_id(circuit_model_id, from_port, from_pin));
VTR_ASSERT_SAFE(valid_circuit_pin_id(circuit_model_id, to_port, to_pin));
/* Walk through the edge list until we find the one */
for (auto edge : edge_ids_[circuit_model_id]) {
if ( (from_port == edge_src_port_ids_[circuit_model_id][edge])
&& (from_pin == edge_src_pin_ids_[circuit_model_id][edge])
&& (to_port == edge_sink_port_ids_[circuit_model_id][edge])
&& (to_pin == edge_sink_pin_ids_[circuit_model_id][edge]) ) {
return edge;
}
}
/* Reach here it means we find nothing! */
return CIRCUIT_EDGE_OPEN_ID;
}
/************************************************************************
* Public Mutators
***********************************************************************/
@ -1388,25 +1411,21 @@ void CircuitLibrary::add_edge(const CircuitModelId& circuit_model_id,
edge_sink_pin_ids_[circuit_model_id].push_back(to_pin);
/* Give a default value for timing values */
std::vector<float> timing_info(2, 0);
edge_timing_info_[circuit_model_id].emplace_back(timing_info);
std::vector<float> timing_info(NUM_CIRCUIT_MODEL_DELAY_TYPES, 0);
edge_timing_info_[circuit_model_id].push_back(timing_info);
return;
}
void CircuitLibrary::set_edge_trise(const CircuitModelId& circuit_model_id, const CircuitEdgeId& circuit_edge_id, const float& trise) {
void CircuitLibrary::set_edge_delay(const CircuitModelId& circuit_model_id,
const CircuitEdgeId& circuit_edge_id,
const enum spice_model_delay_type& delay_type,
const float& delay_value) {
/* validate the circuit_edge_id */
VTR_ASSERT_SAFE(valid_circuit_edge_id(circuit_model_id, circuit_edge_id));
VTR_ASSERT_SAFE(valid_delay_type(circuit_model_id, delay_type));
edge_timing_info_[circuit_model_id][circuit_edge_id][size_t(SPICE_MODEL_DELAY_RISE)] = trise;
return;
}
void CircuitLibrary::set_edge_tfall(const CircuitModelId& circuit_model_id, const CircuitEdgeId& circuit_edge_id, const float& tfall) {
/* validate the circuit_edge_id */
VTR_ASSERT_SAFE(valid_circuit_edge_id(circuit_model_id, circuit_edge_id));
edge_timing_info_[circuit_model_id][circuit_edge_id][size_t(SPICE_MODEL_DELAY_FALL)] = tfall;
edge_timing_info_[circuit_model_id][circuit_edge_id][size_t(delay_type)] = delay_value;
return;
}
@ -1428,11 +1447,20 @@ void CircuitLibrary::set_timing_graph_delays(const CircuitModelId& circuit_model
std::vector<CircuitPortId> input_port_ids;
std::vector<size_t> input_pin_ids;
/* Check each element */
for (const auto& port_info : input_ports) {
for (auto& port_info : input_ports) {
/* Try to find a port by the given name */
CircuitPortId port_id = port(circuit_model_id, port_info.get_name());
/* We must have a valid port and Port width must be 1! */
VTR_ASSERT_SAFE( (CIRCUIT_PORT_OPEN_ID != port_id) && (1 == port_info.get_width()) );
VTR_ASSERT_SAFE(CIRCUIT_PORT_OPEN_ID != port_id);
if (0 == port_info.get_width()) {
/* we need to configure the port width if it is zero.
* This means that parser find some compact port defintion such as <port_name>
*/
size_t port_width = port_size(circuit_model_id, port_id);
port_info.set_width(port_width);
} else {
VTR_ASSERT_SAFE(1 == port_info.get_width());
}
/* The pin id should be valid! */
VTR_ASSERT_SAFE(true == valid_circuit_pin_id(circuit_model_id, port_id, port_info.get_lsb()));
/* This must be an input port! */
@ -1448,11 +1476,20 @@ void CircuitLibrary::set_timing_graph_delays(const CircuitModelId& circuit_model
std::vector<CircuitPortId> output_port_ids;
std::vector<size_t> output_pin_ids;
/* Check each element */
for (const auto& port_info : output_ports) {
for (auto& port_info : output_ports) {
/* Try to find a port by the given name */
CircuitPortId port_id = port(circuit_model_id, port_info.get_name());
/* We must have a valid port and Port width must be 1! */
VTR_ASSERT_SAFE( (CIRCUIT_PORT_OPEN_ID != port_id) && (1 == port_info.get_width()) );
VTR_ASSERT_SAFE(CIRCUIT_PORT_OPEN_ID != port_id);
if (0 == port_info.get_width()) {
/* we need to configure the port width if it is zero.
* This means that parser find some compact port defintion such as <port_name>
*/
size_t port_width = port_size(circuit_model_id, port_id);
port_info.set_width(port_width);
} else {
VTR_ASSERT_SAFE(1 == port_info.get_width());
}
/* The pin id should be valid! */
VTR_ASSERT_SAFE(true == valid_circuit_pin_id(circuit_model_id, port_id, port_info.get_lsb()));
/* This must be an output port! */
@ -1462,6 +1499,28 @@ void CircuitLibrary::set_timing_graph_delays(const CircuitModelId& circuit_model
output_pin_ids.push_back(port_info.get_lsb());
}
/* Parse the delay matrix */
PortDelayParser port_delay_parser(delay_values_[circuit_model_id][size_t(delay_type)]);
/* Make sure the delay matrix size matches */
VTR_ASSERT_SAFE(port_delay_parser.height() == output_port_ids.size());
VTR_ASSERT_SAFE(port_delay_parser.height() == output_pin_ids.size());
VTR_ASSERT_SAFE(port_delay_parser.width() == input_port_ids.size());
VTR_ASSERT_SAFE(port_delay_parser.width() == input_pin_ids.size());
/* Configure timing graph */
for (size_t i = 0; i < port_delay_parser.height(); ++i) {
for (size_t j = 0; j < port_delay_parser.width(); ++j) {
float delay_value = port_delay_parser.delay(i, j);
CircuitEdgeId edge_id = edge(circuit_model_id,
input_port_ids[j], input_pin_ids[j],
output_port_ids[i], output_pin_ids[i]);
/* make sure we have an valid edge_id */
VTR_ASSERT_SAFE(true == valid_circuit_edge_id(circuit_model_id, edge_id));
set_edge_delay(circuit_model_id, edge_id,
delay_type, delay_value);
}
}
}
return;
}

View File

@ -256,6 +256,10 @@ class CircuitLibrary {
public: /* Public Accessors: Methods to find circuit model */
CircuitModelId circuit_model(const std::string& name) const;
CircuitModelId default_circuit_model(const enum e_spice_model_type& type) const;
public: /* Public Accessors: Timing graph */
CircuitEdgeId edge(const CircuitModelId& circuit_model_id,
const CircuitPortId& from_port, const size_t from_pin,
const CircuitPortId& to_port, const size_t to_pin);
public: /* Public Mutators */
CircuitModelId add_circuit_model();
/* Fundamental information */
@ -429,8 +433,11 @@ class CircuitLibrary {
void add_edge(const CircuitModelId& circuit_model_id,
const CircuitPortId& from_port, const size_t& from_pin,
const CircuitPortId& to_port, const size_t& to_pin);
void set_edge_trise(const CircuitModelId& circuit_model_id, const CircuitEdgeId& circuit_edge_id, const float& trise);
void set_edge_tfall(const CircuitModelId& circuit_model_id, const CircuitEdgeId& circuit_edge_id, const float& tfall);
void set_edge_delay(const CircuitModelId& circuit_model_id,
const CircuitEdgeId& circuit_edge_id,
const enum spice_model_delay_type& delay_type,
const float& delay_value);
/* validate the circuit_edge_id */
void set_timing_graph_delays(const CircuitModelId& circuit_model_id);
public: /* Internal mutators: build fast look-ups */
void build_circuit_model_lookup();

View File

@ -54,10 +54,9 @@
* Constructors
***********************************************************************/
PortParser::PortParser (const std::string& data) {
set_data(data);
set_default_bracket();
set_default_delim();
parse();
set_data(data);
}
/************************************************************************
@ -148,9 +147,8 @@ void PortParser::set_default_delim() {
* Constructors
***********************************************************************/
MultiPortParser::MultiPortParser (const std::string& data) {
set_data(data);
set_default_delim();
parse();
set_data(data);
}
/************************************************************************
@ -208,6 +206,125 @@ void MultiPortParser::clear() {
return;
}
/************************************************************************
* Member functions for PortDelayParser class
***********************************************************************/
/************************************************************************
* Constructors
***********************************************************************/
PortDelayParser::PortDelayParser (const std::string& data) {
set_default_element_delim();
set_default_line_delim();
set_data(data);
}
/************************************************************************
* Public Accessors
***********************************************************************/
/* Get the data string */
std::string PortDelayParser::data() const {
return data_;
}
/* Get the size of delay matrix [height, width]*/
size_t PortDelayParser::height() const {
return delay_matrix_.dim_size(0);
}
size_t PortDelayParser::width() const {
return delay_matrix_.dim_size(1);
}
vtr::Point<size_t> PortDelayParser::delay_size() const {
vtr::Point<size_t> matrix_size(height(), width());
return matrix_size;
}
float PortDelayParser::delay(size_t x, size_t y) const {
/* Make sure x and y are in range */
VTR_ASSERT_SAFE( (x < width()) && (y < height()) );
return delay_matrix_[x][y];
}
/************************************************************************
* Public Mutators
***********************************************************************/
void PortDelayParser::set_data(const std::string& data) {
data_ = data;
parse();
return;
}
/************************************************************************
* Internal Mutators
***********************************************************************/
/* Split the data line into fragments and parse one by one */
void PortDelayParser::parse() {
/* Clear content */
clear();
/* Create a tokenizer */
StringToken delay_tokenizer(data_);
/* Ensure a clean start! Trim whitespace at the beginning and end of the string */
delay_tokenizer.trim();
/* Split the data into different lines */
std::vector<std::string> delay_lines = delay_tokenizer.split(line_delim_);
/* The number of lines is actually the height of delay matrix */
size_t matrix_height = delay_lines.size();
size_t matrix_width = 0;
/* Visit each line and split with element_delim */
for (const auto& line : delay_lines) {
/* Create a tokenizer for each line */
StringToken line_tokenizer(line);
std::vector<std::string> delay_elements = line_tokenizer.split(element_delim_);
/* Get maximum number of length, which is the width of delay matrix */
matrix_width = std::max(matrix_width, delay_elements.size());
}
/* Resize matrix */
delay_matrix_.resize({matrix_height, matrix_width});
/* Fill matrix */
for (const auto& line : delay_lines) {
/* Create a tokenizer for each line */
StringToken line_tokenizer(line);
std::vector<std::string> delay_elements = line_tokenizer.split(element_delim_);
/* Get maximum number of length, which is the width of delay matrix */
for (const auto& element : delay_elements) {
delay_matrix_[size_t(&line - &delay_lines[0])][size_t(&element - &delay_elements[0])] = stof(element);
}
}
return;
}
void PortDelayParser::set_default_element_delim() {
/* Ensure a clean start */
element_delim_.clear();
element_delim_.push_back(' ');
element_delim_.push_back('\t');
return;
}
void PortDelayParser::set_default_line_delim() {
/* Ensure a clean start */
line_delim_.clear();
line_delim_.push_back('\n');
line_delim_.push_back('\r');
return;
}
void PortDelayParser::clear() {
delay_matrix_.clear();
return;
}
/************************************************************************
* End of file : port_parser.cpp
***********************************************************************/

View File

@ -50,6 +50,7 @@
#include <string>
#include <vector>
#include "vtr_ndmatrix.h"
#include "vtr_geometry.h"
#include "device_port.h"
@ -111,6 +112,33 @@ class MultiPortParser {
std::vector<BasicPort> ports_;
};
/************************************************************************
* PortDelayParser: a parser for 2D delay matrix
***********************************************************************/
class PortDelayParser {
public : /* Constructors*/
PortDelayParser (const std::string& data);
public : /* Public Accessors */
std::string data() const;
size_t height() const;
size_t width() const;
vtr::Point<size_t> delay_size() const;
float delay(size_t x, size_t y) const;
public : /* Public Mutators */
void set_data(const std::string& data);
private : /* Private Mutators */
void parse();
void set_default_element_delim();
void set_default_line_delim();
void clear();
private: /* Internal data */
std::string data_; /* Lines to be splited */
std::vector<char> element_delim_;
std::vector<char> line_delim_;
vtr::Matrix<float> delay_matrix_;
};
#endif
/************************************************************************

View File

@ -99,6 +99,18 @@ std::vector<std::string> StringToken::split(const char* delim) const {
return split(delims);
}
/* Split the string using a given delim */
std::vector<std::string> StringToken::split(const std::vector<char>& delims) const {
/* Create delims */
std::string delims_str;
for (const auto& delim : delims) {
delims_str.push_back(delim);
}
return split(delims_str);
}
/* Split the string */
std::vector<std::string> StringToken::split() {
/* Add a default delim */
@ -127,6 +139,26 @@ void StringToken::add_delim(const char& delim) {
delims_.push_back(delim);
}
/* Remove the string repeated at the beginning of string */
void StringToken::ltrim(const std::string& sensitive_word) {
size_t start = data_.find_first_not_of(sensitive_word);
data_ = (start == std::string::npos) ? "" : data_.substr(start);
return;
}
/* Remove the string repeated at the end of string */
void StringToken::rtrim(const std::string& sensitive_word) {
size_t end = data_.find_last_not_of(sensitive_word);
data_ = (end == std::string::npos) ? "" : data_.substr(0, end + 1);
return;
}
void StringToken::trim() {
rtrim(" ");
ltrim(" ");
return;
}
/************************************************************************
* Internal Mutators
***********************************************************************/

View File

@ -65,10 +65,14 @@ class StringToken {
std::vector<std::string> split(const std::string& delims) const;
std::vector<std::string> split(const char& delim) const;
std::vector<std::string> split(const char* delim) const;
std::vector<std::string> split(const std::vector<char>& delim) const;
std::vector<std::string> split();
public : /* Public Mutators */
void set_data(const std::string& data);
void add_delim(const char& delim);
void ltrim(const std::string& sensitive_word);
void rtrim(const std::string& sensitive_word);
void trim();
private : /* Private Mutators */
void add_default_delim();
private: /* Internal data */