From 74da4ed51adf702fe2713611b7655aa7a42bb212 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 7 Aug 2019 11:38:45 -0600 Subject: [PATCH 01/18] start creating the class for circuit models --- vpr7_x2p/libarchfpga/CMakeLists.txt | 3 +- .../fpga_spice_include/circuit_library.cpp | 58 ++++ .../SRC/fpga_spice_include/circuit_library.h | 316 ++++++++++++++++++ vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h | 4 + 4 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp create mode 100644 vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h diff --git a/vpr7_x2p/libarchfpga/CMakeLists.txt b/vpr7_x2p/libarchfpga/CMakeLists.txt index 714349130..528310c1d 100644 --- a/vpr7_x2p/libarchfpga/CMakeLists.txt +++ b/vpr7_x2p/libarchfpga/CMakeLists.txt @@ -35,11 +35,12 @@ set_target_properties(libarchfpga PROPERTIES PREFIX "") #Avoid extra 'lib' prefi # Specify dependency target_link_libraries(libarchfpga + libvtrutil libpcre libprinthandler) add_executable(read_arch ${EXEC_SOURCES}) -target_link_libraries(read_arch libarchfpga) +target_link_libraries(read_arch libarchfpga libvtrutil) # install: TO BE TESTED diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp new file mode 100644 index 000000000..d873d716a --- /dev/null +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -0,0 +1,58 @@ +/********************************************************** + * MIT License + * + * Copyright (c) 2018 LNIS - The University of Utah + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ***********************************************************************/ + +/************************************************************************ + * Filename: circuit_library.cpp + * Created by: Xifan Tang + * Change history: + * +-------------------------------------+ + * | Date | Author | Notes + * +-------------------------------------+ + * | 2019/08/07 | Xifan Tang | Created + * +-------------------------------------+ + ***********************************************************************/ + +#include "circuit_library.h" + +/************************************************************************ + * Member functions for class CircuitLibrary + ***********************************************************************/ + +/************************************************************************ + * Constructors + ***********************************************************************/ + +/************************************************************************ + * Accessors + ***********************************************************************/ + +/* Aggregates */ +CircuitLibrary::circuit_model_range CircuitLibrary::circuit_models() const { + return vtr::make_range(circuit_model_ids_.begin(), circuit_model_ids_.end()); +} + + +/************************************************************************ + * 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 new file mode 100644 index 000000000..3c4a5aebb --- /dev/null +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -0,0 +1,316 @@ +/********************************************************** + * MIT License + * + * Copyright (c) 2018 LNIS - The University of Utah + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ***********************************************************************/ + +/************************************************************************ + * Filename: circuit_library.h + * Created by: Xifan Tang + * Change history: + * +-------------------------------------+ + * | Date | Author | Notes + * +-------------------------------------+ + * | 2019/08/06 | Xifan Tang | Created + * +-------------------------------------+ + ***********************************************************************/ + +/* IMPORTANT: + * The following preprocessing flags are added to + * avoid compilation error when this headers are included in more than 1 times + */ +#ifndef CIRCUIT_LIBRARY_H +#define CIRCUIT_LIBRARY_H + +/* + * Notes in include header files in a head file + * Only include the neccessary header files + * that is required by the data types in the function/class declarations! + */ +/* Header files should be included in a sequence */ +/* Standard header files required go first */ +#include "vtr_strong_id.h" + +#include "vtr_vector.h" +#include "vtr_range.h" + +#include "spice_types.h" + +/************************************************************************ + * Create strong id for Circuit Models/Ports to avoid illegal type casting + ***********************************************************************/ +struct circuit_model_id_tag; +struct circuit_port_id_tag; +struct circuit_edge_id_tag; + +typedef vtr::StrongId CircuitModelId; +typedef vtr::StrongId CircuitPortId; +typedef vtr::StrongId CircuitEdgeId; + +/************************************************************************ + * The class CircuitLibrary is a critical data structure for OpenFPGA + * It stores all the circuit-level details from XML architecture file + * + * It includes the following data: + * + * ------ Fundamental Information ----- + * 1. circuit_model_ids_ : unique identifier to find a circuit model + * Use a strong id for search, to avoid illegal type casting + * 2. circuit_model_types_: types of the circuit model, see details in the definition of enum e_spice_model_type + * 3. circuit_model_names_: unique names for each circuit models. + * It should be the same as user-defined Verilog modules, if it is not auto-generated + * 4. circuit_model_prefix_: the prefix of a circuit model when it is instanciated + * 5. verilog_netlist_: specified path and file name of Verilog netlist if a circuit model is not auto-generated + * 6. spice_netlist_: specified path and file name of SPICE netlist if a circuit model is not auto-generated + * 7. is_default_: indicate if the circuit model is the default one among all those in the same type + * + * ------ Verilog generation options ----- + * 1. dump_structural_verilog_: if Verilog generator will output structural Verilog syntax for the circuit model + * 2. dump_explicit_port_map_: if Verilog generator will use explicit port mapping when instanciate the circuit model + * + * ------ Design technology information ----- + * 1. design_tech_: the design technology [cmos|rram] for each circuit model + * 2. power_gated_: specify if the circuit model is power-gated (contain a input to turn on/off VDD and GND) + * + * ------ Buffer existence ----- + * Use vectors to simplify the defition of buffer existence: + * index (low=0 to high) represents INPUT, OUTPUT, LUT_INPUT_BUF, LUT_INPUT_INV, LUT_INTER_BUFFER + * 1. buffer_existence_: specify if this circuit model has an buffer + * 2. buffer_circuit_model_name_: specify the name of circuit model for the buffer + * 3. buffer_circuit_model_id_: specify the id of circuit model for the buffer + * + * ------ Pass-gate-related parameters ------ + * 1. pass_gate_logic_circuit_model_name_: specify the name of circuit model for the pass gate logic + * 2. pass_gate_logic_circuit_model_id_: specify the id of circuit model for the pass gate logic + * + * ------ Port information ------ + * 1. port_types_: types of ports belonging to a circuit model + * 2. port_sizes_: width of ports belonging to a circuit model + * 3. port_prefix_: prefix of a port when instance of a circuit model + * 4. port_lib_names_: port name in the standard cell library, only used when explicit_port_mapping is enabled + * 5. port_inv_prefix_: the prefix to be added for the inverted port. This is mainly used by SRAM ports, which have an coupled inverterd port + * 6. port_is_mode_select: specify if this port is used to select operating modes of the circuit model + * 7. port_is_global: specify if this port is a global signal shared by other circuit model + * 8. port_is_reset: specify if this port is a reset signal which needs special pulse widths in testbenches + * 9. port_is_set: specify if this port is a set signal which needs special pulse widths in testbenches + * 10. port_is_config_enable: specify if this port is a config_enable signal which needs special pulse widths in testbenches + * 11. port_is_prog: specify if this port is for FPGA programming use which needs special pulse widths in testbenches + * 12. port_circuit_model_name: the name of circuit model linked to the port + * 13. port_circuit_model_ids_: the Id of circuit model linked to the port + * 14. port_inv_circuit_model_names_: the name of inverter circuit model linked to the port + * 15. port_inv_circuit_model_ids_: the Id of inverter circuit model linked to the port + * 16. port_tri_state_map_: only applicable to inputs of LUTs, the tri-state map applied to each pin of this port + * 17. port_lut_frac_level_: only applicable to outputs of LUTs, indicate which level of outputs inside LUT multiplexing structure will be used + * 18. port_lut_output_mask_: only applicable to outputs of LUTs, indicate which output at an internal level of LUT multiplexing structure will be used + * 19. port_sram_orgz_: only applicable to SRAM ports, indicate how the SRAMs will be organized, either memory decoders or scan-chains + * + * ------ Delay information ------ + * 1. delay_types_: type of pin-to-pin delay, either rising_edge of falling_edge + * 2. delay_in_port_names_: name of input ports that the pin-to-pin delay is linked to + * 3. delay_in_port_names_: name of output ports that the pin-to-pin delay is linked to + * 4. delay_values_: delay values of the pin-to-pin delay + * + * ------ Timing graph information: TODO: consider using tatum? ------ + * Timing graph is allocated when delay information is made + * 1. edge_ids_ : ids of edges in the timing graph + * 2. port_in_edge_ids_: ids of input edges for each pin of a circuit port + * 3. port_out_edge_ids_: ids of output edges for each pin of a circuit port + * 4. edge_src_port_ids_: ids of source ports that each edge is connected to + * 5. edge_src_pin_ids_: ids of source pin that each edge is connected to + * 6. edge_sink_port_ids_: ids of sink ports that each edge is connected to + * 7. edge_sink_pin_ids_: ids of sink pin that each edge is connected to + * 8. edge_trise_: rising delay of the edge + * 9. edge_tfall_: falling delay of the edge + * + * ------ Buffer/Inverter-related parameters ------ + * Note: only applicable to circuit models whose type is buffer or inverter + * 1. buffer_types_: type of the buffer, either buffer or inverter + * 2. buffer_location_maps_: location of the buffer, only applicable to LUTs + * 3. buffer_sizes_: size of buffer (transistor size for the first stage) + * 4. buffer_is_tapered_: specify if this buffer has multiple stages + * 5. buffer_num_levels: specify the number of levels of this buffer (if this is defined as multi-level buffer) + * 6. buffer_f_per_stage: specify the driving strength of the buffer by stage + * + * ------ Pass-gate-logic-related parameters ------ + * Note: only applicable to circuit models whose type is pass-gate-logic + * 1. pass_gate_logic_types_: types of the pass-gate-logic, either transmission-gate or pass-transistor + * 2. pass_gate_logic_nmos_sizes_: size of NMOS transistor in the pass-gate-logic + * 3. pass_gate_logic_pmos_sizes_: size of PMOS transistor in the pass-gate-logic, only applicable for transmission-gates + * + * ------ Multiplexer-related parameters ------ + * Note: only applicable to circuit models whose type is MUX + * 1. mux_structure_: specify the structure of a multiplexer, one-level, multi-level or tree-like + * 2. mux_num_levels_: specify the number of levels for a multiplexer + * 3. mux_add_const_input_: specify if this multiplexer has a constant input + * 4. mux_const_input_values_: specify the value of the constant input for this multiplexer (valid only when mux_add_const_input is true) + * 5. mux_use_local_encoder_: specify if the mux as a local encoder between SRAMs and multiplexing structure + * 6. mux_advanced_rram_design_: specify if the multiplexer will use advanced RRAM circuit design topology + * + * ------ LUT-related parameters ------ + * Note: only applicable to circuit models whose type is LUT + * 1. lut_is_fracturable_: specify if this LUT is built with fracturable structure + * + * ------ RRAM-related parameters ------ + * Note: only applicable to circuit models whose design technology is RRAM + * 1. rlrs: RRAM resistance in Low-Resistance State (LRS) + * 2. rhrs: RRAM resistance in High-Resistance State (HRS) + * The following transistor sizes are applicable for 4T1R programming structures + * 3. wprog_set_nmos: size of n-type programming transistor used to set a RRAM + * 4. wprog_set_pmos: size of p-type programming transistor used to set a RRAM + * 5. wprog_reset_nmos: size of n-type programming transistor used to reset a RRAM + * 6. wprog_reset_pmos: size of p-type programming transistor used to reset a RRAM + * + * ------ Metal wire-related parameters ------ + * Note: only applicable to circuit models whose type is wires or channel wires + * 1. wire_types_: types of the metal wire for the circuit_model + * 2. wire_res_val_: resistance value of the metal wire for the circuit model + * 3. wire_cap_val_: capacitance value of the metal wire for the circuit model + * 4. wire_num_levels_: number of levels of the metal wire model for the circuit model + ***********************************************************************/ +class CircuitLibrary { + public: /* Types */ + typedef vtr::vector::const_iterator circuit_model_iterator; + typedef vtr::vector::const_iterator circuit_port_iterator; + typedef vtr::vector::const_iterator circuit_edge_iterator; + /* Create range */ + typedef vtr::Range circuit_model_range; + typedef vtr::Range circuit_port_range; + typedef vtr::Range circuit_edge_range; + /* local enumeration for buffer existence */ + enum e_buffer_type: unsigned char{ + INPUT = 0, OUTPUT, LUT_INPUT_BUFFER, LUT_INPUT_INV, LUT_INTER_BUFFER, NUM_BUFFER_TYPE /* Last one is a counter */ + }; + public: /* Constructors */ + public: /* Accessors */ + /* Aggregates */ + circuit_model_range circuit_models() const; + public: /* Mutators */ + private: /* Internal functions */ + private: /* Internal data */ + /* Fundamental information */ + vtr::vector circuit_model_ids_; + vtr::vector circuit_model_types_; + vtr::vector circuit_model_names_; + vtr::vector circuit_model_prefix_; + vtr::vector verilog_netlists_; + vtr::vector spice_netlists_; + vtr::vector is_default_; + + /* Verilog generator options */ + vtr::vector dump_structural_verilog_; + vtr::vector dump_explicit_port_map_; + + /* Design technology information */ + vtr::vector design_tech_; + vtr::vector power_gated_; + + /* Buffer existence */ + vtr::vector> buffer_existence_; + vtr::vector> buffer_circuit_model_name_; + vtr::vector> buffer_circuit_model_id_; + + /* Pass-gate-related parameters */ + vtr::vector pass_gate_logic_circuit_model_name_; + vtr::vector pass_gate_logic_circuit_model_id_; + + /* Port information */ + vtr::vector> port_types_; + vtr::vector> port_sizes_; + vtr::vector> port_prefix_; + vtr::vector> port_lib_names_; + vtr::vector> port_inv_prefix_; + vtr::vector> port_is_mode_select_; + vtr::vector> port_is_global_; + vtr::vector> port_is_reset_; + vtr::vector> port_is_set_; + vtr::vector> port_is_config_enable_; + vtr::vector> port_is_prog_; + vtr::vector> port_circuit_model_names_; + vtr::vector> port_circuit_model_ids_; + vtr::vector> port_inv_circuit_model_names_; + vtr::vector> port_inv_circuit_model_ids_; + vtr::vector> port_tri_state_map_; + vtr::vector> port_lut_frac_level_; + vtr::vector>> port_lut_output_mask_; + vtr::vector> port_sram_orgz_; + + /* Timing graphs */ + 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_pin_ids_; + vtr::vector> edge_sink_ports_; + vtr::vector> edge_sink_pin_ids_; + vtr::vector> edge_trise_; + vtr::vector> edge_tfall_; + + /* Delay information */ + vtr::vector> delay_types_; + vtr::vector> delay_in_port_names_; + vtr::vector> delay_out_port_names_; + vtr::vector> delay_values_; + + /* Buffer/Inverter-related parameters */ + vtr::vector buffer_types_; + vtr::vector buffer_location_maps_; + vtr::vector buffer_sizes_; + vtr::vector buffer_is_tapered_; + vtr::vector buffer_num_levels_; + vtr::vector buffer_f_per_stage_; + + /* Pass-gate-related parameters */ + vtr::vector pass_gate_logic_types_; + vtr::vector pass_gate_logic_nmos_sizes_; + vtr::vector pass_gate_logic_pmos_sizes_; + + /* Multiplexer-related parameters */ + vtr::vector mux_structure_; + vtr::vector mux_num_levels_; + vtr::vector mux_add_const_input_; + vtr::vector mux_const_input_values_; + vtr::vector mux_use_local_encoder_; + vtr::vector mux_advanced_rram_design_; + + /* LUT-related parameters */ + vtr::vector lut_is_fracturable_; + + /* RRAM-related design technology information */ + vtr::vector rlrs_; + vtr::vector rhrs_; + vtr::vector wprog_set_nmos_; + vtr::vector wprog_set_pmos_; + vtr::vector wprog_reset_nmos_; + vtr::vector wprog_reset_pmos_; + + /* Wire parameters */ + vtr::vector wire_types_; + vtr::vector wire_res_val_; + vtr::vector wire_cap_val_; + vtr::vector wire_num_levels_; + +}; + +#endif + +/************************************************************************ + * End of file : circuit_library.cpp + ***********************************************************************/ diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h index 49c1d78f4..6dd2437fb 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h @@ -411,3 +411,7 @@ class DeviceRRGSB { #endif +/************************************************************************ + * End of file : rr_blocks.h + ***********************************************************************/ + From 38962c4607f19f6052d551721ac8db8afa89f4e4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 7 Aug 2019 15:45:27 -0600 Subject: [PATCH 02/18] adding member functions for circuit library --- libs/libvtrutil/src/vtr_geometry.h | 1 + libs/libvtrutil/src/vtr_geometry.tpp | 6 + .../fpga_spice_include/circuit_library.cpp | 160 +++++++++++++++++- .../SRC/fpga_spice_include/circuit_library.h | 65 ++++--- .../SRC/fpga_spice_include/spice_types.h | 18 +- 5 files changed, 221 insertions(+), 29 deletions(-) diff --git a/libs/libvtrutil/src/vtr_geometry.h b/libs/libvtrutil/src/vtr_geometry.h index 2ff45e6d0..e19dff1c0 100644 --- a/libs/libvtrutil/src/vtr_geometry.h +++ b/libs/libvtrutil/src/vtr_geometry.h @@ -49,6 +49,7 @@ template class Point { public: //Constructors Point(T x_val, T y_val); + Point(); public: //Accessors diff --git a/libs/libvtrutil/src/vtr_geometry.tpp b/libs/libvtrutil/src/vtr_geometry.tpp index 658f564fe..b06f29189 100644 --- a/libs/libvtrutil/src/vtr_geometry.tpp +++ b/libs/libvtrutil/src/vtr_geometry.tpp @@ -10,6 +10,12 @@ namespace vtr { //pass } + template + Point::Point() { + //pass + } + + template T Point::x() const { return x_; 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 d873d716a..e192cb6af 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,8 @@ * +-------------------------------------+ ***********************************************************************/ +#include "vtr_assert.h" + #include "circuit_library.h" /************************************************************************ @@ -44,15 +46,167 @@ ***********************************************************************/ /************************************************************************ - * Accessors + * Accessors : aggregates ***********************************************************************/ - -/* Aggregates */ CircuitLibrary::circuit_model_range CircuitLibrary::circuit_models() const { return vtr::make_range(circuit_model_ids_.begin(), circuit_model_ids_.end()); } +/************************************************************************ + * Accessors : Methods to find circuit model + ***********************************************************************/ +/* Find a circuit model by a given name and return its id */ +CircuitModelId CircuitLibrary::get_circuit_model_id_by_name(const std::string& name) const { + CircuitModelId ret = CIRCUIT_MODEL_OPEN_ID; + size_t num_found = 0; + for (circuit_model_string_iterator it = circuit_model_names_.begin(); + it != circuit_model_names_.end(); + it++) { + /* Bypass unmatched names */ + if ( 0 != name.compare(*it) ) { + continue; + } + /* Find one and record it + * FIXME: I feel that we may have a better way in getting the CircuitModelId + */ + ret = CircuitModelId(it - circuit_model_names_.begin()); + num_found++; + } + VTR_ASSERT((0 == num_found) || (1 == num_found)); + return ret; +} + +/* Get the CircuitModelId of a default circuit model with a given type */ +CircuitModelId CircuitLibrary::get_default_circuit_model_id(const enum e_spice_model_type& type) const { + /* Default circuit model id is the first element by type in the fast look-up */ + return circuit_model_lookup_[size_t(type)].front(); +} + +/************************************************************************ + * Mutators + ***********************************************************************/ +/* Add a circuit model to the library, and return it Id */ +CircuitModelId CircuitLibrary::add_circuit_model() { + /* Create a new id*/ + CircuitModelId circuit_model_id = CircuitModelId(circuit_model_ids_.size()); + /* Update the id list */ + circuit_model_ids_.push_back(circuit_model_id); + + /* Initialize other attributes */ + /* Fundamental information */ + circuit_model_types_.push_back(NUM_CIRCUIT_MODEL_TYPES); + circuit_model_names_.emplace_back(); + circuit_model_prefix_.emplace_back(); + circuit_model_verilog_netlists_.emplace_back(); + circuit_model_spice_netlists_.emplace_back(); + circuit_model_is_default_.push_back(false); + + /* Verilog generator options */ + dump_structural_verilog_.push_back(false); + dump_explicit_port_map_.push_back(false); + + /* Design technology information */ + design_tech_.push_back(NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES); + power_gated_.push_back(false); + + /* Buffer existence */ + buffer_existence_.emplace_back(); + buffer_circuit_model_names_.emplace_back(); + buffer_circuit_model_ids_.emplace_back(); + + /* Pass-gate-related parameters */ + pass_gate_logic_circuit_model_names_.emplace_back(); + pass_gate_logic_circuit_model_ids_.emplace_back(); + + /* Port information */ + port_types_.emplace_back(); + port_sizes_.emplace_back(); + port_prefix_.emplace_back(); + port_lib_names_.emplace_back(); + port_is_mode_select_.emplace_back(); + port_is_global_.emplace_back(); + port_is_reset_.emplace_back(); + port_is_set_.emplace_back(); + port_is_config_enable_.emplace_back(); + port_is_prog_.emplace_back(); + port_circuit_model_names_.emplace_back(); + port_circuit_model_ids_.emplace_back(); + port_inv_circuit_model_names_.emplace_back(); + port_inv_circuit_model_ids_.emplace_back(); + port_tri_state_maps_.emplace_back(); + port_lut_frac_level_.emplace_back(); + port_lut_output_masks_.emplace_back(); + port_sram_orgz_.emplace_back(); + + /* Timing graphs */ + edge_ids_.emplace_back(); + port_in_edge_ids_.emplace_back(); + port_out_edge_ids_.emplace_back(); + edge_src_ports_.emplace_back(); + edge_src_pin_ids_.emplace_back(); + edge_sink_ports_.emplace_back(); + edge_sink_pin_ids_.emplace_back(); + edge_trise_.emplace_back(); + edge_tfall_.emplace_back(); + + /* Delay information */ + delay_types_.emplace_back(); + delay_in_port_names_.emplace_back(); + delay_out_port_names_.emplace_back(); + delay_values_.emplace_back(); + + /* Buffer/Inverter-related parameters */ + buffer_types_.push_back(NUM_CIRCUIT_MODEL_BUF_TYPES); + buffer_location_maps_.emplace_back(); + buffer_sizes_.push_back(-1); + buffer_is_tapered_.push_back(false); + buffer_num_levels_.push_back(-1); + buffer_f_per_stage_.push_back(-1); + + /* Pass-gate-related parameters */ + pass_gate_logic_types_.push_back(NUM_CIRCUIT_MODEL_PASS_GATE_TYPES); + pass_gate_logic_nmos_sizes_.push_back(-1); + pass_gate_logic_pmos_sizes_.push_back(-1); + + /* Multiplexer-related parameters */ + mux_structure_.push_back(NUM_CIRCUIT_MODEL_STRUCTURE_TYPES); + mux_num_levels_.push_back(-1); + mux_add_const_input_.push_back(false); + mux_const_input_values_.push_back(-1); + mux_use_local_encoder_.push_back(false); + mux_advanced_rram_design_.push_back(false); + + /* LUT-related parameters */ + lut_is_fracturable_.push_back(false); + + /* RRAM-related design technology information */ + rram_res_.emplace_back(); + wprog_set_.emplace_back(); + wprog_reset_.emplace_back(); + + /* Wire parameters */ + wire_types_.push_back(NUM_WIRE_MODEL_TYPES); + wire_rc_.emplace_back(); + wire_num_levels_.push_back(-1); + + /* Invalidate fast look-up*/ + + + return circuit_model_id; +} + +/************************************************************************ + * Internal Mutators + ***********************************************************************/ +/* Link the inv_circuit_model_id for each port of a circuit model. + * We search the inv_circuit_model_name in the CircuitLibrary and + * configure the port inv_circuit_model_id + */ +void CircuitLibrary::set_circuit_model_port_inv_circuit_model(const CircuitModelId& circuit_model_id) { + 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 3c4a5aebb..bedfabb7f 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -48,6 +48,7 @@ /* Header files should be included in a sequence */ /* Standard header files required go first */ #include "vtr_strong_id.h" +#include "vtr_geometry.h" #include "vtr_vector.h" #include "vtr_range.h" @@ -65,6 +66,12 @@ typedef vtr::StrongId CircuitModelId; typedef vtr::StrongId CircuitPortId; typedef vtr::StrongId CircuitEdgeId; + +/* Alias for open ids */ +#define CIRCUIT_MODEL_OPEN_ID CircuitModelId(-1) +#define CIRCUIT_PORT_OPEN_ID CircuitPortId(-1) +#define CIRCUIT_EDGE_OPEN_ID CircuitEdgeId(-1) + /************************************************************************ * The class CircuitLibrary is a critical data structure for OpenFPGA * It stores all the circuit-level details from XML architecture file @@ -82,6 +89,12 @@ typedef vtr::StrongId CircuitEdgeId; * 6. spice_netlist_: specified path and file name of SPICE netlist if a circuit model is not auto-generated * 7. is_default_: indicate if the circuit model is the default one among all those in the same type * + * ------ Fast look-ups----- + * 1. circuit_model_lookup_: A multi-dimension vector to provide fast look-up on circuit models for users + * It classifies CircuitModelIds by their type and set the default model in the first element for each type. + * 2. circuit_model_port_lookup_: A multi-dimension vector to provide fast look-up on ports of circuit models for users + * It classifies Ports by their types + * * ------ Verilog generation options ----- * 1. dump_structural_verilog_: if Verilog generator will output structural Verilog syntax for the circuit model * 2. dump_explicit_port_map_: if Verilog generator will use explicit port mapping when instanciate the circuit model @@ -188,6 +201,7 @@ typedef vtr::StrongId CircuitEdgeId; class CircuitLibrary { public: /* Types */ typedef vtr::vector::const_iterator circuit_model_iterator; + typedef vtr::vector::const_iterator circuit_model_string_iterator; typedef vtr::vector::const_iterator circuit_port_iterator; typedef vtr::vector::const_iterator circuit_edge_iterator; /* Create range */ @@ -199,20 +213,35 @@ class CircuitLibrary { INPUT = 0, OUTPUT, LUT_INPUT_BUFFER, LUT_INPUT_INV, LUT_INTER_BUFFER, NUM_BUFFER_TYPE /* Last one is a counter */ }; public: /* Constructors */ - public: /* Accessors */ - /* Aggregates */ + public: /* Accessors: aggregates */ circuit_model_range circuit_models() const; + public: /* Accessors: Basic data query */ + public: /* Accessors: Methods to find circuit model */ + CircuitModelId get_circuit_model_id_by_name(const std::string& name) const ; + CircuitModelId get_default_circuit_model_id(const enum e_spice_model_type& type) const; public: /* Mutators */ - private: /* Internal functions */ + CircuitModelId add_circuit_model(); + public: /* Internal mutators */ + void set_circuit_model_port_inv_circuit_model(const CircuitModelId& circuit_model_id); + private: /* Internal validators */ private: /* Internal data */ /* Fundamental information */ vtr::vector circuit_model_ids_; vtr::vector circuit_model_types_; vtr::vector circuit_model_names_; vtr::vector circuit_model_prefix_; - vtr::vector verilog_netlists_; - vtr::vector spice_netlists_; - vtr::vector is_default_; + vtr::vector circuit_model_verilog_netlists_; + vtr::vector circuit_model_spice_netlists_; + vtr::vector circuit_model_is_default_; + + /* fast look-up for circuit models to categorize by types + * [type][num_ids] + * Important: we force the default circuit model in the first element for each type + */ + typedef std::vector> CircuitModelLookup; + mutable CircuitModelLookup circuit_model_lookup_; /* [circuit_model_type][circuit_model_ids] */ + typedef std::vector>>> CircuitModelPortLookup; + mutable CircuitModelPortLookup circuit_model_port_lookup_; /* [circuit_model_type][circuit_model_id][port_type][port_ids] */ /* Verilog generator options */ vtr::vector dump_structural_verilog_; @@ -224,12 +253,12 @@ class CircuitLibrary { /* Buffer existence */ vtr::vector> buffer_existence_; - vtr::vector> buffer_circuit_model_name_; - vtr::vector> buffer_circuit_model_id_; + vtr::vector> buffer_circuit_model_names_; + vtr::vector> buffer_circuit_model_ids_; /* Pass-gate-related parameters */ - vtr::vector pass_gate_logic_circuit_model_name_; - vtr::vector pass_gate_logic_circuit_model_id_; + vtr::vector pass_gate_logic_circuit_model_names_; + vtr::vector pass_gate_logic_circuit_model_ids_; /* Port information */ vtr::vector> port_types_; @@ -247,9 +276,9 @@ class CircuitLibrary { vtr::vector> port_circuit_model_ids_; vtr::vector> port_inv_circuit_model_names_; vtr::vector> port_inv_circuit_model_ids_; - vtr::vector> port_tri_state_map_; + vtr::vector> port_tri_state_maps_; vtr::vector> port_lut_frac_level_; - vtr::vector>> port_lut_output_mask_; + vtr::vector>> port_lut_output_masks_; vtr::vector> port_sram_orgz_; /* Timing graphs */ @@ -294,17 +323,13 @@ class CircuitLibrary { vtr::vector lut_is_fracturable_; /* RRAM-related design technology information */ - vtr::vector rlrs_; - vtr::vector rhrs_; - vtr::vector wprog_set_nmos_; - vtr::vector wprog_set_pmos_; - vtr::vector wprog_reset_nmos_; - vtr::vector wprog_reset_pmos_; + vtr::vector> rram_res_; /* x => R_LRS, y => R_HRS */ + vtr::vector> wprog_set_; /* x => wprog_set_nmos, y=> wprog_set_pmos */ + vtr::vector> wprog_reset_; /* x => wprog_reset_nmos, y=> wprog_reset_pmos */ /* Wire parameters */ vtr::vector wire_types_; - vtr::vector wire_res_val_; - vtr::vector wire_cap_val_; + vtr::vector> wire_rc_; /* x => wire_res_val, y=> wire_cap_val */ vtr::vector wire_num_levels_; }; diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h index 722816380..d3ad32ae7 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h @@ -28,29 +28,34 @@ enum e_spice_model_type { SPICE_MODEL_IOPAD, SPICE_MODEL_INVBUF, SPICE_MODEL_PASSGATE, - SPICE_MODEL_GATE + SPICE_MODEL_GATE, + NUM_CIRCUIT_MODEL_TYPES }; enum e_spice_model_design_tech { SPICE_MODEL_DESIGN_CMOS, - SPICE_MODEL_DESIGN_RRAM + SPICE_MODEL_DESIGN_RRAM, + NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES }; enum e_spice_model_structure { SPICE_MODEL_STRUCTURE_TREE, SPICE_MODEL_STRUCTURE_ONELEVEL, SPICE_MODEL_STRUCTURE_MULTILEVEL, - SPICE_MODEL_STRUCTURE_CROSSBAR + SPICE_MODEL_STRUCTURE_CROSSBAR, + NUM_CIRCUIT_MODEL_STRUCTURE_TYPES }; enum e_spice_model_buffer_type { SPICE_MODEL_BUF_INV, - SPICE_MODEL_BUF_BUF + SPICE_MODEL_BUF_BUF, + NUM_CIRCUIT_MODEL_BUF_TYPES }; enum e_spice_model_pass_gate_logic_type { SPICE_MODEL_PASS_GATE_TRANSMISSION, - SPICE_MODEL_PASS_GATE_TRANSISTOR + SPICE_MODEL_PASS_GATE_TRANSISTOR, + NUM_CIRCUIT_MODEL_PASS_GATE_TYPES }; enum e_spice_model_gate_type { @@ -69,7 +74,8 @@ enum e_spice_trans_type { enum e_wire_model_type { WIRE_MODEL_PIE, - WIRE_MODEL_T + WIRE_MODEL_T, + NUM_WIRE_MODEL_TYPES, }; enum e_spice_model_port_type { From ed4642a23f7e06b2538db11c234b431638a9a763 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 7 Aug 2019 17:12:05 -0600 Subject: [PATCH 03/18] adding basic mutators --- .../fpga_spice_include/circuit_library.cpp | 229 +++++++++++++++++- .../SRC/fpga_spice_include/circuit_library.h | 45 +++- 2 files changed, 259 insertions(+), 15 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 e192cb6af..2a6e32756 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,8 @@ * +-------------------------------------+ ***********************************************************************/ +#include + #include "vtr_assert.h" #include "circuit_library.h" @@ -46,7 +48,7 @@ ***********************************************************************/ /************************************************************************ - * Accessors : aggregates + * Public Accessors : aggregates ***********************************************************************/ CircuitLibrary::circuit_model_range CircuitLibrary::circuit_models() const { return vtr::make_range(circuit_model_ids_.begin(), circuit_model_ids_.end()); @@ -54,7 +56,7 @@ CircuitLibrary::circuit_model_range CircuitLibrary::circuit_models() const { /************************************************************************ - * Accessors : Methods to find circuit model + * Public Accessors : Methods to find circuit model ***********************************************************************/ /* Find a circuit model by a given name and return its id */ CircuitModelId CircuitLibrary::get_circuit_model_id_by_name(const std::string& name) const { @@ -84,7 +86,7 @@ CircuitModelId CircuitLibrary::get_default_circuit_model_id(const enum e_spice_m } /************************************************************************ - * Mutators + * Public Mutators ***********************************************************************/ /* Add a circuit model to the library, and return it Id */ CircuitModelId CircuitLibrary::add_circuit_model() { @@ -107,7 +109,7 @@ CircuitModelId CircuitLibrary::add_circuit_model() { dump_explicit_port_map_.push_back(false); /* Design technology information */ - design_tech_.push_back(NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES); + design_tech_types_.push_back(NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES); power_gated_.push_back(false); /* Buffer existence */ @@ -190,23 +192,240 @@ CircuitModelId CircuitLibrary::add_circuit_model() { wire_rc_.emplace_back(); wire_num_levels_.push_back(-1); - /* Invalidate fast look-up*/ + /* Update circuit port fast look-up */ + circuit_model_port_lookup_.emplace_back(); + /* Invalidate fast look-up*/ + invalidate_circuit_model_lookup(); return circuit_model_id; } +/* Set the type of a Circuit Model */ +void CircuitLibrary::set_circuit_model_type(const CircuitModelId& circuit_model_id, + const enum e_spice_model_type& type) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + circuit_model_types_[circuit_model_id] = type; + return; +} + +/* Set the name of a Circuit Model */ +void CircuitLibrary::set_circuit_model_name(const CircuitModelId& circuit_model_id, const std::string& name) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + circuit_model_names_[circuit_model_id] = name; + return; +} + +/* Set the prefix of a Circuit Model */ +void CircuitLibrary::set_circuit_model_prefix(const CircuitModelId& circuit_model_id, const std::string& prefix) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + circuit_model_prefix_[circuit_model_id] = prefix; + return; +} + +/* Set the verilog_netlist of a Circuit Model */ +void CircuitLibrary::set_circuit_model_verilog_netlist(const CircuitModelId& circuit_model_id, const std::string& verilog_netlist) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + circuit_model_verilog_netlists_[circuit_model_id] = verilog_netlist; + return; +} + +/* Set the spice_netlist of a Circuit Model */ +void CircuitLibrary::set_circuit_model_spice_netlist(const CircuitModelId& circuit_model_id, const std::string& spice_netlist) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + circuit_model_spice_netlists_[circuit_model_id] = spice_netlist; + return; +} + +/* Set the is_default of a Circuit Model */ +void CircuitLibrary::set_circuit_model_is_default(const CircuitModelId& circuit_model_id, const bool& is_default) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + circuit_model_is_default_[circuit_model_id] = is_default; + return; +} + +/* Set the dump_structural_verilog of a Circuit Model */ +void CircuitLibrary::set_circuit_model_dump_structural_verilog(const CircuitModelId& circuit_model_id, const bool& dump_structural_verilog) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + dump_structural_verilog_[circuit_model_id] = dump_structural_verilog; + return; +} + +/* Set the dump_explicit_port_map of a Circuit Model */ +void CircuitLibrary::set_circuit_model_dump_explicit_port_map(const CircuitModelId& circuit_model_id, const bool& dump_explicit_port_map) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + dump_explicit_port_map_[circuit_model_id] = dump_explicit_port_map; + return; +} + +/* Set the type of design technology of a Circuit Model */ +void CircuitLibrary::set_circuit_model_design_tech_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_design_tech& design_tech_type) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + design_tech_types_[circuit_model_id] = design_tech_type; + return; +} + +/* Set the power-gated flag of a Circuit Model */ +void CircuitLibrary::set_circuit_model_power_gated(const CircuitModelId& circuit_model_id, const bool& power_gated) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + power_gated_[circuit_model_id] = power_gated; + return; +} + +/* Set input buffer information for the circuit model */ +void CircuitLibrary::set_circuit_model_input_buffer(const CircuitModelId& circuit_model_id, + const bool& existence, const std::string& circuit_model_name) { + /* Just call the base function and give the proper type */ + set_circuit_model_buffer(circuit_model_id, INPUT, existence, circuit_model_name); + return; +} + +/* Set output buffer information for the circuit model */ +void CircuitLibrary::set_circuit_model_output_buffer(const CircuitModelId& circuit_model_id, + const bool& existence, const std::string& circuit_model_name) { + /* Just call the base function and give the proper type */ + set_circuit_model_buffer(circuit_model_id, OUTPUT, existence, circuit_model_name); + return; +} + +/* Set input buffer information for the circuit model, only applicable to LUTs! */ +void CircuitLibrary::set_circuit_model_lut_input_buffer(const CircuitModelId& circuit_model_id, + const bool& existence, const std::string& circuit_model_name) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Make sure the circuit model is a LUT! */ + VTR_ASSERT_SAFE(SPICE_MODEL_LUT == circuit_model_types_[circuit_model_id]); + /* Just call the base function and give the proper type */ + set_circuit_model_buffer(circuit_model_id, LUT_INPUT_BUFFER, existence, circuit_model_name); + return; +} + +/* Set input inverter information for the circuit model, only applicable to LUTs! */ +void CircuitLibrary::set_circuit_model_lut_input_inverter(const CircuitModelId& circuit_model_id, + const bool& existence, const std::string& circuit_model_name) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Make sure the circuit model is a LUT! */ + VTR_ASSERT_SAFE(SPICE_MODEL_LUT == circuit_model_types_[circuit_model_id]); + /* Just call the base function and give the proper type */ + set_circuit_model_buffer(circuit_model_id, LUT_INPUT_INVERTER, existence, circuit_model_name); + return; +} + +/* Set intermediate buffer information for the circuit model, only applicable to LUTs! */ +void CircuitLibrary::set_circuit_model_lut_intermediate_buffer(const CircuitModelId& circuit_model_id, + const bool& existence, const std::string& circuit_model_name) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Make sure the circuit model is a LUT! */ + VTR_ASSERT_SAFE(SPICE_MODEL_LUT == circuit_model_types_[circuit_model_id]); + /* Just call the base function and give the proper type */ + set_circuit_model_buffer(circuit_model_id, LUT_INTER_BUFFER, existence, circuit_model_name); + return; +} + /************************************************************************ * Internal Mutators ***********************************************************************/ +/* Set the information for a buffer + * For a buffer type, we check if it is in the range of vector + * If yes, just assign values + * If no, resize the vector and then assign values + */ +void CircuitLibrary::set_circuit_model_buffer(const CircuitModelId& circuit_model_id, const enum e_buffer_type buffer_type, + const bool& existence, const std::string& circuit_model_name) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Check the range of vector */ + if (size_t(buffer_type) >= buffer_existence_[circuit_model_id].size()) { + /* Resize and assign values */ + buffer_existence_[circuit_model_id].resize(size_t(buffer_type) + 1); + buffer_circuit_model_names_[circuit_model_id].resize(size_t(buffer_type) + 1); + buffer_circuit_model_ids_[circuit_model_id].resize(size_t(buffer_type) + 1); + } + /* Now we are in the range, assign values */ + buffer_existence_[circuit_model_id][size_t(buffer_type)] = existence; + buffer_circuit_model_names_[circuit_model_id][size_t(buffer_type)] = circuit_model_name; + buffer_circuit_model_ids_[circuit_model_id][size_t(buffer_type)] = CIRCUIT_MODEL_OPEN_ID; /* Set an OPEN id here, which will be linked later */ + return; +} + /* Link the inv_circuit_model_id for each port of a circuit model. * We search the inv_circuit_model_name in the CircuitLibrary and * configure the port inv_circuit_model_id */ void CircuitLibrary::set_circuit_model_port_inv_circuit_model(const CircuitModelId& circuit_model_id) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* TODO: complete this function when port mutators are finished */ return; } + +/************************************************************************ + * Internal mutators: build fast look-ups + ***********************************************************************/ +void CircuitLibrary::build_circuit_model_lookup() { + /* invalidate fast look-up */ + invalidate_circuit_model_lookup(); + /* Classify circuit models by type */ + circuit_model_lookup_.resize(NUM_CIRCUIT_MODEL_TYPES); + /* Walk through circuit_models and categorize */ + for (auto& id : circuit_model_ids_) { + circuit_model_lookup_[circuit_model_types_[id]].push_back(id); + } + /* Make the default circuit_model to be the first element for each type */ + for (auto& type : circuit_model_lookup_) { + /* if the first element is already a default model, we skip this */ + if (true == circuit_model_is_default_[type[0]]) { + continue; + } + /* Check the array, and try to find a default model */ + for (size_t id = 0; id < type.size(); ++id) { + if (false == circuit_model_is_default_[type[id]]) { + continue; + } + /* Once we find a default model, swap with the first element and finish the loop */ + std::swap(type[0], type[id]); + break; + } + } + return; +} + +/************************************************************************ + * Internal invalidators/validators + ***********************************************************************/ +/* Validators */ +bool CircuitLibrary::valid_circuit_model_id(const CircuitModelId& circuit_model_id) const { + return ( size_t(circuit_model_id) < circuit_model_ids_.size() ) && ( circuit_model_id == circuit_model_ids_[circuit_model_id] ); +} + +/* Invalidators */ +/* Empty fast lookup for circuit_models*/ +void CircuitLibrary::invalidate_circuit_model_lookup() const { + circuit_model_lookup_.clear(); + return; +} + +/* Empty fast lookup for circuit ports for a circuit_model */ +void CircuitLibrary::invalidate_circuit_model_port_lookup(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + circuit_model_port_lookup_[size_t(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 bedfabb7f..b6a5464b4 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -47,6 +47,8 @@ */ /* Header files should be included in a sequence */ /* Standard header files required go first */ +#include + #include "vtr_strong_id.h" #include "vtr_geometry.h" @@ -100,7 +102,7 @@ typedef vtr::StrongId CircuitEdgeId; * 2. dump_explicit_port_map_: if Verilog generator will use explicit port mapping when instanciate the circuit model * * ------ Design technology information ----- - * 1. design_tech_: the design technology [cmos|rram] for each circuit model + * 1. design_tech_types_: the design technology [cmos|rram] for each circuit model * 2. power_gated_: specify if the circuit model is power-gated (contain a input to turn on/off VDD and GND) * * ------ Buffer existence ----- @@ -210,20 +212,43 @@ class CircuitLibrary { typedef vtr::Range circuit_edge_range; /* local enumeration for buffer existence */ enum e_buffer_type: unsigned char{ - INPUT = 0, OUTPUT, LUT_INPUT_BUFFER, LUT_INPUT_INV, LUT_INTER_BUFFER, NUM_BUFFER_TYPE /* Last one is a counter */ + INPUT = 0, OUTPUT, LUT_INPUT_BUFFER, LUT_INPUT_INVERTER, LUT_INTER_BUFFER, NUM_BUFFER_TYPE /* Last one is a counter */ }; public: /* Constructors */ public: /* Accessors: aggregates */ circuit_model_range circuit_models() const; - public: /* Accessors: Basic data query */ - public: /* Accessors: Methods to find circuit model */ + public: /* Public Accessors: Basic data query */ + public: /* Public Accessors: Methods to find circuit model */ CircuitModelId get_circuit_model_id_by_name(const std::string& name) const ; CircuitModelId get_default_circuit_model_id(const enum e_spice_model_type& type) const; - public: /* Mutators */ + public: /* Public Mutators */ CircuitModelId add_circuit_model(); - public: /* Internal mutators */ + void set_circuit_model_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_type& type); + void set_circuit_model_name(const CircuitModelId& circuit_model_id, const std::string& name); + void set_circuit_model_prefix(const CircuitModelId& circuit_model_id, const std::string& prefix); + void set_circuit_model_verilog_netlist(const CircuitModelId& circuit_model_id, const std::string& verilog_netlist); + void set_circuit_model_spice_netlist(const CircuitModelId& circuit_model_id, const std::string& spice_netlist); + void set_circuit_model_is_default(const CircuitModelId& circuit_model_id, const bool& is_default); + void set_circuit_model_dump_structural_verilog(const CircuitModelId& circuit_model_id, const bool& dump_structural_verilog); + void set_circuit_model_dump_explicit_port_map(const CircuitModelId& circuit_model_id, const bool& dump_explicit_port_map); + void set_circuit_model_design_tech_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_design_tech& design_tech_type); + void set_circuit_model_power_gated(const CircuitModelId& circuit_model_id, const bool& power_gated); + void set_circuit_model_input_buffer(const CircuitModelId& circuit_model_id, const bool& existence, const std::string& circuit_model_name); + void set_circuit_model_output_buffer(const CircuitModelId& circuit_model_id, const bool& existence, const std::string& circuit_model_name); + void set_circuit_model_lut_input_buffer(const CircuitModelId& circuit_model_id, const bool& existence, const std::string& circuit_model_name); + void set_circuit_model_lut_input_inverter(const CircuitModelId& circuit_model_id, const bool& existence, const std::string& circuit_model_name); + void set_circuit_model_lut_intermediate_buffer(const CircuitModelId& circuit_model_id, const bool& existence, const std::string& circuit_model_name); + public: /* Internal mutators: link circuit_models */ + void set_circuit_model_buffer(const CircuitModelId& circuit_model_id, const enum e_buffer_type buffer_type, const bool& existence, const std::string& circuit_model_name); void set_circuit_model_port_inv_circuit_model(const CircuitModelId& circuit_model_id); - private: /* Internal validators */ + public: /* Internal mutators: build fast look-ups */ + void build_circuit_model_lookup(); + private: /* Internal invalidators/validators */ + /* Validators */ + bool valid_circuit_model_id(const CircuitModelId& circuit_model_id) const; + /* Invalidators */ + void invalidate_circuit_model_lookup() const; + void invalidate_circuit_model_port_lookup(const CircuitModelId& circuit_model_id) const; private: /* Internal data */ /* Fundamental information */ vtr::vector circuit_model_ids_; @@ -240,15 +265,15 @@ class CircuitLibrary { */ typedef std::vector> CircuitModelLookup; mutable CircuitModelLookup circuit_model_lookup_; /* [circuit_model_type][circuit_model_ids] */ - typedef std::vector>>> CircuitModelPortLookup; - mutable CircuitModelPortLookup circuit_model_port_lookup_; /* [circuit_model_type][circuit_model_id][port_type][port_ids] */ + typedef std::vector>> CircuitModelPortLookup; + mutable CircuitModelPortLookup circuit_model_port_lookup_; /* [circuit_model_id][port_type][port_ids] */ /* Verilog generator options */ vtr::vector dump_structural_verilog_; vtr::vector dump_explicit_port_map_; /* Design technology information */ - vtr::vector design_tech_; + vtr::vector design_tech_types_; vtr::vector power_gated_; /* Buffer existence */ From 9f8c7a3fc74e86142f199f65ad883a2ecb6a8593 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 7 Aug 2019 17:47:39 -0600 Subject: [PATCH 04/18] adding port mutators --- .../fpga_spice_include/circuit_library.cpp | 80 ++++++++++++++++++- .../SRC/fpga_spice_include/circuit_library.h | 73 +++++++++++------ .../SRC/fpga_spice_include/spice_types.h | 6 +- 3 files changed, 132 insertions(+), 27 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 2a6e32756..3bc99a079 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -117,11 +117,12 @@ CircuitModelId CircuitLibrary::add_circuit_model() { buffer_circuit_model_names_.emplace_back(); buffer_circuit_model_ids_.emplace_back(); - /* Pass-gate-related parameters */ + /* Pass-gate-related parameters */ pass_gate_logic_circuit_model_names_.emplace_back(); pass_gate_logic_circuit_model_ids_.emplace_back(); /* Port information */ + port_ids_.emplace_back(); port_types_.emplace_back(); port_sizes_.emplace_back(); port_prefix_.emplace_back(); @@ -334,6 +335,77 @@ void CircuitLibrary::set_circuit_model_lut_intermediate_buffer(const CircuitMode return; } +/* Set pass-gate logic information of a circuit model */ +void CircuitLibrary::set_circuit_model_pass_gate_logic(const CircuitModelId& circuit_model_id, const std::string& circuit_model_name) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + pass_gate_logic_circuit_model_names_[circuit_model_id] = circuit_model_name; + return; +} + +/* Add a port to a circuit model */ +CircuitPortId CircuitLibrary::add_circuit_model_port(const CircuitModelId& circuit_model_id) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Create a port id */ + CircuitPortId circuit_port_id = CircuitPortId(port_ids_[circuit_model_id].size()); + /* Update the id list */ + port_ids_[circuit_model_id].push_back(circuit_port_id); + + /* Initialize other attributes */ + port_types_[circuit_model_id].push_back(NUM_CIRCUIT_MODEL_PORT_TYPES); + port_sizes_[circuit_model_id].push_back(-1); + port_prefix_[circuit_model_id].emplace_back(); + port_lib_names_[circuit_model_id].emplace_back(); + port_inv_prefix_[circuit_model_id].emplace_back(); + port_is_mode_select_[circuit_model_id].push_back(false); + port_is_global_[circuit_model_id].push_back(false); + port_is_reset_[circuit_model_id].push_back(false); + port_is_set_[circuit_model_id].push_back(false); + port_is_config_enable_[circuit_model_id].push_back(false); + port_is_prog_[circuit_model_id].push_back(false); + port_circuit_model_names_[circuit_model_id].emplace_back(); + port_circuit_model_ids_[circuit_model_id].push_back(CIRCUIT_MODEL_OPEN_ID); + port_inv_circuit_model_names_[circuit_model_id].emplace_back(); + port_inv_circuit_model_ids_[circuit_model_id].push_back(CIRCUIT_MODEL_OPEN_ID); + port_tri_state_maps_[circuit_model_id].emplace_back(); + port_lut_frac_level_[circuit_model_id].push_back(-1); + port_lut_output_masks_[circuit_model_id].emplace_back(); + port_sram_orgz_[circuit_model_id].push_back(NUM_CIRCUIT_MODEL_SRAM_ORGZ_TYPES); + + return circuit_port_id; +} + +/* Set the type for a port of a circuit model */ +void CircuitLibrary::set_port_types(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const enum e_spice_model_port_type& port_type) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_types_[circuit_model_id][circuit_port_id] = port_type; + return; +} + +/* Set the size for a port of a circuit model */ +void CircuitLibrary::set_port_sizes(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const size_t& port_size) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_sizes_[circuit_model_id][circuit_port_id] = port_size; + return; +} + +/* Set the prefix for a port of a circuit model */ +void CircuitLibrary::set_port_prefix(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::string& port_prefix) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_prefix_[circuit_model_id][circuit_port_id] = port_prefix; + return; +} + /************************************************************************ * Internal Mutators ***********************************************************************/ @@ -411,6 +483,12 @@ bool CircuitLibrary::valid_circuit_model_id(const CircuitModelId& circuit_model_ return ( size_t(circuit_model_id) < circuit_model_ids_.size() ) && ( circuit_model_id == circuit_model_ids_[circuit_model_id] ); } +bool CircuitLibrary::valid_circuit_port_id(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return ( size_t(circuit_port_id) < port_ids_[circuit_model_id].size() ) && ( circuit_port_id == port_ids_[circuit_model_id][circuit_port_id] ); +} + /* Invalidators */ /* Empty fast lookup for circuit_models*/ void CircuitLibrary::invalidate_circuit_model_lookup() const { 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 b6a5464b4..4a0e791a1 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -117,25 +117,26 @@ typedef vtr::StrongId CircuitEdgeId; * 2. pass_gate_logic_circuit_model_id_: specify the id of circuit model for the pass gate logic * * ------ Port information ------ - * 1. port_types_: types of ports belonging to a circuit model - * 2. port_sizes_: width of ports belonging to a circuit model - * 3. port_prefix_: prefix of a port when instance of a circuit model - * 4. port_lib_names_: port name in the standard cell library, only used when explicit_port_mapping is enabled - * 5. port_inv_prefix_: the prefix to be added for the inverted port. This is mainly used by SRAM ports, which have an coupled inverterd port - * 6. port_is_mode_select: specify if this port is used to select operating modes of the circuit model - * 7. port_is_global: specify if this port is a global signal shared by other circuit model - * 8. port_is_reset: specify if this port is a reset signal which needs special pulse widths in testbenches - * 9. port_is_set: specify if this port is a set signal which needs special pulse widths in testbenches - * 10. port_is_config_enable: specify if this port is a config_enable signal which needs special pulse widths in testbenches - * 11. port_is_prog: specify if this port is for FPGA programming use which needs special pulse widths in testbenches - * 12. port_circuit_model_name: the name of circuit model linked to the port - * 13. port_circuit_model_ids_: the Id of circuit model linked to the port - * 14. port_inv_circuit_model_names_: the name of inverter circuit model linked to the port - * 15. port_inv_circuit_model_ids_: the Id of inverter circuit model linked to the port - * 16. port_tri_state_map_: only applicable to inputs of LUTs, the tri-state map applied to each pin of this port - * 17. port_lut_frac_level_: only applicable to outputs of LUTs, indicate which level of outputs inside LUT multiplexing structure will be used - * 18. port_lut_output_mask_: only applicable to outputs of LUTs, indicate which output at an internal level of LUT multiplexing structure will be used - * 19. port_sram_orgz_: only applicable to SRAM ports, indicate how the SRAMs will be organized, either memory decoders or scan-chains + * 1. port_ids_: unique id of ports belonging to a circuit model + * 2. port_types_: types of ports belonging to a circuit model + * 3. port_sizes_: width of ports belonging to a circuit model + * 4. port_prefix_: prefix of a port when instance of a circuit model + * 5. port_lib_names_: port name in the standard cell library, only used when explicit_port_mapping is enabled + * 6. port_inv_prefix_: the prefix to be added for the inverted port. This is mainly used by SRAM ports, which have an coupled inverterd port + * 7. port_is_mode_select: specify if this port is used to select operating modes of the circuit model + * 8. port_is_global: specify if this port is a global signal shared by other circuit model + * 9. port_is_reset: specify if this port is a reset signal which needs special pulse widths in testbenches + * 10. port_is_set: specify if this port is a set signal which needs special pulse widths in testbenches + * 11. port_is_config_enable: specify if this port is a config_enable signal which needs special pulse widths in testbenches + * 12. port_is_prog: specify if this port is for FPGA programming use which needs special pulse widths in testbenches + * 13. port_circuit_model_name: the name of circuit model linked to the port + * 14. port_circuit_model_ids_: the Id of circuit model linked to the port + * 15. port_inv_circuit_model_names_: the name of inverter circuit model linked to the port + * 16. port_inv_circuit_model_ids_: the Id of inverter circuit model linked to the port + * 17. port_tri_state_map_: only applicable to inputs of LUTs, the tri-state map applied to each pin of this port + * 18. port_lut_frac_level_: only applicable to outputs of LUTs, indicate which level of outputs inside LUT multiplexing structure will be used + * 19. port_lut_output_mask_: only applicable to outputs of LUTs, indicate which output at an internal level of LUT multiplexing structure will be used + * 20. port_sram_orgz_: only applicable to SRAM ports, indicate how the SRAMs will be organized, either memory decoders or scan-chains * * ------ Delay information ------ * 1. delay_types_: type of pin-to-pin delay, either rising_edge of falling_edge @@ -223,21 +224,43 @@ class CircuitLibrary { CircuitModelId get_default_circuit_model_id(const enum e_spice_model_type& type) const; public: /* Public Mutators */ CircuitModelId add_circuit_model(); + /* Fundamental information */ void set_circuit_model_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_type& type); void set_circuit_model_name(const CircuitModelId& circuit_model_id, const std::string& name); void set_circuit_model_prefix(const CircuitModelId& circuit_model_id, const std::string& prefix); void set_circuit_model_verilog_netlist(const CircuitModelId& circuit_model_id, const std::string& verilog_netlist); void set_circuit_model_spice_netlist(const CircuitModelId& circuit_model_id, const std::string& spice_netlist); void set_circuit_model_is_default(const CircuitModelId& circuit_model_id, const bool& is_default); + /* Verilog generator options */ void set_circuit_model_dump_structural_verilog(const CircuitModelId& circuit_model_id, const bool& dump_structural_verilog); void set_circuit_model_dump_explicit_port_map(const CircuitModelId& circuit_model_id, const bool& dump_explicit_port_map); + /* Design technology information */ void set_circuit_model_design_tech_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_design_tech& design_tech_type); void set_circuit_model_power_gated(const CircuitModelId& circuit_model_id, const bool& power_gated); - void set_circuit_model_input_buffer(const CircuitModelId& circuit_model_id, const bool& existence, const std::string& circuit_model_name); - void set_circuit_model_output_buffer(const CircuitModelId& circuit_model_id, const bool& existence, const std::string& circuit_model_name); - void set_circuit_model_lut_input_buffer(const CircuitModelId& circuit_model_id, const bool& existence, const std::string& circuit_model_name); - void set_circuit_model_lut_input_inverter(const CircuitModelId& circuit_model_id, const bool& existence, const std::string& circuit_model_name); - void set_circuit_model_lut_intermediate_buffer(const CircuitModelId& circuit_model_id, const bool& existence, const std::string& circuit_model_name); + /* Buffer existence */ + void set_circuit_model_input_buffer(const CircuitModelId& circuit_model_id, + const bool& existence, const std::string& circuit_model_name); + void set_circuit_model_output_buffer(const CircuitModelId& circuit_model_id, + const bool& existence, const std::string& circuit_model_name); + void set_circuit_model_lut_input_buffer(const CircuitModelId& circuit_model_id, + const bool& existence, const std::string& circuit_model_name); + void set_circuit_model_lut_input_inverter(const CircuitModelId& circuit_model_id, + const bool& existence, const std::string& circuit_model_name); + void set_circuit_model_lut_intermediate_buffer(const CircuitModelId& circuit_model_id, + const bool& existence, const std::string& circuit_model_name); + /* Pass-gate-related parameters */ + void set_circuit_model_pass_gate_logic(const CircuitModelId& circuit_model_id, const std::string& circuit_model_name); + /* Port information */ + CircuitPortId add_circuit_model_port(const CircuitModelId& circuit_model_id); + void set_port_types(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const enum e_spice_model_port_type& port_type); + void set_port_sizes(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const size_t& port_size); + void set_port_prefix(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::string& port_prefix); public: /* Internal mutators: link circuit_models */ void set_circuit_model_buffer(const CircuitModelId& circuit_model_id, const enum e_buffer_type buffer_type, const bool& existence, const std::string& circuit_model_name); void set_circuit_model_port_inv_circuit_model(const CircuitModelId& circuit_model_id); @@ -246,6 +269,7 @@ class CircuitLibrary { private: /* Internal invalidators/validators */ /* Validators */ 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; /* Invalidators */ void invalidate_circuit_model_lookup() const; void invalidate_circuit_model_port_lookup(const CircuitModelId& circuit_model_id) const; @@ -286,6 +310,7 @@ class CircuitLibrary { vtr::vector pass_gate_logic_circuit_model_ids_; /* Port information */ + vtr::vector> port_ids_; vtr::vector> port_types_; vtr::vector> port_sizes_; vtr::vector> port_prefix_; diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h index d3ad32ae7..7711285a2 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h @@ -87,7 +87,8 @@ enum e_spice_model_port_type { SPICE_MODEL_PORT_BL, SPICE_MODEL_PORT_BLB, SPICE_MODEL_PORT_WL, - SPICE_MODEL_PORT_WLB + SPICE_MODEL_PORT_WLB, + NUM_CIRCUIT_MODEL_PORT_TYPES }; /* For process corner */ @@ -102,7 +103,8 @@ enum e_sram_orgz { SPICE_SRAM_STANDALONE, /* SRAMs are organized and accessed as standalone elements */ SPICE_SRAM_SCAN_CHAIN, /* SRAMs are organized and accessed by a scan-chain */ SPICE_SRAM_MEMORY_BANK, /* SRAMs are organized and accessed by memory bank */ - SPICE_SRAM_LOCAL_ENCODER /* SRAMs are organized and accessed by a local encoder */ + SPICE_SRAM_LOCAL_ENCODER, /* SRAMs are organized and accessed by a local encoder */ + NUM_CIRCUIT_MODEL_SRAM_ORGZ_TYPES }; enum e_spice_accuracy_type { From 03a64e2ad815222fc5db169373a4576273a566aa Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 7 Aug 2019 20:54:27 -0600 Subject: [PATCH 05/18] complete the mutators for ports --- .../fpga_spice_include/circuit_library.cpp | 167 ++++++++++++++++++ .../SRC/fpga_spice_include/circuit_library.h | 48 +++++ 2 files changed, 215 insertions(+) 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 3bc99a079..8a3943b18 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -406,6 +406,173 @@ void CircuitLibrary::set_port_prefix(const CircuitModelId& circuit_model_id, return; } +/* Set the lib_name for a port of a circuit model */ +void CircuitLibrary::set_port_lib_name(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::string& lib_name) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_lib_names_[circuit_model_id][circuit_port_id] = lib_name; + return; +} + +/* Set the inv_prefix for a port of a circuit model */ +void CircuitLibrary::set_port_inv_prefix(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::string& inv_prefix) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_inv_prefix_[circuit_model_id][circuit_port_id] = inv_prefix; + return; +} + +/* Set the is_mode_select for a port of a circuit model */ +void CircuitLibrary::set_port_is_mode_select(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const bool& is_mode_select) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_is_mode_select_[circuit_model_id][circuit_port_id] = is_mode_select; + return; +} + +/* Set the is_global for a port of a circuit model */ +void CircuitLibrary::set_port_is_global(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const bool& is_global) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_is_global_[circuit_model_id][circuit_port_id] = is_global; + return; +} + +/* Set the is_reset for a port of a circuit model */ +void CircuitLibrary::set_port_is_reset(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const bool& is_reset) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_is_reset_[circuit_model_id][circuit_port_id] = is_reset; + return; +} + +/* Set the is_set for a port of a circuit model */ +void CircuitLibrary::set_port_is_set(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const bool& is_set) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_is_set_[circuit_model_id][circuit_port_id] = is_set; + return; +} + +/* Set the is_config_enable for a port of a circuit model */ +void CircuitLibrary::set_port_is_config_enable(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const bool& is_config_enable) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_is_config_enable_[circuit_model_id][circuit_port_id] = is_config_enable; + return; +} + +/* Set the is_prog for a port of a circuit model */ +void CircuitLibrary::set_port_is_prog(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const bool& is_prog) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_is_prog_[circuit_model_id][circuit_port_id] = is_prog; + return; +} + +/* Set the circuit_model_name for a port of a circuit model */ +void CircuitLibrary::set_port_circuit_model_name(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::string& circuit_model_name) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_circuit_model_names_[circuit_model_id][circuit_port_id] = circuit_model_name; + return; +} + +/* Set the circuit_model_id for a port of a circuit model */ +void CircuitLibrary::set_port_circuit_model_id(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const CircuitModelId& port_circuit_model_id) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_circuit_model_ids_[circuit_model_id][circuit_port_id] = port_circuit_model_id; + return; +} + +/* Set the inv_circuit_model_name for a port of a circuit model */ +void CircuitLibrary::set_port_inv_circuit_model_name(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::string& inv_circuit_model_name) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_inv_circuit_model_names_[circuit_model_id][circuit_port_id] = inv_circuit_model_name; + return; +} + +/* Set the inv_circuit_model_id for a port of a circuit model */ +void CircuitLibrary::set_port_inv_circuit_model_id(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const CircuitModelId& inv_circuit_model_id) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_inv_circuit_model_ids_[circuit_model_id][circuit_port_id] = inv_circuit_model_id; + return; +} + +/* Set the tri-state map for a port of a circuit model */ +void CircuitLibrary::set_port_tri_state_map(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::string& tri_state_map) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_tri_state_maps_[circuit_model_id][circuit_port_id] = tri_state_map; + return; +} + +/* Set the LUT fracturable level for a port of a circuit model, only applicable to LUTs */ +void CircuitLibrary::set_port_lut_frac_level(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const size_t& lut_frac_level) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + /* Make sure this is a LUT */ + VTR_ASSERT_SAFE(SPICE_MODEL_LUT == circuit_model_types_[circuit_model_id]); + port_lut_frac_level_[circuit_model_id][circuit_port_id] = lut_frac_level; + return; +} + +/* Set the LUT fracturable level for a port of a circuit model, only applicable to LUTs */ +void CircuitLibrary::set_port_lut_output_mask(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::vector& lut_output_masks) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + /* Make sure this is a LUT */ + VTR_ASSERT_SAFE(SPICE_MODEL_LUT == circuit_model_types_[circuit_model_id]); + port_lut_output_masks_[circuit_model_id][circuit_port_id] = lut_output_masks; + return; +} + +/* Set the SRAM organization for a port of a circuit model, only applicable to SRAM ports */ +void CircuitLibrary::set_port_sram_orgz(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const enum e_sram_orgz& sram_orgz) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + /* Make sure this is a SRAM port */ + VTR_ASSERT_SAFE(SPICE_MODEL_PORT_SRAM == port_types_[circuit_model_id][circuit_port_id]); + port_sram_orgz_[circuit_model_id][circuit_port_id] = sram_orgz; + return; +} + + /************************************************************************ * Internal Mutators ***********************************************************************/ 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 4a0e791a1..b9918fbeb 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -261,6 +261,54 @@ class CircuitLibrary { void set_port_prefix(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id, const std::string& port_prefix); + void set_port_lib_name(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::string& lib_name); + void set_port_inv_prefix(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::string& inv_prefix); + void set_port_is_mode_select(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const bool& is_mode_select); + void set_port_is_global(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const bool& is_global); + void set_port_is_reset(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const bool& is_reset); + void set_port_is_set(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const bool& is_set); + void set_port_is_config_enable(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const bool& is_config_enable); + void set_port_is_prog(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const bool& is_prog); + void set_port_circuit_model_name(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::string& circuit_model_name); + void set_port_circuit_model_id(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const CircuitModelId& port_circuit_model_id); + void set_port_inv_circuit_model_name(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::string& inv_circuit_model_name); + void set_port_inv_circuit_model_id(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const CircuitModelId& inv_circuit_model_id); + void set_port_tri_state_map(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::string& tri_state_map); + void set_port_lut_frac_level(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const size_t& lut_frac_level); + void set_port_lut_output_mask(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const std::vector& lut_output_masks); + void set_port_sram_orgz(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const enum e_sram_orgz& sram_orgz); public: /* Internal mutators: link circuit_models */ void set_circuit_model_buffer(const CircuitModelId& circuit_model_id, const enum e_buffer_type buffer_type, const bool& existence, const std::string& circuit_model_name); void set_circuit_model_port_inv_circuit_model(const CircuitModelId& circuit_model_id); From 5b0c9572c3347c5b4e012fa94212c7b8755e85b1 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 7 Aug 2019 21:19:16 -0600 Subject: [PATCH 06/18] add mutators for delay_info --- .../fpga_spice_include/circuit_library.cpp | 62 +++++++++++++++++++ .../SRC/fpga_spice_include/circuit_library.h | 13 ++++ .../SRC/fpga_spice_include/spice_types.h | 3 +- 3 files changed, 77 insertions(+), 1 deletion(-) 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 8a3943b18..74270df51 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -572,6 +572,62 @@ void CircuitLibrary::set_port_sram_orgz(const CircuitModelId& circuit_model_id, return; } +/* Delay information */ +/* Add a delay info: + * Check if the delay type is in the range of vector + * if yes, assign values + * if no, resize and assign values + */ +void CircuitLibrary::add_delay_info(const CircuitModelId& circuit_model_id, + const enum spice_model_delay_type& delay_type) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Check the range of vector */ + if (size_t(delay_type) >= delay_types_[circuit_model_id].size()) { + /* Resize */ + delay_types_[circuit_model_id].resize(size_t(delay_type) + 1); + delay_in_port_names_[circuit_model_id].resize(size_t(delay_type) + 1); + delay_out_port_names_[circuit_model_id].resize(size_t(delay_type) + 1); + delay_values_[circuit_model_id].resize(size_t(delay_type) + 1); + } + delay_types_[circuit_model_id][size_t(delay_type)] = delay_type; + return; +} + +void CircuitLibrary::set_delay_in_port_names(const CircuitModelId& circuit_model_id, + const enum spice_model_delay_type& delay_type, + const std::string& in_port_names) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Validate delay_type */ + VTR_ASSERT_SAFE(valid_delay_type(circuit_model_id, delay_type)); + delay_in_port_names_[circuit_model_id][size_t(delay_type)] = in_port_names; + return; +} + +void CircuitLibrary::set_delay_out_port_names(const CircuitModelId& circuit_model_id, + const enum spice_model_delay_type& delay_type, + const std::string& out_port_names) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Validate delay_type */ + VTR_ASSERT_SAFE(valid_delay_type(circuit_model_id, delay_type)); + delay_out_port_names_[circuit_model_id][size_t(delay_type)] = out_port_names; + return; +} + +void CircuitLibrary::set_delay_values(const CircuitModelId& circuit_model_id, + const enum spice_model_delay_type& delay_type, + const std::string& delay_values) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Validate delay_type */ + VTR_ASSERT_SAFE(valid_delay_type(circuit_model_id, delay_type)); + delay_values_[circuit_model_id][size_t(delay_type)] = delay_values; + return; +} + +/* Buffer/Inverter-related parameters */ /************************************************************************ * Internal Mutators @@ -656,6 +712,12 @@ bool CircuitLibrary::valid_circuit_port_id(const CircuitModelId& circuit_model_i return ( size_t(circuit_port_id) < port_ids_[circuit_model_id].size() ) && ( circuit_port_id == port_ids_[circuit_model_id][circuit_port_id] ); } +bool CircuitLibrary::valid_delay_type(const CircuitModelId& circuit_model_id, const enum spice_model_delay_type& delay_type) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return ( size_t(delay_type) < delay_types_[circuit_model_id].size() ) && ( delay_type == delay_types_[circuit_model_id][size_t(delay_type)] ); +} + /* Invalidators */ /* Empty fast lookup for circuit_models*/ void CircuitLibrary::invalidate_circuit_model_lookup() const { 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 b9918fbeb..a918ff369 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -309,6 +309,18 @@ class CircuitLibrary { void set_port_sram_orgz(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id, const enum e_sram_orgz& sram_orgz); + /* Delay information */ + void add_delay_info(const CircuitModelId& circuit_model_id, + const enum spice_model_delay_type& delay_type); + void set_delay_in_port_names(const CircuitModelId& circuit_model_id, + const enum spice_model_delay_type& delay_type, + const std::string& in_port_names); + void set_delay_out_port_names(const CircuitModelId& circuit_model_id, + const enum spice_model_delay_type& delay_type, + const std::string& out_port_names); + void set_delay_values(const CircuitModelId& circuit_model_id, + const enum spice_model_delay_type& delay_type, + const std::string& delay_values); public: /* Internal mutators: link circuit_models */ void set_circuit_model_buffer(const CircuitModelId& circuit_model_id, const enum e_buffer_type buffer_type, const bool& existence, const std::string& circuit_model_name); void set_circuit_model_port_inv_circuit_model(const CircuitModelId& circuit_model_id); @@ -318,6 +330,7 @@ class CircuitLibrary { /* Validators */ 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; /* Invalidators */ void invalidate_circuit_model_lookup() const; void invalidate_circuit_model_port_lookup(const CircuitModelId& circuit_model_id) const; diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h index 7711285a2..d16c2de5d 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h @@ -12,7 +12,8 @@ enum e_spice_tech_lib_type { enum spice_model_delay_type { SPICE_MODEL_DELAY_RISE, - SPICE_MODEL_DELAY_FALL + SPICE_MODEL_DELAY_FALL, + NUM_CIRCUIT_MODEL_DELAY_TYPES }; /*Struct for a SPICE model of a module*/ From ad8c33e1bafc276359c1fd64054dfc7545b018cb Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 8 Aug 2019 11:33:11 -0600 Subject: [PATCH 07/18] complete the mutators --- libs/libvtrutil/src/vtr_geometry.h | 3 + libs/libvtrutil/src/vtr_geometry.tpp | 10 + .../fpga_spice_include/circuit_library.cpp | 286 +++++++++++++++++- .../SRC/fpga_spice_include/circuit_library.h | 64 +++- 4 files changed, 348 insertions(+), 15 deletions(-) diff --git a/libs/libvtrutil/src/vtr_geometry.h b/libs/libvtrutil/src/vtr_geometry.h index e19dff1c0..ce9cfe59f 100644 --- a/libs/libvtrutil/src/vtr_geometry.h +++ b/libs/libvtrutil/src/vtr_geometry.h @@ -60,6 +60,9 @@ class Point { friend bool operator== <>(Point lhs, Point rhs); friend bool operator!= <>(Point lhs, Point rhs); friend bool operator< <>(Point lhs, Point rhs); + public: //Mutators + void set_x(T x_val); + void set_y(T y_val); private: T x_; T y_; diff --git a/libs/libvtrutil/src/vtr_geometry.tpp b/libs/libvtrutil/src/vtr_geometry.tpp index b06f29189..76b1ad457 100644 --- a/libs/libvtrutil/src/vtr_geometry.tpp +++ b/libs/libvtrutil/src/vtr_geometry.tpp @@ -42,6 +42,16 @@ namespace vtr { return std::make_tuple(lhs.x(), lhs.y()) < std::make_tuple(rhs.x(), rhs.y()); } + template + void Point::set_x(T x_val) { + x_ = x_val; + } + + template + void Point::set_y(T y_val) { + y_ = y_val; + } + /* * Rect */ 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 74270df51..c56a956de 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -54,6 +54,27 @@ CircuitLibrary::circuit_model_range CircuitLibrary::circuit_models() const { return vtr::make_range(circuit_model_ids_.begin(), circuit_model_ids_.end()); } +/************************************************************************ + * Public Accessors : Basic data query + ***********************************************************************/ +enum e_spice_model_type CircuitLibrary::circuit_model_type(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return circuit_model_types_[circuit_model_id]; +} + +enum e_spice_model_port_type CircuitLibrary::port_type(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return port_types_[circuit_model_id][circuit_port_id]; +} + +enum e_spice_model_design_tech CircuitLibrary::design_tech_type(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return design_tech_types_[circuit_model_id]; +} /************************************************************************ * Public Accessors : Methods to find circuit model @@ -163,22 +184,19 @@ CircuitModelId CircuitLibrary::add_circuit_model() { buffer_types_.push_back(NUM_CIRCUIT_MODEL_BUF_TYPES); buffer_location_maps_.emplace_back(); buffer_sizes_.push_back(-1); - buffer_is_tapered_.push_back(false); buffer_num_levels_.push_back(-1); buffer_f_per_stage_.push_back(-1); /* Pass-gate-related parameters */ pass_gate_logic_types_.push_back(NUM_CIRCUIT_MODEL_PASS_GATE_TYPES); - pass_gate_logic_nmos_sizes_.push_back(-1); - pass_gate_logic_pmos_sizes_.push_back(-1); + pass_gate_logic_sizes_.emplace_back(); /* Multiplexer-related parameters */ mux_structure_.push_back(NUM_CIRCUIT_MODEL_STRUCTURE_TYPES); mux_num_levels_.push_back(-1); - mux_add_const_input_.push_back(false); mux_const_input_values_.push_back(-1); mux_use_local_encoder_.push_back(false); - mux_advanced_rram_design_.push_back(false); + mux_use_advanced_rram_design_.push_back(false); /* LUT-related parameters */ lut_is_fracturable_.push_back(false); @@ -543,7 +561,7 @@ void CircuitLibrary::set_port_lut_frac_level(const CircuitModelId& circuit_model /* validate the circuit_port_id */ VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); /* Make sure this is a LUT */ - VTR_ASSERT_SAFE(SPICE_MODEL_LUT == circuit_model_types_[circuit_model_id]); + VTR_ASSERT_SAFE(SPICE_MODEL_LUT == circuit_model_type(circuit_model_id)); port_lut_frac_level_[circuit_model_id][circuit_port_id] = lut_frac_level; return; } @@ -555,7 +573,7 @@ void CircuitLibrary::set_port_lut_output_mask(const CircuitModelId& circuit_mode /* validate the circuit_port_id */ VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); /* Make sure this is a LUT */ - VTR_ASSERT_SAFE(SPICE_MODEL_LUT == circuit_model_types_[circuit_model_id]); + VTR_ASSERT_SAFE(SPICE_MODEL_LUT == circuit_model_type(circuit_model_id)); port_lut_output_masks_[circuit_model_id][circuit_port_id] = lut_output_masks; return; } @@ -567,7 +585,7 @@ void CircuitLibrary::set_port_sram_orgz(const CircuitModelId& circuit_model_id, /* validate the circuit_port_id */ VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); /* Make sure this is a SRAM port */ - VTR_ASSERT_SAFE(SPICE_MODEL_PORT_SRAM == port_types_[circuit_model_id][circuit_port_id]); + VTR_ASSERT_SAFE(SPICE_MODEL_PORT_SRAM == port_type(circuit_model_id, circuit_port_id)); port_sram_orgz_[circuit_model_id][circuit_port_id] = sram_orgz; return; } @@ -617,8 +635,8 @@ void CircuitLibrary::set_delay_out_port_names(const CircuitModelId& circuit_mode } void CircuitLibrary::set_delay_values(const CircuitModelId& circuit_model_id, - const enum spice_model_delay_type& delay_type, - const std::string& delay_values) { + const enum spice_model_delay_type& delay_type, + const std::string& delay_values) { /* validate the circuit_model_id */ VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); /* Validate delay_type */ @@ -628,6 +646,254 @@ void CircuitLibrary::set_delay_values(const CircuitModelId& circuit_model_id, } /* Buffer/Inverter-related parameters */ +void CircuitLibrary::set_buffer_type(const CircuitModelId& circuit_model_id, + const enum e_spice_model_buffer_type& buffer_type) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be BUFFER or INVERTER */ + VTR_ASSERT_SAFE(SPICE_MODEL_INVBUF == circuit_model_type(circuit_model_id)); + buffer_types_[circuit_model_id] = buffer_type; + return; +} + +void CircuitLibrary::set_buffer_location_map(const CircuitModelId& circuit_model_id, + const std::string& location_map) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be BUFFER or INVERTER */ + VTR_ASSERT_SAFE(SPICE_MODEL_INVBUF == circuit_model_type(circuit_model_id)); + buffer_location_maps_[circuit_model_id] = location_map; + return; +} + +void CircuitLibrary::set_buffer_size(const CircuitModelId& circuit_model_id, + const size_t& buffer_size) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be BUFFER or INVERTER */ + VTR_ASSERT_SAFE(SPICE_MODEL_INVBUF == circuit_model_type(circuit_model_id)); + buffer_sizes_[circuit_model_id] = buffer_size; + return; +} + +void CircuitLibrary::set_buffer_num_levels(const CircuitModelId& circuit_model_id, + const size_t& num_levels) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be BUFFER or INVERTER */ + VTR_ASSERT_SAFE(SPICE_MODEL_INVBUF == circuit_model_type(circuit_model_id)); + buffer_num_levels_[circuit_model_id] = num_levels; + return; +} + +void CircuitLibrary::set_buffer_f_per_stage(const CircuitModelId& circuit_model_id, + const size_t& f_per_stage) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be BUFFER or INVERTER */ + VTR_ASSERT_SAFE(SPICE_MODEL_INVBUF == circuit_model_type(circuit_model_id)); + buffer_f_per_stage_[circuit_model_id] = f_per_stage; + return; +} + +/* Pass-gate-related parameters */ +void CircuitLibrary::set_pass_gate_logic_type(const CircuitModelId& circuit_model_id, + const enum e_spice_model_pass_gate_logic_type& pass_gate_logic_type) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be BUFFER or INVERTER */ + VTR_ASSERT_SAFE(SPICE_MODEL_PASSGATE == circuit_model_type(circuit_model_id)); + pass_gate_logic_types_[circuit_model_id] = pass_gate_logic_type; + return; +} + +void CircuitLibrary::set_pass_gate_logic_nmos_size(const CircuitModelId& circuit_model_id, + const size_t& nmos_size) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be BUFFER or INVERTER */ + VTR_ASSERT_SAFE(SPICE_MODEL_PASSGATE == circuit_model_type(circuit_model_id)); + pass_gate_logic_sizes_[circuit_model_id].set_x(nmos_size); + return; +} + +void CircuitLibrary::set_pass_gate_logic_pmos_size(const CircuitModelId& circuit_model_id, + const size_t& pmos_size) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be BUFFER or INVERTER */ + VTR_ASSERT_SAFE(SPICE_MODEL_PASSGATE == circuit_model_type(circuit_model_id)); + pass_gate_logic_sizes_[circuit_model_id].set_y(pmos_size); + return; +} + +/* Multiplexer-related parameters */ +void CircuitLibrary::set_mux_structure(const CircuitModelId& circuit_model_id, + const enum e_spice_model_structure& mux_structure) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be MUX */ + VTR_ASSERT_SAFE(SPICE_MODEL_MUX == circuit_model_type(circuit_model_id)); + mux_structure_[circuit_model_id] = mux_structure; + return; +} + +void CircuitLibrary::set_mux_num_levels(const CircuitModelId& circuit_model_id, + const size_t& num_levels) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be MUX */ + VTR_ASSERT_SAFE(SPICE_MODEL_MUX == circuit_model_type(circuit_model_id)); + mux_num_levels_[circuit_model_id] = num_levels; + return; +} + +void CircuitLibrary::set_mux_const_input_value(const CircuitModelId& circuit_model_id, + const size_t& const_input_value) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be MUX */ + VTR_ASSERT_SAFE(SPICE_MODEL_MUX == circuit_model_type(circuit_model_id)); + mux_const_input_values_[circuit_model_id] = const_input_value; + return; +} + +void CircuitLibrary::set_mux_use_local_encoder(const CircuitModelId& circuit_model_id, + const bool& use_local_encoder) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be MUX */ + VTR_ASSERT_SAFE(SPICE_MODEL_MUX == circuit_model_type(circuit_model_id)); + mux_use_local_encoder_[circuit_model_id] = use_local_encoder; + return; +} + +void CircuitLibrary::set_mux_use_advanced_rram_design(const CircuitModelId& circuit_model_id, + const bool& use_advanced_rram_design) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be MUX */ + VTR_ASSERT_SAFE(SPICE_MODEL_MUX == circuit_model_type(circuit_model_id)); + mux_use_advanced_rram_design_[circuit_model_id] = use_advanced_rram_design; + return; +} + +/* LUT-related parameters */ +void CircuitLibrary::set_lut_is_fracturable(const CircuitModelId& circuit_model_id, + const bool& is_fracturable) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be LUT */ + VTR_ASSERT_SAFE(SPICE_MODEL_LUT == circuit_model_type(circuit_model_id)); + lut_is_fracturable_[circuit_model_id] = is_fracturable; + return; +} + +/* RRAM-related design technology information */ +void CircuitLibrary::set_rram_rlrs(const CircuitModelId& circuit_model_id, + const float& rlrs) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the design_tech of this circuit_model should be RRAM */ + VTR_ASSERT_SAFE(SPICE_MODEL_DESIGN_RRAM == design_tech_type(circuit_model_id)); + rram_res_[circuit_model_id].set_x(rlrs); + return; +} + +void CircuitLibrary::set_rram_rhrs(const CircuitModelId& circuit_model_id, + const float& rhrs) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the design_tech of this circuit_model should be RRAM */ + VTR_ASSERT_SAFE(SPICE_MODEL_DESIGN_RRAM == design_tech_type(circuit_model_id)); + rram_res_[circuit_model_id].set_y(rhrs); + return; +} + +void CircuitLibrary::set_rram_wprog_set_nmos(const CircuitModelId& circuit_model_id, + const float& wprog_set_nmos) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the design_tech of this circuit_model should be RRAM */ + VTR_ASSERT_SAFE(SPICE_MODEL_DESIGN_RRAM == design_tech_type(circuit_model_id)); + wprog_set_[circuit_model_id].set_x(wprog_set_nmos); + return; +} + +void CircuitLibrary::set_rram_wprog_set_pmos(const CircuitModelId& circuit_model_id, + const float& wprog_set_pmos) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the design_tech of this circuit_model should be RRAM */ + VTR_ASSERT_SAFE(SPICE_MODEL_DESIGN_RRAM == design_tech_type(circuit_model_id)); + wprog_set_[circuit_model_id].set_y(wprog_set_pmos); + return; +} + +void CircuitLibrary::set_rram_wprog_reset_nmos(const CircuitModelId& circuit_model_id, + const float& wprog_reset_nmos) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the design_tech of this circuit_model should be RRAM */ + VTR_ASSERT_SAFE(SPICE_MODEL_DESIGN_RRAM == design_tech_type(circuit_model_id)); + wprog_reset_[circuit_model_id].set_x(wprog_reset_nmos); + return; +} + +void CircuitLibrary::set_rram_wprog_reset_pmos(const CircuitModelId& circuit_model_id, + const float& wprog_reset_pmos) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the design_tech of this circuit_model should be RRAM */ + VTR_ASSERT_SAFE(SPICE_MODEL_DESIGN_RRAM == design_tech_type(circuit_model_id)); + wprog_reset_[circuit_model_id].set_y(wprog_reset_pmos); + return; +} + +/* Wire parameters */ +void CircuitLibrary::set_wire_type(const CircuitModelId& circuit_model_id, + const enum e_wire_model_type& wire_type) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be WIRE or CHAN_WIRE */ + VTR_ASSERT_SAFE( (SPICE_MODEL_WIRE == circuit_model_type(circuit_model_id)) + || (SPICE_MODEL_CHAN_WIRE == circuit_model_type(circuit_model_id)) ); + wire_types_[circuit_model_id] = wire_type; + return; +} + +void CircuitLibrary::set_wire_r(const CircuitModelId& circuit_model_id, + const float& r_val) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be WIRE or CHAN_WIRE */ + VTR_ASSERT_SAFE( (SPICE_MODEL_WIRE == circuit_model_type(circuit_model_id)) + || (SPICE_MODEL_CHAN_WIRE == circuit_model_type(circuit_model_id)) ); + wire_rc_[circuit_model_id].set_x(r_val); + return; +} + +void CircuitLibrary::set_wire_c(const CircuitModelId& circuit_model_id, + const float& c_val) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be WIRE or CHAN_WIRE */ + VTR_ASSERT_SAFE( (SPICE_MODEL_WIRE == circuit_model_type(circuit_model_id)) + || (SPICE_MODEL_CHAN_WIRE == circuit_model_type(circuit_model_id)) ); + wire_rc_[circuit_model_id].set_y(c_val); + return; +} + +void CircuitLibrary::set_wire_num_levels(const CircuitModelId& circuit_model_id, + const size_t& num_level) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be WIRE or CHAN_WIRE */ + VTR_ASSERT_SAFE( (SPICE_MODEL_WIRE == circuit_model_type(circuit_model_id)) + || (SPICE_MODEL_CHAN_WIRE == circuit_model_type(circuit_model_id)) ); + wire_num_levels_[circuit_model_id] = num_level; + return; +} /************************************************************************ * Internal Mutators 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 a918ff369..b175622a5 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -218,6 +218,9 @@ class CircuitLibrary { public: /* Constructors */ public: /* Accessors: aggregates */ circuit_model_range circuit_models() const; + enum e_spice_model_type circuit_model_type(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; + enum e_spice_model_design_tech design_tech_type(const CircuitModelId& circuit_model_id) const; public: /* Public Accessors: Basic data query */ public: /* Public Accessors: Methods to find circuit model */ CircuitModelId get_circuit_model_id_by_name(const std::string& name) const ; @@ -321,6 +324,60 @@ class CircuitLibrary { void set_delay_values(const CircuitModelId& circuit_model_id, const enum spice_model_delay_type& delay_type, const std::string& delay_values); + /* Buffer/Inverter-related parameters */ + void set_buffer_type(const CircuitModelId& circuit_model_id, + const enum e_spice_model_buffer_type& buffer_type); + void set_buffer_location_map(const CircuitModelId& circuit_model_id, + const std::string& location_map); + void set_buffer_size(const CircuitModelId& circuit_model_id, + const size_t& buffer_size); + void set_buffer_num_levels(const CircuitModelId& circuit_model_id, + const size_t& num_levels); + void set_buffer_f_per_stage(const CircuitModelId& circuit_model_id, + const size_t& f_per_stage); + /* Pass-gate-related parameters */ + void set_pass_gate_logic_type(const CircuitModelId& circuit_model_id, + const enum e_spice_model_pass_gate_logic_type& pass_gate_logic_type); + void set_pass_gate_logic_nmos_size(const CircuitModelId& circuit_model_id, + const size_t& nmos_size); + void set_pass_gate_logic_pmos_size(const CircuitModelId& circuit_model_id, + const size_t& pmos_size); + /* Multiplexer-related parameters */ + void set_mux_structure(const CircuitModelId& circuit_model_id, + const enum e_spice_model_structure& mux_structure); + void set_mux_num_levels(const CircuitModelId& circuit_model_id, + const size_t& num_levels); + void set_mux_const_input_value(const CircuitModelId& circuit_model_id, + const size_t& const_input_value); + void set_mux_use_local_encoder(const CircuitModelId& circuit_model_id, + const bool& use_local_encoder); + void set_mux_use_advanced_rram_design(const CircuitModelId& circuit_model_id, + const bool& use_advanced_rram_design); + /* LUT-related parameters */ + void set_lut_is_fracturable(const CircuitModelId& circuit_model_id, + const bool& is_fracturable); + /* RRAM-related design technology information */ + void set_rram_rlrs(const CircuitModelId& circuit_model_id, + const float& rlrs); + void set_rram_rhrs(const CircuitModelId& circuit_model_id, + const float& rhrs); + void set_rram_wprog_set_nmos(const CircuitModelId& circuit_model_id, + const float& wprog_set_nmos); + void set_rram_wprog_set_pmos(const CircuitModelId& circuit_model_id, + const float& wprog_set_pmos); + void set_rram_wprog_reset_nmos(const CircuitModelId& circuit_model_id, + const float& wprog_reset_nmos); + void set_rram_wprog_reset_pmos(const CircuitModelId& circuit_model_id, + const float& wprog_reset_pmos); + /* Wire parameters */ + void set_wire_type(const CircuitModelId& circuit_model_id, + const enum e_wire_model_type& wire_type); + void set_wire_r(const CircuitModelId& circuit_model_id, + const float& r_val); + void set_wire_c(const CircuitModelId& circuit_model_id, + const float& c_val); + void set_wire_num_levels(const CircuitModelId& circuit_model_id, + const size_t& num_level); public: /* Internal mutators: link circuit_models */ void set_circuit_model_buffer(const CircuitModelId& circuit_model_id, const enum e_buffer_type buffer_type, const bool& existence, const std::string& circuit_model_name); void set_circuit_model_port_inv_circuit_model(const CircuitModelId& circuit_model_id); @@ -413,22 +470,19 @@ class CircuitLibrary { vtr::vector buffer_types_; vtr::vector buffer_location_maps_; vtr::vector buffer_sizes_; - vtr::vector buffer_is_tapered_; vtr::vector buffer_num_levels_; vtr::vector buffer_f_per_stage_; /* Pass-gate-related parameters */ vtr::vector pass_gate_logic_types_; - vtr::vector pass_gate_logic_nmos_sizes_; - vtr::vector pass_gate_logic_pmos_sizes_; + vtr::vector> pass_gate_logic_sizes_; /* x=> nmos_size; y => pmos_size */ /* Multiplexer-related parameters */ vtr::vector mux_structure_; vtr::vector mux_num_levels_; - vtr::vector mux_add_const_input_; vtr::vector mux_const_input_values_; vtr::vector mux_use_local_encoder_; - vtr::vector mux_advanced_rram_design_; + vtr::vector mux_use_advanced_rram_design_; /* LUT-related parameters */ vtr::vector lut_is_fracturable_; From e19485bbb7ed257c2e99c07096fc525aec0d1d92 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 8 Aug 2019 14:16:29 -0600 Subject: [PATCH 08/18] add more accessors and more to be added when plug into framework --- .../fpga_spice_include/circuit_library.cpp | 182 +++++++++++++++++- .../SRC/fpga_spice_include/circuit_library.h | 32 ++- 2 files changed, 201 insertions(+), 13 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 c56a956de..ff78158fe 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -55,14 +55,105 @@ CircuitLibrary::circuit_model_range CircuitLibrary::circuit_models() const { } /************************************************************************ - * Public Accessors : Basic data query + * Public Accessors : Basic data query on Circuit Models ***********************************************************************/ +/* Access the type of a circuit model */ enum e_spice_model_type CircuitLibrary::circuit_model_type(const CircuitModelId& circuit_model_id) const { /* validate the circuit_model_id */ VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); return circuit_model_types_[circuit_model_id]; } +/* Access the name of a circuit model */ +std::string CircuitLibrary::circuit_model_name(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return circuit_model_names_[circuit_model_id]; +} + +/* Access the prefix of a circuit model */ +std::string CircuitLibrary::circuit_model_prefix(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return circuit_model_prefix_[circuit_model_id]; +} + +/* Access the path + file of user-defined verilog netlist of a circuit model */ +std::string CircuitLibrary::circuit_model_verilog_netlist(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return circuit_model_verilog_netlists_[circuit_model_id]; +} + +/* Access the path + file of user-defined spice netlist of a circuit model */ +std::string CircuitLibrary::circuit_model_spice_netlist(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return circuit_model_spice_netlists_[circuit_model_id]; +} + +/* Access the is_default flag (check if this is the default circuit model in the type) of a circuit model */ +bool CircuitLibrary::circuit_model_is_default(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return circuit_model_is_default_[circuit_model_id]; +} + +/* Access the dump_structural_verilog flag of a circuit model */ +bool CircuitLibrary::dump_structural_verilog(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return dump_structural_verilog_[circuit_model_id]; +} + +/* Access the dump_explicit_port_map flag of a circuit model */ +bool CircuitLibrary::dump_explicit_port_map(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return dump_explicit_port_map_[circuit_model_id]; +} + +/* Access the design technology type of a circuit model */ +enum e_spice_model_design_tech CircuitLibrary::design_tech_type(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return design_tech_types_[circuit_model_id]; +} + +/* Access the is_power_gated flag of a circuit model */ +bool CircuitLibrary::is_power_gated(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return is_power_gated_[circuit_model_id]; +} + +/* Return a flag showing if inputs are buffered for a circuit model */ +bool CircuitLibrary::is_input_buffered(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return buffer_existence_[circuit_model_id][INPUT]; +} + +/* Return a flag showing if outputs are buffered for a circuit model */ +bool CircuitLibrary::is_output_buffered(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return buffer_existence_[circuit_model_id][OUTPUT]; +} + +/* Return a flag showing if intermediate stages of a LUT are buffered for a circuit model */ +bool CircuitLibrary::is_lut_intermediate_buffered(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate the circuit model type is LUT */ + VTR_ASSERT_SAFE(SPICE_MODEL_LUT == circuit_model_type(circuit_model_id)); + return buffer_existence_[circuit_model_id][LUT_INTER_BUFFER]; +} + +/************************************************************************ + * Public Accessors : Basic data query on Circuit Porst + ***********************************************************************/ +/* Access the type of a port of a circuit model */ enum e_spice_model_port_type CircuitLibrary::port_type(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ @@ -70,12 +161,87 @@ enum e_spice_model_port_type CircuitLibrary::port_type(const CircuitModelId& cir return port_types_[circuit_model_id][circuit_port_id]; } -enum e_spice_model_design_tech CircuitLibrary::design_tech_type(const CircuitModelId& circuit_model_id) const { - /* validate the circuit_model_id */ - VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); - return design_tech_types_[circuit_model_id]; +/* Access the type of a port of a circuit model */ +size_t CircuitLibrary::port_size(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return port_sizes_[circuit_model_id][circuit_port_id]; } +/* Access the prefix of a port of a circuit model */ +std::string CircuitLibrary::port_prefix(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return port_prefix_[circuit_model_id][circuit_port_id]; +} + +/* Access the lib_name of a port of a circuit model */ +std::string CircuitLibrary::port_lib_name(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return port_lib_names_[circuit_model_id][circuit_port_id]; +} + +/* Access the inv_prefix of a port of a circuit model */ +std::string CircuitLibrary::port_inv_prefix(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return port_inv_prefix_[circuit_model_id][circuit_port_id]; +} + +/* Return a flag if the port is used in mode-selection purpuse of a circuit model */ +bool CircuitLibrary::port_is_mode_select(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return port_is_mode_select_[circuit_model_id][circuit_port_id]; +} + +/* Return a flag if the port is a global one of a circuit model */ +bool CircuitLibrary::port_is_global(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return port_is_global_[circuit_model_id][circuit_port_id]; +} + +/* Return a flag if the port does a reset functionality in a circuit model */ +bool CircuitLibrary::port_is_reset(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return port_is_reset_[circuit_model_id][circuit_port_id]; +} + +/* Return a flag if the port does a set functionality in a circuit model */ +bool CircuitLibrary::port_is_set(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return port_is_set_[circuit_model_id][circuit_port_id]; +} + +/* Return a flag if the port enables a configuration in a circuit model */ +bool CircuitLibrary::port_is_config_enable(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return port_is_config_enable_[circuit_model_id][circuit_port_id]; +} + +/* Return a flag if the port is used during programming a FPGA in a circuit model */ +bool CircuitLibrary::port_is_prog(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return port_is_prog_[circuit_model_id][circuit_port_id]; +} + + /************************************************************************ * Public Accessors : Methods to find circuit model ***********************************************************************/ @@ -131,7 +297,7 @@ CircuitModelId CircuitLibrary::add_circuit_model() { /* Design technology information */ design_tech_types_.push_back(NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES); - power_gated_.push_back(false); + is_power_gated_.push_back(false); /* Buffer existence */ buffer_existence_.emplace_back(); @@ -294,10 +460,10 @@ void CircuitLibrary::set_circuit_model_design_tech_type(const CircuitModelId& ci } /* Set the power-gated flag of a Circuit Model */ -void CircuitLibrary::set_circuit_model_power_gated(const CircuitModelId& circuit_model_id, const bool& power_gated) { +void CircuitLibrary::set_circuit_model_is_power_gated(const CircuitModelId& circuit_model_id, const bool& is_power_gated) { /* validate the circuit_model_id */ VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); - power_gated_[circuit_model_id] = power_gated; + is_power_gated_[circuit_model_id] = is_power_gated; 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 b175622a5..b129ab089 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -103,7 +103,7 @@ typedef vtr::StrongId CircuitEdgeId; * * ------ Design technology information ----- * 1. design_tech_types_: the design technology [cmos|rram] for each circuit model - * 2. power_gated_: specify if the circuit model is power-gated (contain a input to turn on/off VDD and GND) + * 2. is_power_gated_: specify if the circuit model is power-gated (contain a input to turn on/off VDD and GND) * * ------ Buffer existence ----- * Use vectors to simplify the defition of buffer existence: @@ -217,11 +217,33 @@ class CircuitLibrary { }; public: /* Constructors */ public: /* Accessors: aggregates */ + public: /* Public Accessors: Basic data query on Circuit Models*/ circuit_model_range circuit_models() const; enum e_spice_model_type circuit_model_type(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; + std::string circuit_model_name(const CircuitModelId& circuit_model_id) const; + std::string circuit_model_prefix(const CircuitModelId& circuit_model_id) const; + std::string circuit_model_verilog_netlist(const CircuitModelId& circuit_model_id) const; + std::string circuit_model_spice_netlist(const CircuitModelId& circuit_model_id) const; + bool circuit_model_is_default(const CircuitModelId& circuit_model_id) const; + bool dump_structural_verilog(const CircuitModelId& circuit_model_id) const; + bool dump_explicit_port_map(const CircuitModelId& circuit_model_id) const; enum e_spice_model_design_tech design_tech_type(const CircuitModelId& circuit_model_id) const; - public: /* Public Accessors: Basic data query */ + bool is_power_gated(const CircuitModelId& circuit_model_id) const; + bool is_input_buffered(const CircuitModelId& circuit_model_id) const; + 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*/ + 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; + std::string port_prefix(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; + std::string port_lib_name(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; + std::string port_inv_prefix(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; + bool port_is_mode_select(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; + bool port_is_global(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; + bool port_is_reset(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; + bool port_is_set(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; + bool port_is_config_enable(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; + bool port_is_prog(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; public: /* Public Accessors: Methods to find circuit model */ CircuitModelId get_circuit_model_id_by_name(const std::string& name) const ; CircuitModelId get_default_circuit_model_id(const enum e_spice_model_type& type) const; @@ -239,7 +261,7 @@ class CircuitLibrary { void set_circuit_model_dump_explicit_port_map(const CircuitModelId& circuit_model_id, const bool& dump_explicit_port_map); /* Design technology information */ void set_circuit_model_design_tech_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_design_tech& design_tech_type); - void set_circuit_model_power_gated(const CircuitModelId& circuit_model_id, const bool& power_gated); + void set_circuit_model_is_power_gated(const CircuitModelId& circuit_model_id, const bool& is_power_gated); /* Buffer existence */ void set_circuit_model_input_buffer(const CircuitModelId& circuit_model_id, const bool& existence, const std::string& circuit_model_name); @@ -416,7 +438,7 @@ class CircuitLibrary { /* Design technology information */ vtr::vector design_tech_types_; - vtr::vector power_gated_; + vtr::vector is_power_gated_; /* Buffer existence */ vtr::vector> buffer_existence_; From 158c67075e8c47aa592f37c2e945fb67eca86927 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 8 Aug 2019 17:25:27 -0600 Subject: [PATCH 09/18] built a conversion from spice_models to circuit_library and plug in --- .../fpga_spice_include/circuit_library.cpp | 77 ++++-- .../SRC/fpga_spice_include/circuit_library.h | 41 ++- .../SRC/fpga_spice_include/circuit_types.h | 144 ++++++++++ .../SRC/fpga_spice_include/spice_types.h | 86 +----- vpr7_x2p/libarchfpga/SRC/read_xml_spice.c | 260 +++++++++++++++++- 5 files changed, 480 insertions(+), 128 deletions(-) create mode 100644 vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_types.h 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 ff78158fe..6e067ce3e 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -193,6 +193,15 @@ std::string CircuitLibrary::port_inv_prefix(const CircuitModelId& circuit_model_ return port_inv_prefix_[circuit_model_id][circuit_port_id]; } +/* Return the default value of a port of a circuit model */ +size_t CircuitLibrary::port_default_value(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return port_default_values_[circuit_model_id][circuit_port_id]; +} + + /* Return a flag if the port is used in mode-selection purpuse of a circuit model */ bool CircuitLibrary::port_is_mode_select(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const { @@ -303,6 +312,7 @@ CircuitModelId CircuitLibrary::add_circuit_model() { buffer_existence_.emplace_back(); buffer_circuit_model_names_.emplace_back(); buffer_circuit_model_ids_.emplace_back(); + buffer_location_maps_.emplace_back(); /* Pass-gate-related parameters */ pass_gate_logic_circuit_model_names_.emplace_back(); @@ -314,6 +324,8 @@ CircuitModelId CircuitLibrary::add_circuit_model() { port_sizes_.emplace_back(); port_prefix_.emplace_back(); port_lib_names_.emplace_back(); + port_inv_prefix_.emplace_back(); + port_default_values_.emplace_back(); port_is_mode_select_.emplace_back(); port_is_global_.emplace_back(); port_is_reset_.emplace_back(); @@ -348,7 +360,6 @@ CircuitModelId CircuitLibrary::add_circuit_model() { /* Buffer/Inverter-related parameters */ buffer_types_.push_back(NUM_CIRCUIT_MODEL_BUF_TYPES); - buffer_location_maps_.emplace_back(); buffer_sizes_.push_back(-1); buffer_num_levels_.push_back(-1); buffer_f_per_stage_.push_back(-1); @@ -367,6 +378,9 @@ CircuitModelId CircuitLibrary::add_circuit_model() { /* LUT-related parameters */ lut_is_fracturable_.push_back(false); + /* Gate-related parameters */ + gate_types_.push_back(NUM_SPICE_MODEL_GATE_TYPES); + /* RRAM-related design technology information */ rram_res_.emplace_back(); wprog_set_.emplace_back(); @@ -519,6 +533,15 @@ void CircuitLibrary::set_circuit_model_lut_intermediate_buffer(const CircuitMode return; } +void CircuitLibrary::set_circuit_model_lut_intermediate_buffer_location_map(const CircuitModelId& circuit_model_id, + const std::string& location_map) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + buffer_location_maps_[circuit_model_id][LUT_INTER_BUFFER] = location_map; + return; +} + + /* Set pass-gate logic information of a circuit model */ void CircuitLibrary::set_circuit_model_pass_gate_logic(const CircuitModelId& circuit_model_id, const std::string& circuit_model_name) { /* validate the circuit_model_id */ @@ -542,6 +565,7 @@ CircuitPortId CircuitLibrary::add_circuit_model_port(const CircuitModelId& circu port_prefix_[circuit_model_id].emplace_back(); port_lib_names_[circuit_model_id].emplace_back(); port_inv_prefix_[circuit_model_id].emplace_back(); + port_default_values_[circuit_model_id].push_back(-1); port_is_mode_select_[circuit_model_id].push_back(false); port_is_global_[circuit_model_id].push_back(false); port_is_reset_[circuit_model_id].push_back(false); @@ -561,9 +585,9 @@ CircuitPortId CircuitLibrary::add_circuit_model_port(const CircuitModelId& circu } /* Set the type for a port of a circuit model */ -void CircuitLibrary::set_port_types(const CircuitModelId& circuit_model_id, - const CircuitPortId& circuit_port_id, - const enum e_spice_model_port_type& port_type) { +void CircuitLibrary::set_port_type(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const enum e_spice_model_port_type& port_type) { /* validate the circuit_port_id */ VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); port_types_[circuit_model_id][circuit_port_id] = port_type; @@ -571,9 +595,9 @@ void CircuitLibrary::set_port_types(const CircuitModelId& circuit_model_id, } /* Set the size for a port of a circuit model */ -void CircuitLibrary::set_port_sizes(const CircuitModelId& circuit_model_id, - const CircuitPortId& circuit_port_id, - const size_t& port_size) { +void CircuitLibrary::set_port_size(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const size_t& port_size) { /* validate the circuit_port_id */ VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); port_sizes_[circuit_model_id][circuit_port_id] = port_size; @@ -610,6 +634,16 @@ void CircuitLibrary::set_port_inv_prefix(const CircuitModelId& circuit_model_id, return; } +/* Set the default value for a port of a circuit model */ +void CircuitLibrary::set_port_default_value(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const size_t& default_value) { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + port_default_values_[circuit_model_id][circuit_port_id] = default_value; + return; +} + /* Set the is_mode_select for a port of a circuit model */ void CircuitLibrary::set_port_is_mode_select(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id, @@ -822,18 +856,8 @@ void CircuitLibrary::set_buffer_type(const CircuitModelId& circuit_model_id, return; } -void CircuitLibrary::set_buffer_location_map(const CircuitModelId& circuit_model_id, - const std::string& location_map) { - /* validate the circuit_model_id */ - VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); - /* validate that the type of this circuit_model should be BUFFER or INVERTER */ - VTR_ASSERT_SAFE(SPICE_MODEL_INVBUF == circuit_model_type(circuit_model_id)); - buffer_location_maps_[circuit_model_id] = location_map; - return; -} - void CircuitLibrary::set_buffer_size(const CircuitModelId& circuit_model_id, - const size_t& buffer_size) { + const float& buffer_size) { /* validate the circuit_model_id */ VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); /* validate that the type of this circuit_model should be BUFFER or INVERTER */ @@ -874,7 +898,7 @@ void CircuitLibrary::set_pass_gate_logic_type(const CircuitModelId& circuit_mode } void CircuitLibrary::set_pass_gate_logic_nmos_size(const CircuitModelId& circuit_model_id, - const size_t& nmos_size) { + const float& nmos_size) { /* validate the circuit_model_id */ VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); /* validate that the type of this circuit_model should be BUFFER or INVERTER */ @@ -884,7 +908,7 @@ void CircuitLibrary::set_pass_gate_logic_nmos_size(const CircuitModelId& circuit } void CircuitLibrary::set_pass_gate_logic_pmos_size(const CircuitModelId& circuit_model_id, - const size_t& pmos_size) { + const float& pmos_size) { /* validate the circuit_model_id */ VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); /* validate that the type of this circuit_model should be BUFFER or INVERTER */ @@ -955,6 +979,18 @@ void CircuitLibrary::set_lut_is_fracturable(const CircuitModelId& circuit_model_ return; } +/* Gate-related parameters */ +void CircuitLibrary::set_gate_type(const CircuitModelId& circuit_model_id, + const enum e_spice_model_gate_type& gate_type) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* validate that the type of this circuit_model should be GATE */ + VTR_ASSERT_SAFE(SPICE_MODEL_GATE == circuit_model_type(circuit_model_id)); + gate_types_[circuit_model_id] = gate_type; + return; +} + + /* RRAM-related design technology information */ void CircuitLibrary::set_rram_rlrs(const CircuitModelId& circuit_model_id, const float& rlrs) { @@ -1079,6 +1115,7 @@ void CircuitLibrary::set_circuit_model_buffer(const CircuitModelId& circuit_mode buffer_existence_[circuit_model_id].resize(size_t(buffer_type) + 1); buffer_circuit_model_names_[circuit_model_id].resize(size_t(buffer_type) + 1); buffer_circuit_model_ids_[circuit_model_id].resize(size_t(buffer_type) + 1); + buffer_location_maps_[circuit_model_id].resize(size_t(buffer_type) + 1); } /* Now we are in the range, assign values */ buffer_existence_[circuit_model_id][size_t(buffer_type)] = existence; 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 b129ab089..04eb75fd5 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -55,7 +55,7 @@ #include "vtr_vector.h" #include "vtr_range.h" -#include "spice_types.h" +#include "circuit_types.h" /************************************************************************ * Create strong id for Circuit Models/Ports to avoid illegal type casting @@ -238,6 +238,7 @@ class CircuitLibrary { std::string port_prefix(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; std::string port_lib_name(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; std::string port_inv_prefix(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; + size_t port_default_value(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; bool port_is_mode_select(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; bool port_is_global(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; bool port_is_reset(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; @@ -273,16 +274,18 @@ class CircuitLibrary { const bool& existence, const std::string& circuit_model_name); void set_circuit_model_lut_intermediate_buffer(const CircuitModelId& circuit_model_id, const bool& existence, const std::string& circuit_model_name); + void set_circuit_model_lut_intermediate_buffer_location_map(const CircuitModelId& circuit_model_id, + const std::string& location_map); /* Pass-gate-related parameters */ void set_circuit_model_pass_gate_logic(const CircuitModelId& circuit_model_id, const std::string& circuit_model_name); /* Port information */ CircuitPortId add_circuit_model_port(const CircuitModelId& circuit_model_id); - void set_port_types(const CircuitModelId& circuit_model_id, - const CircuitPortId& circuit_port_id, - const enum e_spice_model_port_type& port_type); - void set_port_sizes(const CircuitModelId& circuit_model_id, - const CircuitPortId& circuit_port_id, - const size_t& port_size); + void set_port_type(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const enum e_spice_model_port_type& port_type); + void set_port_size(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const size_t& port_size); void set_port_prefix(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id, const std::string& port_prefix); @@ -292,6 +295,9 @@ class CircuitLibrary { void set_port_inv_prefix(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id, const std::string& inv_prefix); + void set_port_default_value(const CircuitModelId& circuit_model_id, + const CircuitPortId& circuit_port_id, + const size_t& default_val); void set_port_is_mode_select(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id, const bool& is_mode_select); @@ -349,10 +355,8 @@ class CircuitLibrary { /* Buffer/Inverter-related parameters */ void set_buffer_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_buffer_type& buffer_type); - void set_buffer_location_map(const CircuitModelId& circuit_model_id, - const std::string& location_map); void set_buffer_size(const CircuitModelId& circuit_model_id, - const size_t& buffer_size); + const float& buffer_size); void set_buffer_num_levels(const CircuitModelId& circuit_model_id, const size_t& num_levels); void set_buffer_f_per_stage(const CircuitModelId& circuit_model_id, @@ -361,9 +365,9 @@ class CircuitLibrary { void set_pass_gate_logic_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_pass_gate_logic_type& pass_gate_logic_type); void set_pass_gate_logic_nmos_size(const CircuitModelId& circuit_model_id, - const size_t& nmos_size); + const float& nmos_size); void set_pass_gate_logic_pmos_size(const CircuitModelId& circuit_model_id, - const size_t& pmos_size); + const float& pmos_size); /* Multiplexer-related parameters */ void set_mux_structure(const CircuitModelId& circuit_model_id, const enum e_spice_model_structure& mux_structure); @@ -378,6 +382,9 @@ class CircuitLibrary { /* LUT-related parameters */ void set_lut_is_fracturable(const CircuitModelId& circuit_model_id, const bool& is_fracturable); + /* Gate-related parameters */ + void set_gate_type(const CircuitModelId& circuit_model_id, + const enum e_spice_model_gate_type& gate_type); /* RRAM-related design technology information */ void set_rram_rlrs(const CircuitModelId& circuit_model_id, const float& rlrs); @@ -444,6 +451,7 @@ class CircuitLibrary { vtr::vector> buffer_existence_; vtr::vector> buffer_circuit_model_names_; vtr::vector> buffer_circuit_model_ids_; + vtr::vector> buffer_location_maps_; /* Pass-gate-related parameters */ vtr::vector pass_gate_logic_circuit_model_names_; @@ -456,6 +464,7 @@ class CircuitLibrary { vtr::vector> port_prefix_; vtr::vector> port_lib_names_; vtr::vector> port_inv_prefix_; + vtr::vector> port_default_values_; vtr::vector> port_is_mode_select_; vtr::vector> port_is_global_; vtr::vector> port_is_reset_; @@ -490,14 +499,13 @@ class CircuitLibrary { /* Buffer/Inverter-related parameters */ vtr::vector buffer_types_; - vtr::vector buffer_location_maps_; - vtr::vector buffer_sizes_; + vtr::vector buffer_sizes_; vtr::vector buffer_num_levels_; vtr::vector buffer_f_per_stage_; /* Pass-gate-related parameters */ vtr::vector pass_gate_logic_types_; - vtr::vector> pass_gate_logic_sizes_; /* x=> nmos_size; y => pmos_size */ + vtr::vector> pass_gate_logic_sizes_; /* x=> nmos_size; y => pmos_size */ /* Multiplexer-related parameters */ vtr::vector mux_structure_; @@ -509,6 +517,9 @@ class CircuitLibrary { /* LUT-related parameters */ vtr::vector lut_is_fracturable_; + /* Gate-related parameters */ + vtr::vector gate_types_; + /* RRAM-related design technology information */ vtr::vector> rram_res_; /* x => R_LRS, y => R_HRS */ vtr::vector> wprog_set_; /* x => wprog_set_nmos, y=> wprog_set_pmos */ diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_types.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_types.h new file mode 100644 index 000000000..c13e91934 --- /dev/null +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_types.h @@ -0,0 +1,144 @@ +/********************************************************** + * MIT License + * + * Copyright (c) 2018 LNIS - The University of Utah + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ***********************************************************************/ + +/************************************************************************ + * Filename: circuit_types.h + * Created by: Xifan Tang + * Change history: + * +-------------------------------------+ + * | Date | Author | Notes + * +-------------------------------------+ + * | 2019/08/08 | Xifan Tang | Created + * +-------------------------------------+ + ***********************************************************************/ + +/* IMPORTANT: + * The following preprocessing flags are added to + * avoid compilation error when this headers are included in more than 1 times + */ +#ifndef CIRCUIT_TYPES_H +#define CIRCUIT_TYPES_H + +/************************************************************************ + * This file includes basic enumeration types for circuit models + ***********************************************************************/ +/* + * Notes in include header files in a head file + * Only include the neccessary header files + * that is required by the data types in the function/class declarations! + */ +/* Header files should be included in a sequence */ +/* Standard header files required go first */ + +enum spice_model_delay_type { + SPICE_MODEL_DELAY_RISE, + SPICE_MODEL_DELAY_FALL, + NUM_CIRCUIT_MODEL_DELAY_TYPES +}; + +/*Struct for a SPICE model of a module*/ +enum e_spice_model_type { + SPICE_MODEL_CHAN_WIRE, + SPICE_MODEL_WIRE, + SPICE_MODEL_MUX, + SPICE_MODEL_LUT, + SPICE_MODEL_FF, + SPICE_MODEL_SRAM, + SPICE_MODEL_HARDLOGIC, + SPICE_MODEL_SCFF, + SPICE_MODEL_IOPAD, + SPICE_MODEL_INVBUF, + SPICE_MODEL_PASSGATE, + SPICE_MODEL_GATE, + NUM_CIRCUIT_MODEL_TYPES +}; + +enum e_spice_model_design_tech { + SPICE_MODEL_DESIGN_CMOS, + SPICE_MODEL_DESIGN_RRAM, + NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES +}; + +enum e_spice_model_structure { + SPICE_MODEL_STRUCTURE_TREE, + SPICE_MODEL_STRUCTURE_ONELEVEL, + SPICE_MODEL_STRUCTURE_MULTILEVEL, + SPICE_MODEL_STRUCTURE_CROSSBAR, + NUM_CIRCUIT_MODEL_STRUCTURE_TYPES +}; + +enum e_spice_model_buffer_type { + SPICE_MODEL_BUF_INV, + SPICE_MODEL_BUF_BUF, + NUM_CIRCUIT_MODEL_BUF_TYPES +}; + +enum e_spice_model_pass_gate_logic_type { + SPICE_MODEL_PASS_GATE_TRANSMISSION, + SPICE_MODEL_PASS_GATE_TRANSISTOR, + NUM_CIRCUIT_MODEL_PASS_GATE_TYPES +}; + +enum e_spice_model_gate_type { + SPICE_MODEL_GATE_AND, + SPICE_MODEL_GATE_OR, + SPICE_MODEL_GATE_MUX2, + NUM_SPICE_MODEL_GATE_TYPES +}; + +enum e_wire_model_type { + WIRE_MODEL_PIE, + WIRE_MODEL_T, + NUM_WIRE_MODEL_TYPES, +}; + +enum e_spice_model_port_type { + SPICE_MODEL_PORT_INPUT, + SPICE_MODEL_PORT_OUTPUT, + SPICE_MODEL_PORT_INOUT, + SPICE_MODEL_PORT_CLOCK, + SPICE_MODEL_PORT_SRAM, + SPICE_MODEL_PORT_BL, + SPICE_MODEL_PORT_BLB, + SPICE_MODEL_PORT_WL, + SPICE_MODEL_PORT_WLB, + NUM_CIRCUIT_MODEL_PORT_TYPES +}; + +/* For SRAM */ +enum e_sram_orgz { + SPICE_SRAM_STANDALONE, /* SRAMs are organized and accessed as standalone elements */ + SPICE_SRAM_SCAN_CHAIN, /* SRAMs are organized and accessed by a scan-chain */ + SPICE_SRAM_MEMORY_BANK, /* SRAMs are organized and accessed by memory bank */ + SPICE_SRAM_LOCAL_ENCODER, /* SRAMs are organized and accessed by a local encoder */ + NUM_CIRCUIT_MODEL_SRAM_ORGZ_TYPES +}; + + +#endif + +/************************************************************************ + * End of file : circuit_types.h + ***********************************************************************/ + diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h index d16c2de5d..1c333eb70 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/spice_types.h @@ -3,6 +3,7 @@ #include "util.h" #include "linkedlist.h" +#include "circuit_library.h" /* Xifan TANG: Spice support*/ enum e_spice_tech_lib_type { @@ -10,61 +11,6 @@ enum e_spice_tech_lib_type { SPICE_LIB_ACADEMIA }; -enum spice_model_delay_type { - SPICE_MODEL_DELAY_RISE, - SPICE_MODEL_DELAY_FALL, - NUM_CIRCUIT_MODEL_DELAY_TYPES -}; - -/*Struct for a SPICE model of a module*/ -enum e_spice_model_type { - SPICE_MODEL_CHAN_WIRE, - SPICE_MODEL_WIRE, - SPICE_MODEL_MUX, - SPICE_MODEL_LUT, - SPICE_MODEL_FF, - SPICE_MODEL_SRAM, - SPICE_MODEL_HARDLOGIC, - SPICE_MODEL_SCFF, - SPICE_MODEL_IOPAD, - SPICE_MODEL_INVBUF, - SPICE_MODEL_PASSGATE, - SPICE_MODEL_GATE, - NUM_CIRCUIT_MODEL_TYPES -}; - -enum e_spice_model_design_tech { - SPICE_MODEL_DESIGN_CMOS, - SPICE_MODEL_DESIGN_RRAM, - NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES -}; - -enum e_spice_model_structure { - SPICE_MODEL_STRUCTURE_TREE, - SPICE_MODEL_STRUCTURE_ONELEVEL, - SPICE_MODEL_STRUCTURE_MULTILEVEL, - SPICE_MODEL_STRUCTURE_CROSSBAR, - NUM_CIRCUIT_MODEL_STRUCTURE_TYPES -}; - -enum e_spice_model_buffer_type { - SPICE_MODEL_BUF_INV, - SPICE_MODEL_BUF_BUF, - NUM_CIRCUIT_MODEL_BUF_TYPES -}; - -enum e_spice_model_pass_gate_logic_type { - SPICE_MODEL_PASS_GATE_TRANSMISSION, - SPICE_MODEL_PASS_GATE_TRANSISTOR, - NUM_CIRCUIT_MODEL_PASS_GATE_TYPES -}; - -enum e_spice_model_gate_type { - SPICE_MODEL_GATE_AND, - SPICE_MODEL_GATE_OR, - SPICE_MODEL_GATE_MUX2 -}; - /* Transistor-level basic informations*/ enum e_spice_trans_type { SPICE_TRANS_NMOS, @@ -73,25 +19,6 @@ enum e_spice_trans_type { SPICE_TRANS_IO_PMOS }; -enum e_wire_model_type { - WIRE_MODEL_PIE, - WIRE_MODEL_T, - NUM_WIRE_MODEL_TYPES, -}; - -enum e_spice_model_port_type { - SPICE_MODEL_PORT_INPUT, - SPICE_MODEL_PORT_OUTPUT, - SPICE_MODEL_PORT_INOUT, - SPICE_MODEL_PORT_CLOCK, - SPICE_MODEL_PORT_SRAM, - SPICE_MODEL_PORT_BL, - SPICE_MODEL_PORT_BLB, - SPICE_MODEL_PORT_WL, - SPICE_MODEL_PORT_WLB, - NUM_CIRCUIT_MODEL_PORT_TYPES -}; - /* For process corner */ enum e_process_corner { BEST_CORNER, @@ -99,15 +26,6 @@ enum e_process_corner { WORST_CORNER }; -/* For SRAM */ -enum e_sram_orgz { - SPICE_SRAM_STANDALONE, /* SRAMs are organized and accessed as standalone elements */ - SPICE_SRAM_SCAN_CHAIN, /* SRAMs are organized and accessed by a scan-chain */ - SPICE_SRAM_MEMORY_BANK, /* SRAMs are organized and accessed by memory bank */ - SPICE_SRAM_LOCAL_ENCODER, /* SRAMs are organized and accessed by a local encoder */ - NUM_CIRCUIT_MODEL_SRAM_ORGZ_TYPES -}; - enum e_spice_accuracy_type { SPICE_FRAC, SPICE_ABS }; @@ -450,6 +368,8 @@ struct s_spice { t_spice_tech_lib tech_lib; int num_spice_model; t_spice_model* spice_models; + /* Circuit library, object to replace the legacy spice_models */ + CircuitLibrary circuit_lib; }; /* Information needed to build a Multiplexer architecture*/ diff --git a/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c b/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c index 89c3995a8..5c5d38d3c 100644 --- a/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c +++ b/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c @@ -10,6 +10,8 @@ #include "read_xml_spice_util.h" #include "read_xml_spice.h" +#include "circuit_library.h" + /*********** Subroutines Declaration (only called in this source file) **********/ static void ProcessSpiceMeasParams(ezxml_t Parent, t_spice_meas_params* meas_params); @@ -768,6 +770,8 @@ static void ProcessSpiceModelPort(ezxml_t Node, ||(SPICE_MODEL_PORT_WLB == port->type)) { port->inv_spice_model_name = my_strdup(FindProperty(Node, "inv_circuit_model_name", FALSE)); ezxml_set_attr(Node, "inv_circuit_model_name", NULL); + } else { + port->inv_spice_model_name = NULL; } /* Add a feature to enable/disable the configuration encoders for multiplexers */ @@ -914,6 +918,13 @@ static void ProcessSpiceModel(ezxml_t Parent, /* Check the design technology settings*/ Node = ezxml_child(Parent, "design_technology"); + /* Initialize */ + spice_model->design_tech_info.buffer_info = NULL; + spice_model->design_tech_info.pass_gate_info = NULL; + spice_model->design_tech_info.rram_info = NULL; + spice_model->design_tech_info.mux_info = NULL; + spice_model->design_tech_info.lut_info = NULL; + spice_model->design_tech_info.gate_info = NULL; if (Node) { /* Specify if this spice_model is power gated or not*/ spice_model->design_tech_info.power_gated = GetBooleanProperty(Node,"power_gated", FALSE, FALSE); @@ -941,7 +952,7 @@ static void ProcessSpiceModel(ezxml_t Parent, } else if (0 == strcmp(FindProperty(Node,"type",TRUE),"rram")) { spice_model->design_tech = SPICE_MODEL_DESIGN_RRAM; /* Malloc RRAM info */ - spice_model->design_tech_info.rram_info = (t_spice_model_rram*)my_malloc(sizeof(t_spice_model_rram)); + spice_model->design_tech_info.rram_info = (t_spice_model_rram*)my_calloc(1, sizeof(t_spice_model_rram)); /* Fill information */ ProcessSpiceModelRRAM(Node, spice_model->design_tech_info.rram_info); } else { @@ -955,7 +966,7 @@ static void ProcessSpiceModel(ezxml_t Parent, spice_model->design_tech_info.mux_info = NULL; if (SPICE_MODEL_MUX == spice_model->type) { /* Malloc */ - spice_model->design_tech_info.mux_info = (t_spice_model_mux*)my_malloc(sizeof(t_spice_model_mux)); + spice_model->design_tech_info.mux_info = (t_spice_model_mux*)my_calloc(1, sizeof(t_spice_model_mux)); /* Fill information */ ProcessSpiceModelMUX(Node, spice_model, spice_model->design_tech_info.mux_info); } @@ -964,11 +975,11 @@ static void ProcessSpiceModel(ezxml_t Parent, spice_model->design_tech_info.lut_info = NULL; if (SPICE_MODEL_LUT == spice_model->type) { /* Malloc */ - spice_model->design_tech_info.lut_info = (t_spice_model_lut*)my_malloc(sizeof(t_spice_model_lut)); + spice_model->design_tech_info.lut_info = (t_spice_model_lut*)my_calloc(1, sizeof(t_spice_model_lut)); /* Fill information */ ProcessSpiceModelLUT(Node, spice_model->design_tech_info.lut_info); /* Malloc */ - spice_model->design_tech_info.mux_info = (t_spice_model_mux*)my_malloc(sizeof(t_spice_model_mux)); + spice_model->design_tech_info.mux_info = (t_spice_model_mux*)my_calloc(1, sizeof(t_spice_model_mux)); /* Fill information */ /* Default: tree, no const_inputs */ spice_model->design_tech_info.mux_info->structure = SPICE_MODEL_STRUCTURE_TREE; @@ -1041,7 +1052,7 @@ static void ProcessSpiceModel(ezxml_t Parent, spice_model->input_buffer = NULL; if (Node) { /*Alloc*/ - spice_model->input_buffer = (t_spice_model_buffer*)my_malloc(sizeof(t_spice_model_buffer)); + spice_model->input_buffer = (t_spice_model_buffer*)my_calloc(1, sizeof(t_spice_model_buffer)); ProcessSpiceModelBuffer(Node,spice_model->input_buffer); FreeNode(Node); } else if (SPICE_MODEL_INVBUF != spice_model->type) { @@ -1053,7 +1064,7 @@ static void ProcessSpiceModel(ezxml_t Parent, Node = ezxml_child(Parent, "output_buffer"); spice_model->output_buffer = NULL; if (Node) { - spice_model->output_buffer = (t_spice_model_buffer*)my_malloc(sizeof(t_spice_model_buffer)); + spice_model->output_buffer = (t_spice_model_buffer*)my_calloc(1, sizeof(t_spice_model_buffer)); ProcessSpiceModelBuffer(Node,spice_model->output_buffer); FreeNode(Node); } else if (SPICE_MODEL_INVBUF != spice_model->type) { @@ -1066,7 +1077,7 @@ static void ProcessSpiceModel(ezxml_t Parent, Node = ezxml_child(Parent, "pass_gate_logic"); spice_model->pass_gate_logic = NULL; if (Node) { - spice_model->pass_gate_logic = (t_spice_model_pass_gate_logic*)my_malloc(sizeof(t_spice_model_pass_gate_logic)); + spice_model->pass_gate_logic = (t_spice_model_pass_gate_logic*)my_calloc(1, sizeof(t_spice_model_pass_gate_logic)); /* Find spice_model_name */ spice_model->pass_gate_logic->spice_model_name = my_strdup(FindProperty(Node, "circuit_model_name", TRUE)); ezxml_set_attr(Node, "circuit_model_name", NULL); @@ -1082,7 +1093,7 @@ static void ProcessSpiceModel(ezxml_t Parent, /* Find All the ports*/ spice_model->num_port = CountChildren(Parent, "port", 1); /*Alloc*/ - spice_model->ports = (t_spice_model_port*)my_malloc(spice_model->num_port*sizeof(t_spice_model_port)); + spice_model->ports = (t_spice_model_port*)my_calloc(spice_model->num_port, sizeof(t_spice_model_port)); /* Assign each found spice model*/ for (iport = 0; iport < spice_model->num_port; iport++) { Cur = FindFirstElement(Parent, "port", TRUE); @@ -1091,8 +1102,9 @@ static void ProcessSpiceModel(ezxml_t Parent, } /* Read in wire parameters */ + spice_model->wire_param = NULL; if ((SPICE_MODEL_CHAN_WIRE == spice_model->type)||(SPICE_MODEL_WIRE == spice_model->type)) { - spice_model->wire_param = (t_spice_model_wire_param*)my_malloc(sizeof(t_spice_model_wire_param)); + spice_model->wire_param = (t_spice_model_wire_param*)my_calloc(1, sizeof(t_spice_model_wire_param)); Node = ezxml_child(Parent, "wire_param"); if (Node) { ProcessSpiceModelWireParam(Node,spice_model->wire_param); @@ -1107,7 +1119,7 @@ static void ProcessSpiceModel(ezxml_t Parent, /* Find delay info */ spice_model->num_delay_info = CountChildren(Parent, "delay_matrix", 0); /*Alloc*/ - spice_model->delay_info = (t_spice_model_delay_info*) my_malloc(spice_model->num_delay_info * sizeof(t_spice_model_delay_info)); + spice_model->delay_info = (t_spice_model_delay_info*) my_calloc(spice_model->num_delay_info, sizeof(t_spice_model_delay_info)); /* Assign each found spice model*/ for (i = 0; i < spice_model->num_delay_info; i++) { Cur = FindFirstElement(Parent, "delay_matrix", TRUE); @@ -1508,6 +1520,232 @@ static void ProcessSpiceTechLibTransistors(ezxml_t Parent, return; } +/* Build a circuit library based on the spice_models + * This function does a quick conversion, so that we can proceed to update the downstream codes + * TODO: The circuit library should be incrementally built during XML parsing + * when the downstream is updated, the legacy spice_models will be removed + */ +static +CircuitLibrary build_circuit_library(int num_spice_model, t_spice_model* spice_models) { + CircuitLibrary circuit_lib; + + /* Go spice_model by spice_model */ + for (int imodel = 0; imodel < num_spice_model; ++imodel) { + /* Add a spice model to the circuit_lib */ + CircuitModelId model_id = circuit_lib.add_circuit_model(); + /* Fill fundamental attributes */ + /* Basic information*/ + circuit_lib.set_circuit_model_type(model_id, spice_models[imodel].type); + + std::string name(spice_models[imodel].name); + circuit_lib.set_circuit_model_name(model_id, name); + + std::string prefix(spice_models[imodel].prefix); + circuit_lib.set_circuit_model_prefix(model_id, prefix); + + if (NULL != spice_models[imodel].verilog_netlist) { + std::string verilog_netlist(spice_models[imodel].verilog_netlist); + circuit_lib.set_circuit_model_verilog_netlist(model_id, verilog_netlist); + } + + if (NULL != spice_models[imodel].model_netlist) { + std::string spice_netlist(spice_models[imodel].model_netlist); + circuit_lib.set_circuit_model_spice_netlist(model_id, spice_netlist); + } + + circuit_lib.set_circuit_model_is_default(model_id, 0 != spice_models[imodel].is_default); + + /* Verilog generatioin options */ + circuit_lib.set_circuit_model_dump_structural_verilog(model_id, TRUE == spice_models[imodel].dump_structural_verilog); + + circuit_lib.set_circuit_model_dump_explicit_port_map(model_id, TRUE == spice_models[imodel].dump_explicit_port_map); + + /* Design technology information */ + circuit_lib.set_circuit_model_design_tech_type(model_id, spice_models[imodel].design_tech); + + circuit_lib.set_circuit_model_is_power_gated(model_id, TRUE == spice_models[imodel].design_tech_info.power_gated); + + /* Buffer linking information */ + if (NULL != spice_models[imodel].input_buffer) { + std::string model_name; + if (NULL != spice_models[imodel].input_buffer->spice_model_name) { + model_name = spice_models[imodel].input_buffer->spice_model_name; + } + circuit_lib.set_circuit_model_input_buffer(model_id, 0 != spice_models[imodel].input_buffer->exist, model_name); + } + if (NULL != spice_models[imodel].output_buffer) { + std::string model_name; + if (NULL != spice_models[imodel].output_buffer->spice_model_name) { + model_name = spice_models[imodel].output_buffer->spice_model_name; + } + circuit_lib.set_circuit_model_output_buffer(model_id, 0 != spice_models[imodel].output_buffer->exist, model_name); + } + if (NULL != spice_models[imodel].lut_input_buffer) { + std::string model_name; + if (NULL != spice_models[imodel].lut_input_buffer->spice_model_name) { + model_name = spice_models[imodel].lut_input_buffer->spice_model_name; + } + circuit_lib.set_circuit_model_lut_input_buffer(model_id, 0 != spice_models[imodel].lut_input_buffer->exist, model_name); + } + if (NULL != spice_models[imodel].lut_input_inverter) { + std::string model_name; + if (NULL != spice_models[imodel].lut_input_inverter->spice_model_name) { + model_name = spice_models[imodel].lut_input_inverter->spice_model_name; + } + circuit_lib.set_circuit_model_lut_input_inverter(model_id, 0 != spice_models[imodel].lut_input_inverter->exist, model_name); + } + if (NULL != spice_models[imodel].lut_intermediate_buffer) { + std::string model_name; + if (NULL != spice_models[imodel].lut_intermediate_buffer->spice_model_name) { + model_name = spice_models[imodel].lut_intermediate_buffer->spice_model_name; + } + circuit_lib.set_circuit_model_lut_intermediate_buffer(model_id, 0 != spice_models[imodel].lut_intermediate_buffer->exist, model_name); + + std::string model_location_map; + if (NULL != spice_models[imodel].lut_intermediate_buffer->location_map) { + model_location_map = spice_models[imodel].lut_intermediate_buffer->location_map; + } + circuit_lib.set_circuit_model_lut_intermediate_buffer_location_map(model_id, model_location_map); + } + + /* Pass-gate-logic linking information */ + if (NULL != spice_models[imodel].pass_gate_logic) { + std::string model_name(spice_models[imodel].pass_gate_logic->spice_model_name); + circuit_lib.set_circuit_model_pass_gate_logic(model_id, model_name); + } + + /* Buffer information */ + if (NULL != spice_models[imodel].design_tech_info.buffer_info) { + circuit_lib.set_buffer_type(model_id, spice_models[imodel].design_tech_info.buffer_info->type); + circuit_lib.set_buffer_size(model_id, spice_models[imodel].design_tech_info.buffer_info->size); + if (TRUE == spice_models[imodel].design_tech_info.buffer_info->tapered_buf) { + circuit_lib.set_buffer_num_levels(model_id, spice_models[imodel].design_tech_info.buffer_info->tap_buf_level); + circuit_lib.set_buffer_f_per_stage(model_id, spice_models[imodel].design_tech_info.buffer_info->f_per_stage); + } + } + + /* Pass-gate information */ + if (NULL != spice_models[imodel].design_tech_info.pass_gate_info) { + circuit_lib.set_pass_gate_logic_type(model_id, spice_models[imodel].design_tech_info.pass_gate_info->type); + circuit_lib.set_pass_gate_logic_nmos_size(model_id, spice_models[imodel].design_tech_info.pass_gate_info->nmos_size); + circuit_lib.set_pass_gate_logic_pmos_size(model_id, spice_models[imodel].design_tech_info.pass_gate_info->pmos_size); + } + + /* Multiplexer information */ + if (NULL != spice_models[imodel].design_tech_info.mux_info) { + circuit_lib.set_mux_structure(model_id, spice_models[imodel].design_tech_info.mux_info->structure); + circuit_lib.set_mux_num_levels(model_id, spice_models[imodel].design_tech_info.mux_info->mux_num_level); + if (TRUE == spice_models[imodel].design_tech_info.mux_info->add_const_input) { + circuit_lib.set_mux_const_input_value(model_id, spice_models[imodel].design_tech_info.mux_info->const_input_val); + } + circuit_lib.set_mux_use_local_encoder(model_id, TRUE == spice_models[imodel].design_tech_info.mux_info->local_encoder); + circuit_lib.set_mux_use_advanced_rram_design(model_id, TRUE == spice_models[imodel].design_tech_info.mux_info->advanced_rram_design); + } + + /* LUT information */ + if (NULL != spice_models[imodel].design_tech_info.lut_info) { + circuit_lib.set_lut_is_fracturable(model_id, TRUE == spice_models[imodel].design_tech_info.lut_info->frac_lut); + } + + /* Gate information */ + if (NULL != spice_models[imodel].design_tech_info.gate_info) { + circuit_lib.set_gate_type(model_id, spice_models[imodel].design_tech_info.gate_info->type); + } + + /* RRAM information */ + if (NULL != spice_models[imodel].design_tech_info.rram_info) { + circuit_lib.set_rram_rlrs(model_id, spice_models[imodel].design_tech_info.rram_info->ron); + circuit_lib.set_rram_rhrs(model_id, spice_models[imodel].design_tech_info.rram_info->roff); + circuit_lib.set_rram_wprog_set_nmos(model_id, spice_models[imodel].design_tech_info.rram_info->wprog_set_nmos); + circuit_lib.set_rram_wprog_set_pmos(model_id, spice_models[imodel].design_tech_info.rram_info->wprog_set_pmos); + circuit_lib.set_rram_wprog_reset_nmos(model_id, spice_models[imodel].design_tech_info.rram_info->wprog_reset_nmos); + circuit_lib.set_rram_wprog_reset_pmos(model_id, spice_models[imodel].design_tech_info.rram_info->wprog_reset_pmos); + } + + /* Delay information */ + for (int idelay = 0; idelay < spice_models[imodel].num_delay_info; ++idelay) { + circuit_lib.add_delay_info(model_id, spice_models[imodel].delay_info[idelay].type); + + std::string in_port_names(spice_models[imodel].delay_info[idelay].in_port_name); + circuit_lib.set_delay_in_port_names(model_id, spice_models[imodel].delay_info[idelay].type, in_port_names); + + std::string out_port_names(spice_models[imodel].delay_info[idelay].out_port_name); + circuit_lib.set_delay_out_port_names(model_id, spice_models[imodel].delay_info[idelay].type, out_port_names); + + std::string delay_values(spice_models[imodel].delay_info[idelay].value); + circuit_lib.set_delay_values(model_id, spice_models[imodel].delay_info[idelay].type, delay_values); + } + + /* Wire parameters */ + if (NULL != spice_models[imodel].wire_param) { + circuit_lib.set_wire_type(model_id, spice_models[imodel].wire_param->type); + circuit_lib.set_wire_r(model_id, spice_models[imodel].wire_param->res_val); + circuit_lib.set_wire_c(model_id, spice_models[imodel].wire_param->cap_val); + circuit_lib.set_wire_num_levels(model_id, spice_models[imodel].wire_param->level); + } + + /* Ports */ + for (int iport = 0; iport < spice_models[imodel].num_port; ++iport) { + CircuitPortId port_id = circuit_lib.add_circuit_model_port(model_id); + /* Fill fundamental attributes */ + circuit_lib.set_port_type(model_id, port_id, spice_models[imodel].ports[iport].type); + + circuit_lib.set_port_size(model_id, port_id, spice_models[imodel].ports[iport].size); + + std::string port_prefix(spice_models[imodel].ports[iport].prefix); + circuit_lib.set_port_prefix(model_id, port_id, port_prefix); + + std::string port_lib_name(spice_models[imodel].ports[iport].lib_name); + circuit_lib.set_port_lib_name(model_id, port_id, port_lib_name); + + if (NULL != spice_models[imodel].ports[iport].inv_prefix) { + std::string port_inv_prefix(spice_models[imodel].ports[iport].inv_prefix); + circuit_lib.set_port_inv_prefix(model_id, port_id, port_inv_prefix); + } + + circuit_lib.set_port_default_value(model_id, port_id, spice_models[imodel].ports[iport].default_val); + + circuit_lib.set_port_is_mode_select(model_id, port_id, TRUE == spice_models[imodel].ports[iport].mode_select); + circuit_lib.set_port_is_global(model_id, port_id, TRUE == spice_models[imodel].ports[iport].is_global); + circuit_lib.set_port_is_reset(model_id, port_id, TRUE == spice_models[imodel].ports[iport].is_reset); + circuit_lib.set_port_is_set(model_id, port_id, TRUE == spice_models[imodel].ports[iport].is_set); + circuit_lib.set_port_is_config_enable(model_id, port_id, TRUE == spice_models[imodel].ports[iport].is_config_enable); + circuit_lib.set_port_is_prog(model_id, port_id, TRUE == spice_models[imodel].ports[iport].is_prog); + + if (NULL != spice_models[imodel].ports[iport].spice_model_name) { + std::string port_model_name(spice_models[imodel].ports[iport].spice_model_name); + circuit_lib.set_port_circuit_model_name(model_id, port_id, port_model_name); + } + + if (NULL != spice_models[imodel].ports[iport].inv_spice_model_name) { + std::string port_inv_model_name(spice_models[imodel].ports[iport].inv_spice_model_name); + circuit_lib.set_port_inv_circuit_model_name(model_id, port_id, port_inv_model_name); + } + + if (NULL != spice_models[imodel].ports[iport].tri_state_map) { + std::string port_tri_state_map(spice_models[imodel].ports[iport].tri_state_map); + circuit_lib.set_port_tri_state_map(model_id, port_id, port_tri_state_map); + } + + if (SPICE_MODEL_LUT == spice_models[imodel].type) { + circuit_lib.set_port_lut_frac_level(model_id, port_id, spice_models[imodel].ports[iport].lut_frac_level); + + std::vector port_lut_output_mask; + for (int ipin = 0; ipin < spice_models[imodel].ports[iport].size; ++ipin) { + port_lut_output_mask.push_back(spice_models[imodel].ports[iport].lut_output_mask[ipin]); + } + circuit_lib.set_port_lut_output_mask(model_id, port_id, port_lut_output_mask); + } + + if (SPICE_MODEL_PORT_SRAM == spice_models[imodel].ports[iport].type) { + circuit_lib.set_port_sram_orgz(model_id, port_id, spice_models[imodel].ports[iport].organization); + } + } + } + + return circuit_lib; +} + /* Process the SPICE Settings*/ void ProcessSpiceSettings(ezxml_t Parent, t_spice* spice) { @@ -1541,6 +1779,8 @@ void ProcessSpiceSettings(ezxml_t Parent, assert(imodel == spice->num_spice_model); FreeNode(Node); } + /* Build the CircuitLibrary here from spice_models */ + spice->circuit_lib = build_circuit_library(spice->num_spice_model, spice->spice_models); /* Check codes*/ check_tech_lib(spice->tech_lib, spice->num_spice_model, spice->spice_models); From c8d04c4f0018cbf85c76f531ba4d63044d69c4cc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 8 Aug 2019 21:20:28 -0600 Subject: [PATCH 10/18] plug in fast look-up builder --- .../fpga_spice_include/circuit_library.cpp | 134 +++++++++++++++++- .../SRC/fpga_spice_include/circuit_library.h | 22 ++- vpr7_x2p/libarchfpga/SRC/read_xml_spice.c | 6 + 3 files changed, 151 insertions(+), 11 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 6e067ce3e..b552ebd2b 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -54,6 +54,10 @@ CircuitLibrary::circuit_model_range CircuitLibrary::circuit_models() const { return vtr::make_range(circuit_model_ids_.begin(), circuit_model_ids_.end()); } +CircuitLibrary::circuit_port_range CircuitLibrary::ports(const CircuitModelId& circuit_model_id) const { + return vtr::make_range(port_ids_[circuit_model_id].begin(), port_ids_[circuit_model_id].end()); +} + /************************************************************************ * Public Accessors : Basic data query on Circuit Models ***********************************************************************/ @@ -153,6 +157,13 @@ bool CircuitLibrary::is_lut_intermediate_buffered(const CircuitModelId& circuit_ /************************************************************************ * Public Accessors : Basic data query on Circuit Porst ***********************************************************************/ +/* Access the type of a port of a circuit model */ +size_t CircuitLibrary::num_ports(const CircuitModelId& circuit_model_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + return port_ids_[circuit_model_id].size(); +} + /* Access the type of a port of a circuit model */ enum e_spice_model_port_type CircuitLibrary::port_type(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const { @@ -255,7 +266,7 @@ bool CircuitLibrary::port_is_prog(const CircuitModelId& circuit_model_id, * Public Accessors : Methods to find circuit model ***********************************************************************/ /* Find a circuit model by a given name and return its id */ -CircuitModelId CircuitLibrary::get_circuit_model_id_by_name(const std::string& name) const { +CircuitModelId CircuitLibrary::circuit_model(const std::string& name) const { CircuitModelId ret = CIRCUIT_MODEL_OPEN_ID; size_t num_found = 0; for (circuit_model_string_iterator it = circuit_model_names_.begin(); @@ -276,7 +287,7 @@ CircuitModelId CircuitLibrary::get_circuit_model_id_by_name(const std::string& n } /* Get the CircuitModelId of a default circuit model with a given type */ -CircuitModelId CircuitLibrary::get_default_circuit_model_id(const enum e_spice_model_type& type) const { +CircuitModelId CircuitLibrary::default_circuit_model(const enum e_spice_model_type& type) const { /* Default circuit model id is the first element by type in the fast look-up */ return circuit_model_lookup_[size_t(type)].front(); } @@ -406,6 +417,8 @@ void CircuitLibrary::set_circuit_model_type(const CircuitModelId& circuit_model_ /* validate the circuit_model_id */ VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); circuit_model_types_[circuit_model_id] = type; + /* Build the fast look-up for circuit models */ + build_circuit_model_lookup(); return; } @@ -591,6 +604,8 @@ void CircuitLibrary::set_port_type(const CircuitModelId& circuit_model_id, /* validate the circuit_port_id */ VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); port_types_[circuit_model_id][circuit_port_id] = port_type; + /* Build the fast look-up for circuit model ports */ + build_circuit_model_port_lookup(circuit_model_id); return; } @@ -1098,7 +1113,7 @@ void CircuitLibrary::set_wire_num_levels(const CircuitModelId& circuit_model_id, } /************************************************************************ - * Internal Mutators + * Internal Mutators: builders and linkers ***********************************************************************/ /* Set the information for a buffer * For a buffer type, we check if it is in the range of vector @@ -1124,21 +1139,112 @@ void CircuitLibrary::set_circuit_model_buffer(const CircuitModelId& circuit_mode return; } +/* Link the circuit_model_id for each port of a circuit model. + * We search the inv_circuit_model_name in the CircuitLibrary and + * configure the port inv_circuit_model_id + */ +void CircuitLibrary::link_port_circuit_model(const CircuitModelId& circuit_model_id) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Walk through each ports, get the port id and find the circuit model id by name */ + for (auto& port_id : ports(circuit_model_id)) { + /* Bypass empty name */ + if (true == port_circuit_model_names_[circuit_model_id][port_id].empty()) { + continue; + } + port_circuit_model_ids_[circuit_model_id][port_id] = circuit_model(port_circuit_model_names_[circuit_model_id][port_id]); + } + return; +} + /* Link the inv_circuit_model_id for each port of a circuit model. * We search the inv_circuit_model_name in the CircuitLibrary and * configure the port inv_circuit_model_id */ -void CircuitLibrary::set_circuit_model_port_inv_circuit_model(const CircuitModelId& circuit_model_id) { +void CircuitLibrary::link_port_inv_circuit_model(const CircuitModelId& circuit_model_id) { /* validate the circuit_model_id */ VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); - /* TODO: complete this function when port mutators are finished */ + /* Walk through each ports, get the port id and find the circuit model id by name */ + for (auto& port_id : ports(circuit_model_id)) { + /* Bypass empty name */ + if (true == port_inv_circuit_model_names_[circuit_model_id][port_id].empty()) { + continue; + } + port_inv_circuit_model_ids_[circuit_model_id][port_id] = circuit_model(port_inv_circuit_model_names_[circuit_model_id][port_id]); + } return; } +/* Link all the circuit model ids for each port of a circuit model */ +void CircuitLibrary::link_port_circuit_models(const CircuitModelId& circuit_model_id) { + link_port_circuit_model(circuit_model_id); + link_port_inv_circuit_model(circuit_model_id); + return; +} + +/* Link the buffer_circuit_model + * We search the buffer_circuit_model_name in the CircuitLibrary and + * configure the buffer_circuit_model_id + */ +void CircuitLibrary::link_buffer_circuit_model(const CircuitModelId& circuit_model_id) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Get the circuit model id by name, skip those with empty names*/ + for (size_t buffer_id = 0; buffer_id < buffer_circuit_model_names_[circuit_model_id].size(); ++buffer_id) { + if (true == buffer_circuit_model_names_[circuit_model_id][buffer_id].empty()) { + return; + } + buffer_circuit_model_ids_[circuit_model_id][buffer_id] = circuit_model(buffer_circuit_model_names_[circuit_model_id][buffer_id]); + } + return; +} + +/* Link the buffer_circuit_model + * We search the buffer_circuit_model_name in the CircuitLibrary and + * configure the buffer_circuit_model_id + */ +void CircuitLibrary::link_pass_gate_logic_circuit_model(const CircuitModelId& circuit_model_id) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Get the circuit model id by name, skip those with empty names*/ + if (true == pass_gate_logic_circuit_model_names_[circuit_model_id].empty()) { + return; + } + pass_gate_logic_circuit_model_ids_[circuit_model_id] = circuit_model(pass_gate_logic_circuit_model_names_[circuit_model_id]); + return; +} + +/* Build the links for attributes of each circuit_model by searching the circuit_model_names */ +void CircuitLibrary::build_circuit_model_links() { + /* Walk through each circuit model, build links one by one */ + for (auto& circuit_model_id : circuit_models()) { + /* Build links for buffers, pass-gates circuit_model */ + link_buffer_circuit_model(circuit_model_id); + link_pass_gate_logic_circuit_model(circuit_model_id); + /* Build links for ports */ + link_port_circuit_models(circuit_model_id); + } + return; +} + +/* Build the timing graph for a circuit models*/ +void CircuitLibrary::build_circuit_model_timing_graph(const CircuitModelId& circuit_model_id) { + return; +} + +/* Build the timing graph for a circuit models*/ +void CircuitLibrary::build_timing_graphs() { + /* Walk through each circuit model, build timing graph one by one */ + for (auto& circuit_model_id : circuit_models()) { + build_circuit_model_timing_graph(circuit_model_id); + } + return; +} /************************************************************************ * Internal mutators: build fast look-ups ***********************************************************************/ +/* Build fast look-up for circuit models */ void CircuitLibrary::build_circuit_model_lookup() { /* invalidate fast look-up */ invalidate_circuit_model_lookup(); @@ -1150,6 +1256,10 @@ void CircuitLibrary::build_circuit_model_lookup() { } /* Make the default circuit_model to be the first element for each type */ for (auto& type : circuit_model_lookup_) { + /* Skip zero-length parts of look-up */ + if (true == type.empty()) { + continue; + } /* if the first element is already a default model, we skip this */ if (true == circuit_model_is_default_[type[0]]) { continue; @@ -1167,6 +1277,20 @@ void CircuitLibrary::build_circuit_model_lookup() { return; } +/* Build fast look-up for circuit model ports */ +void CircuitLibrary::build_circuit_model_port_lookup(const CircuitModelId& circuit_model_id) { + /* invalidate fast look-up */ + invalidate_circuit_model_port_lookup(circuit_model_id); + /* Classify circuit models by type */ + circuit_model_port_lookup_[size_t(circuit_model_id)].resize(NUM_CIRCUIT_MODEL_PORT_TYPES); + /* Walk through circuit_models and categorize */ + for (auto& port_id : port_ids_[circuit_model_id]) { + circuit_model_port_lookup_[size_t(circuit_model_id)][port_type(circuit_model_id, port_id)].push_back(port_id); + } + return; +} + + /************************************************************************ * Internal invalidators/validators ***********************************************************************/ 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 04eb75fd5..612e99ff1 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -233,6 +233,8 @@ 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; std::string port_prefix(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; @@ -246,8 +248,8 @@ class CircuitLibrary { bool port_is_config_enable(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; bool port_is_prog(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; public: /* Public Accessors: Methods to find circuit model */ - CircuitModelId get_circuit_model_id_by_name(const std::string& name) const ; - CircuitModelId get_default_circuit_model_id(const enum e_spice_model_type& type) const; + CircuitModelId circuit_model(const std::string& name) const; + CircuitModelId default_circuit_model(const enum e_spice_model_type& type) const; public: /* Public Mutators */ CircuitModelId add_circuit_model(); /* Fundamental information */ @@ -407,11 +409,19 @@ class CircuitLibrary { const float& c_val); void set_wire_num_levels(const CircuitModelId& circuit_model_id, const size_t& num_level); - public: /* Internal mutators: link circuit_models */ + public: /* Public Mutators: builders */ void set_circuit_model_buffer(const CircuitModelId& circuit_model_id, const enum e_buffer_type buffer_type, const bool& existence, const std::string& circuit_model_name); - void set_circuit_model_port_inv_circuit_model(const CircuitModelId& circuit_model_id); + void link_port_circuit_model(const CircuitModelId& circuit_model_id); + void link_port_inv_circuit_model(const CircuitModelId& circuit_model_id); + void link_port_circuit_models(const CircuitModelId& circuit_model_id); + void link_buffer_circuit_model(const CircuitModelId& circuit_model_id); + void link_pass_gate_logic_circuit_model(const CircuitModelId& circuit_model_id); + void build_circuit_model_links(); + void build_circuit_model_timing_graph(const CircuitModelId& circuit_model_id); + void build_timing_graphs(); public: /* Internal mutators: build fast look-ups */ void build_circuit_model_lookup(); + void build_circuit_model_port_lookup(const CircuitModelId& circuit_model_id); private: /* Internal invalidators/validators */ /* Validators */ bool valid_circuit_model_id(const CircuitModelId& circuit_model_id) const; @@ -482,8 +492,8 @@ class CircuitLibrary { /* Timing graphs */ vtr::vector> edge_ids_; - vtr::vector>> port_in_edge_ids_; - vtr::vector>> port_out_edge_ids_; + vtr::vector>> port_in_edge_ids_; + vtr::vector>> port_out_edge_ids_; vtr::vector> edge_src_ports_; vtr::vector> edge_src_pin_ids_; vtr::vector> edge_sink_ports_; diff --git a/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c b/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c index 5c5d38d3c..ba7cb7cec 100644 --- a/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c +++ b/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c @@ -1743,6 +1743,12 @@ CircuitLibrary build_circuit_library(int num_spice_model, t_spice_model* spice_m } } + /* Build circuit_model links */ + circuit_lib.build_circuit_model_links(); + + /* Build timing graph */ + circuit_lib.build_timing_graphs(); + return circuit_lib; } From 6b5ac2e1ef9a1a6cd29bbcb7d17721e3a64e1bb9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 9 Aug 2019 12:45:03 -0600 Subject: [PATCH 11/18] 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_; From 3d7adb3dd974a0a1a0c17a25f8b59e3bb66682f8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 9 Aug 2019 15:52:28 -0600 Subject: [PATCH 12/18] start developing parsers for delay values --- .../fpga_spice_include/circuit_library.cpp | 131 ++++++++++++++++-- .../SRC/fpga_spice_include/circuit_library.h | 11 +- 2 files changed, 125 insertions(+), 17 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 132186cfe..dd7862c3c 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -66,8 +66,7 @@ std::vector CircuitLibrary::input_ports(const CircuitModelId& cir 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)) ) { + if ( false == is_input_port(circuit_model_id, port_id) ) { continue; } input_ports.push_back(port_id); @@ -81,12 +80,11 @@ std::vector CircuitLibrary::input_ports(const CircuitModelId& cir 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)) ) { + /* We skip input ports */ + if ( false == is_output_port(circuit_model_id, port_id) ) { continue; } - output_ports.push_back(port_id); + output_ports.push_back(port_id); } return output_ports; } @@ -201,9 +199,47 @@ bool CircuitLibrary::is_lut_intermediate_buffered(const CircuitModelId& circuit_ /************************************************************************ * Public Accessors : Basic data query on Circuit Porst ***********************************************************************/ + +/* identify if this port is an input port */ +bool CircuitLibrary::is_input_port(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const { + /* validate the circuit_model_id and circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + /* Only SPICE_MODEL_OUTPUT AND INOUT are considered as outputs */ + return ( (SPICE_MODEL_PORT_OUTPUT != port_type(circuit_model_id, circuit_port_id)) + && (SPICE_MODEL_PORT_INOUT != port_type(circuit_model_id, circuit_port_id)) ); +} + +/* identify if this port is an output port */ +bool CircuitLibrary::is_output_port(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const { + /* validate the circuit_model_id and circuit_port_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + /* Only SPICE_MODEL_OUTPUT AND INOUT are considered as outputs */ + return ( (SPICE_MODEL_PORT_OUTPUT == port_type(circuit_model_id, circuit_port_id)) + || (SPICE_MODEL_PORT_INOUT == port_type(circuit_model_id, circuit_port_id)) ); +} + +/* Given a name and return the port id */ +CircuitPortId CircuitLibrary::port(const CircuitModelId& circuit_model_id, const std::string& name) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Walk through the ports and try to find a matched name */ + CircuitPortId ret = CIRCUIT_PORT_OPEN_ID; + size_t num_found = 0; + for (auto port_id : ports(circuit_model_id)) { + if (0 != name.compare(port_prefix(circuit_model_id, port_id))) { + continue; /* Not the one, go to the next*/ + } + ret = port_id; /* Find one */ + num_found++; + } + /* Make sure we will not find two ports with the same name */ + VTR_ASSERT_SAFE( (0 == num_found) || (1 == num_found) ); + return ret; +} + /* Access the type of a port of a circuit model */ size_t CircuitLibrary::num_ports(const CircuitModelId& circuit_model_id) const { - /* validate the circuit_port_id */ + /* validate the circuit_model_id */ VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); return port_ids_[circuit_model_id].size(); } @@ -404,8 +440,7 @@ CircuitModelId CircuitLibrary::add_circuit_model() { edge_src_pin_ids_.emplace_back(); edge_sink_port_ids_.emplace_back(); edge_sink_pin_ids_.emplace_back(); - edge_trise_.emplace_back(); - edge_tfall_.emplace_back(); + edge_timing_info_.emplace_back(); /* Delay information */ delay_types_.emplace_back(); @@ -1307,6 +1342,7 @@ void CircuitLibrary::build_timing_graphs() { invalidate_circuit_model_timing_graph(circuit_model_id); build_circuit_model_timing_graph(circuit_model_id); /* Annotate timing information */ + set_timing_graph_delays(circuit_model_id); } return; } @@ -1351,8 +1387,8 @@ 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 */ - edge_trise_[circuit_model_id].push_back(0); - edge_tfall_[circuit_model_id].push_back(0); + std::vector timing_info(2, 0); + edge_timing_info_[circuit_model_id].emplace_back(timing_info); return; } @@ -1361,7 +1397,7 @@ void CircuitLibrary::set_edge_trise(const CircuitModelId& circuit_model_id, cons /* 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; + edge_timing_info_[circuit_model_id][circuit_edge_id][size_t(SPICE_MODEL_DELAY_RISE)] = trise; return; } @@ -1369,10 +1405,76 @@ void CircuitLibrary::set_edge_tfall(const CircuitModelId& circuit_model_id, cons /* 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; + edge_timing_info_[circuit_model_id][circuit_edge_id][size_t(SPICE_MODEL_DELAY_FALL)] = tfall; return; } +/* Decode input names of delay_info to CircuitPorts */ +std::vector CircuitLibrary::get_delay_info_input_port_ids(const CircuitModelId& circuit_model_id, + const enum spice_model_delay_type& delay_type) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Parse the string */ +// MultiPortParser input_port_parser(delay_in_port_names[circuit_model_id][size_t(delay_type)]); +// input_port_parser.add_delima(" "); +// std::vector input_port_names = input_port_parser.port_names(); + + /* Find port ids with given names */ + std::vector input_port_ids; +// for (const auto& name : input_port_names) { + /* We must have a valid port ! */ +// VTR_ASSERT_SAFE(CIRCUIT_PORT_OPEN_ID != port(circuit_model_id, name)); + /* Convert to CircuitPortId */ +// input_port_ids.push_back(port(circuit_model_id, name)); + /* This must be an input port! */ +// VTR_ASSERT_SAFE(true == is_input_port(circuit_model_id, input_port_ids.back())); +// } + return input_port_ids; +} + +/* Decode input names of delay_info to CircuitPorts */ +std::vector CircuitLibrary::get_delay_info_output_port_ids(const CircuitModelId& circuit_model_id, + const enum spice_model_delay_type& delay_type) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Parse the string */ +// MultiPortParser output_port_parser(delay_out_port_names[circuit_model_id][size_t(delay_type)]); +// output_port_parser.add_delima(" "); +// std::vector output_port_names = output_port_parser.port_names(); + + /* Find port ids with given names */ + std::vector output_port_ids; +// for (const auto& name : output_port_names) { + /* We must have a valid port ! */ +// VTR_ASSERT_SAFE(CIRCUIT_PORT_OPEN_ID != port(circuit_model_id, name)); + /* Convert to CircuitPortId */ +// output_port_ids.push_back(port(circuit_model_id, name)); + /* This must be an output port! */ +// VTR_ASSERT_SAFE(true == is_output_port(circuit_model_id, output_port_ids.back())); +// } + return output_port_ids; +} + + +/* Annotate delay values on a timing graph */ +void CircuitLibrary::set_timing_graph_delays(const CircuitModelId& circuit_model_id) { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); + /* Go one delay_info by another */ + for (size_t i_delay_type = 0; i_delay_type < delay_types_[circuit_model_id].size(); ++i_delay_type) { + /* Parse the input port names and output names. + * We will store the parsing results in vectors: + * 1. vector for port ids for each port name + * 2. vector for pin ids for each port name + */ + std::vector input_port_ids; + std::vector input_pin_ids; + + std::vector output_port_ids; + std::vector output_pin_ids; + } + return; +} /************************************************************************ * Internal mutators: build fast look-ups @@ -1481,8 +1583,7 @@ void CircuitLibrary::invalidate_circuit_model_timing_graph(const CircuitModelId& 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(); + edge_timing_info_[circuit_model_id].clear(); 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 04c220876..72300d4e1 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -237,6 +237,9 @@ 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*/ + bool is_input_port(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; + bool is_output_port(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const; + CircuitPortId port(const CircuitModelId& circuit_model_id, const std::string& name) 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; @@ -428,6 +431,11 @@ class CircuitLibrary { 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); + std::vector get_delay_info_input_port_ids(const CircuitModelId& circuit_model_id, + const enum spice_model_delay_type& delay_type) const; + std::vector get_delay_info_output_port_ids(const CircuitModelId& circuit_model_id, + const enum spice_model_delay_type& delay_type) const; + void set_timing_graph_delays(const CircuitModelId& circuit_model_id); public: /* Internal mutators: build fast look-ups */ void build_circuit_model_lookup(); void build_circuit_model_port_lookup(const CircuitModelId& circuit_model_id); @@ -509,8 +517,7 @@ class CircuitLibrary { vtr::vector> edge_src_pin_ids_; vtr::vector> edge_sink_port_ids_; vtr::vector> edge_sink_pin_ids_; - vtr::vector> edge_trise_; - vtr::vector> edge_tfall_; + vtr::vector>> edge_timing_info_; /* x0 => trise, x1 => tfall */ /* Delay information */ vtr::vector> delay_types_; From f80e58c753d44c88f3438118bbcdbe8a3dfe17ad Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 9 Aug 2019 16:36:22 -0600 Subject: [PATCH 13/18] developing a in-house tokenizer --- .../SRC/fpga_spice_include/string_token.cpp | 120 ++++++++++++++++++ .../SRC/fpga_spice_include/string_token.h | 81 ++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.cpp create mode 100644 vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.h diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.cpp b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.cpp new file mode 100644 index 000000000..3b1ae265c --- /dev/null +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.cpp @@ -0,0 +1,120 @@ +/********************************************************** + * MIT License + * + * Copyright (c) 2018 LNIS - The University of Utah + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ***********************************************************************/ + +/************************************************************************ + * Filename: string_token.cpp + * Created by: Xifan Tang + * Change history: + * +-------------------------------------+ + * | Date | Author | Notes + * +-------------------------------------+ + * | 2019/08/09 | Xifan Tang | Created + * +-------------------------------------+ + ***********************************************************************/ + +/************************************************************************ + * Member functions for StringToken class + ***********************************************************************/ + +#include "string.h" + +#include "vtr_assert.h" + +#include "string_token.h" + +/************************************************************************ + * Constructors + ***********************************************************************/ +StringToken::StringToken (const std::string& data) { + set_data(data); +} + +/************************************************************************ + * Public Accessors + ***********************************************************************/ +/* Get the data string */ +std::string StringToken::data() const { + return data_; +} + +/* Split the string */ +std::vector StringToken::split() { + /* Return vector */ + std::vector ret; + + /* Add a default delim */ + if (true == delims_.empty()) { + add_default_delim(); + } + /* Create delims */ + std::string delims; + for (const auto& delim : delims_) { + delims.push_back(delim); + } + /* Get a writable char array */ + char* tmp = new char[data_.size() + 1]; + std::copy(data_.begin(), data_.end(), tmp); + tmp[data_.size()] = '\0'; + /* Split using strtok */ + char* result = strtok(tmp, delims.c_str()); + while (NULL != result) { + std::string result_str(result); + /* Store the token */ + ret.push_back(result_str); + /* Got to next */ + result = strtok(NULL, delims.c_str()); + } + + /* Free the tmp */ + delete[] tmp; + + return ret; +} + +/************************************************************************ + * Public Mutators + ***********************************************************************/ +void StringToken::set_data(const std::string& data) { + data_ = data; + return; +} + +/* Add a delima to the list */ +void StringToken::add_delim(const char& delim) { + delims_.push_back(delim); +} + +/************************************************************************ + * Internal Mutators + ***********************************************************************/ +void StringToken::add_default_delim() { + VTR_ASSERT_SAFE(true == delims_.empty()); + delims_.push_back(' '); + return; +} + +/************************************************************************ + * End of file : string_token.cpp + ***********************************************************************/ + diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.h new file mode 100644 index 000000000..3387659b2 --- /dev/null +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.h @@ -0,0 +1,81 @@ +/********************************************************** + * MIT License + * + * Copyright (c) 2018 LNIS - The University of Utah + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ***********************************************************************/ + +/************************************************************************ + * Filename: string_token.h + * Created by: Xifan Tang + * Change history: + * +-------------------------------------+ + * | Date | Author | Notes + * +-------------------------------------+ + * | 2019/08/09 | Xifan Tang | Created + * +-------------------------------------+ + ***********************************************************************/ + +/* IMPORTANT: + * The following preprocessing flags are added to + * avoid compilation error when this headers are included in more than 1 times + */ +#ifndef STRING_TOKEN_H +#define STRING_TOKEN_H + +/* + * Notes in include header files in a head file + * Only include the neccessary header files + * that is required by the data types in the function/class declarations! + */ +/* Header files should be included in a sequence */ +/* Standard header files required go first */ +#include +#include + + +/************************************************************************ + * This file includes a tokenizer for string objects + * It splits a string with given delima and return a vector of tokens + * It can accept different delima in splitting strings + ***********************************************************************/ + +class StringToken { + public : /* Constructors*/ + StringToken (const std::string& data); + public : /* Public Accessors */ + std::string data() const; + std::vector split(); + public : /* Public Mutators */ + void set_data(const std::string& data); + void add_delim(const char& delim); + private : /* Private Mutators */ + void add_default_delim(); + private: /* Internal data */ + std::string data_; /* Lines to be splited */ + std::vector delims_; +}; + +#endif + +/************************************************************************ + * End of file : string_token.h + ***********************************************************************/ + From 2c7d6e3de42d42d677295ee870edf6d418bbd036 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 9 Aug 2019 17:48:55 -0600 Subject: [PATCH 14/18] adding port parsers --- libs/libvtrutil/src/vtr_geometry.h | 1 + libs/libvtrutil/src/vtr_geometry.tpp | 6 + .../SRC/fpga_spice_include/port_parser.cpp | 142 ++++++++++++++++++ .../SRC/fpga_spice_include/port_parser.h | 93 ++++++++++++ .../SRC/fpga_spice_include/string_token.cpp | 44 ++++-- .../SRC/fpga_spice_include/string_token.h | 3 + 6 files changed, 278 insertions(+), 11 deletions(-) create mode 100644 vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.cpp create mode 100644 vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.h diff --git a/libs/libvtrutil/src/vtr_geometry.h b/libs/libvtrutil/src/vtr_geometry.h index ce9cfe59f..24d641cfa 100644 --- a/libs/libvtrutil/src/vtr_geometry.h +++ b/libs/libvtrutil/src/vtr_geometry.h @@ -63,6 +63,7 @@ class Point { public: //Mutators void set_x(T x_val); void set_y(T y_val); + void swap(); private: T x_; T y_; diff --git a/libs/libvtrutil/src/vtr_geometry.tpp b/libs/libvtrutil/src/vtr_geometry.tpp index 76b1ad457..6ec15ded7 100644 --- a/libs/libvtrutil/src/vtr_geometry.tpp +++ b/libs/libvtrutil/src/vtr_geometry.tpp @@ -52,6 +52,12 @@ namespace vtr { y_ = y_val; } + template + void Point::swap() { + std::swap(x_, y_); + } + + /* * Rect */ diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.cpp b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.cpp new file mode 100644 index 000000000..945cac4d1 --- /dev/null +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.cpp @@ -0,0 +1,142 @@ +/********************************************************** + * MIT License + * + * Copyright (c) 2018 LNIS - The University of Utah + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ***********************************************************************/ + +/************************************************************************ + * Filename: port_parser.cpp + * Created by: Xifan Tang + * Change history: + * +-------------------------------------+ + * | Date | Author | Notes + * +-------------------------------------+ + * | 2019/08/09 | Xifan Tang | Created + * +-------------------------------------+ + ***********************************************************************/ + +/************************************************************************ + * Member functions for PortParser class + ***********************************************************************/ + +#include "string.h" + +#include "vtr_assert.h" +#include "vtr_geometry.h" + +#include "string_token.h" + +#include "port_parser.h" + +/************************************************************************ + * Constructors + ***********************************************************************/ +PortParser::PortParser (const std::string& data) { + set_data(data); + set_default_bracket(); + set_default_delim(); + parse(); +} + +/************************************************************************ + * Public Accessors + ***********************************************************************/ +/* Get the data string */ +std::string PortParser::data() const { + return data_; +} + + +/************************************************************************ + * Public Mutators + ***********************************************************************/ +void PortParser::set_data(const std::string& data) { + data_ = data; + parse(); + return; +} + +/************************************************************************ + * Internal Mutators + ***********************************************************************/ +/* Parse the data */ +void PortParser::parse() { + /* Create a tokenizer */ + StringToken tokenizer(data_); + + /* Split the data into and */ + std::vector port_tokens = tokenizer.split(bracket_.x()); + /* Make sure we have a port name! */ + VTR_ASSERT_SAFE ((1 == port_tokens.size()) || (2 == port_tokens.size())); + /* Store the port name! */ + port_name_ = port_tokens[0]; + + /* If we only have one token */ + if (1 == port_tokens.size()) { + pin_range_.set_x(-1); + pin_range_.set_y(-1); + return; /* We can finish here */ + } + + /* Chomp the ']' */ + tokenizer.set_data(port_tokens[1]); + std::vector pin_tokens = tokenizer.split(bracket_.y()); + /* Make sure we have a valid string! */ + VTR_ASSERT_SAFE (1 == port_tokens.size()); + + /* Split the pin string now */ + tokenizer.set_data(port_tokens[0]); + pin_tokens = tokenizer.split(delim_); + + /* Check if we have LSB and MSB or just one */ + if ( 1 == pin_tokens.size() ) { + /* Single pin */ + pin_range_.set_x(stoi(pin_tokens[0])); + pin_range_.set_y(stoi(pin_tokens[0])); + } else if ( 2 == pin_tokens.size() ) { + /* A number of pin */ + pin_range_.set_x(stoi(pin_tokens[0])); + pin_range_.set_y(stoi(pin_tokens[1])); + } + + /* Reorder to ensure LSB <= MSB */ + if (pin_range_.x() > pin_range_.y()) { + pin_range_.swap(); + } + + return; +} + +void PortParser::set_default_bracket() { + bracket_.set_x('['); + bracket_.set_y(']'); + return; +} + +void PortParser::set_default_delim() { + delim_ = ':'; + 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 new file mode 100644 index 000000000..3845b2c84 --- /dev/null +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.h @@ -0,0 +1,93 @@ +/********************************************************** + * MIT License + * + * Copyright (c) 2018 LNIS - The University of Utah + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ***********************************************************************/ + +/************************************************************************ + * Filename: port_parser.h + * Created by: Xifan Tang + * Change history: + * +-------------------------------------+ + * | Date | Author | Notes + * +-------------------------------------+ + * | 2019/08/09 | Xifan Tang | Created + * +-------------------------------------+ + ***********************************************************************/ + +/* IMPORTANT: + * The following preprocessing flags are added to + * avoid compilation error when this headers are included in more than 1 times + */ +#ifndef PORT_PARSER_H +#define PORT_PARSER_H + +/* + * Notes in include header files in a head file + * Only include the neccessary header files + * that is required by the data types in the function/class declarations! + */ +/* Header files should be included in a sequence */ +/* Standard header files required go first */ +#include +#include + +#include "string_token.h" + +/************************************************************************ + * This file includes parsers for port definition in the architecture XML + * language. Note that it is also compatiable to Verilog syntax. + * It means we may reuse this for constructing a structural Verilog parser + * Supported port definition: + * 1. [:] + * 2. [:] + * 3. [] + * 4. [] + * 5. + * In case 4 and 5, we will assign (-1,-1) for LSB and MSB + ***********************************************************************/ + +class PortParser{ + public : /* Constructors*/ + PortParser (const std::string& data); + public : /* Public Accessors */ + std::string data() const; + std::vector split(); + public : /* Public Mutators */ + void set_data(const std::string& data); + private : /* Private Mutators */ + void parse(); + void set_default_bracket(); + void set_default_delim(); + private: /* Internal data */ + std::string data_; /* Lines to be splited */ + vtr::Point bracket_; + char delim_; + std::string port_name_; + vtr::Point pin_range_; +}; + +#endif + +/************************************************************************ + * End of file : port_parser.h + ***********************************************************************/ + 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 3b1ae265c..f040f5214 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.cpp @@ -58,20 +58,11 @@ std::string StringToken::data() const { return data_; } -/* Split the string */ -std::vector StringToken::split() { +/* Split the string using a given delim */ +std::vector StringToken::split(const std::string& delims) const { /* Return vector */ std::vector ret; - /* Add a default delim */ - if (true == delims_.empty()) { - add_default_delim(); - } - /* Create delims */ - std::string delims; - for (const auto& delim : delims_) { - delims.push_back(delim); - } /* Get a writable char array */ char* tmp = new char[data_.size() + 1]; std::copy(data_.begin(), data_.end(), tmp); @@ -92,6 +83,37 @@ std::vector StringToken::split() { return ret; } +/* Split the string using a given delim */ +std::vector StringToken::split(const char& delim) const { + /* Create delims */ + std::string delims(1, delim); + + return split(delims); +} + +/* Split the string using a given delim */ +std::vector StringToken::split(const char* delim) const { + /* Create delims */ + std::string delims(delim); + + return split(delims); +} + +/* Split the string */ +std::vector StringToken::split() { + /* Add a default delim */ + if (true == delims_.empty()) { + add_default_delim(); + } + /* Create delims */ + std::string delims; + for (const auto& delim : delims_) { + delims.push_back(delim); + } + + return split(delims); +} + /************************************************************************ * Public 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 3387659b2..d5385269d 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/string_token.h @@ -62,6 +62,9 @@ class StringToken { StringToken (const std::string& data); public : /* Public Accessors */ std::string data() const; + 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(); public : /* Public Mutators */ void set_data(const std::string& data); From c004699a146bd7f4dc23edc7cea5d9a6e45c5fc6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 9 Aug 2019 21:00:41 -0600 Subject: [PATCH 15/18] complete parsers for ports --- .../fpga_spice_include/circuit_library.cpp | 92 +++++++++--------- .../SRC/fpga_spice_include/circuit_library.h | 5 +- .../SRC/fpga_spice_include}/device_port.cpp | 12 +++ .../SRC/fpga_spice_include}/device_port.h | 7 +- .../SRC/fpga_spice_include/port_parser.cpp | 94 ++++++++++++++++--- .../SRC/fpga_spice_include/port_parser.h | 34 ++++++- 6 files changed, 176 insertions(+), 68 deletions(-) rename vpr7_x2p/{vpr/SRC/fpga_x2p/base => libarchfpga/SRC/fpga_spice_include}/device_port.cpp (96%) rename vpr7_x2p/{vpr/SRC/fpga_x2p/base => libarchfpga/SRC/fpga_spice_include}/device_port.h (93%) 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 dd7862c3c..46df9d44a 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -38,6 +38,7 @@ #include "vtr_assert.h" +#include "port_parser.h" #include "circuit_library.h" /************************************************************************ @@ -1409,69 +1410,58 @@ void CircuitLibrary::set_edge_tfall(const CircuitModelId& circuit_model_id, cons return; } -/* Decode input names of delay_info to CircuitPorts */ -std::vector CircuitLibrary::get_delay_info_input_port_ids(const CircuitModelId& circuit_model_id, - const enum spice_model_delay_type& delay_type) const { - /* validate the circuit_model_id */ - VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); - /* Parse the string */ -// MultiPortParser input_port_parser(delay_in_port_names[circuit_model_id][size_t(delay_type)]); -// input_port_parser.add_delima(" "); -// std::vector input_port_names = input_port_parser.port_names(); - - /* Find port ids with given names */ - std::vector input_port_ids; -// for (const auto& name : input_port_names) { - /* We must have a valid port ! */ -// VTR_ASSERT_SAFE(CIRCUIT_PORT_OPEN_ID != port(circuit_model_id, name)); - /* Convert to CircuitPortId */ -// input_port_ids.push_back(port(circuit_model_id, name)); - /* This must be an input port! */ -// VTR_ASSERT_SAFE(true == is_input_port(circuit_model_id, input_port_ids.back())); -// } - return input_port_ids; -} - -/* Decode input names of delay_info to CircuitPorts */ -std::vector CircuitLibrary::get_delay_info_output_port_ids(const CircuitModelId& circuit_model_id, - const enum spice_model_delay_type& delay_type) const { - /* validate the circuit_model_id */ - VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); - /* Parse the string */ -// MultiPortParser output_port_parser(delay_out_port_names[circuit_model_id][size_t(delay_type)]); -// output_port_parser.add_delima(" "); -// std::vector output_port_names = output_port_parser.port_names(); - - /* Find port ids with given names */ - std::vector output_port_ids; -// for (const auto& name : output_port_names) { - /* We must have a valid port ! */ -// VTR_ASSERT_SAFE(CIRCUIT_PORT_OPEN_ID != port(circuit_model_id, name)); - /* Convert to CircuitPortId */ -// output_port_ids.push_back(port(circuit_model_id, name)); - /* This must be an output port! */ -// VTR_ASSERT_SAFE(true == is_output_port(circuit_model_id, output_port_ids.back())); -// } - return output_port_ids; -} - - /* Annotate delay values on a timing graph */ void CircuitLibrary::set_timing_graph_delays(const CircuitModelId& circuit_model_id) { /* validate the circuit_model_id */ VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); /* Go one delay_info by another */ - for (size_t i_delay_type = 0; i_delay_type < delay_types_[circuit_model_id].size(); ++i_delay_type) { + for (const auto& delay_type : delay_types_[circuit_model_id]) { /* Parse the input port names and output names. * We will store the parsing results in vectors: * 1. vector for port ids for each port name * 2. vector for pin ids for each port name */ + + /* Parse the string for inputs */ + MultiPortParser input_port_parser(delay_in_port_names_[circuit_model_id][size_t(delay_type)]); + std::vector input_ports = input_port_parser.ports(); std::vector input_port_ids; std::vector input_pin_ids; + /* Check each element */ + for (const 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()) ); + /* 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! */ + VTR_ASSERT_SAFE(true == is_input_port(circuit_model_id, port_id)); + /* Push to */ + input_port_ids.push_back(port_id); + input_pin_ids.push_back(port_info.get_lsb()); + } + /* Parse the string for outputs */ + MultiPortParser output_port_parser(delay_out_port_names_[circuit_model_id][size_t(delay_type)]); + std::vector output_ports = output_port_parser.ports(); std::vector output_port_ids; std::vector output_pin_ids; + /* Check each element */ + for (const 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()) ); + /* 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! */ + VTR_ASSERT_SAFE(true == is_output_port(circuit_model_id, port_id)); + /* Push to */ + output_port_ids.push_back(port_id); + output_pin_ids.push_back(port_info.get_lsb()); + } + } return; } @@ -1539,6 +1529,12 @@ bool CircuitLibrary::valid_circuit_port_id(const CircuitModelId& circuit_model_i return ( size_t(circuit_port_id) < port_ids_[circuit_model_id].size() ) && ( circuit_port_id == port_ids_[circuit_model_id][circuit_port_id] ); } +bool CircuitLibrary::valid_circuit_pin_id(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id, const size_t& pin_id) const { + /* validate the circuit_model_id */ + VTR_ASSERT_SAFE(valid_circuit_port_id(circuit_model_id, circuit_port_id)); + return ( size_t(pin_id) < port_size(circuit_model_id, circuit_port_id) ); +} + bool CircuitLibrary::valid_delay_type(const CircuitModelId& circuit_model_id, const enum spice_model_delay_type& delay_type) const { /* validate the circuit_model_id */ VTR_ASSERT_SAFE(valid_circuit_model_id(circuit_model_id)); 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 72300d4e1..8002c77c0 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -431,10 +431,6 @@ class CircuitLibrary { 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); - std::vector get_delay_info_input_port_ids(const CircuitModelId& circuit_model_id, - const enum spice_model_delay_type& delay_type) const; - std::vector get_delay_info_output_port_ids(const CircuitModelId& circuit_model_id, - const enum spice_model_delay_type& delay_type) const; void set_timing_graph_delays(const CircuitModelId& circuit_model_id); public: /* Internal mutators: build fast look-ups */ void build_circuit_model_lookup(); @@ -443,6 +439,7 @@ class CircuitLibrary { /* Validators */ 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_circuit_pin_id(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id, const size_t& pin_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 */ diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/device_port.cpp b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/device_port.cpp similarity index 96% rename from vpr7_x2p/vpr/SRC/fpga_x2p/base/device_port.cpp rename to vpr7_x2p/libarchfpga/SRC/fpga_spice_include/device_port.cpp index 6ab88ac94..2e181fce5 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/device_port.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/device_port.cpp @@ -37,14 +37,26 @@ size_t BasicPort::get_lsb() const { return lsb_; } +/* get the name */ +std::string BasicPort::get_name() const { + return name_; +} + /* Mutators */ /* copy */ void BasicPort::set(const BasicPort& basic_port) { + name_ = basic_port.get_name(); lsb_ = basic_port.get_lsb(); msb_ = basic_port.get_msb(); return; } + +/* set the port LSB and MSB */ +void BasicPort::set_name(const std::string& name) { + name_ = name; + return; +} /* set the port LSB and MSB */ void BasicPort::set_width(size_t width) { diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/device_port.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/device_port.h similarity index 93% rename from vpr7_x2p/vpr/SRC/fpga_x2p/base/device_port.h rename to vpr7_x2p/libarchfpga/SRC/fpga_spice_include/device_port.h index 905a4d0bf..fbf887421 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/device_port.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/device_port.h @@ -5,6 +5,8 @@ #ifndef DEVICE_PORT_H #define DEVICE_PORT_H +#include + /* A basic port */ class BasicPort { public: /* Constructors */ @@ -14,8 +16,11 @@ class BasicPort { size_t get_width() const; /* get the port width */ size_t get_msb() const; /* get the LSB */ size_t get_lsb() const; /* get the LSB */ + std::string get_name() const; /* get the name */ + bool is_valid() const; /* check if port size is valid > 0 */ public: /* Mutators */ void set(const BasicPort& basic_port); /* copy */ + void set_name(const std::string& name); /* set the port LSB and MSB */ void set_width(size_t width); /* set the port LSB and MSB */ void set_width(size_t lsb, size_t msb); /* set the port LSB and MSB */ void set_lsb(size_t lsb); @@ -28,8 +33,8 @@ class BasicPort { void combine(const BasicPort& port); /* Combine two ports */ private: /* internal functions */ void make_invalid(); /* Make a port invalid */ - bool is_valid() const; /* check if port size is valid > 0 */ private: /* Internal Data */ + std::string name_; /* Name of this port */ size_t msb_; /* Most Significant Bit of this port */ size_t lsb_; /* Least Significant Bit of this port */ }; 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 945cac4d1..c9e5eff16 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.cpp @@ -34,7 +34,7 @@ ***********************************************************************/ /************************************************************************ - * Member functions for PortParser class + * Member functions for Port parsers ***********************************************************************/ #include "string.h" @@ -46,6 +46,10 @@ #include "port_parser.h" +/************************************************************************ + * Member functions for PortParser class + ***********************************************************************/ + /************************************************************************ * Constructors ***********************************************************************/ @@ -64,6 +68,9 @@ std::string PortParser::data() const { return data_; } +BasicPort PortParser::port() const { + return port_; +} /************************************************************************ * Public Mutators @@ -87,12 +94,11 @@ void PortParser::parse() { /* Make sure we have a port name! */ VTR_ASSERT_SAFE ((1 == port_tokens.size()) || (2 == port_tokens.size())); /* Store the port name! */ - port_name_ = port_tokens[0]; + port_.set_name(port_tokens[0]); /* If we only have one token */ if (1 == port_tokens.size()) { - pin_range_.set_x(-1); - pin_range_.set_y(-1); + port_.set_width(0); return; /* We can finish here */ } @@ -109,17 +115,15 @@ void PortParser::parse() { /* Check if we have LSB and MSB or just one */ if ( 1 == pin_tokens.size() ) { /* Single pin */ - pin_range_.set_x(stoi(pin_tokens[0])); - pin_range_.set_y(stoi(pin_tokens[0])); + port_.set_width(stoi(pin_tokens[0]), stoi(pin_tokens[0])); } else if ( 2 == pin_tokens.size() ) { /* A number of pin */ - pin_range_.set_x(stoi(pin_tokens[0])); - pin_range_.set_y(stoi(pin_tokens[1])); + port_.set_width(stoi(pin_tokens[0]), stoi(pin_tokens[1])); } - /* Reorder to ensure LSB <= MSB */ - if (pin_range_.x() > pin_range_.y()) { - pin_range_.swap(); + /* Re-order to ensure LSB <= MSB */ + if (false == port_.is_valid()) { + port_.revert(); } return; @@ -136,6 +140,74 @@ void PortParser::set_default_delim() { return; } +/************************************************************************ + * Member functions for MultiPortParser class + ***********************************************************************/ + +/************************************************************************ + * Constructors + ***********************************************************************/ +MultiPortParser::MultiPortParser (const std::string& data) { + set_data(data); + set_default_delim(); + parse(); +} + +/************************************************************************ + * Public Accessors + ***********************************************************************/ +/* Get the data string */ +std::string MultiPortParser::data() const { + return data_; +} + +std::vector MultiPortParser::ports() const { + return ports_; +} + +/************************************************************************ + * Public Mutators + ***********************************************************************/ +void MultiPortParser::set_data(const std::string& data) { + data_ = data; + parse(); + return; +} + +/************************************************************************ + * Internal Mutators + ***********************************************************************/ +/* Split the data line into fragments and parse one by one */ +void MultiPortParser::parse() { + /* Clear content */ + clear(); + + /* Create a tokenizer */ + StringToken tokenizer(data_); + + /* Split the data into and */ + std::vector port_tokens = tokenizer.split(delim_); + + /* Use PortParser for each token */ + for (const auto& port : port_tokens) { + PortParser port_parser(port); + /* Get the port name, LSB and MSB */ + ports_.push_back(port_parser.port()); + } + + return; +} + +void MultiPortParser::set_default_delim() { + delim_ = ' '; + return; +} + +void MultiPortParser::clear() { + ports_.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 3845b2c84..ddd527559 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/port_parser.h @@ -50,12 +50,19 @@ #include #include +#include "vtr_geometry.h" + +#include "device_port.h" #include "string_token.h" /************************************************************************ * This file includes parsers for port definition in the architecture XML * language. Note that it is also compatiable to Verilog syntax. * It means we may reuse this for constructing a structural Verilog parser + ***********************************************************************/ + +/************************************************************************ + * Class PortParser: single port parser * Supported port definition: * 1. [:] * 2. [:] @@ -64,13 +71,12 @@ * 5. * In case 4 and 5, we will assign (-1,-1) for LSB and MSB ***********************************************************************/ - class PortParser{ public : /* Constructors*/ PortParser (const std::string& data); public : /* Public Accessors */ std::string data() const; - std::vector split(); + BasicPort port() const; public : /* Public Mutators */ void set_data(const std::string& data); private : /* Private Mutators */ @@ -81,8 +87,28 @@ class PortParser{ std::string data_; /* Lines to be splited */ vtr::Point bracket_; char delim_; - std::string port_name_; - vtr::Point pin_range_; + BasicPort port_; +}; + +/************************************************************************ + * MultiPortParser: a parser for multiple ports in one line + ***********************************************************************/ +class MultiPortParser { + public : /* Constructors*/ + MultiPortParser (const std::string& data); + public : /* Public Accessors */ + std::string data() const; + std::vector ports() const; + public : /* Public Mutators */ + void set_data(const std::string& data); + private : /* Private Mutators */ + void parse(); + void set_default_delim(); + void clear(); + private: /* Internal data */ + std::string data_; /* Lines to be splited */ + char delim_; + std::vector ports_; }; #endif From fbdab32a2df6c584eb32bef0c23569454ef4823d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 10 Aug 2019 13:03:24 -0600 Subject: [PATCH 16/18] timing graph for circuit models are working --- .../fpga_spice_include/circuit_library.cpp | 91 ++++++++++--- .../SRC/fpga_spice_include/circuit_library.h | 11 +- .../SRC/fpga_spice_include/port_parser.cpp | 125 +++++++++++++++++- .../SRC/fpga_spice_include/port_parser.h | 28 ++++ .../SRC/fpga_spice_include/string_token.cpp | 32 +++++ .../SRC/fpga_spice_include/string_token.h | 4 + 6 files changed, 269 insertions(+), 22 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 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 */ From d4ae160d3a36227b65f1274141eac3d06355bdde Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 12 Aug 2019 14:20:11 -0600 Subject: [PATCH 17/18] start adding circuit library checkers --- .../SRC/fpga_spice_include/read_xml_spice.h | 49 +++++++++++++++++++ vpr7_x2p/libarchfpga/SRC/read_xml_spice.c | 43 +++++++++++++++- 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/read_xml_spice.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/read_xml_spice.h index bb4d55b91..b22f478e9 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/read_xml_spice.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/read_xml_spice.h @@ -1,6 +1,55 @@ +/********************************************************** + * MIT License + * + * Copyright (c) 2018 LNIS - The University of Utah + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ***********************************************************************/ + +/************************************************************************ + * Filename: read_xml_spice.h + * Created by: Xifan Tang + * Change history: + * +-------------------------------------+ + * | Date | Author | Notes + * +-------------------------------------+ + * | 2015/XX/XX | Xifan Tang | Created + * +-------------------------------------+ + ***********************************************************************/ + +/* IMPORTANT: + * The following preprocessing flags are added to + * avoid compilation error when this headers are included in more than 1 times + */ +#ifndef READ_XML_SPICE_H +#define READ_XML_SPICE_H + /* Xifan TANG: Spice Support*/ void ProcessSpiceSRAM(INOUTP ezxml_t Node, OUTP struct s_arch* arch); void ProcessSpiceSettings(ezxml_t Parent, t_spice* spice); + +#endif + +/************************************************************************ + * End of file : read_xml_spice.h + ***********************************************************************/ + diff --git a/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c b/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c index ba7cb7cec..63403cd94 100644 --- a/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c +++ b/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c @@ -1,3 +1,40 @@ +/********************************************************** + * MIT License + * + * Copyright (c) 2018 LNIS - The University of Utah + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ***********************************************************************/ + +/************************************************************************ + * Filename: read_xml_spice.c + * Created by: Xifan Tang + * Change history: + * +-------------------------------------+ + * | Date | Author | Notes + * +-------------------------------------+ + * | 2015/XX/XX | Xifan Tang | Created + * +-------------------------------------+ + * | 2019/08/12 | Xifan Tang | Code construction for circuit library + * +-------------------------------------+ + ***********************************************************************/ + #include #include #include "util.h" @@ -11,6 +48,7 @@ #include "read_xml_spice.h" #include "circuit_library.h" +#include "check_circuit_library.h" /*********** Subroutines Declaration (only called in this source file) **********/ static void ProcessSpiceMeasParams(ezxml_t Parent, @@ -1787,6 +1825,7 @@ void ProcessSpiceSettings(ezxml_t Parent, } /* Build the CircuitLibrary here from spice_models */ spice->circuit_lib = build_circuit_library(spice->num_spice_model, spice->spice_models); + //check_circuit_library(spice->circuit_lib); /* Check codes*/ check_tech_lib(spice->tech_lib, spice->num_spice_model, spice->spice_models); @@ -1795,4 +1834,6 @@ void ProcessSpiceSettings(ezxml_t Parent, return; } - +/************************************************************************ + * End of file : read_xml_spice.c + ***********************************************************************/ From c56f289d3e44e6f72ebfb283a9a0f16015932191 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 12 Aug 2019 16:45:33 -0600 Subject: [PATCH 18/18] add checkers for circuit library --- .../check_circuit_library.cpp | 254 ++++++++++++++++++ .../check_circuit_library.h | 60 +++++ .../fpga_spice_include/circuit_library.cpp | 33 +++ .../SRC/fpga_spice_include/circuit_library.h | 3 + .../SRC/fpga_spice_include/circuit_types.h | 4 + vpr7_x2p/libarchfpga/SRC/read_xml_spice.c | 2 +- 6 files changed, 355 insertions(+), 1 deletion(-) create mode 100644 vpr7_x2p/libarchfpga/SRC/fpga_spice_include/check_circuit_library.cpp create mode 100644 vpr7_x2p/libarchfpga/SRC/fpga_spice_include/check_circuit_library.h diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/check_circuit_library.cpp b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/check_circuit_library.cpp new file mode 100644 index 000000000..f136dba4c --- /dev/null +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/check_circuit_library.cpp @@ -0,0 +1,254 @@ +/********************************************************** + * MIT License + * + * Copyright (c) 2018 LNIS - The University of Utah + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ***********************************************************************/ + +/************************************************************************ + * Filename: check_circuit_library.cpp + * Created by: Xifan Tang + * Change history: + * +-------------------------------------+ + * | Date | Author | Notes + * +-------------------------------------+ + * | 2019/08/12 | Xifan Tang | Created + * +-------------------------------------+ + ***********************************************************************/ + +/* Header files should be included in a sequence */ +/* Standard header files required go first */ +#include "util.h" +#include "check_circuit_library.h" + + +/* 1. Circuit models have unique names, return the number of errors */ +static +size_t check_circuit_library_unique_names(const CircuitLibrary& circuit_lib) { + size_t num_err = 0; + + for (size_t i = 0; i < circuit_lib.num_circuit_models(); ++i) { + /* Skip for the last element, because the inner loop will access it */ + if (i == circuit_lib.num_circuit_models() - 1) { + continue; + } + /* Get the name of reference */ + const std::string& i_name = circuit_lib.circuit_model_name(CircuitModelId(i)); + for (size_t j = i + 1; j < circuit_lib.num_circuit_models(); ++j) { + /* Compare the name of candidate */ + const std::string& j_name = circuit_lib.circuit_model_name(CircuitModelId(j)); + /* Compare the name and skip for different names */ + if (0 != i_name.compare(j_name)) { + continue; + } + vpr_printf(TIO_MESSAGE_ERROR, + "Circuit model(index=%d) and (index=%d) share the same name, which is invalid!\n", + i , j, i_name.c_str()); + /* Incremental the counter for errors */ + num_err++; + } + } + + return num_err; +} + + +/* 1. Circuit models have unique names, return the number of errors */ +static +size_t check_circuit_library_unique_prefix(const CircuitLibrary& circuit_lib) { + size_t num_err = 0; + + for (size_t i = 0; i < circuit_lib.num_circuit_models(); ++i) { + /* Skip for the last element, because the inner loop will access it */ + if (i == circuit_lib.num_circuit_models() - 1) { + continue; + } + /* Get the name of reference */ + const std::string& i_prefix = circuit_lib.circuit_model_prefix(CircuitModelId(i)); + for (size_t j = i + 1; j < circuit_lib.num_circuit_models(); ++j) { + /* Compare the name of candidate */ + const std::string& j_prefix = circuit_lib.circuit_model_prefix(CircuitModelId(j)); + /* Compare the name and skip for different prefix */ + if (0 != i_prefix.compare(j_prefix)) { + continue; + } + vpr_printf(TIO_MESSAGE_ERROR, + "Circuit model(name=%s) and (name=%s) share the same prefix, which is invalid!\n", + circuit_lib.circuit_model_name(CircuitModelId(i)).c_str(), + circuit_lib.circuit_model_name(CircuitModelId(j)).c_str(), + i_prefix.c_str()); + /* Incremental the counter for errors */ + num_err++; + } + } + + return num_err; +} + +/* A generic function to check the port list of a circuit model in a given type */ +static +size_t check_circuit_model_required(const CircuitLibrary& circuit_lib, + const enum e_spice_model_type& circuit_model_type_to_check) { + size_t num_err = 0; + + /* We must have an IOPAD*/ + if ( 0 == circuit_lib.circuit_models_by_type(circuit_model_type_to_check).size()) { + vpr_printf(TIO_MESSAGE_ERROR, + "At least one %s circuit model is required!\n", + CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_model_type_to_check)]); + /* Incremental the counter for errors */ + num_err++; + } + + return num_err; +} + +/* A generic function to check the port list of a circuit model in a given type */ +static +size_t check_circuit_model_port_required(const CircuitLibrary& circuit_lib, + const enum e_spice_model_type& circuit_model_type_to_check, + const std::vector& port_types_to_check) { + size_t num_err = 0; + + for (const auto& id : circuit_lib.circuit_models_by_type(circuit_model_type_to_check)) { + for (const auto& port_type: port_types_to_check) { + if (0 == circuit_lib.ports_by_type(id, port_type).size()) { + vpr_printf(TIO_MESSAGE_ERROR, + "%s circuit model(name=%s) does not have %s port\n", + CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_model_type_to_check)], + circuit_lib.circuit_model_name(id).c_str(), + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(port_type)]); + /* Incremental the counter for errors */ + num_err++; + } + } + } + + return num_err; +} + +/************************************************************************ + * Check points to make sure we have a valid circuit library + * Detailed checkpoints: + * 1. Circuit models have unique names + * 2. Circuit models have unique prefix + * 3. Check IOPADs have input and output ports + * 4. Check MUXes has been defined and has input and output ports + ***********************************************************************/ +void check_circuit_library(const CircuitLibrary& circuit_lib) { + size_t num_err = 0; + + vpr_printf(TIO_MESSAGE_INFO, "Checking circuit models...\n"); + + /* 1. Circuit models have unique names + * For each circuit model, we always make sure it does not share any name with any circuit model locating after it + */ + num_err += check_circuit_library_unique_names(circuit_lib); + + /* 2. Circuit models have unique prefix + * For each circuit model, we always make sure it does not share any prefix with any circuit model locating after it + */ + num_err += check_circuit_library_unique_prefix(circuit_lib); + + /* 3. Check io has been defined and has input and output ports + * [a] We must have an IOPAD! + * [b] For each IOPAD, we must have at least an input, an output, an INOUT and an SRAM port + */ + num_err += check_circuit_model_required(circuit_lib, SPICE_MODEL_IOPAD); + + std::vector iopad_port_types_required; + iopad_port_types_required.push_back(SPICE_MODEL_PORT_INPUT); + iopad_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT); + iopad_port_types_required.push_back(SPICE_MODEL_PORT_INOUT); + iopad_port_types_required.push_back(SPICE_MODEL_PORT_SRAM); + + num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_IOPAD, iopad_port_types_required); + + /* 4. Check mux has been defined and has input and output ports + * [a] We must have a MUX! + * [b] For each MUX, we must have at least an input, an output, and an SRAM port + */ + num_err += check_circuit_model_required(circuit_lib, SPICE_MODEL_MUX); + + std::vector mux_port_types_required; + mux_port_types_required.push_back(SPICE_MODEL_PORT_INPUT); + mux_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT); + mux_port_types_required.push_back(SPICE_MODEL_PORT_SRAM); + + num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_MUX, mux_port_types_required); + + /* 5. We must have at least one SRAM or SCFF */ + if ( ( 0 == circuit_lib.circuit_models_by_type(SPICE_MODEL_SRAM).size()) + && ( 0 == circuit_lib.circuit_models_by_type(SPICE_MODEL_SCFF).size()) ) { + vpr_printf(TIO_MESSAGE_ERROR, + "At least one %s or %s circuit model is required!\n", + CIRCUIT_MODEL_TYPE_STRING[size_t(SPICE_MODEL_SRAM)], + CIRCUIT_MODEL_TYPE_STRING[size_t(SPICE_MODEL_SCFF)]); + /* Incremental the counter for errors */ + num_err++; + } + + /* 6. SRAM must have at least an input and an output ports*/ + std::vector sram_port_types_required; + sram_port_types_required.push_back(SPICE_MODEL_PORT_INPUT); + sram_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT); + + num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_SRAM, sram_port_types_required); + + /* 7. SCFF must have at least an input and an output ports*/ + std::vector scff_port_types_required; + scff_port_types_required.push_back(SPICE_MODEL_PORT_CLOCK); + scff_port_types_required.push_back(SPICE_MODEL_PORT_INPUT); + scff_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT); + + num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_SCFF, scff_port_types_required); + + /* 8. FF must have at least an input and an output ports*/ + std::vector ff_port_types_required; + ff_port_types_required.push_back(SPICE_MODEL_PORT_CLOCK); + ff_port_types_required.push_back(SPICE_MODEL_PORT_INPUT); + ff_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT); + + num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_FF, ff_port_types_required); + + /* 9. LUY must have at least an input, an output and a SRAM ports*/ + std::vector lut_port_types_required; + lut_port_types_required.push_back(SPICE_MODEL_PORT_SRAM); + lut_port_types_required.push_back(SPICE_MODEL_PORT_INPUT); + lut_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT); + + num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_LUT, lut_port_types_required); + + /* If we have any errors, exit */ + vpr_printf(TIO_MESSAGE_ERROR, + "Finished checking circuit library with %d errors!\n", + num_err); + + if (0 < num_err) { + exit(1); + } + + return; +} + +/************************************************************************ + * End of file : check_circuit_library.cpp + ***********************************************************************/ + diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/check_circuit_library.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/check_circuit_library.h new file mode 100644 index 000000000..4dd9d1307 --- /dev/null +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/check_circuit_library.h @@ -0,0 +1,60 @@ +/********************************************************** + * MIT License + * + * Copyright (c) 2018 LNIS - The University of Utah + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + ***********************************************************************/ + +/************************************************************************ + * Filename: check_circuit_library.h + * Created by: Xifan Tang + * Change history: + * +-------------------------------------+ + * | Date | Author | Notes + * +-------------------------------------+ + * | 2019/08/12 | Xifan Tang | Created + * +-------------------------------------+ + ***********************************************************************/ + +/* IMPORTANT: + * The following preprocessing flags are added to + * avoid compilation error when this headers are included in more than 1 times + */ +#ifndef CHECK_CIRCUIT_LIBRARY_H +#define CHECK_CIRCUIT_LIBRARY_H + +/* + * Notes in include header files in a head file + * Only include the neccessary header files + * that is required by the data types in the function/class declarations! + */ +/* Header files should be included in a sequence */ +/* Standard header files required go first */ +#include "circuit_library.h" + +/* Check points to make sure we have a valid circuit library */ +void check_circuit_library(const CircuitLibrary& circuit_lib); + +#endif + +/************************************************************************ + * End of file : check_circuit_library.h + ***********************************************************************/ + 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 240cefcf7..e8487bdff 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.cpp @@ -60,6 +60,34 @@ 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()); } +/* Find circuit models in the same type (defined by users) and return a list of ids */ +std::vector CircuitLibrary::circuit_models_by_type(const enum e_spice_model_type& type) const { + std::vector type_ids; + for (auto id : circuit_models()) { + /* Skip unmatched types */ + if (type != circuit_model_type(id)) { + continue; + } + /* Matched type, update the vector */ + type_ids.push_back(id); + } + return type_ids; +} + +/* Find the ports of a circuit model by a given type, return a list of qualified ports */ +std::vector CircuitLibrary::ports_by_type(const CircuitModelId& circuit_model_id, + const enum e_spice_model_port_type& type) const { + std::vector port_ids; + for (const auto& port_id : ports(circuit_model_id)) { + /* We skip unmatched ports */ + if ( type != port_type(circuit_model_id, port_id) ) { + continue; + } + port_ids.push_back(port_id); + } + return port_ids; +} + /* Create a vector for all the ports whose directionality is input * This includes all the ports other than whose types are OUPUT or INOUT */ @@ -104,6 +132,11 @@ std::vector CircuitLibrary::pins(const CircuitModelId& circuit_model_id, /************************************************************************ * Public Accessors : Basic data query on Circuit Models ***********************************************************************/ +/* Get the number of circuit models */ +size_t CircuitLibrary::num_circuit_models() const { + return circuit_model_ids_.size(); +} + /* Access the type of a circuit model */ enum e_spice_model_type CircuitLibrary::circuit_model_type(const CircuitModelId& circuit_model_id) const { /* validate the circuit_model_id */ 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 cdaf5f426..b655730d0 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_library.h @@ -219,10 +219,13 @@ class CircuitLibrary { public: /* Accessors: aggregates */ circuit_model_range circuit_models() const; circuit_port_range ports(const CircuitModelId& circuit_model_id) const; + std::vector circuit_models_by_type(const enum e_spice_model_type& type) const; + std::vector ports_by_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_port_type& port_type) 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*/ + size_t num_circuit_models() const; 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; diff --git a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_types.h b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_types.h index c13e91934..0ad9790dd 100644 --- a/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_types.h +++ b/vpr7_x2p/libarchfpga/SRC/fpga_spice_include/circuit_types.h @@ -73,6 +73,8 @@ enum e_spice_model_type { SPICE_MODEL_GATE, NUM_CIRCUIT_MODEL_TYPES }; +/* Strings correspond to each port type */ +constexpr std::array CIRCUIT_MODEL_TYPE_STRING = {{"CHAN_WIRE", "WIRE", "MUX", "LUT", "FF", "SRAM", "HARDLOGIC", "SCFF", "IOPAD", "INVBUF", "PASSGATE", "GATE"}}; enum e_spice_model_design_tech { SPICE_MODEL_DESIGN_CMOS, @@ -125,6 +127,8 @@ enum e_spice_model_port_type { SPICE_MODEL_PORT_WLB, NUM_CIRCUIT_MODEL_PORT_TYPES }; +/* Strings correspond to each port type */ +constexpr std::array CIRCUIT_MODEL_PORT_TYPE_STRING = {{"INPUT", "OUTPUT", "INOUT", "CLOCK", "SRAM", "BL", "BLB", "WL", "WLB"}}; /* For SRAM */ enum e_sram_orgz { diff --git a/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c b/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c index 63403cd94..ac0892cf8 100644 --- a/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c +++ b/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c @@ -1825,7 +1825,7 @@ void ProcessSpiceSettings(ezxml_t Parent, } /* Build the CircuitLibrary here from spice_models */ spice->circuit_lib = build_circuit_library(spice->num_spice_model, spice->spice_models); - //check_circuit_library(spice->circuit_lib); + check_circuit_library(spice->circuit_lib); /* Check codes*/ check_tech_lib(spice->tech_lib, spice->num_spice_model, spice->spice_models);