Merge remote-tracking branch 'origin/dev' into heterogeneous
This commit is contained in:
commit
30c0f2b6b7
|
@ -0,0 +1,467 @@
|
||||||
|
/**********************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 LNIS - The University of Utah
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Filename: check_circuit_library.cpp
|
||||||
|
* Created by: Xifan Tang
|
||||||
|
* Change history:
|
||||||
|
* +-------------------------------------+
|
||||||
|
* | Date | Author | Notes
|
||||||
|
* +-------------------------------------+
|
||||||
|
* | 2019/08/12 | Xifan Tang | Created
|
||||||
|
* +-------------------------------------+
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < circuit_lib.num_circuit_models(); ++i) {
|
||||||
|
/* Skip for the last element, because the inner loop will access it */
|
||||||
|
if (i == circuit_lib.num_circuit_models() - 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Get the name of reference */
|
||||||
|
const std::string& i_name = circuit_lib.circuit_model_name(CircuitModelId(i));
|
||||||
|
for (size_t j = i + 1; j < circuit_lib.num_circuit_models(); ++j) {
|
||||||
|
/* Compare the name of candidate */
|
||||||
|
const std::string& j_name = circuit_lib.circuit_model_name(CircuitModelId(j));
|
||||||
|
/* Compare the name and skip for different names */
|
||||||
|
if (0 != i_name.compare(j_name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"Circuit model(index=%d) and (index=%d) share the same name, which is invalid!\n",
|
||||||
|
i , j, i_name.c_str());
|
||||||
|
/* Incremental the counter for errors */
|
||||||
|
num_err++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < circuit_lib.num_circuit_models(); ++i) {
|
||||||
|
/* Skip for the last element, because the inner loop will access it */
|
||||||
|
if (i == circuit_lib.num_circuit_models() - 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Get the name of reference */
|
||||||
|
const std::string& i_prefix = circuit_lib.circuit_model_prefix(CircuitModelId(i));
|
||||||
|
for (size_t j = i + 1; j < circuit_lib.num_circuit_models(); ++j) {
|
||||||
|
/* Compare the name of candidate */
|
||||||
|
const std::string& j_prefix = circuit_lib.circuit_model_prefix(CircuitModelId(j));
|
||||||
|
/* Compare the name and skip for different prefix */
|
||||||
|
if (0 != i_prefix.compare(j_prefix)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"Circuit model(name=%s) and (name=%s) share the same prefix, which is invalid!\n",
|
||||||
|
circuit_lib.circuit_model_name(CircuitModelId(i)).c_str(),
|
||||||
|
circuit_lib.circuit_model_name(CircuitModelId(j)).c_str(),
|
||||||
|
i_prefix.c_str());
|
||||||
|
/* Incremental the counter for errors */
|
||||||
|
num_err++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* A generic function to check the port list of a circuit model in a given type
|
||||||
|
* 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) {
|
||||||
|
size_t num_err = 0;
|
||||||
|
|
||||||
|
/* We must have an IOPAD*/
|
||||||
|
if ( 0 == circuit_lib.circuit_models_by_type(circuit_model_type_to_check).size()) {
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"At least one %s circuit model is required!\n",
|
||||||
|
CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_model_type_to_check)]);
|
||||||
|
/* Incremental the counter for errors */
|
||||||
|
num_err++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* A generic function to check the port list of a circuit model in a given type
|
||||||
|
* 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,
|
||||||
|
const std::vector<enum e_spice_model_port_type>& port_types_to_check) {
|
||||||
|
size_t num_err = 0;
|
||||||
|
|
||||||
|
for (const auto& id : circuit_lib.circuit_models_by_type(circuit_model_type_to_check)) {
|
||||||
|
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:
|
||||||
|
* 1. Circuit models have unique names
|
||||||
|
* 2. Circuit models have unique prefix
|
||||||
|
* 3. Check IOPADs have input and output ports
|
||||||
|
* 4. Check MUXes has been defined and has input and output ports
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
vpr_printf(TIO_MESSAGE_INFO, "Checking circuit models...\n");
|
||||||
|
|
||||||
|
/* 1. Circuit models have unique names
|
||||||
|
* For each circuit model, we always make sure it does not share any name with any circuit model locating after it
|
||||||
|
*/
|
||||||
|
num_err += check_circuit_library_unique_names(circuit_lib);
|
||||||
|
|
||||||
|
/* 2. Circuit models have unique prefix
|
||||||
|
* For each circuit model, we always make sure it does not share any prefix with any circuit model locating after it
|
||||||
|
*/
|
||||||
|
num_err += check_circuit_library_unique_prefix(circuit_lib);
|
||||||
|
|
||||||
|
/* 3. Check io has been defined and has input and output ports
|
||||||
|
* [a] We must have an IOPAD!
|
||||||
|
* [b] For each IOPAD, we must have at least an input, an output, an INOUT and an SRAM port
|
||||||
|
*/
|
||||||
|
num_err += check_circuit_model_required(circuit_lib, SPICE_MODEL_IOPAD);
|
||||||
|
|
||||||
|
std::vector<enum e_spice_model_port_type> iopad_port_types_required;
|
||||||
|
iopad_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
|
||||||
|
iopad_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
|
||||||
|
iopad_port_types_required.push_back(SPICE_MODEL_PORT_INOUT);
|
||||||
|
iopad_port_types_required.push_back(SPICE_MODEL_PORT_SRAM);
|
||||||
|
|
||||||
|
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_IOPAD, iopad_port_types_required);
|
||||||
|
|
||||||
|
/* 4. Check mux has been defined and has input and output ports
|
||||||
|
* [a] We must have a MUX!
|
||||||
|
* [b] For each MUX, we must have at least an input, an output, and an SRAM port
|
||||||
|
*/
|
||||||
|
num_err += check_circuit_model_required(circuit_lib, SPICE_MODEL_MUX);
|
||||||
|
|
||||||
|
std::vector<enum e_spice_model_port_type> mux_port_types_required;
|
||||||
|
mux_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
|
||||||
|
mux_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
|
||||||
|
mux_port_types_required.push_back(SPICE_MODEL_PORT_SRAM);
|
||||||
|
|
||||||
|
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_MUX, mux_port_types_required);
|
||||||
|
|
||||||
|
/* 5. We must have at least one SRAM or SCFF */
|
||||||
|
if ( ( 0 == circuit_lib.circuit_models_by_type(SPICE_MODEL_SRAM).size())
|
||||||
|
&& ( 0 == circuit_lib.circuit_models_by_type(SPICE_MODEL_SCFF).size()) ) {
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"At least one %s or %s circuit model is required!\n",
|
||||||
|
CIRCUIT_MODEL_TYPE_STRING[size_t(SPICE_MODEL_SRAM)],
|
||||||
|
CIRCUIT_MODEL_TYPE_STRING[size_t(SPICE_MODEL_SCFF)]);
|
||||||
|
/* Incremental the counter for errors */
|
||||||
|
num_err++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 6. SRAM must have at least an input and an output ports*/
|
||||||
|
std::vector<enum e_spice_model_port_type> sram_port_types_required;
|
||||||
|
sram_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
|
||||||
|
sram_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
|
||||||
|
|
||||||
|
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_SRAM, sram_port_types_required);
|
||||||
|
|
||||||
|
/* 7. SCFF must have at least 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);
|
||||||
|
scff_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
|
||||||
|
|
||||||
|
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_SCFF, scff_port_types_required);
|
||||||
|
|
||||||
|
/* 8. FF must have at least 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);
|
||||||
|
ff_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
|
||||||
|
|
||||||
|
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_FF, ff_port_types_required);
|
||||||
|
|
||||||
|
/* 9. 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);
|
||||||
|
lut_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
|
||||||
|
|
||||||
|
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_LUT, lut_port_types_required);
|
||||||
|
|
||||||
|
/* 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_INFO,
|
||||||
|
"Finished checking circuit library with %d errors!\n",
|
||||||
|
num_err);
|
||||||
|
|
||||||
|
if (0 < num_err) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* End of file : check_circuit_library.cpp
|
||||||
|
***********************************************************************/
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/**********************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 LNIS - The University of Utah
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Filename: check_circuit_library.h
|
||||||
|
* Created by: Xifan Tang
|
||||||
|
* Change history:
|
||||||
|
* +-------------------------------------+
|
||||||
|
* | Date | Author | Notes
|
||||||
|
* +-------------------------------------+
|
||||||
|
* | 2019/08/12 | Xifan Tang | Created
|
||||||
|
* +-------------------------------------+
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
/* IMPORTANT:
|
||||||
|
* The following preprocessing flags are added to
|
||||||
|
* avoid compilation error when this headers are included in more than 1 times
|
||||||
|
*/
|
||||||
|
#ifndef CHECK_CIRCUIT_LIBRARY_H
|
||||||
|
#define CHECK_CIRCUIT_LIBRARY_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notes in include header files in a head file
|
||||||
|
* Only include the neccessary header files
|
||||||
|
* that is required by the data types in the function/class declarations!
|
||||||
|
*/
|
||||||
|
/* Header files should be included in a sequence */
|
||||||
|
/* Standard header files required go first */
|
||||||
|
#include "circuit_library.h"
|
||||||
|
|
||||||
|
/* Check points to make sure we have a valid circuit library */
|
||||||
|
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
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* End of file : check_circuit_library.h
|
||||||
|
***********************************************************************/
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -216,11 +216,13 @@ class CircuitLibrary {
|
||||||
INPUT = 0, OUTPUT, LUT_INPUT_BUFFER, LUT_INPUT_INVERTER, LUT_INTER_BUFFER, NUM_BUFFER_TYPE /* Last one is a counter */
|
INPUT = 0, OUTPUT, LUT_INPUT_BUFFER, LUT_INPUT_INVERTER, LUT_INTER_BUFFER, NUM_BUFFER_TYPE /* Last one is a counter */
|
||||||
};
|
};
|
||||||
public: /* Constructors */
|
public: /* Constructors */
|
||||||
|
CircuitLibrary();
|
||||||
public: /* Accessors: aggregates */
|
public: /* Accessors: aggregates */
|
||||||
circuit_model_range circuit_models() const;
|
circuit_model_range circuit_models() const;
|
||||||
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 +241,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 +261,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,
|
||||||
|
@ -112,7 +114,7 @@ enum e_spice_model_gate_type {
|
||||||
enum e_wire_model_type {
|
enum e_wire_model_type {
|
||||||
WIRE_MODEL_PIE,
|
WIRE_MODEL_PIE,
|
||||||
WIRE_MODEL_T,
|
WIRE_MODEL_T,
|
||||||
NUM_WIRE_MODEL_TYPES,
|
NUM_WIRE_MODEL_TYPES
|
||||||
};
|
};
|
||||||
|
|
||||||
enum e_spice_model_port_type {
|
enum e_spice_model_port_type {
|
||||||
|
@ -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
|
|
@ -1,254 +0,0 @@
|
||||||
/**********************************************************
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2018 LNIS - The University of Utah
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
***********************************************************************/
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* Filename: check_circuit_library.cpp
|
|
||||||
* Created by: Xifan Tang
|
|
||||||
* Change history:
|
|
||||||
* +-------------------------------------+
|
|
||||||
* | Date | Author | Notes
|
|
||||||
* +-------------------------------------+
|
|
||||||
* | 2019/08/12 | Xifan Tang | Created
|
|
||||||
* +-------------------------------------+
|
|
||||||
***********************************************************************/
|
|
||||||
|
|
||||||
/* Header files should be included in a sequence */
|
|
||||||
/* Standard header files required go first */
|
|
||||||
#include "util.h"
|
|
||||||
#include "check_circuit_library.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* 1. Circuit models have unique names, return the number of errors */
|
|
||||||
static
|
|
||||||
size_t check_circuit_library_unique_names(const CircuitLibrary& circuit_lib) {
|
|
||||||
size_t num_err = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < circuit_lib.num_circuit_models(); ++i) {
|
|
||||||
/* Skip for the last element, because the inner loop will access it */
|
|
||||||
if (i == circuit_lib.num_circuit_models() - 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Get the name of reference */
|
|
||||||
const std::string& i_name = circuit_lib.circuit_model_name(CircuitModelId(i));
|
|
||||||
for (size_t j = i + 1; j < circuit_lib.num_circuit_models(); ++j) {
|
|
||||||
/* Compare the name of candidate */
|
|
||||||
const std::string& j_name = circuit_lib.circuit_model_name(CircuitModelId(j));
|
|
||||||
/* Compare the name and skip for different names */
|
|
||||||
if (0 != i_name.compare(j_name)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"Circuit model(index=%d) and (index=%d) share the same name, which is invalid!\n",
|
|
||||||
i , j, i_name.c_str());
|
|
||||||
/* Incremental the counter for errors */
|
|
||||||
num_err++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return num_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 1. Circuit models have unique names, return the number of errors */
|
|
||||||
static
|
|
||||||
size_t check_circuit_library_unique_prefix(const CircuitLibrary& circuit_lib) {
|
|
||||||
size_t num_err = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < circuit_lib.num_circuit_models(); ++i) {
|
|
||||||
/* Skip for the last element, because the inner loop will access it */
|
|
||||||
if (i == circuit_lib.num_circuit_models() - 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Get the name of reference */
|
|
||||||
const std::string& i_prefix = circuit_lib.circuit_model_prefix(CircuitModelId(i));
|
|
||||||
for (size_t j = i + 1; j < circuit_lib.num_circuit_models(); ++j) {
|
|
||||||
/* Compare the name of candidate */
|
|
||||||
const std::string& j_prefix = circuit_lib.circuit_model_prefix(CircuitModelId(j));
|
|
||||||
/* Compare the name and skip for different prefix */
|
|
||||||
if (0 != i_prefix.compare(j_prefix)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"Circuit model(name=%s) and (name=%s) share the same prefix, which is invalid!\n",
|
|
||||||
circuit_lib.circuit_model_name(CircuitModelId(i)).c_str(),
|
|
||||||
circuit_lib.circuit_model_name(CircuitModelId(j)).c_str(),
|
|
||||||
i_prefix.c_str());
|
|
||||||
/* Incremental the counter for errors */
|
|
||||||
num_err++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return num_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A generic function to check the port list of a circuit model in a given type */
|
|
||||||
static
|
|
||||||
size_t check_circuit_model_required(const CircuitLibrary& circuit_lib,
|
|
||||||
const enum e_spice_model_type& circuit_model_type_to_check) {
|
|
||||||
size_t num_err = 0;
|
|
||||||
|
|
||||||
/* We must have an IOPAD*/
|
|
||||||
if ( 0 == circuit_lib.circuit_models_by_type(circuit_model_type_to_check).size()) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"At least one %s circuit model is required!\n",
|
|
||||||
CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_model_type_to_check)]);
|
|
||||||
/* Incremental the counter for errors */
|
|
||||||
num_err++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return num_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A generic function to check the port list of a circuit model in a given type */
|
|
||||||
static
|
|
||||||
size_t check_circuit_model_port_required(const CircuitLibrary& circuit_lib,
|
|
||||||
const enum e_spice_model_type& circuit_model_type_to_check,
|
|
||||||
const std::vector<enum e_spice_model_port_type>& port_types_to_check) {
|
|
||||||
size_t num_err = 0;
|
|
||||||
|
|
||||||
for (const auto& id : circuit_lib.circuit_models_by_type(circuit_model_type_to_check)) {
|
|
||||||
for (const auto& port_type: port_types_to_check) {
|
|
||||||
if (0 == circuit_lib.ports_by_type(id, port_type).size()) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"%s circuit model(name=%s) does not have %s port\n",
|
|
||||||
CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_model_type_to_check)],
|
|
||||||
circuit_lib.circuit_model_name(id).c_str(),
|
|
||||||
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(port_type)]);
|
|
||||||
/* Incremental the counter for errors */
|
|
||||||
num_err++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return num_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* Check points to make sure we have a valid circuit library
|
|
||||||
* Detailed checkpoints:
|
|
||||||
* 1. Circuit models have unique names
|
|
||||||
* 2. Circuit models have unique prefix
|
|
||||||
* 3. Check IOPADs have input and output ports
|
|
||||||
* 4. Check MUXes has been defined and has input and output ports
|
|
||||||
***********************************************************************/
|
|
||||||
void check_circuit_library(const CircuitLibrary& circuit_lib) {
|
|
||||||
size_t num_err = 0;
|
|
||||||
|
|
||||||
vpr_printf(TIO_MESSAGE_INFO, "Checking circuit models...\n");
|
|
||||||
|
|
||||||
/* 1. Circuit models have unique names
|
|
||||||
* For each circuit model, we always make sure it does not share any name with any circuit model locating after it
|
|
||||||
*/
|
|
||||||
num_err += check_circuit_library_unique_names(circuit_lib);
|
|
||||||
|
|
||||||
/* 2. Circuit models have unique prefix
|
|
||||||
* For each circuit model, we always make sure it does not share any prefix with any circuit model locating after it
|
|
||||||
*/
|
|
||||||
num_err += check_circuit_library_unique_prefix(circuit_lib);
|
|
||||||
|
|
||||||
/* 3. Check io has been defined and has input and output ports
|
|
||||||
* [a] We must have an IOPAD!
|
|
||||||
* [b] For each IOPAD, we must have at least an input, an output, an INOUT and an SRAM port
|
|
||||||
*/
|
|
||||||
num_err += check_circuit_model_required(circuit_lib, SPICE_MODEL_IOPAD);
|
|
||||||
|
|
||||||
std::vector<enum e_spice_model_port_type> iopad_port_types_required;
|
|
||||||
iopad_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
|
|
||||||
iopad_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
|
|
||||||
iopad_port_types_required.push_back(SPICE_MODEL_PORT_INOUT);
|
|
||||||
iopad_port_types_required.push_back(SPICE_MODEL_PORT_SRAM);
|
|
||||||
|
|
||||||
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_IOPAD, iopad_port_types_required);
|
|
||||||
|
|
||||||
/* 4. Check mux has been defined and has input and output ports
|
|
||||||
* [a] We must have a MUX!
|
|
||||||
* [b] For each MUX, we must have at least an input, an output, and an SRAM port
|
|
||||||
*/
|
|
||||||
num_err += check_circuit_model_required(circuit_lib, SPICE_MODEL_MUX);
|
|
||||||
|
|
||||||
std::vector<enum e_spice_model_port_type> mux_port_types_required;
|
|
||||||
mux_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
|
|
||||||
mux_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
|
|
||||||
mux_port_types_required.push_back(SPICE_MODEL_PORT_SRAM);
|
|
||||||
|
|
||||||
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_MUX, mux_port_types_required);
|
|
||||||
|
|
||||||
/* 5. We must have at least one SRAM or SCFF */
|
|
||||||
if ( ( 0 == circuit_lib.circuit_models_by_type(SPICE_MODEL_SRAM).size())
|
|
||||||
&& ( 0 == circuit_lib.circuit_models_by_type(SPICE_MODEL_SCFF).size()) ) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"At least one %s or %s circuit model is required!\n",
|
|
||||||
CIRCUIT_MODEL_TYPE_STRING[size_t(SPICE_MODEL_SRAM)],
|
|
||||||
CIRCUIT_MODEL_TYPE_STRING[size_t(SPICE_MODEL_SCFF)]);
|
|
||||||
/* Incremental the counter for errors */
|
|
||||||
num_err++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 6. SRAM must have at least an input and an output ports*/
|
|
||||||
std::vector<enum e_spice_model_port_type> sram_port_types_required;
|
|
||||||
sram_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
|
|
||||||
sram_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
|
|
||||||
|
|
||||||
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_SRAM, sram_port_types_required);
|
|
||||||
|
|
||||||
/* 7. SCFF must have at least an input and an output ports*/
|
|
||||||
std::vector<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);
|
|
||||||
scff_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
|
|
||||||
|
|
||||||
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_SCFF, scff_port_types_required);
|
|
||||||
|
|
||||||
/* 8. FF must have at least an input and an output ports*/
|
|
||||||
std::vector<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);
|
|
||||||
ff_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
|
|
||||||
|
|
||||||
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_FF, ff_port_types_required);
|
|
||||||
|
|
||||||
/* 9. LUY must have at least an input, an output and a SRAM ports*/
|
|
||||||
std::vector<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);
|
|
||||||
lut_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
|
|
||||||
|
|
||||||
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_LUT, lut_port_types_required);
|
|
||||||
|
|
||||||
/* If we have any errors, exit */
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"Finished checking circuit library with %d errors!\n",
|
|
||||||
num_err);
|
|
||||||
|
|
||||||
if (0 < num_err) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* End of file : check_circuit_library.cpp
|
|
||||||
***********************************************************************/
|
|
||||||
|
|
|
@ -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,10 +1023,11 @@ 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);
|
||||||
|
|
||||||
|
|
||||||
spice_model->design_tech_info.gate_info = NULL;
|
spice_model->design_tech_info.gate_info = NULL;
|
||||||
if (SPICE_MODEL_GATE == spice_model->type) {
|
if (SPICE_MODEL_GATE == spice_model->type) {
|
||||||
/* Malloc */
|
/* Malloc */
|
||||||
|
@ -1071,13 +1072,15 @@ static void ProcessSpiceModel(ezxml_t Parent,
|
||||||
|
|
||||||
/* LUT intermediate buffers */
|
/* LUT intermediate buffers */
|
||||||
Node = ezxml_child(Parent, "lut_intermediate_buffer");
|
Node = ezxml_child(Parent, "lut_intermediate_buffer");
|
||||||
spice_model->lut_intermediate_buffer = (t_spice_model_buffer*)my_calloc(1, sizeof(t_spice_model_buffer));
|
spice_model->lut_intermediate_buffer = NULL;
|
||||||
if (Node) {
|
if (Node) {
|
||||||
|
spice_model->lut_intermediate_buffer = (t_spice_model_buffer*)my_calloc(1, sizeof(t_spice_model_buffer));
|
||||||
/* Malloc the lut_input_buffer */
|
/* Malloc the lut_input_buffer */
|
||||||
ProcessSpiceModelBuffer(Node,spice_model->lut_intermediate_buffer);
|
ProcessSpiceModelBuffer(Node,spice_model->lut_intermediate_buffer);
|
||||||
FreeNode(Node);
|
FreeNode(Node);
|
||||||
} else if ((SPICE_MODEL_LUT == spice_model->type)
|
} else if ((SPICE_MODEL_LUT == spice_model->type)
|
||||||
|| (SPICE_MODEL_MUX == spice_model->type)) {
|
|| (SPICE_MODEL_MUX == spice_model->type)) {
|
||||||
|
spice_model->lut_intermediate_buffer = (t_spice_model_buffer*)my_calloc(1, sizeof(t_spice_model_buffer));
|
||||||
/* Assign default values */
|
/* Assign default values */
|
||||||
spice_model->lut_intermediate_buffer->exist = 0;
|
spice_model->lut_intermediate_buffer->exist = 0;
|
||||||
spice_model->lut_intermediate_buffer->spice_model = NULL;
|
spice_model->lut_intermediate_buffer->spice_model = NULL;
|
||||||
|
@ -1632,7 +1635,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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1186,7 +1186,7 @@ static void SetupSynVerilogOpts(t_options Options,
|
||||||
/* SynVerilog needs the input from spice modeling */
|
/* SynVerilog needs the input from spice modeling */
|
||||||
if (FALSE == arch->read_xml_spice) {
|
if (FALSE == arch->read_xml_spice) {
|
||||||
arch->read_xml_spice = syn_verilog_opts->dump_syn_verilog;
|
arch->read_xml_spice = syn_verilog_opts->dump_syn_verilog;
|
||||||
arch->spice = (t_spice*)my_malloc(sizeof(t_spice));
|
arch->spice = (t_spice*)my_calloc(1, sizeof(t_spice));
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -524,7 +524,7 @@ static void add_latch(int doall, INP t_model *latch_model) {
|
||||||
/* Store the initial value */
|
/* Store the initial value */
|
||||||
logical_block[num_logical_blocks - 1].init_val = my_atoi(saved_names[4]);
|
logical_block[num_logical_blocks - 1].init_val = my_atoi(saved_names[4]);
|
||||||
/* Add clock identification */
|
/* Add clock identification */
|
||||||
logical_block[logical_block[num_logical_blocks - 1].clock_net].is_clock = TRUE;
|
logical_block[vpack_net[logical_block[num_logical_blocks - 1].clock_net].node_block[0]].is_clock = TRUE;
|
||||||
/*END*/
|
/*END*/
|
||||||
|
|
||||||
num_latches++;
|
num_latches++;
|
||||||
|
@ -722,6 +722,9 @@ static void add_subckt(int doall, t_model *user_models) {
|
||||||
add_vpack_net(circuit_signal_name[i], RECEIVER,
|
add_vpack_net(circuit_signal_name[i], RECEIVER,
|
||||||
num_logical_blocks - 1, port->index,
|
num_logical_blocks - 1, port->index,
|
||||||
my_atoi(pin_number), TRUE, doall);
|
my_atoi(pin_number), TRUE, doall);
|
||||||
|
|
||||||
|
/* Add clock identification */
|
||||||
|
logical_block[vpack_net[logical_block[num_logical_blocks - 1].clock_net].node_block[0]].is_clock = TRUE;
|
||||||
} else {
|
} else {
|
||||||
logical_block[num_logical_blocks - 1].input_nets[port->index][my_atoi(
|
logical_block[num_logical_blocks - 1].input_nets[port->index][my_atoi(
|
||||||
pin_number)] = add_vpack_net(
|
pin_number)] = add_vpack_net(
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
rm tags
|
rm tags
|
||||||
ctags -R shell_main.c main.c ./* ../../libarchfpga/SRC/include/*.[ch] ../../libarchfpga/SRC/fpga_spice_include/*.[ch] ../../libarchfpga/SRC/*.[ch] ../../pcre/SRC/*.[ch]
|
ctags -R shell_main.c main.c ./* ../../libarchfpga/SRC/* ../../pcre/SRC/*.[ch]
|
||||||
|
|
|
@ -341,6 +341,33 @@ void add_edges_for_two_rr_nodes(const t_rr_graph* rr_graph,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Get the track_id of a routing track w.r.t its coordinator
|
||||||
|
* In tileable routing architecture, the track_id changes SB by SB.
|
||||||
|
* Therefore the track_ids are stored in a vector, indexed by the relative coordinator
|
||||||
|
* based on the starting point of the track
|
||||||
|
* For routing tracks in INC_DIRECTION
|
||||||
|
* (xlow, ylow) should be the starting point
|
||||||
|
*
|
||||||
|
* (xlow, ylow) (xhigh, yhigh)
|
||||||
|
* track_id[0] -------------------------------> track_id[xhigh - xlow + yhigh - ylow]
|
||||||
|
*
|
||||||
|
* For routing tracks in DEC_DIRECTION
|
||||||
|
* (xhigh, yhigh) should be the starting point
|
||||||
|
*
|
||||||
|
* (xlow, ylow) (xhigh, yhigh)
|
||||||
|
* track_id[0] <------------------------------- track_id[xhigh - xlow + yhigh - ylow]
|
||||||
|
*
|
||||||
|
*
|
||||||
|
***********************************************************************/
|
||||||
|
short get_rr_node_actual_track_id(const t_rr_node* track_rr_node,
|
||||||
|
const DeviceCoordinator& coord) {
|
||||||
|
DeviceCoordinator low_coord(track_rr_node->xlow, track_rr_node->ylow);
|
||||||
|
size_t offset = (int)abs((int)coord.get_x() - (int)low_coord.get_x() + (int)coord.get_y() - (int)low_coord.get_y());
|
||||||
|
return track_rr_node->track_ids[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Get the coordinator of a starting point of a routing track
|
* Get the coordinator of a starting point of a routing track
|
||||||
* For routing tracks in INC_DIRECTION
|
* For routing tracks in INC_DIRECTION
|
||||||
|
|
|
@ -35,6 +35,9 @@ void add_edges_for_two_rr_nodes(const t_rr_graph* rr_graph,
|
||||||
const std::vector<int> des_rr_node,
|
const std::vector<int> des_rr_node,
|
||||||
const std::vector<short> driver_switches);
|
const std::vector<short> driver_switches);
|
||||||
|
|
||||||
|
short get_rr_node_actual_track_id(const t_rr_node* track_rr_node,
|
||||||
|
const DeviceCoordinator& coord);
|
||||||
|
|
||||||
DeviceCoordinator get_track_rr_node_start_coordinator(const t_rr_node* track_rr_node);
|
DeviceCoordinator get_track_rr_node_start_coordinator(const t_rr_node* track_rr_node);
|
||||||
|
|
||||||
DeviceCoordinator get_track_rr_node_end_coordinator(const t_rr_node* track_rr_node);
|
DeviceCoordinator get_track_rr_node_end_coordinator(const t_rr_node* track_rr_node);
|
||||||
|
|
|
@ -1005,8 +1005,7 @@ int rec_count_num_conf_bits_pb_type_physical_mode(t_pb_type* cur_pb_type,
|
||||||
cur_pb_type->physical_mode_num_conf_bits = 0;
|
cur_pb_type->physical_mode_num_conf_bits = 0;
|
||||||
|
|
||||||
/* Recursively finish all the child pb_types*/
|
/* Recursively finish all the child pb_types*/
|
||||||
if ((NULL == cur_pb_type->spice_model_name)
|
if ( FALSE == is_primitive_pb_type(cur_pb_type)) {
|
||||||
&& (NULL == cur_pb_type->physical_pb_type_name)) {
|
|
||||||
/* Find the mode that define_idle_mode*/
|
/* Find the mode that define_idle_mode*/
|
||||||
mode_index = find_pb_type_physical_mode_index((*cur_pb_type));
|
mode_index = find_pb_type_physical_mode_index((*cur_pb_type));
|
||||||
for (ipb = 0; ipb < cur_pb_type->modes[mode_index].num_pb_type_children; ipb++) {
|
for (ipb = 0; ipb < cur_pb_type->modes[mode_index].num_pb_type_children; ipb++) {
|
||||||
|
@ -1017,14 +1016,14 @@ int rec_count_num_conf_bits_pb_type_physical_mode(t_pb_type* cur_pb_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if this has defined a spice_model*/
|
/* Check if this has defined a spice_model*/
|
||||||
if ((NULL != cur_pb_type->spice_model_name)
|
if ( TRUE == is_primitive_pb_type(cur_pb_type)) {
|
||||||
|| (NULL != cur_pb_type->physical_pb_type_name)) {
|
|
||||||
sum_num_conf_bits = count_num_conf_bits_one_spice_model(cur_pb_type->phy_pb_type->spice_model, cur_sram_orgz_info->type, 0);
|
sum_num_conf_bits = count_num_conf_bits_one_spice_model(cur_pb_type->phy_pb_type->spice_model, cur_sram_orgz_info->type, 0);
|
||||||
cur_pb_type->physical_mode_num_conf_bits = sum_num_conf_bits;
|
cur_pb_type->physical_mode_num_conf_bits = sum_num_conf_bits;
|
||||||
/* calculate the number of reserved configuration bits */
|
/* calculate the number of reserved configuration bits */
|
||||||
cur_pb_type->physical_mode_num_reserved_conf_bits =
|
cur_pb_type->physical_mode_num_reserved_conf_bits =
|
||||||
count_num_reserved_conf_bits_one_spice_model(cur_pb_type->phy_pb_type->spice_model,
|
count_num_reserved_conf_bits_one_spice_model(cur_pb_type->phy_pb_type->spice_model,
|
||||||
cur_sram_orgz_info->type, 0);
|
cur_sram_orgz_info->type, 0);
|
||||||
|
|
||||||
} else { /* Count the sum of configuration bits of all the children pb_types */
|
} else { /* Count the sum of configuration bits of all the children pb_types */
|
||||||
/* Find the mode that define_idle_mode*/
|
/* Find the mode that define_idle_mode*/
|
||||||
mode_index = find_pb_type_physical_mode_index((*cur_pb_type));
|
mode_index = find_pb_type_physical_mode_index((*cur_pb_type));
|
||||||
|
@ -1234,6 +1233,28 @@ void init_grids_num_conf_bits(t_sram_orgz_info* cur_sram_orgz_info) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Initialize the number of configuration bits for each pb_type
|
||||||
|
* in the list of type descriptors
|
||||||
|
*******************************************************************/
|
||||||
|
void init_pb_types_num_conf_bits(t_sram_orgz_info* cur_sram_orgz_info) {
|
||||||
|
for (int itype = 0; itype < num_types; ++itype) {
|
||||||
|
/* bypass EMPTY_TYPES */
|
||||||
|
if (EMPTY_TYPE == &(type_descriptors[itype])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int capacity= type_descriptors[itype].capacity;
|
||||||
|
assert(0 < capacity);
|
||||||
|
|
||||||
|
/* check capacity and if this has been mapped */
|
||||||
|
for (int iz = 0; iz < capacity; iz++) {
|
||||||
|
/* Check in all the blocks(clustered logic block), there is a match x,y,z*/
|
||||||
|
rec_count_num_conf_bits_pb_type_physical_mode(type_descriptors[itype].pb_type, cur_sram_orgz_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* With given spice_model_port, find the pb_type port with same name and type*/
|
/* With given spice_model_port, find the pb_type port with same name and type*/
|
||||||
t_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type,
|
t_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type,
|
||||||
t_spice_model_port* spice_model_port) {
|
t_spice_model_port* spice_model_port) {
|
||||||
|
@ -1301,6 +1322,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) {
|
||||||
|
@ -1794,6 +1816,29 @@ void init_grids_num_iopads() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Initialize the number of configuration bits for each pb_type
|
||||||
|
* in the list of type descriptors
|
||||||
|
*******************************************************************/
|
||||||
|
void init_pb_types_num_iopads() {
|
||||||
|
for (int itype = 0; itype < num_types; ++itype) {
|
||||||
|
/* bypass EMPTY_TYPES */
|
||||||
|
if (EMPTY_TYPE == &(type_descriptors[itype])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int capacity= type_descriptors[itype].capacity;
|
||||||
|
assert(0 < capacity);
|
||||||
|
|
||||||
|
/* check capacity and if this has been mapped */
|
||||||
|
for (int iz = 0; iz < capacity; iz++) {
|
||||||
|
/* Check in all the blocks(clustered logic block), there is a match x,y,z*/
|
||||||
|
rec_count_num_iopads_pb_type_physical_mode(type_descriptors[itype].pb_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Count the number of mode configuration bits of a grid (type_descriptor) in default mode */
|
/* Count the number of mode configuration bits of a grid (type_descriptor) in default mode */
|
||||||
void rec_count_num_mode_bits_pb_type_default_mode(t_pb_type* cur_pb_type) {
|
void rec_count_num_mode_bits_pb_type_default_mode(t_pb_type* cur_pb_type) {
|
||||||
int mode_index, ipb, jpb;
|
int mode_index, ipb, jpb;
|
||||||
|
|
|
@ -93,6 +93,8 @@ void init_one_grid_num_conf_bits(int ix, int iy,
|
||||||
|
|
||||||
void init_grids_num_conf_bits(t_sram_orgz_info* cur_sram_orgz_info);
|
void init_grids_num_conf_bits(t_sram_orgz_info* cur_sram_orgz_info);
|
||||||
|
|
||||||
|
void init_pb_types_num_conf_bits(t_sram_orgz_info* cur_sram_orgz_info);
|
||||||
|
|
||||||
void map_clb_pins_to_pb_graph_pins();
|
void map_clb_pins_to_pb_graph_pins();
|
||||||
|
|
||||||
t_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type,
|
t_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type,
|
||||||
|
@ -102,7 +104,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);
|
||||||
|
@ -136,6 +137,8 @@ void init_one_grid_num_iopads(int ix, int iy);
|
||||||
|
|
||||||
void init_grids_num_iopads();
|
void init_grids_num_iopads();
|
||||||
|
|
||||||
|
void init_pb_types_num_iopads();
|
||||||
|
|
||||||
void rec_count_num_mode_bits_pb_type_default_mode(t_pb_type* cur_pb_type);
|
void rec_count_num_mode_bits_pb_type_default_mode(t_pb_type* cur_pb_type);
|
||||||
|
|
||||||
void rec_count_num_mode_bits_pb(t_pb* cur_pb);
|
void rec_count_num_mode_bits_pb(t_pb* cur_pb);
|
||||||
|
|
|
@ -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
|
||||||
|
***********************************************************************/
|
|
@ -23,7 +23,7 @@
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Filename: check_circuit_library.h
|
* Filename: link_arch_circuit_lib.h
|
||||||
* Created by: Xifan Tang
|
* Created by: Xifan Tang
|
||||||
* Change history:
|
* Change history:
|
||||||
* +-------------------------------------+
|
* +-------------------------------------+
|
||||||
|
@ -37,8 +37,8 @@
|
||||||
* The following preprocessing flags are added to
|
* The following preprocessing flags are added to
|
||||||
* avoid compilation error when this headers are included in more than 1 times
|
* avoid compilation error when this headers are included in more than 1 times
|
||||||
*/
|
*/
|
||||||
#ifndef CHECK_CIRCUIT_LIBRARY_H
|
#ifndef LINK_ARCH_CIRCUIT_LIB_H
|
||||||
#define CHECK_CIRCUIT_LIBRARY_H
|
#define LINK_ARCH_CIRCUIT_LIB_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notes in include header files in a head file
|
* Notes in include header files in a head file
|
||||||
|
@ -47,14 +47,22 @@
|
||||||
*/
|
*/
|
||||||
/* 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 "circuit_library.h"
|
|
||||||
|
|
||||||
/* Check points to make sure we have a valid circuit library */
|
CircuitModelId link_circuit_model_by_name_and_type(const char* circuit_model_name,
|
||||||
void check_circuit_library(const CircuitLibrary& circuit_lib);
|
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
|
#endif
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* End of file : check_circuit_library.h
|
* End of file : link_arch_circuit_lib.h
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
|
@ -242,8 +242,10 @@ void vpr_fpga_verilog(t_vpr_setup vpr_setup,
|
||||||
/* Initialize the number of configuration bits of all the grids */
|
/* Initialize the number of configuration bits of all the grids */
|
||||||
vpr_printf(TIO_MESSAGE_INFO, "Count the number of configuration bits, IO pads in each logic block...\n");
|
vpr_printf(TIO_MESSAGE_INFO, "Count the number of configuration bits, IO pads in each logic block...\n");
|
||||||
/* init_grids_num_conf_bits(sram_verilog_orgz_type); */
|
/* init_grids_num_conf_bits(sram_verilog_orgz_type); */
|
||||||
init_grids_num_conf_bits(sram_verilog_orgz_info);
|
//init_grids_num_conf_bits(sram_verilog_orgz_info);
|
||||||
init_grids_num_iopads();
|
init_pb_types_num_conf_bits(sram_verilog_orgz_info);
|
||||||
|
//init_grids_num_iopads();
|
||||||
|
init_pb_types_num_iopads();
|
||||||
/* init_grids_num_mode_bits(); */
|
/* init_grids_num_mode_bits(); */
|
||||||
|
|
||||||
dump_verilog_defines_preproc(src_dir_path,
|
dump_verilog_defines_preproc(src_dir_path,
|
||||||
|
|
|
@ -1751,6 +1751,7 @@ void dump_verilog_phy_pb_graph_node_rec(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
/* update stamped sram counter */
|
/* update stamped sram counter */
|
||||||
stamped_sram_cnt += cur_pb_type->physical_mode_num_conf_bits;
|
stamped_sram_cnt += cur_pb_type->physical_mode_num_conf_bits;
|
||||||
/* Check */
|
/* Check */
|
||||||
|
if (stamped_sram_cnt != get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info))
|
||||||
assert(stamped_sram_cnt == get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info));
|
assert(stamped_sram_cnt == get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info));
|
||||||
assert(stamped_iopad_cnt == iopad_verilog_model->cnt);
|
assert(stamped_iopad_cnt == iopad_verilog_model->cnt);
|
||||||
/* Finish for primitive node, return */
|
/* Finish for primitive node, return */
|
||||||
|
|
|
@ -2350,7 +2350,7 @@ void dump_verilog_routing_switch_box_unique_subckt(t_sram_orgz_info* cur_sram_or
|
||||||
dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info,
|
dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info,
|
||||||
rr_gsb.get_sb_conf_bits_lsb(),
|
rr_gsb.get_sb_conf_bits_lsb(),
|
||||||
rr_gsb.get_sb_conf_bits_msb(),
|
rr_gsb.get_sb_conf_bits_msb(),
|
||||||
VERILOG_PORT_OUTPUT, is_explicit_mapping);
|
VERILOG_PORT_INPUT, is_explicit_mapping);
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
fprintf(fp, "`endif\n");
|
fprintf(fp, "`endif\n");
|
||||||
}
|
}
|
||||||
|
@ -3967,7 +3967,7 @@ void dump_verilog_routing_resources(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
/* Create a snapshot on sram_orgz_info */
|
/* Create a snapshot on sram_orgz_info */
|
||||||
t_sram_orgz_info* stamped_sram_orgz_info = snapshot_sram_orgz_info(cur_sram_orgz_info);
|
t_sram_orgz_info* stamped_sram_orgz_info = snapshot_sram_orgz_info(cur_sram_orgz_info);
|
||||||
|
|
||||||
/* Output unique side modules */
|
/* Output unique side modules
|
||||||
for (size_t side = 0; side < device_rr_gsb.get_max_num_sides(); ++side) {
|
for (size_t side = 0; side < device_rr_gsb.get_max_num_sides(); ++side) {
|
||||||
Side side_manager(side);
|
Side side_manager(side);
|
||||||
for (size_t iseg = 0; iseg < device_rr_gsb.get_num_segments(); ++iseg) {
|
for (size_t iseg = 0; iseg < device_rr_gsb.get_num_segments(); ++iseg) {
|
||||||
|
@ -3978,12 +3978,17 @@ void dump_verilog_routing_resources(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/* Output unique modules */
|
/* Output unique modules */
|
||||||
for (size_t isb = 0; isb < device_rr_gsb.get_num_sb_unique_module(); ++isb) {
|
for (size_t isb = 0; isb < device_rr_gsb.get_num_sb_unique_module(); ++isb) {
|
||||||
const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(isb);
|
const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(isb);
|
||||||
|
/*
|
||||||
dump_verilog_routing_switch_box_unique_module(cur_sram_orgz_info, verilog_dir,
|
dump_verilog_routing_switch_box_unique_module(cur_sram_orgz_info, verilog_dir,
|
||||||
subckt_dir, unique_mirror, explicit_port_mapping);
|
subckt_dir, unique_mirror, explicit_port_mapping);
|
||||||
|
*/
|
||||||
|
dump_verilog_routing_switch_box_unique_subckt(cur_sram_orgz_info, verilog_dir,
|
||||||
|
subckt_dir, unique_mirror, explicit_port_mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore sram_orgz_info to the base */
|
/* Restore sram_orgz_info to the base */
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include "buffer_insertion.h"
|
#include "buffer_insertion.h"
|
||||||
/* end */
|
/* end */
|
||||||
|
|
||||||
|
#include "rr_graph_builder_utils.h"
|
||||||
|
|
||||||
/* Xifan TANG: useful functions for pb_pin_eq_auto_detect */
|
/* Xifan TANG: useful functions for pb_pin_eq_auto_detect */
|
||||||
void reassign_rr_node_net_num_from_scratch();
|
void reassign_rr_node_net_num_from_scratch();
|
||||||
|
|
||||||
|
@ -1214,7 +1216,18 @@ void print_route(char *route_file) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A kind of dirty fix for tileable routing,
|
||||||
|
* the track_ids is allocated by tileable routing.
|
||||||
|
* If the vector is not empty, it means tileable routing is enabled
|
||||||
|
* we need another function to get the track_id rather than ptc_num
|
||||||
|
*/
|
||||||
|
if (0 == rr_node[inode].track_ids.size()) {
|
||||||
fprintf(fp, "%d ", rr_node[inode].ptc_num);
|
fprintf(fp, "%d ", rr_node[inode].ptc_num);
|
||||||
|
} else {
|
||||||
|
/* Xifan Tang: for routing tracks, get the actual track ids */
|
||||||
|
DeviceCoordinator cur_coord(ilow, jlow);
|
||||||
|
fprintf(fp, "%d ", get_rr_node_actual_track_id(&(rr_node[inode]), cur_coord));
|
||||||
|
}
|
||||||
|
|
||||||
/* Uncomment line below if you're debugging and want to see the switch types *
|
/* Uncomment line below if you're debugging and want to see the switch types *
|
||||||
* used in the routing. */
|
* used in the routing. */
|
||||||
|
|
Loading…
Reference in New Issue