From 6b5ac2e1ef9a1a6cd29bbcb7d17721e3a64e1bb9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 9 Aug 2019 12:45:03 -0600 Subject: [PATCH] add timing graph builder for circuit models --- .../fpga_spice_include/circuit_library.cpp | 166 +++++++++++++++++- .../SRC/fpga_spice_include/circuit_library.h | 19 +- 2 files changed, 178 insertions(+), 7 deletions(-) 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 b552ebd2b..132186cfe 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -33,6 +33,7 @@ * +-------------------------------------+ ***********************************************************************/ +#include #include #include "vtr_assert.h" @@ -58,6 +59,49 @@ CircuitLibrary::circuit_port_range CircuitLibrary::ports(const CircuitModelId& c return vtr::make_range(port_ids_[circuit_model_id].begin(), port_ids_[circuit_model_id].end()); } +/* Create a vector for all the ports whose directionality is input + * This includes all the ports other than whose types are OUPUT or INOUT + */ +std::vector CircuitLibrary::input_ports(const CircuitModelId& circuit_model_id) const { + std::vector input_ports; + for (const auto& port_id : ports(circuit_model_id)) { + /* We skip output ports */ + if ( (SPICE_MODEL_PORT_OUTPUT == port_type(circuit_model_id, port_id)) + || (SPICE_MODEL_PORT_INOUT == port_type(circuit_model_id, port_id)) ) { + continue; + } + input_ports.push_back(port_id); + } + return input_ports; +} + +/* Create a vector for all the ports whose directionality is output + * This includes all the ports whose types are OUPUT or INOUT + */ +std::vector CircuitLibrary::output_ports(const CircuitModelId& circuit_model_id) const { + std::vector output_ports; + for (const auto& port_id : ports(circuit_model_id)) { + /* We skip output ports */ + if ( (SPICE_MODEL_PORT_OUTPUT != port_type(circuit_model_id, port_id)) + && (SPICE_MODEL_PORT_INOUT != port_type(circuit_model_id, port_id)) ) { + continue; + } + output_ports.push_back(port_id); + } + return output_ports; +} + +/* Create a vector for the pin indices, which is bounded by the size of a port + * Start from 0 and end to port_size - 1 + */ +std::vector CircuitLibrary::pins(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const { + std::vector pin_range(port_size(circuit_model_id, circuit_port_id)); + /* Create a vector, with sequentially increasing numbers */ + std::iota(pin_range.begin(), pin_range.end(), 0); + return pin_range; +} + + /************************************************************************ * Public Accessors : Basic data query on Circuit Models ***********************************************************************/ @@ -356,9 +400,9 @@ CircuitModelId CircuitLibrary::add_circuit_model() { edge_ids_.emplace_back(); port_in_edge_ids_.emplace_back(); port_out_edge_ids_.emplace_back(); - edge_src_ports_.emplace_back(); + edge_src_port_ids_.emplace_back(); edge_src_pin_ids_.emplace_back(); - edge_sink_ports_.emplace_back(); + edge_sink_port_ids_.emplace_back(); edge_sink_pin_ids_.emplace_back(); edge_trise_.emplace_back(); edge_tfall_.emplace_back(); @@ -594,6 +638,10 @@ CircuitPortId CircuitLibrary::add_circuit_model_port(const CircuitModelId& circu port_lut_output_masks_[circuit_model_id].emplace_back(); port_sram_orgz_[circuit_model_id].push_back(NUM_CIRCUIT_MODEL_SRAM_ORGZ_TYPES); + /* For timing graphs */ + port_in_edge_ids_[circuit_model_id].emplace_back(); + port_out_edge_ids_[circuit_model_id].emplace_back(); + return circuit_port_id; } @@ -1229,6 +1277,25 @@ void CircuitLibrary::build_circuit_model_links() { /* Build the timing graph for a circuit models*/ void CircuitLibrary::build_circuit_model_timing_graph(const CircuitModelId& circuit_model_id) { + /* Now we start allocating a timing graph + * Add outgoing edges for each input pin of the circuit model + */ + for (auto& from_port_id : input_ports(circuit_model_id)) { + /* Add edges for each input pin */ + for (auto& from_pin_id : pins(circuit_model_id, from_port_id)) { + /* We should walk through output pins here */ + for (auto& to_port_id : output_ports(circuit_model_id)) { + for (auto& to_pin_id : pins(circuit_model_id, to_port_id)) { + /* Skip self-loops */ + if (from_port_id == to_port_id) { + continue; + } + /* Add an edge to bridge the from_pin_id and to_pin_id */ + add_edge(circuit_model_id, from_port_id, from_pin_id, to_port_id, to_pin_id); + } + } + } + } return; } @@ -1236,11 +1303,77 @@ void CircuitLibrary::build_circuit_model_timing_graph(const CircuitModelId& circ void CircuitLibrary::build_timing_graphs() { /* Walk through each circuit model, build timing graph one by one */ for (auto& circuit_model_id : circuit_models()) { + /* Free the timing graph if it already exists, we will rebuild one */ + invalidate_circuit_model_timing_graph(circuit_model_id); build_circuit_model_timing_graph(circuit_model_id); + /* Annotate timing information */ } return; } +/************************************************************************ + * Internal mutators: build timing graphs + ***********************************************************************/ +/* Add an edge between two pins of two ports, and assign an default timing value */ +void CircuitLibrary::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) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + + /* Create an edge in the edge id list */ + CircuitEdgeId edge_id = CircuitEdgeId(edge_ids_[circuit_model_id].size()); + /* Expand the edge list */ + edge_ids_[circuit_model_id].push_back(edge_id); + + /* Initialize other attributes */ + + /* Update the list of incoming edges for to_port */ + /* Resize upon need */ + if (to_pin >= port_in_edge_ids_[circuit_model_id][to_port].size()) { + port_in_edge_ids_[circuit_model_id][to_port].resize(to_pin + 1); + } + port_in_edge_ids_[circuit_model_id][to_port][to_pin] = edge_id; + + /* Update the list of outgoing edges for from_port */ + /* Resize upon need */ + if (from_pin >= port_out_edge_ids_[circuit_model_id][from_port].size()) { + port_out_edge_ids_[circuit_model_id][from_port].resize(from_pin + 1); + } + port_out_edge_ids_[circuit_model_id][from_port][from_pin] = edge_id; + + /* Update source ports and pins of the edge */ + edge_src_port_ids_[circuit_model_id].push_back(from_port); + edge_src_pin_ids_[circuit_model_id].push_back(from_pin); + + /* Update sink ports and pins of the edge */ + edge_sink_port_ids_[circuit_model_id].push_back(to_port); + edge_sink_pin_ids_[circuit_model_id].push_back(to_pin); + + /* Give a default value for timing values */ + edge_trise_[circuit_model_id].push_back(0); + edge_tfall_[circuit_model_id].push_back(0); + + return; +} + +void CircuitLibrary::set_edge_trise(const CircuitModelId& circuit_model_id, const CircuitEdgeId& circuit_edge_id, const float& trise) { + /* validate the circuit_edge_id */ + VTR_ASSERT_SAFE(valid_circuit_edge_id(circuit_model_id, circuit_edge_id)); + + edge_trise_[circuit_model_id][circuit_edge_id] = 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_tfall_[circuit_model_id][circuit_edge_id] = tfall; + return; +} + + /************************************************************************ * Internal mutators: build fast look-ups ***********************************************************************/ @@ -1290,7 +1423,6 @@ void CircuitLibrary::build_circuit_model_port_lookup(const CircuitModelId& circu return; } - /************************************************************************ * Internal invalidators/validators ***********************************************************************/ @@ -1311,6 +1443,12 @@ bool CircuitLibrary::valid_delay_type(const CircuitModelId& circuit_model_id, co return ( size_t(delay_type) < delay_types_[circuit_model_id].size() ) && ( delay_type == delay_types_[circuit_model_id][size_t(delay_type)] ); } +bool CircuitLibrary::valid_circuit_edge_id(const CircuitModelId& circuit_model_id, const CircuitEdgeId& circuit_edge_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return ( size_t(circuit_edge_id) < edge_ids_[circuit_model_id].size() ) && ( circuit_edge_id == edge_ids_[circuit_model_id][circuit_edge_id] ); +} + /* Invalidators */ /* Empty fast lookup for circuit_models*/ void CircuitLibrary::invalidate_circuit_model_lookup() const { @@ -1326,6 +1464,28 @@ void CircuitLibrary::invalidate_circuit_model_port_lookup(const CircuitModelId& return; } +/* Clear all the data structure related to the timing graph */ +void CircuitLibrary::invalidate_circuit_model_timing_graph(const CircuitModelId& circuit_model_id) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + edge_ids_[circuit_model_id].clear(); + + for (const auto& port_id : ports(circuit_model_id)) { + port_in_edge_ids_[circuit_model_id][port_id].clear(); + port_out_edge_ids_[circuit_model_id][port_id].clear(); + } + + edge_src_port_ids_[circuit_model_id].clear(); + edge_src_pin_ids_[circuit_model_id].clear(); + + edge_sink_port_ids_[circuit_model_id].clear(); + edge_sink_pin_ids_[circuit_model_id].clear(); + + edge_trise_[circuit_model_id].clear(); + edge_tfall_[circuit_model_id].clear(); + return; +} + /************************************************************************ * End of file : circuit_library.cpp ***********************************************************************/ 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 612e99ff1..04c220876 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -217,8 +217,12 @@ class CircuitLibrary { }; public: /* Constructors */ public: /* Accessors: aggregates */ - public: /* Public Accessors: Basic data query on Circuit Models*/ circuit_model_range circuit_models() const; + circuit_port_range ports(const CircuitModelId& circuit_model_id) const; + std::vector input_ports(const CircuitModelId& circuit_model_id) const; + std::vector output_ports(const CircuitModelId& circuit_model_id) const; + std::vector pins(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; + public: /* Public Accessors: Basic data query on Circuit Models*/ enum e_spice_model_type circuit_model_type(const CircuitModelId& circuit_model_id) const; std::string circuit_model_name(const CircuitModelId& circuit_model_id) const; std::string circuit_model_prefix(const CircuitModelId& circuit_model_id) const; @@ -233,7 +237,6 @@ class CircuitLibrary { bool is_output_buffered(const CircuitModelId& circuit_model_id) const; bool is_lut_intermediate_buffered(const CircuitModelId& circuit_model_id) const; public: /* Public Accessors: Basic data query on Circuit Ports*/ - circuit_port_range ports(const CircuitModelId& circuit_model_id) const; size_t num_ports(const CircuitModelId& circuit_model_id) const; enum e_spice_model_port_type port_type(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; size_t port_size(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; @@ -419,6 +422,12 @@ class CircuitLibrary { void build_circuit_model_links(); void build_circuit_model_timing_graph(const CircuitModelId& circuit_model_id); void build_timing_graphs(); + public: /* Internal mutators: build timing graphs */ + 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); public: /* Internal mutators: build fast look-ups */ void build_circuit_model_lookup(); void build_circuit_model_port_lookup(const CircuitModelId& circuit_model_id); @@ -427,9 +436,11 @@ class CircuitLibrary { bool valid_circuit_model_id(const CircuitModelId& circuit_model_id) const; bool valid_circuit_port_id(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; bool valid_delay_type(const CircuitModelId& circuit_model_id, const enum spice_model_delay_type& delay_type) const; + bool valid_circuit_edge_id(const CircuitModelId& circuit_model_id, const CircuitEdgeId& circuit_edge_id) const; /* Invalidators */ void invalidate_circuit_model_lookup() const; void invalidate_circuit_model_port_lookup(const CircuitModelId& circuit_model_id) const; + void invalidate_circuit_model_timing_graph(const CircuitModelId& circuit_model_id); private: /* Internal data */ /* Fundamental information */ vtr::vector circuit_model_ids_; @@ -494,9 +505,9 @@ class CircuitLibrary { vtr::vector> edge_ids_; vtr::vector>> port_in_edge_ids_; vtr::vector>> port_out_edge_ids_; - vtr::vector> edge_src_ports_; + vtr::vector> edge_src_port_ids_; vtr::vector> edge_src_pin_ids_; - vtr::vector> edge_sink_ports_; + vtr::vector> edge_sink_port_ids_; vtr::vector> edge_sink_pin_ids_; vtr::vector> edge_trise_; vtr::vector> edge_tfall_;