timing graph for circuit models are working
This commit is contained in:
parent
c004699a14
commit
fbdab32a2d
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
***********************************************************************/
|
||||
|
|
|
@ -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
|
||||
|
||||
/************************************************************************
|
||||
|
|
|
@ -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
|
||||
***********************************************************************/
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue