Merge remote-tracking branch 'origin/dev' into heterogeneous

This commit is contained in:
AurelienUoU 2019-08-14 09:11:54 -06:00
commit 30c0f2b6b7
45 changed files with 1535 additions and 448 deletions

View File

@ -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
***********************************************************************/

View File

@ -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
***********************************************************************/

View File

@ -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 */
};
public: /* Constructors */
CircuitLibrary();
public: /* Accessors: aggregates */
circuit_model_range circuit_models() 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<CircuitPortId> ports_by_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_port_type& port_type) const;
std::vector<CircuitPortId> ports_by_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_port_type& port_type, const bool& include_global_port) const;
std::vector<CircuitPortId> input_ports(const CircuitModelId& circuit_model_id) const;
std::vector<CircuitPortId> output_ports(const CircuitModelId& circuit_model_id) const;
std::vector<size_t> pins(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const;
@ -239,11 +241,13 @@ class CircuitLibrary {
bool is_input_buffered(const CircuitModelId& circuit_model_id) const;
bool is_output_buffered(const CircuitModelId& circuit_model_id) const;
bool is_lut_intermediate_buffered(const CircuitModelId& circuit_model_id) const;
enum e_spice_model_structure mux_structure(const CircuitModelId& circuit_model_id) const;
public: /* Public Accessors: Basic data query on Circuit Ports*/
bool is_input_port(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const;
bool is_output_port(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const;
CircuitPortId port(const CircuitModelId& circuit_model_id, const std::string& name) const;
size_t num_ports(const CircuitModelId& circuit_model_id) const;
size_t num_ports_by_type(const CircuitModelId& circuit_model_id, const enum e_spice_model_port_type& port_type, const bool& include_global_port) const;
enum e_spice_model_port_type port_type(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const;
size_t port_size(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const;
std::string port_prefix(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const;
@ -257,6 +261,7 @@ class CircuitLibrary {
bool port_is_config_enable(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const;
bool port_is_prog(const CircuitModelId& circuit_model_id, const CircuitPortId& circuit_port_id) const;
public: /* Public Accessors: Methods to find circuit model */
CircuitModelId circuit_model(const char* name) const;
CircuitModelId circuit_model(const std::string& name) const;
CircuitModelId default_circuit_model(const enum e_spice_model_type& type) const;
public: /* Public Accessors: Timing graph */

View File

@ -89,6 +89,8 @@ enum e_spice_model_structure {
SPICE_MODEL_STRUCTURE_CROSSBAR,
NUM_CIRCUIT_MODEL_STRUCTURE_TYPES
};
/* Strings correspond to each type of mux structure */
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_STRUCTURE_TYPES> CIRCUIT_MODEL_STRUCTURE_TYPE_STRING = {{"TREE-LIKE", "ONE-LEVEL", "MULTI-LEVEL", "CROSSBAR"}};
enum e_spice_model_buffer_type {
SPICE_MODEL_BUF_INV,
@ -112,7 +114,7 @@ enum e_spice_model_gate_type {
enum e_wire_model_type {
WIRE_MODEL_PIE,
WIRE_MODEL_T,
NUM_WIRE_MODEL_TYPES,
NUM_WIRE_MODEL_TYPES
};
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 */
NUM_CIRCUIT_MODEL_SRAM_ORGZ_TYPES
};
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_SRAM_ORGZ_TYPES> CIRCUIT_MODEL_SRAM_ORGZ_TYPE_STRING = {{"STANDALONE", "SCAN-CHAIN", "MEMORY_BANK", "LOCAL_ENCODER"}};
#endif

View File

@ -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
***********************************************************************/

View File

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

View File

@ -1023,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->add_const_input = FALSE;
spice_model->design_tech_info.mux_info->const_input_val = 0;
spice_model->design_tech_info.mux_info->advanced_rram_design = FALSE;
spice_model->design_tech_info.mux_info->local_encoder = FALSE;
}
ezxml_set_attr(Node, "fracturable_lut", NULL);
spice_model->design_tech_info.gate_info = NULL;
if (SPICE_MODEL_GATE == spice_model->type) {
/* Malloc */
@ -1071,13 +1072,15 @@ static void ProcessSpiceModel(ezxml_t Parent,
/* LUT intermediate buffers */
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) {
spice_model->lut_intermediate_buffer = (t_spice_model_buffer*)my_calloc(1, sizeof(t_spice_model_buffer));
/* Malloc the lut_input_buffer */
ProcessSpiceModelBuffer(Node,spice_model->lut_intermediate_buffer);
FreeNode(Node);
} else if ((SPICE_MODEL_LUT == 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 */
spice_model->lut_intermediate_buffer->exist = 0;
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);
}
if (NULL != spice_models[imodel].lut_intermediate_buffer) {
if ( (NULL != spice_models[imodel].lut_intermediate_buffer)
&& (1 == spice_models[imodel].lut_intermediate_buffer->exist) ) {
std::string model_name;
if (NULL != spice_models[imodel].lut_intermediate_buffer->spice_model_name) {
model_name = spice_models[imodel].lut_intermediate_buffer->spice_model_name;

View File

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

View File

@ -1186,7 +1186,7 @@ static void SetupSynVerilogOpts(t_options Options,
/* SynVerilog needs the input from spice modeling */
if (FALSE == arch->read_xml_spice) {
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;

View File

@ -524,7 +524,7 @@ static void add_latch(int doall, INP t_model *latch_model) {
/* Store the initial value */
logical_block[num_logical_blocks - 1].init_val = my_atoi(saved_names[4]);
/* 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*/
num_latches++;
@ -722,6 +722,9 @@ static void add_subckt(int doall, t_model *user_models) {
add_vpack_net(circuit_signal_name[i], RECEIVER,
num_logical_blocks - 1, port->index,
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 {
logical_block[num_logical_blocks - 1].input_nets[port->index][my_atoi(
pin_number)] = add_vpack_net(

View File

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

View File

@ -1,2 +1,2 @@
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]

View File

@ -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
* For routing tracks in INC_DIRECTION

View File

@ -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<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_end_coordinator(const t_rr_node* track_rr_node);

View File

@ -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;
/* Recursively finish all the child pb_types*/
if ((NULL == cur_pb_type->spice_model_name)
&& (NULL == cur_pb_type->physical_pb_type_name)) {
if ( FALSE == is_primitive_pb_type(cur_pb_type)) {
/* Find the mode that define_idle_mode*/
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++) {
@ -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*/
if ((NULL != cur_pb_type->spice_model_name)
|| (NULL != cur_pb_type->physical_pb_type_name)) {
if ( TRUE == is_primitive_pb_type(cur_pb_type)) {
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;
/* calculate the number of reserved configuration 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,
cur_sram_orgz_info->type, 0);
} else { /* Count the sum of configuration bits of all the children pb_types */
/* Find the mode that define_idle_mode*/
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;
}
/********************************************************************
* 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*/
t_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type,
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;
}
t_port** find_pb_type_ports_match_spice_model_port_type(t_pb_type* pb_type,
enum e_spice_model_port_type port_type,
int* port_num) {
@ -1794,6 +1816,29 @@ void init_grids_num_iopads() {
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 */
void rec_count_num_mode_bits_pb_type_default_mode(t_pb_type* cur_pb_type) {
int mode_index, ipb, jpb;

View File

@ -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_pb_types_num_conf_bits(t_sram_orgz_info* cur_sram_orgz_info);
void map_clb_pins_to_pb_graph_pins();
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,
int* port_num);
enum e_interconnect find_pb_graph_pin_in_edges_interc_type(t_pb_graph_pin pb_graph_pin);
t_spice_model* find_pb_graph_pin_in_edges_interc_spice_model(t_pb_graph_pin pb_graph_pin);
@ -136,6 +137,8 @@ void init_one_grid_num_iopads(int ix, int iy);
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(t_pb* cur_pb);

View File

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

View File

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

View File

@ -23,7 +23,7 @@
***********************************************************************/
/************************************************************************
* Filename: check_circuit_library.h
* Filename: link_arch_circuit_lib.h
* Created by: Xifan Tang
* Change history:
* +-------------------------------------+
@ -37,8 +37,8 @@
* 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
#ifndef LINK_ARCH_CIRCUIT_LIB_H
#define LINK_ARCH_CIRCUIT_LIB_H
/*
* Notes in include header files in a head file
@ -47,14 +47,22 @@
*/
/* Header files should be included in a sequence */
/* Standard header files required go first */
#include "circuit_library.h"
/* Check points to make sure we have a valid circuit library */
void check_circuit_library(const CircuitLibrary& circuit_lib);
CircuitModelId link_circuit_model_by_name_and_type(const char* circuit_model_name,
const CircuitLibrary& circuit_lib,
const enum e_spice_model_type& model_type);
t_port* find_pb_type_port_match_circuit_model_port(const t_pb_type* pb_type,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const CircuitPortId& circuit_port);
void link_circuit_library_to_arch(t_arch* arch,
t_det_routing_arch* routing_arch);
#endif
/************************************************************************
* End of file : check_circuit_library.h
* End of file : link_arch_circuit_lib.h
***********************************************************************/

View File

@ -242,8 +242,10 @@ void vpr_fpga_verilog(t_vpr_setup vpr_setup,
/* 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");
/* init_grids_num_conf_bits(sram_verilog_orgz_type); */
init_grids_num_conf_bits(sram_verilog_orgz_info);
init_grids_num_iopads();
//init_grids_num_conf_bits(sram_verilog_orgz_info);
init_pb_types_num_conf_bits(sram_verilog_orgz_info);
//init_grids_num_iopads();
init_pb_types_num_iopads();
/* init_grids_num_mode_bits(); */
dump_verilog_defines_preproc(src_dir_path,

View File

@ -1751,6 +1751,7 @@ void dump_verilog_phy_pb_graph_node_rec(t_sram_orgz_info* cur_sram_orgz_info,
/* update stamped sram counter */
stamped_sram_cnt += cur_pb_type->physical_mode_num_conf_bits;
/* 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_iopad_cnt == iopad_verilog_model->cnt);
/* Finish for primitive node, return */

View File

@ -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,
rr_gsb.get_sb_conf_bits_lsb(),
rr_gsb.get_sb_conf_bits_msb(),
VERILOG_PORT_OUTPUT, is_explicit_mapping);
VERILOG_PORT_INPUT, is_explicit_mapping);
fprintf(fp, "\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 */
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) {
Side side_manager(side);
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 */
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);
/*
dump_verilog_routing_switch_box_unique_module(cur_sram_orgz_info, verilog_dir,
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 */

View File

@ -20,6 +20,8 @@
#include "buffer_insertion.h"
/* end */
#include "rr_graph_builder_utils.h"
/* Xifan TANG: useful functions for pb_pin_eq_auto_detect */
void reassign_rr_node_net_num_from_scratch();
@ -1214,7 +1216,18 @@ void print_route(char *route_file) {
break;
}
fprintf(fp, "%d ", rr_node[inode].ptc_num);
/* 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);
} 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 *
* used in the routing. */