diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp index 46df9d44a..240cefcf7 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -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 timing_info(2, 0); - edge_timing_info_[circuit_model_id].emplace_back(timing_info); + std::vector 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 input_port_ids; std::vector 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 + */ + 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 output_port_ids; std::vector 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 + */ + 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; } diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h index 8002c77c0..cdaf5f426 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -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(); diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.cpp b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.cpp index c9e5eff16..9453787e3 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.cpp @@ -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 PortDelayParser::delay_size() const { + vtr::Point 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 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 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 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 ***********************************************************************/ diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.h index ddd527559..9105a7082 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.h @@ -50,6 +50,7 @@ #include #include +#include "vtr_ndmatrix.h" #include "vtr_geometry.h" #include "device_port.h" @@ -111,6 +112,33 @@ class MultiPortParser { std::vector 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 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 element_delim_; + std::vector line_delim_; + vtr::Matrix delay_matrix_; +}; + + #endif /************************************************************************ diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.cpp b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.cpp index f040f5214..2f6dab90c 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.cpp @@ -99,6 +99,18 @@ std::vector StringToken::split(const char* delim) const { return split(delims); } +/* Split the string using a given delim */ +std::vector StringToken::split(const std::vector& 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 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 ***********************************************************************/ diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.h index d5385269d..c0a4c1614 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.h @@ -65,10 +65,14 @@ class StringToken { std::vector split(const std::string& delims) const; std::vector split(const char& delim) const; std::vector split(const char* delim) const; + std::vector split(const std::vector& delim) const; std::vector 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 */