add linking functions for circuit models and architecture, memory sanitizing is ongoing

This commit is contained in:
tangxifan 2019-08-13 13:25:23 -06:00
parent c56f289d3e
commit 392f579836
14 changed files with 1166 additions and 186 deletions

View File

@ -33,13 +33,27 @@
* +-------------------------------------+
***********************************************************************/
/************************************************************************
* Function to perform fundamental checking for the circuit library
* such as
* 1. if default circuit models are defined
* 2. if any circuit models shared the same name or prefix
* 3. if nay circuit model miss mandatory ports
***********************************************************************/
/* Header files should be included in a sequence */
/* Standard header files required go first */
#include "vtr_assert.h"
#include "util.h"
#include "check_circuit_library.h"
/* 1. Circuit models have unique names, return the number of errors */
/************************************************************************
* Circuit models have unique names, return the number of errors
* If not found, we give an error
***********************************************************************/
static
size_t check_circuit_library_unique_names(const CircuitLibrary& circuit_lib) {
size_t num_err = 0;
@ -70,7 +84,10 @@ size_t check_circuit_library_unique_names(const CircuitLibrary& circuit_lib) {
}
/* 1. Circuit models have unique names, return the number of errors */
/************************************************************************
* Circuit models have unique names, return the number of errors
* If not found, we give an error
***********************************************************************/
static
size_t check_circuit_library_unique_prefix(const CircuitLibrary& circuit_lib) {
size_t num_err = 0;
@ -102,7 +119,10 @@ size_t check_circuit_library_unique_prefix(const CircuitLibrary& circuit_lib) {
return num_err;
}
/* A generic function to check the port list of a circuit model in a given type */
/************************************************************************
* A generic function to check the port list of a circuit model in a given type
* If not found, we give an error
***********************************************************************/
static
size_t check_circuit_model_required(const CircuitLibrary& circuit_lib,
const enum e_spice_model_type& circuit_model_type_to_check) {
@ -120,7 +140,92 @@ size_t check_circuit_model_required(const CircuitLibrary& circuit_lib,
return num_err;
}
/* A generic function to check the port list of a circuit model in a given type */
/************************************************************************
* A generic function to check the port list of a circuit model in a given type
* If not found, we give an error
***********************************************************************/
size_t check_one_circuit_model_port_required(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const std::vector<enum e_spice_model_port_type>& port_types_to_check) {
size_t num_err = 0;
for (const auto& port_type: port_types_to_check) {
if (0 == circuit_lib.ports_by_type(circuit_model, 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_lib.circuit_model_type(circuit_model))],
circuit_lib.circuit_model_name(circuit_model).c_str(),
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(port_type)]);
/* Incremental the counter for errors */
num_err++;
}
}
return num_err;
}
/************************************************************************
* A generic function to check the port size of a given circuit model
* if the port size does not match, we give an error
***********************************************************************/
size_t check_one_circuit_model_port_size_required(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const CircuitPortId& circuit_port,
const size_t& port_size_to_check) {
size_t num_err = 0;
if (port_size_to_check != circuit_lib.port_size(circuit_model, circuit_port)) {
vpr_printf(TIO_MESSAGE_ERROR,
"Port of circuit model(name=%s) does not have a port(type=%s) of size=%d.\n",
circuit_lib.circuit_model_name(circuit_model).c_str(),
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(circuit_model, circuit_port))],
port_size_to_check);
/* Incremental the counter for errors */
num_err++;
}
return num_err;
}
/************************************************************************
* A generic function to check the port size of a given circuit model
* if the number of ports in the given type does not match, we give an error
* for each port, if the port size does not match, we give an error
***********************************************************************/
size_t check_one_circuit_model_port_type_and_size_required(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const enum e_spice_model_port_type& port_type_to_check,
const size_t& num_ports_to_check,
const size_t& port_size_to_check,
const bool& include_global_ports) {
size_t num_err = 0;
std::vector<CircuitPortId> ports = circuit_lib.ports_by_type(circuit_model, port_type_to_check, include_global_ports);
if (num_ports_to_check != ports.size()) {
vpr_printf(TIO_MESSAGE_ERROR,
"Expect %d %s ports for a %s circuit model, but only have %d %s ports!\n",
num_ports_to_check,
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(port_type_to_check)],
CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_lib.circuit_model_type(circuit_model))],
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(port_type_to_check)],
ports.size());
num_err++;
}
for (const auto& port : ports) {
num_err += check_one_circuit_model_port_size_required(circuit_lib,
circuit_model,
port, port_size_to_check);
}
return num_err;
}
/************************************************************************
* A generic function to check the port list of circuit models in a given type
* If not found, we give an error
***********************************************************************/
static
size_t check_circuit_model_port_required(const CircuitLibrary& circuit_lib,
const enum e_spice_model_type& circuit_model_type_to_check,
@ -128,22 +233,119 @@ size_t check_circuit_model_port_required(const CircuitLibrary& circuit_lib,
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++;
}
}
num_err += check_one_circuit_model_port_required(circuit_lib, id, port_types_to_check);
}
return num_err;
}
/************************************************************************
* A generic function to find the default circuit model with a given type
* If not found, we give an error
***********************************************************************/
static
size_t check_required_default_circuit_model(const CircuitLibrary& circuit_lib,
const enum e_spice_model_type& circuit_model_type) {
size_t num_err = 0;
if (CIRCUIT_MODEL_OPEN_ID == circuit_lib.default_circuit_model(circuit_model_type)) {
vpr_printf(TIO_MESSAGE_ERROR,
"A default circuit model for the type %s! Try to define it in your architecture file!\n",
CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_model_type)]);
exit(1);
}
return num_err;
}
/************************************************************************
* A function to check the port map of FF circuit model
***********************************************************************/
size_t check_ff_circuit_model_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
size_t num_err = 0;
/* Check the type of circuit model */
VTR_ASSERT(SPICE_MODEL_FF == circuit_lib.circuit_model_type(circuit_model));
/* Check if we have D, Set and Reset */
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
SPICE_MODEL_PORT_INPUT,
3, 1, false);
/* Check if we have a clock */
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
SPICE_MODEL_PORT_CLOCK,
1, 1, false);
/* Check if we have output */
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
SPICE_MODEL_PORT_OUTPUT,
1, 1, false);
return num_err;
}
/************************************************************************
* A function to check the port map of SCFF circuit model
***********************************************************************/
size_t check_scff_circuit_model_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
size_t num_err = 0;
/* Check the type of circuit model */
VTR_ASSERT(SPICE_MODEL_SCFF == circuit_lib.circuit_model_type(circuit_model));
/* Check if we have D, Set and Reset */
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
SPICE_MODEL_PORT_INPUT,
1, 1, false);
/* Check if we have a clock */
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
SPICE_MODEL_PORT_CLOCK,
1, 1, true);
/* Check if we have output */
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
SPICE_MODEL_PORT_OUTPUT,
2, 1, false);
return num_err;
}
/************************************************************************
* A function to check the port map of SRAM circuit model
***********************************************************************/
size_t check_sram_circuit_model_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const bool& check_blwl) {
size_t num_err = 0;
/* Check the type of circuit model */
VTR_ASSERT(SPICE_MODEL_SRAM == circuit_lib.circuit_model_type(circuit_model));
/* Check if we has 1 output with size 2 */
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
SPICE_MODEL_PORT_OUTPUT,
1, 2, false);
/* basic check finished here */
if (false == check_blwl) {
return num_err;
}
/* If bl and wl are required, check their existence */
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
SPICE_MODEL_PORT_BL,
1, 1, false);
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
SPICE_MODEL_PORT_WL,
1, 1, false);
return num_err;
}
/************************************************************************
* Check points to make sure we have a valid circuit library
* Detailed checkpoints:
@ -151,6 +353,12 @@ size_t check_circuit_model_port_required(const CircuitLibrary& circuit_lib,
* 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
* 5. We must have at least one SRAM or SCFF
* 6. SRAM must have at least an input and an output ports
* 7. SCFF must have at least a clock, an input and an output ports
* 8. FF must have at least a clock, an input and an output ports
* 9. LUT must have at least an input, an output and a SRAM ports
* 10. We must have default circuit models for these types: MUX, channel wires and wires
***********************************************************************/
void check_circuit_library(const CircuitLibrary& circuit_lib) {
size_t num_err = 0;
@ -212,7 +420,7 @@ void check_circuit_library(const CircuitLibrary& circuit_lib) {
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*/
/* 7. SCFF must have at least a clock, an input and an output ports*/
std::vector<enum e_spice_model_port_type> scff_port_types_required;
scff_port_types_required.push_back(SPICE_MODEL_PORT_CLOCK);
scff_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
@ -220,7 +428,7 @@ void check_circuit_library(const CircuitLibrary& circuit_lib) {
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*/
/* 8. FF must have at least a clock, an input and an output ports*/
std::vector<enum e_spice_model_port_type> ff_port_types_required;
ff_port_types_required.push_back(SPICE_MODEL_PORT_CLOCK);
ff_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
@ -228,7 +436,7 @@ void check_circuit_library(const CircuitLibrary& circuit_lib) {
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*/
/* 9. LUT must have at least an input, an output and a SRAM ports*/
std::vector<enum e_spice_model_port_type> lut_port_types_required;
lut_port_types_required.push_back(SPICE_MODEL_PORT_SRAM);
lut_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
@ -236,6 +444,11 @@ void check_circuit_library(const CircuitLibrary& circuit_lib) {
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_LUT, lut_port_types_required);
/* 10. We must have default circuit models for these types: MUX, channel wires and wires */
num_err += check_required_default_circuit_model(circuit_lib, SPICE_MODEL_MUX);
num_err += check_required_default_circuit_model(circuit_lib, SPICE_MODEL_CHAN_WIRE);
num_err += check_required_default_circuit_model(circuit_lib, SPICE_MODEL_WIRE);
/* If we have any errors, exit */
vpr_printf(TIO_MESSAGE_ERROR,
"Finished checking circuit library with %d errors!\n",

View File

@ -50,6 +50,32 @@
#include "circuit_library.h"
/* Check points to make sure we have a valid circuit library */
size_t check_one_circuit_model_port_required(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const std::vector<enum e_spice_model_port_type>& port_types_to_check);
size_t check_one_circuit_model_port_size_required(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const CircuitPortId& circuit_port,
const size_t& port_size_to_check);
size_t check_one_circuit_model_port_type_and_size_required(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const enum e_spice_model_port_type& port_type_to_check,
const size_t& num_ports_to_check,
const size_t& port_size_to_check,
const bool& include_global_ports);
size_t check_ff_circuit_model_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model);
size_t check_scff_circuit_model_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model);
size_t check_sram_circuit_model_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const bool& check_blwl);
void check_circuit_library(const CircuitLibrary& circuit_lib);
#endif

View File

@ -221,6 +221,7 @@ class CircuitLibrary {
circuit_port_range ports(const CircuitModelId& circuit_model_id) const;
std::vector<CircuitModelId> circuit_models_by_type(const enum e_spice_model_type& type) const;
std::vector<CircuitPortId> ports_by_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_port_type& port_type) const;
std::vector<CircuitPortId> ports_by_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_port_type& port_type, const bool& include_global_port) const;
std::vector<CircuitPortId> input_ports(const CircuitModelId& circuit_model_id) const;
std::vector<CircuitPortId> output_ports(const CircuitModelId& circuit_model_id) const;
std::vector<size_t> pins(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const;
@ -239,11 +240,13 @@ class CircuitLibrary {
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;
enum e_spice_model_structure mux_structure(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;
size_t num_ports_by_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_port_type& port_type, const bool& include_global_port) 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;
@ -257,6 +260,7 @@ 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 circuit_model(const char* name) const;
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 */

View File

@ -89,6 +89,8 @@ enum e_spice_model_structure {
SPICE_MODEL_STRUCTURE_CROSSBAR,
NUM_CIRCUIT_MODEL_STRUCTURE_TYPES
};
/* Strings correspond to each type of mux structure */
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_STRUCTURE_TYPES> CIRCUIT_MODEL_STRUCTURE_TYPE_STRING = {{"TREE-LIKE", "ONE-LEVEL", "MULTI-LEVEL", "CROSSBAR"}};
enum e_spice_model_buffer_type {
SPICE_MODEL_BUF_INV,
@ -138,6 +140,7 @@ enum e_sram_orgz {
SPICE_SRAM_LOCAL_ENCODER, /* SRAMs are organized and accessed by a local encoder */
NUM_CIRCUIT_MODEL_SRAM_ORGZ_TYPES
};
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_SRAM_ORGZ_TYPES> CIRCUIT_MODEL_SRAM_ORGZ_TYPE_STRING = {{"STANDALONE", "SCAN-CHAIN", "MEMORY_BANK", "LOCAL_ENCODER"}};
#endif

View File

@ -396,6 +396,7 @@ struct s_spice_mux_model {
struct s_sram_inf_orgz {
char* spice_model_name; // Xifan TANG: Spice Support
t_spice_model* spice_model; // Xifan TANG: Spice Support
CircuitModelId circuit_model;
enum e_sram_orgz type;
};

View File

@ -265,6 +265,7 @@ struct s_port {
/* FPGA_SPICE_model support:
* mapped SPICE model port */
t_spice_model_port* spice_model_port;
CircuitPortId circuit_model_port;
char* physical_mode_pin;
int physical_mode_pin_rotate_offset; /* The pin number will rotate by an offset unit when mapping to physical modes */
int phy_mode_pin_rotate_offset_acc; /* The pin number will rotate by an offset unit when mapping to physical modes */
@ -341,6 +342,7 @@ struct s_interconnect {
/* Xifan TANG: SPICE Support*/
char* spice_model_name;
t_spice_model* spice_model;
CircuitModelId circuit_model;
int fan_in;
int fan_out;
int num_mux;
@ -658,6 +660,7 @@ struct s_pb_type {
char* physical_mode_name;
char* spice_model_name;
t_spice_model* spice_model;
CircuitModelId circuit_model;
char* mode_bits; /* Mode bits to select */
int spice_model_sram_offset;
char* physical_pb_type_name;
@ -846,6 +849,7 @@ typedef struct s_segment_inf {
/* Xifan TANG: SPICE model support*/
char* spice_model_name;
t_spice_model* spice_model;
CircuitModelId circuit_model;
/* mrFPGA: Xifan TANG */
short seg_switch;
/* end */
@ -879,6 +883,7 @@ typedef struct s_switch_inf {
/* Xifan TANG: spice support*/
char* spice_model_name;
t_spice_model* spice_model;
CircuitModelId circuit_model;
/* Xifan TANG: switch structure */
enum e_spice_model_structure structure;
int switch_num_level;
@ -922,6 +927,7 @@ typedef struct s_direct_inf {
/* Xifan Tang: FPGA-SPICE support */
char* spice_model_name;
t_spice_model* spice_model;
CircuitModelId circuit_model;
} t_direct_inf;

View File

@ -1023,6 +1023,8 @@ static void ProcessSpiceModel(ezxml_t Parent,
spice_model->design_tech_info.mux_info->structure = SPICE_MODEL_STRUCTURE_TREE;
spice_model->design_tech_info.mux_info->add_const_input = FALSE;
spice_model->design_tech_info.mux_info->const_input_val = 0;
spice_model->design_tech_info.mux_info->advanced_rram_design = FALSE;
spice_model->design_tech_info.mux_info->local_encoder = FALSE;
}
ezxml_set_attr(Node, "fracturable_lut", NULL);
@ -1632,7 +1634,8 @@ CircuitLibrary build_circuit_library(int num_spice_model, t_spice_model* spice_m
}
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) {
if ( (NULL != spice_models[imodel].lut_intermediate_buffer)
&& (1 == spice_models[imodel].lut_intermediate_buffer->exist) ) {
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;

View File

@ -1128,6 +1128,7 @@ typedef struct s_clb_to_clb_directs {
int y_offset;
int z_offset;
t_spice_model* spice_model;
CircuitModelId circuit_model;
char* name;
} t_clb_to_clb_directs;

View File

@ -1301,6 +1301,7 @@ t_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type,
return ret;
}
t_port** find_pb_type_ports_match_spice_model_port_type(t_pb_type* pb_type,
enum e_spice_model_port_type port_type,
int* port_num) {

View File

@ -102,7 +102,6 @@ t_port** find_pb_type_ports_match_spice_model_port_type(t_pb_type* pb_type,
enum e_spice_model_port_type port_type,
int* port_num);
enum e_interconnect find_pb_graph_pin_in_edges_interc_type(t_pb_graph_pin pb_graph_pin);
t_spice_model* find_pb_graph_pin_in_edges_interc_spice_model(t_pb_graph_pin pb_graph_pin);

View File

@ -33,6 +33,7 @@
#include "verilog_api.h"
#include "fpga_x2p_unique_routing.h"
#include "link_arch_circuit_lib.h"
#include "fpga_x2p_setup.h"
/***** Subroutines Declarations *****/
@ -1322,10 +1323,14 @@ void fpga_x2p_setup(t_vpr_setup vpr_setup,
/* Start time count */
t_start = clock();
vpr_printf(TIO_MESSAGE_INFO, "\nFPGA-SPICE Tool suites Initilization begins...\n");
vpr_printf(TIO_MESSAGE_INFO, "\nFPGA-X2P Tool suites Initilization begins...\n");
/* Initialize Arch SPICE MODELS*/
/* FIXME: this function is going to be removed when new linking function is working
* Initialize Arch SPICE MODELS
*/
init_check_arch_spice_models(Arch, &(vpr_setup.RoutingArch));
/* Link circuit models to architecture */
link_circuit_library_to_arch(Arch, &(vpr_setup.RoutingArch));
/* Initialize idle mode and physical mode of each pb_type and pb_graph_node */
init_check_arch_pb_type_idle_and_phy_mode();

View File

@ -0,0 +1,592 @@
/**********************************************************
* 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: link_arch_circuit_lib.cpp
* Created by: Xifan Tang
* Change history:
* +-------------------------------------+
* | Date | Author | Notes
* +-------------------------------------+
* | 2019/08/12 | Xifan Tang | Created
* +-------------------------------------+
***********************************************************************/
/************************************************************************
* This file includes key functions to link circuit models to the architecture modules
***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <assert.h>
#include <sys/stat.h>
#include <unistd.h>
/* Include vpr structs*/
#include "util.h"
#include "physical_types.h"
#include "vpr_types.h"
#include "globals.h"
#include "rr_graph.h"
#include "vpr_utils.h"
#include "path_delay.h"
#include "stats.h"
#include "route_common.h"
/* Include vtr libraries */
#include "vtr_assert.h"
/* Include spice support headers*/
#include "linkedlist.h"
#include "fpga_x2p_types.h"
#include "fpga_x2p_globals.h"
#include "fpga_x2p_utils.h"
#include "fpga_x2p_timing_utils.h"
#include "fpga_x2p_backannotate_utils.h"
#include "fpga_x2p_pbtypes_utils.h"
#include "verilog_api.h"
#include "check_circuit_library.h"
#include "link_arch_circuit_lib.h"
/************************************************************************
* Find a circuit model with a given name
* Case 1: if the circuit_model_name is not defined,
* we find a default circuit model and check its type
* Case 2: if the circuit_model_name is defined,
* we find a matched circuit model and check its type
***********************************************************************/
CircuitModelId link_circuit_model_by_name_and_type(const char* circuit_model_name,
const CircuitLibrary& circuit_lib,
const enum e_spice_model_type& model_type) {
CircuitModelId circuit_model = CIRCUIT_MODEL_OPEN_ID;
/* If the circuit_model_name is not defined, we use the default*/
if (NULL == circuit_model_name) {
circuit_model = circuit_lib.default_circuit_model(model_type);
} else {
circuit_model = circuit_lib.circuit_model(circuit_model_name);
}
/* Check the circuit model, we should have one! */
if (CIRCUIT_MODEL_OPEN_ID == circuit_model) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,LINE[%d]) Fail to find a defined circuit model called %s!\n",
__FILE__, __LINE__,
circuit_lib.circuit_model_name(circuit_model).c_str());
return circuit_model; /* Return here, no need to check the model_type */
}
/* Check the type of circuit model, make sure it is the one we want */
if (model_type != circuit_lib.circuit_model_type(circuit_model)) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,LINE[%d]) Invalid type when trying to find circuit model called %s! Expect %s but found %s!\n",
__FILE__, __LINE__,
circuit_model_name,
CIRCUIT_MODEL_TYPE_STRING[size_t(model_type)],
CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_lib.circuit_model_type(circuit_model))]);
}
return circuit_model;
}
/************************************************************************
* Link circuit model to the SRAM organization
* Case 1: standalone organization required a SRAM circuit model
* Case 1: scan-chain organization required a SCFF circuit model
* Case 1: memory-bank organization required a SRAM circuit model
***********************************************************************/
static
void link_one_sram_inf_orgz(t_sram_inf_orgz* cur_sram_inf_orgz,
const CircuitLibrary& circuit_lib) {
/* If cur_sram_inf_orgz is not initialized, do nothing */
if (NULL == cur_sram_inf_orgz) {
return;
}
/* Check the type of SRAM_Ciruit_MODEL required by different sram organization */
/* check SRAM ports
* Checker for circuit models used by the SRAM organization
* either SRAMs or SCFFs
* 1. It will check the basic port required for SRAMs and SCFFs
* 2. It will check any special ports required for SRAMs and SCFFs
*/
switch (cur_sram_inf_orgz->type) {
case SPICE_SRAM_STANDALONE:
cur_sram_inf_orgz->circuit_model = link_circuit_model_by_name_and_type(cur_sram_inf_orgz->spice_model_name, circuit_lib, SPICE_MODEL_SRAM);
/* check SRAM ports */
check_sram_circuit_model_ports(circuit_lib, cur_sram_inf_orgz->circuit_model, false);
break;
case SPICE_SRAM_MEMORY_BANK:
cur_sram_inf_orgz->circuit_model = link_circuit_model_by_name_and_type(cur_sram_inf_orgz->spice_model_name, circuit_lib, SPICE_MODEL_SRAM);
/* check if this one has bit lines and word lines */
check_sram_circuit_model_ports(circuit_lib, cur_sram_inf_orgz->circuit_model, true);
break;
case SPICE_SRAM_SCAN_CHAIN:
/* check Scan-chain Flip-flop ports */
cur_sram_inf_orgz->circuit_model = link_circuit_model_by_name_and_type(cur_sram_inf_orgz->spice_model_name, circuit_lib, SPICE_MODEL_SCFF);
check_scff_circuit_model_ports(circuit_lib, cur_sram_inf_orgz->circuit_model);
break;
case SPICE_SRAM_LOCAL_ENCODER:
/* Wipe out LOCAL ENCODER, it is not supported here ! */
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,LINE[%d]) Local encoder SRAM organization is not supported!\n",
__FILE__, __LINE__);
exit(1);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,LINE[%d]) Invalid SRAM organization!\n",
__FILE__, __LINE__);
exit(1);
}
/* RRAM Scan-chain is not supported yet. Now just forbidden this option */
if ( (SPICE_SRAM_SCAN_CHAIN == cur_sram_inf_orgz->type)
&& (SPICE_MODEL_DESIGN_RRAM == circuit_lib.design_tech_type(cur_sram_inf_orgz->circuit_model)) ) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,LINE[%d]) RRAM-based Scan-chain Flip-flop has not been supported yet!\n",
__FILE__, __LINE__);
exit(1);
}
return;
}
static
void link_sram_inf(t_sram_inf* cur_sram_inf,
const CircuitLibrary& circuit_lib) {
/* We have two branches:
* 1. SPICE SRAM organization information
* 2. Verilog SRAM organization information
*/
link_one_sram_inf_orgz(cur_sram_inf->spice_sram_inf_orgz,
circuit_lib);
link_one_sram_inf_orgz(cur_sram_inf->verilog_sram_inf_orgz,
circuit_lib);
return;
}
/**************************************************************************
* With given circuit port, find the pb_type port with same name and type
**************************************************************************/
t_port* find_pb_type_port_match_circuit_model_port(const t_pb_type* pb_type,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const CircuitPortId& circuit_port) {
t_port* ret = NULL;
size_t num_found = 0;
/* Search ports */
for (int iport = 0; iport < pb_type->num_ports; iport++) {
/* Match the name and port size*/
if ( (0 == circuit_lib.port_prefix(circuit_model, circuit_port).compare(pb_type->ports[iport].name))
&& (size_t(pb_type->ports[iport].num_pins) == circuit_lib.port_size(circuit_model, circuit_port))) {
/* Match the type*/
switch (circuit_lib.port_type(circuit_model, circuit_port)) {
case SPICE_MODEL_PORT_INPUT:
if ((IN_PORT == pb_type->ports[iport].type)
&&(0 == pb_type->ports[iport].is_clock)) {
ret = &(pb_type->ports[iport]);
num_found++;
}
break;
case SPICE_MODEL_PORT_OUTPUT:
if (OUT_PORT == pb_type->ports[iport].type) {
ret = &(pb_type->ports[iport]);
}
break;
case SPICE_MODEL_PORT_CLOCK:
if ((IN_PORT == pb_type->ports[iport].type)&&(1 == pb_type->ports[iport].is_clock)) {
ret = &(pb_type->ports[iport]);
num_found++;
}
break;
case SPICE_MODEL_PORT_INOUT :
if ((INOUT_PORT == pb_type->ports[iport].type)&&(0 == pb_type->ports[iport].is_clock)) {
ret = &(pb_type->ports[iport]);
num_found++;
}
break;
case SPICE_MODEL_PORT_SRAM:
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s, [LINE%d])Invalid type for circuit model port(%s)!\n",
__FILE__, __LINE__, circuit_lib.port_prefix(circuit_model, circuit_port));
exit(1);
}
}
}
/* We should find only 1 match */
if (1 < num_found) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d])More than 1 pb_type(%s) port match spice_model_port(%s)!\n",
__FILE__, __LINE__, pb_type->name, circuit_lib.port_prefix(circuit_model, circuit_port).c_str());
exit(1);
}
return ret;
}
/************************************************************************
* Map (synchronize) pb_type ports to circuit model ports
***********************************************************************/
static
int link_pb_type_port_to_circuit_model_ports(const t_pb_type* cur_pb_type,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
/* Check */
assert(NULL != cur_pb_type);
/* Initialize each port */
for (int iport = 0; iport < cur_pb_type->num_ports; iport++) {
cur_pb_type->ports[iport].circuit_model_port = CIRCUIT_PORT_OPEN_ID;
}
/* Return if SPICE_MODEL is NULL */
if (CIRCUIT_MODEL_OPEN_ID == circuit_model) {
return 0;
}
/* For each port, find a SPICE model port, which has the same name and port size */
for (auto& port : circuit_lib.ports(circuit_model)) {
t_port* cur_pb_type_port = find_pb_type_port_match_circuit_model_port(cur_pb_type, circuit_lib, circuit_model, port);
/* Not every spice_model_port can find a mapped pb_type_port.
* Since a pb_type only includes necessary ports in technology mapping.
* ports for physical designs may be ignored !
*/
if (NULL != cur_pb_type_port) {
cur_pb_type_port->circuit_model_port = port;
}
}
/* Although some spice_model_port may not have a corresponding pb_type_port
* but each pb_type_port should be mapped to a spice_model_port
*/
for (int iport = 0; iport < cur_pb_type->num_ports; iport++) {
if (CIRCUIT_PORT_OPEN_ID == cur_pb_type->ports[iport].circuit_model_port) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d])Pb_type(%s) Port(%s) cannot find a corresponding port in SPICE model(%s)\n",
__FILE__, __LINE__, cur_pb_type->name, cur_pb_type->ports[iport].name,
circuit_lib.circuit_model_name(circuit_model).c_str());
exit(1);
}
}
return cur_pb_type->num_ports;
}
/************************************************************************
* Find a circuit model for an interconnect in pb_type
* Case 1: if the circuit_model_name is not defined,
* we find a default circuit model and check its type
* Case 2: if the circuit_model_name is defined,
* we find a matched circuit model and check its type
***********************************************************************/
static
void link_pb_type_interc_circuit_model_by_type(t_interconnect* cur_interc,
const CircuitLibrary& circuit_lib,
const enum e_spice_model_type& model_type) {
/* If the circuit_model_name is not defined, we use the default*/
cur_interc->circuit_model = link_circuit_model_by_name_and_type(cur_interc->spice_model_name,
circuit_lib,
model_type);
/* Check the circuit model, we should have one! */
if (CIRCUIT_MODEL_OPEN_ID == cur_interc->circuit_model) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,LINE[%d]) Error in linking circuit model for interconnect(name %s)! Check [LINE%d] in architecture file)!\n",
__FILE__, __LINE__,
cur_interc->name,
cur_interc->line_num);
exit(1);
}
/* Special check for MUXes:
* If the multiplexers do not have any input buffers, the loop breaker cannot be disabled
*/
if (SPICE_MODEL_MUX == model_type) {
if (NULL != cur_interc->loop_breaker_string) {
if (false == circuit_lib.is_input_buffered(cur_interc->circuit_model)) {
vpr_printf(TIO_MESSAGE_INFO,
"Line[%d] Cannot disable an interconnect without input buffering.\n",
cur_interc->line_num);
}
}
}
return;
}
/************************************************************************
* Find a circuit model for an interconnect in pb_type
* Case 1: if this is a DIRECT interconnection,
* we will try to find a circuit model whose type is WIRE
* Case 2: if this is a COMPLETE interconnection, we should evaluate
* the number of multiplexer required.
* when it does require multiplexers
* we will try to find a circuit model whose type is MUX
* otherwise,
* we will try to find a circuit model whose type is WIRE
* Case 3: if this is a MUX interconnection,
* we will try to find a circuit model whose type is WIRE
***********************************************************************/
static
void link_pb_type_interc_circuit_model(t_interconnect* cur_interc,
const CircuitLibrary& circuit_lib) {
switch (cur_interc->type) {
case DIRECT_INTERC:
link_pb_type_interc_circuit_model_by_type(cur_interc, circuit_lib, SPICE_MODEL_WIRE);
break;
case COMPLETE_INTERC:
/* Special for Completer Interconnection:
* 1. The input number is 1, this infers a direct interconnection.
* 2. The input number is larger than 1, this infers multplexers
* according to interconnect[j].num_mux identify the number of input at this level
*/
if (0 == cur_interc->num_mux) {
link_pb_type_interc_circuit_model_by_type(cur_interc, circuit_lib, SPICE_MODEL_WIRE);
} else {
link_pb_type_interc_circuit_model_by_type(cur_interc, circuit_lib, SPICE_MODEL_MUX);
}
break;
case MUX_INTERC:
link_pb_type_interc_circuit_model_by_type(cur_interc, circuit_lib, SPICE_MODEL_MUX);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,LINE[%d]) Unknown type of interconnection (name=%s) defined in architecture file(LINE%d)!\n",
__FILE__, __LINE__, cur_interc->name, cur_interc->line_num);
exit(1);
}
return;
}
/************************************************************************
* Walk through the pb_types in a recursive way
* Find circuit_model_name definition in pb_types
* Try to match the name with defined spice_models
***********************************************************************/
static
void link_pb_types_circuit_model_rec(t_pb_type* cur_pb_type,
const CircuitLibrary& circuit_lib) {
if (NULL == cur_pb_type) {
vpr_printf(TIO_MESSAGE_WARNING,
"(File:%s,LINE[%d])cur_pb_type is null pointor!\n",
__FILE__, __LINE__);
return;
}
/* If there is a circuit_model_name or physical_pb_type_name referring to a physical pb type,
* this is a leaf node!
*/
if ( TRUE == is_primitive_pb_type(cur_pb_type) ) {
/* What annoys me is VPR create a sub pb_type for each lut which suppose to be a leaf node
* This may bring software convience but ruins SPICE modeling
*/
if (NULL != cur_pb_type->physical_pb_type_name) {
/* if this is not a physical pb_type, we do not care its circuit_model_name*/
return;
}
/* Let's find a matched circuit model!*/
cur_pb_type->circuit_model = circuit_lib.circuit_model(cur_pb_type->spice_model_name);
if (CIRCUIT_MODEL_OPEN_ID == cur_pb_type->circuit_model) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,LINE[%d]) Fail to find a defined circuit model called %s, in pb_type(%s)!\n",
__FILE__, __LINE__, cur_pb_type->spice_model_name, cur_pb_type->name);
exit(1);
}
/* Map pb_type ports to SPICE model ports*/
link_pb_type_port_to_circuit_model_ports(cur_pb_type, circuit_lib, cur_pb_type->circuit_model);
return;
}
/* Otherwise, initialize it to be OPEN node */
cur_pb_type->circuit_model = CIRCUIT_MODEL_OPEN_ID;
/* Traversal the hierarchy*/
for (int imode = 0; imode < cur_pb_type->num_modes; imode++) {
/* Task 1: Find the interconnections and match the spice_model */
for (int jinterc = 0; jinterc < cur_pb_type->modes[imode].num_interconnect; jinterc++) {
/* Initialize it to be OPEN node */
cur_pb_type->modes[imode].interconnect[jinterc].circuit_model = CIRCUIT_MODEL_OPEN_ID;
link_pb_type_interc_circuit_model(&(cur_pb_type->modes[imode].interconnect[jinterc]),
circuit_lib);
}
/* Task 2: Find the child pb_type, do matching recursively */
for (int ipb = 0; ipb < cur_pb_type->modes[imode].num_pb_type_children; ipb++) {
link_pb_types_circuit_model_rec(&(cur_pb_type->modes[imode].pb_type_children[ipb]), circuit_lib);
}
}
return;
}
/* Check if the spice model structure is the same with the switch_inf structure */
static
size_t check_circuit_model_structure_match_switch_inf(const t_switch_inf& target_switch_inf,
const CircuitLibrary& circuit_lib) {
size_t num_err = 0;
VTR_ASSERT_SAFE(CIRCUIT_MODEL_OPEN_ID != target_switch_inf.circuit_model);
if (target_switch_inf.structure != circuit_lib.mux_structure(target_switch_inf.circuit_model)) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,[LINE%d]) Mismatch in MUX structure between circuit model(%s, %s) and switch_inf(%s, %s)!\n",
__FILE__, __LINE__,
circuit_lib.circuit_model_name(target_switch_inf.circuit_model).c_str(),
CIRCUIT_MODEL_STRUCTURE_TYPE_STRING[size_t(circuit_lib.mux_structure(target_switch_inf.circuit_model))],
target_switch_inf.name,
CIRCUIT_MODEL_STRUCTURE_TYPE_STRING[size_t(target_switch_inf.structure)]);
num_err++;
}
return num_err;
}
/************************************************************************
* Initialize and check circuit models defined in architecture
* Tasks:
* 1. Link the circuit model defined in pb_types and routing switches
* 2. Add default circuit model for any inexplicit definition
***********************************************************************/
void link_circuit_library_to_arch(t_arch* arch,
t_det_routing_arch* routing_arch) {
vpr_printf(TIO_MESSAGE_INFO, "Linking circuit models to modules in FPGA architecture...\n");
/* Check Circuit models first*/
VTR_ASSERT_SAFE( (NULL != arch) && (NULL != arch->spice) );
/* 1. Link the spice model defined in pb_types and routing switches */
/* Step A: Check routing switches, connection blocks*/
if (0 >= arch->num_cb_switch) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, LINE[%d]) Define Switches for Connection Blocks is mandatory in FPGA X2P support! Miss this part in architecture file.\n",
__FILE__,__LINE__);
exit(1);
}
for (int i = 0; i < arch->num_cb_switch; i++) {
arch->cb_switches[i].circuit_model = link_circuit_model_by_name_and_type(arch->cb_switches[i].spice_model_name,
arch->spice->circuit_lib, SPICE_MODEL_MUX);
if (CIRCUIT_MODEL_OPEN_ID == arch->cb_switches[i].circuit_model) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, LINE[%d])Invalid circuit model name(%s) of Switch(%s) is undefined in circuit models!\n",
__FILE__, __LINE__, arch->cb_switches[i].spice_model_name, arch->cb_switches[i].name);
exit(1);
}
/* Check the spice model structure is matched with the structure in switch_inf */
if (0 < check_circuit_model_structure_match_switch_inf(arch->cb_switches[i], arch->spice->circuit_lib)) {
exit(1);
}
}
/* Step B: Check switch list: Switch Box*/
if (0 >= arch->num_switches) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, LINE[%d]) Define Switches for Switch Boxes is mandatory in FPGA X2P support! Miss this part in architecture file.\n",
__FILE__, __LINE__);
exit(1);
}
for (int i = 0; i < arch->num_switches; i++) {
arch->Switches[i].circuit_model = link_circuit_model_by_name_and_type(arch->Switches[i].spice_model_name,
arch->spice->circuit_lib, SPICE_MODEL_MUX);
if (CIRCUIT_MODEL_OPEN_ID == arch->Switches[i].circuit_model) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, LINE[%d])Invalid circuit model name(%s) of Switch(%s) is undefined in circuit models!\n",
__FILE__, __LINE__, arch->Switches[i].spice_model_name, arch->Switches[i].name);
exit(1);
}
/* Check the spice model structure is matched with the structure in switch_inf */
if (0 < check_circuit_model_structure_match_switch_inf(arch->Switches[i], arch->spice->circuit_lib)) {
exit(1);
}
}
/* Update the switches in detailed routing architecture settings*/
for (int i = 0; i < routing_arch->num_switch; i++) {
switch_inf[i].circuit_model = link_circuit_model_by_name_and_type(switch_inf[i].spice_model_name,
arch->spice->circuit_lib, SPICE_MODEL_MUX);
if (CIRCUIT_MODEL_OPEN_ID == switch_inf[i].circuit_model) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, LINE[%d])Invalid circuit model name(%s) of Switch(%s) is undefined in circuit models!\n",
__FILE__, __LINE__, switch_inf[i].spice_model_name, switch_inf[i].name);
exit(1);
}
}
/* Step C: Find SRAM Model*/
link_sram_inf(&(arch->sram_inf), arch->spice->circuit_lib);
/* Step D: Find the segment spice_model*/
for (int i = 0; i < arch->num_segments; i++) {
arch->Segments[i].circuit_model = link_circuit_model_by_name_and_type(arch->Segments[i].spice_model_name,
arch->spice->circuit_lib, SPICE_MODEL_CHAN_WIRE);
if (CIRCUIT_MODEL_OPEN_ID == arch->Segments[i].circuit_model) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, LINE[%d])Invalid circuit model name(%s) of Segment(Length:%d) is undefined in circuit models!\n",
__FILE__ ,__LINE__,
arch->Segments[i].spice_model_name,
arch->Segments[i].length);
exit(1);
}
}
/* Step E: Direct connections between CLBs */
for (int i = 0; i < arch->num_directs; i++) {
arch->Directs[i].circuit_model = link_circuit_model_by_name_and_type(arch->Directs[i].spice_model_name,
arch->spice->circuit_lib, SPICE_MODEL_WIRE);
/* Check SPICE model type */
if (CIRCUIT_MODEL_OPEN_ID == arch->Directs[i].circuit_model) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, LINE[%d])Invalid circuit model name(%s) of CLB to CLB Direct Connection (name=%s) is undefined in circuit models!\n",
__FILE__ ,__LINE__,
arch->Directs[i].spice_model_name,
arch->Directs[i].name);
exit(1);
}
/* Copy it to clb2clb_directs */
clb2clb_direct[i].circuit_model = arch->Directs[i].circuit_model;
}
/* 2. Search Complex Blocks (Pb_Types), Link spice_model according to the spice_model_name*/
for (int i = 0; i < num_types; i++) {
if (NULL != type_descriptors[i].pb_type) {
link_pb_types_circuit_model_rec(type_descriptors[i].pb_type, arch->spice->circuit_lib);
}
}
vpr_printf(TIO_MESSAGE_INFO, "Linking circuit models to modules in FPGA architecture...Completed\n");
return;
}
/************************************************************************
* End of file : link_arch_circuit_lib.cpp
***********************************************************************/

View File

@ -0,0 +1,68 @@
/**********************************************************
* 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: link_arch_circuit_lib.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 LINK_ARCH_CIRCUIT_LIB_H
#define LINK_ARCH_CIRCUIT_LIB_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 */
CircuitModelId link_circuit_model_by_name_and_type(const char* circuit_model_name,
const CircuitLibrary& circuit_lib,
const enum e_spice_model_type& model_type);
t_port* find_pb_type_port_match_circuit_model_port(const t_pb_type* pb_type,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const CircuitPortId& circuit_port);
void link_circuit_library_to_arch(t_arch* arch,
t_det_routing_arch* routing_arch);
#endif
/************************************************************************
* End of file : link_arch_circuit_lib.h
***********************************************************************/