add linking functions for circuit models and architecture, memory sanitizing is ongoing
This commit is contained in:
parent
c56f289d3e
commit
392f579836
|
@ -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 */
|
/* Header files should be included in a sequence */
|
||||||
/* Standard header files required go first */
|
/* Standard header files required go first */
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#include "check_circuit_library.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
|
static
|
||||||
size_t check_circuit_library_unique_names(const CircuitLibrary& circuit_lib) {
|
size_t check_circuit_library_unique_names(const CircuitLibrary& circuit_lib) {
|
||||||
size_t num_err = 0;
|
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
|
static
|
||||||
size_t check_circuit_library_unique_prefix(const CircuitLibrary& circuit_lib) {
|
size_t check_circuit_library_unique_prefix(const CircuitLibrary& circuit_lib) {
|
||||||
size_t num_err = 0;
|
size_t num_err = 0;
|
||||||
|
@ -102,7 +119,10 @@ size_t check_circuit_library_unique_prefix(const CircuitLibrary& circuit_lib) {
|
||||||
return num_err;
|
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
|
static
|
||||||
size_t check_circuit_model_required(const CircuitLibrary& circuit_lib,
|
size_t check_circuit_model_required(const CircuitLibrary& circuit_lib,
|
||||||
const enum e_spice_model_type& circuit_model_type_to_check) {
|
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;
|
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
|
static
|
||||||
size_t check_circuit_model_port_required(const CircuitLibrary& circuit_lib,
|
size_t check_circuit_model_port_required(const CircuitLibrary& circuit_lib,
|
||||||
const enum e_spice_model_type& circuit_model_type_to_check,
|
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;
|
size_t num_err = 0;
|
||||||
|
|
||||||
for (const auto& id : circuit_lib.circuit_models_by_type(circuit_model_type_to_check)) {
|
for (const auto& id : circuit_lib.circuit_models_by_type(circuit_model_type_to_check)) {
|
||||||
for (const auto& port_type: port_types_to_check) {
|
num_err += check_one_circuit_model_port_required(circuit_lib, id, 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;
|
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
|
* Check points to make sure we have a valid circuit library
|
||||||
* Detailed checkpoints:
|
* Detailed checkpoints:
|
||||||
|
@ -151,6 +353,12 @@ size_t check_circuit_model_port_required(const CircuitLibrary& circuit_lib,
|
||||||
* 2. Circuit models have unique prefix
|
* 2. Circuit models have unique prefix
|
||||||
* 3. Check IOPADs have input and output ports
|
* 3. Check IOPADs have input and output ports
|
||||||
* 4. Check MUXes has been defined and has 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) {
|
void check_circuit_library(const CircuitLibrary& circuit_lib) {
|
||||||
size_t num_err = 0;
|
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);
|
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;
|
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_CLOCK);
|
||||||
scff_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
|
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);
|
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;
|
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_CLOCK);
|
||||||
ff_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
|
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);
|
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;
|
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_SRAM);
|
||||||
lut_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
|
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);
|
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 */
|
/* If we have any errors, exit */
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
"Finished checking circuit library with %d errors!\n",
|
"Finished checking circuit library with %d errors!\n",
|
||||||
|
|
|
@ -50,6 +50,32 @@
|
||||||
#include "circuit_library.h"
|
#include "circuit_library.h"
|
||||||
|
|
||||||
/* Check points to make sure we have a valid circuit library */
|
/* 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);
|
void check_circuit_library(const CircuitLibrary& circuit_lib);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -221,6 +221,7 @@ class CircuitLibrary {
|
||||||
circuit_port_range ports(const CircuitModelId& circuit_model_id) const;
|
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<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;
|
||||||
|
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> input_ports(const CircuitModelId& circuit_model_id) const;
|
||||||
std::vector<CircuitPortId> output_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;
|
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_input_buffered(const CircuitModelId& circuit_model_id) const;
|
||||||
bool is_output_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;
|
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*/
|
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_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;
|
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;
|
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(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;
|
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;
|
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_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_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;
|
bool port_is_prog(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const;
|
||||||
public: /* Public Accessors: Methods to find circuit model */
|
public: /* Public Accessors: Methods to find circuit model */
|
||||||
|
CircuitModelId circuit_model(const char* name) const;
|
||||||
CircuitModelId circuit_model(const std::string& name) const;
|
CircuitModelId circuit_model(const std::string& name) const;
|
||||||
CircuitModelId default_circuit_model(const enum e_spice_model_type& type) const;
|
CircuitModelId default_circuit_model(const enum e_spice_model_type& type) const;
|
||||||
public: /* Public Accessors: Timing graph */
|
public: /* Public Accessors: Timing graph */
|
||||||
|
|
|
@ -89,6 +89,8 @@ enum e_spice_model_structure {
|
||||||
SPICE_MODEL_STRUCTURE_CROSSBAR,
|
SPICE_MODEL_STRUCTURE_CROSSBAR,
|
||||||
NUM_CIRCUIT_MODEL_STRUCTURE_TYPES
|
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 {
|
enum e_spice_model_buffer_type {
|
||||||
SPICE_MODEL_BUF_INV,
|
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 */
|
SPICE_SRAM_LOCAL_ENCODER, /* SRAMs are organized and accessed by a local encoder */
|
||||||
NUM_CIRCUIT_MODEL_SRAM_ORGZ_TYPES
|
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
|
#endif
|
||||||
|
|
|
@ -396,6 +396,7 @@ struct s_spice_mux_model {
|
||||||
struct s_sram_inf_orgz {
|
struct s_sram_inf_orgz {
|
||||||
char* spice_model_name; // Xifan TANG: Spice Support
|
char* spice_model_name; // Xifan TANG: Spice Support
|
||||||
t_spice_model* spice_model; // Xifan TANG: Spice Support
|
t_spice_model* spice_model; // Xifan TANG: Spice Support
|
||||||
|
CircuitModelId circuit_model;
|
||||||
enum e_sram_orgz type;
|
enum e_sram_orgz type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -265,6 +265,7 @@ struct s_port {
|
||||||
/* FPGA_SPICE_model support:
|
/* FPGA_SPICE_model support:
|
||||||
* mapped SPICE model port */
|
* mapped SPICE model port */
|
||||||
t_spice_model_port* spice_model_port;
|
t_spice_model_port* spice_model_port;
|
||||||
|
CircuitPortId circuit_model_port;
|
||||||
char* physical_mode_pin;
|
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 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 */
|
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*/
|
/* Xifan TANG: SPICE Support*/
|
||||||
char* spice_model_name;
|
char* spice_model_name;
|
||||||
t_spice_model* spice_model;
|
t_spice_model* spice_model;
|
||||||
|
CircuitModelId circuit_model;
|
||||||
int fan_in;
|
int fan_in;
|
||||||
int fan_out;
|
int fan_out;
|
||||||
int num_mux;
|
int num_mux;
|
||||||
|
@ -658,6 +660,7 @@ struct s_pb_type {
|
||||||
char* physical_mode_name;
|
char* physical_mode_name;
|
||||||
char* spice_model_name;
|
char* spice_model_name;
|
||||||
t_spice_model* spice_model;
|
t_spice_model* spice_model;
|
||||||
|
CircuitModelId circuit_model;
|
||||||
char* mode_bits; /* Mode bits to select */
|
char* mode_bits; /* Mode bits to select */
|
||||||
int spice_model_sram_offset;
|
int spice_model_sram_offset;
|
||||||
char* physical_pb_type_name;
|
char* physical_pb_type_name;
|
||||||
|
@ -846,6 +849,7 @@ typedef struct s_segment_inf {
|
||||||
/* Xifan TANG: SPICE model support*/
|
/* Xifan TANG: SPICE model support*/
|
||||||
char* spice_model_name;
|
char* spice_model_name;
|
||||||
t_spice_model* spice_model;
|
t_spice_model* spice_model;
|
||||||
|
CircuitModelId circuit_model;
|
||||||
/* mrFPGA: Xifan TANG */
|
/* mrFPGA: Xifan TANG */
|
||||||
short seg_switch;
|
short seg_switch;
|
||||||
/* end */
|
/* end */
|
||||||
|
@ -879,6 +883,7 @@ typedef struct s_switch_inf {
|
||||||
/* Xifan TANG: spice support*/
|
/* Xifan TANG: spice support*/
|
||||||
char* spice_model_name;
|
char* spice_model_name;
|
||||||
t_spice_model* spice_model;
|
t_spice_model* spice_model;
|
||||||
|
CircuitModelId circuit_model;
|
||||||
/* Xifan TANG: switch structure */
|
/* Xifan TANG: switch structure */
|
||||||
enum e_spice_model_structure structure;
|
enum e_spice_model_structure structure;
|
||||||
int switch_num_level;
|
int switch_num_level;
|
||||||
|
@ -922,6 +927,7 @@ typedef struct s_direct_inf {
|
||||||
/* Xifan Tang: FPGA-SPICE support */
|
/* Xifan Tang: FPGA-SPICE support */
|
||||||
char* spice_model_name;
|
char* spice_model_name;
|
||||||
t_spice_model* spice_model;
|
t_spice_model* spice_model;
|
||||||
|
CircuitModelId circuit_model;
|
||||||
} t_direct_inf;
|
} t_direct_inf;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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->structure = SPICE_MODEL_STRUCTURE_TREE;
|
||||||
spice_model->design_tech_info.mux_info->add_const_input = FALSE;
|
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->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);
|
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);
|
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;
|
std::string model_name;
|
||||||
if (NULL != spice_models[imodel].lut_intermediate_buffer->spice_model_name) {
|
if (NULL != spice_models[imodel].lut_intermediate_buffer->spice_model_name) {
|
||||||
model_name = spice_models[imodel].lut_intermediate_buffer->spice_model_name;
|
model_name = spice_models[imodel].lut_intermediate_buffer->spice_model_name;
|
||||||
|
|
|
@ -1128,6 +1128,7 @@ typedef struct s_clb_to_clb_directs {
|
||||||
int y_offset;
|
int y_offset;
|
||||||
int z_offset;
|
int z_offset;
|
||||||
t_spice_model* spice_model;
|
t_spice_model* spice_model;
|
||||||
|
CircuitModelId circuit_model;
|
||||||
char* name;
|
char* name;
|
||||||
} t_clb_to_clb_directs;
|
} t_clb_to_clb_directs;
|
||||||
|
|
||||||
|
|
|
@ -1301,6 +1301,7 @@ t_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
t_port** find_pb_type_ports_match_spice_model_port_type(t_pb_type* pb_type,
|
t_port** find_pb_type_ports_match_spice_model_port_type(t_pb_type* pb_type,
|
||||||
enum e_spice_model_port_type port_type,
|
enum e_spice_model_port_type port_type,
|
||||||
int* port_num) {
|
int* port_num) {
|
||||||
|
|
|
@ -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,
|
enum e_spice_model_port_type port_type,
|
||||||
int* port_num);
|
int* port_num);
|
||||||
|
|
||||||
|
|
||||||
enum e_interconnect find_pb_graph_pin_in_edges_interc_type(t_pb_graph_pin pb_graph_pin);
|
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);
|
t_spice_model* find_pb_graph_pin_in_edges_interc_spice_model(t_pb_graph_pin pb_graph_pin);
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "verilog_api.h"
|
#include "verilog_api.h"
|
||||||
#include "fpga_x2p_unique_routing.h"
|
#include "fpga_x2p_unique_routing.h"
|
||||||
|
|
||||||
|
#include "link_arch_circuit_lib.h"
|
||||||
#include "fpga_x2p_setup.h"
|
#include "fpga_x2p_setup.h"
|
||||||
|
|
||||||
/***** Subroutines Declarations *****/
|
/***** Subroutines Declarations *****/
|
||||||
|
@ -1322,10 +1323,14 @@ void fpga_x2p_setup(t_vpr_setup vpr_setup,
|
||||||
/* Start time count */
|
/* Start time count */
|
||||||
t_start = clock();
|
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));
|
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 */
|
/* Initialize idle mode and physical mode of each pb_type and pb_graph_node */
|
||||||
init_check_arch_pb_type_idle_and_phy_mode();
|
init_check_arch_pb_type_idle_and_phy_mode();
|
||||||
|
|
|
@ -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
|
||||||
|
***********************************************************************/
|
|
@ -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
|
||||||
|
***********************************************************************/
|
||||||
|
|
Loading…
Reference in New Issue