immigrate XML parser for circuit_lib to library readarchopenfpga

This commit is contained in:
tangxifan 2020-01-12 18:11:00 -07:00
parent 15ffdc03f0
commit 48ecb6e48b
21 changed files with 4821 additions and 3 deletions

View File

@ -159,6 +159,7 @@ enable_testing()
#
#add_subdirectory(iverilog)
add_subdirectory(libs)
add_subdirectory(libopenfpga)
add_subdirectory(yosys)
add_subdirectory(abc)
add_subdirectory(ace2)

View File

@ -0,0 +1,3 @@
# OpenFPGA-related libraries
add_subdirectory(libini)
add_subdirectory(libarchopenfpga)

View File

@ -0,0 +1,539 @@
/************************************************************************
* 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 "vtr_log.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_models(); ++i) {
/* Skip for the last element, because the inner loop will access it */
if (i == circuit_lib.num_models() - 1) {
continue;
}
/* Get the name of reference */
const std::string& i_name = circuit_lib.model_name(CircuitModelId(i));
for (size_t j = i + 1; j < circuit_lib.num_models(); ++j) {
/* Compare the name of candidate */
const std::string& j_name = circuit_lib.model_name(CircuitModelId(j));
/* Compare the name and skip for different names */
if (0 != i_name.compare(j_name)) {
continue;
}
VTR_LOG_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_models(); ++i) {
/* Skip for the last element, because the inner loop will access it */
if (i == circuit_lib.num_models() - 1) {
continue;
}
/* Get the name of reference */
const std::string& i_prefix = circuit_lib.model_prefix(CircuitModelId(i));
for (size_t j = i + 1; j < circuit_lib.num_models(); ++j) {
/* Compare the name of candidate */
const std::string& j_prefix = circuit_lib.model_prefix(CircuitModelId(j));
/* Compare the name and skip for different prefix */
if (0 != i_prefix.compare(j_prefix)) {
continue;
}
VTR_LOG_ERROR("Circuit model(name=%s) and (name=%s) share the same prefix, which is invalid!\n",
circuit_lib.model_name(CircuitModelId(i)).c_str(),
circuit_lib.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_circuit_model_type& circuit_model_type_to_check) {
size_t num_err = 0;
/* We must have an IOPAD*/
if ( 0 == circuit_lib.models_by_type(circuit_model_type_to_check).size()) {
VTR_LOG_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_circuit_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.model_ports_by_type(circuit_model, port_type).size()) {
VTR_LOG_ERROR("%s circuit model(name=%s) does not have %s port\n",
CIRCUIT_MODEL_TYPE_STRING[size_t(circuit_lib.model_type(circuit_model))],
circuit_lib.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_port)) {
VTR_LOG_ERROR(circuit_lib.model_name(circuit_model).c_str(),
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(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_circuit_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.model_ports_by_type(circuit_model, port_type_to_check, false == include_global_ports);
if (num_ports_to_check != ports.size()) {
VTR_LOG_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.model_type(circuit_model))],
ports.size(),
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(port_type_to_check)]);
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_circuit_model_type& circuit_model_type_to_check,
const std::vector<enum e_circuit_model_port_type>& port_types_to_check) {
size_t num_err = 0;
for (const auto& id : circuit_lib.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_circuit_model_type& circuit_model_type) {
size_t num_err = 0;
if (CircuitModelId::INVALID() == circuit_lib.default_model(circuit_model_type)) {
VTR_LOG_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(CIRCUIT_MODEL_FF == circuit_lib.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,
CIRCUIT_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,
CIRCUIT_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,
CIRCUIT_MODEL_PORT_OUTPUT,
1, 1, false);
return num_err;
}
/************************************************************************
* A function to check the port map of CCFF circuit model
***********************************************************************/
size_t check_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
size_t num_err = 0;
/* Check the type of circuit model */
VTR_ASSERT(CIRCUIT_MODEL_CCFF == circuit_lib.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,
CIRCUIT_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,
CIRCUIT_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,
CIRCUIT_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(CIRCUIT_MODEL_SRAM == circuit_lib.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,
CIRCUIT_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,
CIRCUIT_MODEL_PORT_BL,
1, 1, false);
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
CIRCUIT_MODEL_PORT_WL,
1, 1, false);
return num_err;
}
/* Check all the ports make sure, they satisfy the restriction */
static
size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) {
size_t num_err = 0;
/* Check global ports: make sure all the global ports are input ports */
for (const auto& port : circuit_lib.ports()) {
if ( (circuit_lib.port_is_global(port))
&& (!circuit_lib.is_input_port(port)) ) {
VTR_LOG_ERROR("Circuit port (type=%s) of model (name=%s) is defined as global but not an input port!\n",
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))],
circuit_lib.model_name(port).c_str());
num_err++;
}
}
/* Check set/reset/config_enable ports: make sure they are all global ports */
for (const auto& port : circuit_lib.ports()) {
if ( ( (circuit_lib.port_is_set(port))
|| (circuit_lib.port_is_reset(port))
|| (circuit_lib.port_is_config_enable(port)) )
&& (!circuit_lib.port_is_global(port)) ) {
VTR_LOG_ERROR("Circuit port (type=%s) of model (name=%s) is defined as a set/reset/config_enable port but it is not global!\n",
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))],
circuit_lib.model_name(port).c_str());
num_err++;
}
}
/* Check the tri-state map of ports, the length should match the port size! */
for (const auto& port : circuit_lib.ports()) {
if (circuit_lib.port_tri_state_map(port).empty()) {
continue; /* No tri-state map is found, go to the next */
}
if (circuit_lib.port_tri_state_map(port).length() == circuit_lib.port_size(port)) {
continue; /* Sizes match, go to the next */
}
/* We have a problem here, sizes do not match, leave a message and raise the error flag */
VTR_LOG_ERROR("Tri-state map (=%s) of circuit port (type=%s) of model (name=%s) does not match the port size (=%lu)!\n",
circuit_lib.port_tri_state_map(port).c_str(),
CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))],
circuit_lib.model_name(port).c_str(),
circuit_lib.port_size(port));
num_err++;
}
/* Check all the global ports which sare the same name also share the same attributes:
* default_value, is_config, is_reset, is_set etc.
*/
std::vector<CircuitPortId> global_ports;
/* Collect all the global ports */
for (auto port : circuit_lib.ports()) {
/* By pass non-global ports*/
if (false == circuit_lib.port_is_global(port)) {
continue;
}
global_ports.push_back(port);
}
for (size_t iport = 0; iport < global_ports.size() - 1; ++iport) {
for (size_t jport = iport + 1; jport < global_ports.size(); ++jport) {
/* Bypass those do not share the same name */
if (0 != circuit_lib.port_prefix(global_ports[iport]).compare(circuit_lib.port_prefix(global_ports[jport]))) {
continue;
}
/* Check if a same port share the same attributes */
CircuitModelId iport_parent_model = circuit_lib.port_parent_model(global_ports[iport]);
CircuitModelId jport_parent_model = circuit_lib.port_parent_model(global_ports[jport]);
if (circuit_lib.port_default_value(global_ports[iport]) != circuit_lib.port_default_value(global_ports[jport])) {
VTR_LOG_ERROR("Global ports %s from circuit model %s and %s share the same name but have different dfefault values(%lu and %lu)!\n",
circuit_lib.port_prefix(global_ports[iport]).c_str(),
circuit_lib.model_name(iport_parent_model).c_str(),
circuit_lib.model_name(jport_parent_model).c_str(),
circuit_lib.port_default_value(global_ports[iport]),
circuit_lib.port_default_value(global_ports[jport])
);
num_err++;
}
if (circuit_lib.port_is_reset(global_ports[iport]) != circuit_lib.port_is_reset(global_ports[jport])) {
VTR_LOG_ERROR("Global ports %s from circuit model %s and %s share the same name but have different is_reset attributes!\n",
circuit_lib.port_prefix(global_ports[iport]).c_str(),
circuit_lib.model_name(iport_parent_model).c_str(),
circuit_lib.model_name(jport_parent_model).c_str()
);
num_err++;
}
if (circuit_lib.port_is_set(global_ports[iport]) != circuit_lib.port_is_set(global_ports[jport])) {
VTR_LOG_ERROR("Global ports %s from circuit model %s and %s share the same name but have different is_set attributes!\n",
circuit_lib.port_prefix(global_ports[iport]).c_str(),
circuit_lib.model_name(iport_parent_model).c_str(),
circuit_lib.model_name(jport_parent_model).c_str()
);
num_err++;
}
if (circuit_lib.port_is_config_enable(global_ports[iport]) != circuit_lib.port_is_config_enable(global_ports[jport])) {
VTR_LOG_ERROR("Global ports %s from circuit model %s and %s share the same name but have different is_config_enable attributes!\n",
circuit_lib.port_prefix(global_ports[iport]).c_str(),
circuit_lib.model_name(iport_parent_model).c_str(),
circuit_lib.model_name(jport_parent_model).c_str()
);
num_err++;
}
if (circuit_lib.port_is_prog(global_ports[iport]) != circuit_lib.port_is_prog(global_ports[jport])) {
VTR_LOG_ERROR("Global ports %s from circuit model %s and %s share the same name but have different is_prog attributes!\n",
circuit_lib.port_prefix(global_ports[iport]).c_str(),
circuit_lib.model_name(iport_parent_model).c_str(),
circuit_lib.model_name(jport_parent_model).c_str()
);
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
* 5. We must have at least one SRAM or CCFF
* 6. SRAM must have at least an input and an output ports
* 7. CCFF 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;
VTR_LOG("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);
/* Check global ports */
num_err += check_circuit_library_ports(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, CIRCUIT_MODEL_IOPAD);
std::vector<enum e_circuit_model_port_type> iopad_port_types_required;
iopad_port_types_required.push_back(CIRCUIT_MODEL_PORT_INPUT);
iopad_port_types_required.push_back(CIRCUIT_MODEL_PORT_OUTPUT);
iopad_port_types_required.push_back(CIRCUIT_MODEL_PORT_INOUT);
iopad_port_types_required.push_back(CIRCUIT_MODEL_PORT_SRAM);
num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_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, CIRCUIT_MODEL_MUX);
std::vector<enum e_circuit_model_port_type> mux_port_types_required;
mux_port_types_required.push_back(CIRCUIT_MODEL_PORT_INPUT);
mux_port_types_required.push_back(CIRCUIT_MODEL_PORT_OUTPUT);
mux_port_types_required.push_back(CIRCUIT_MODEL_PORT_SRAM);
num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_MUX, mux_port_types_required);
/* 5. We must have at least one SRAM or CCFF */
if ( ( 0 == circuit_lib.models_by_type(CIRCUIT_MODEL_SRAM).size())
&& ( 0 == circuit_lib.models_by_type(CIRCUIT_MODEL_CCFF).size()) ) {
VTR_LOG_ERROR("At least one %s or %s circuit model is required!\n",
CIRCUIT_MODEL_TYPE_STRING[size_t(CIRCUIT_MODEL_SRAM)],
CIRCUIT_MODEL_TYPE_STRING[size_t(CIRCUIT_MODEL_CCFF)]);
/* Incremental the counter for errors */
num_err++;
}
/* 6. SRAM must have at least an input and an output ports*/
std::vector<enum e_circuit_model_port_type> sram_port_types_required;
sram_port_types_required.push_back(CIRCUIT_MODEL_PORT_INPUT);
sram_port_types_required.push_back(CIRCUIT_MODEL_PORT_OUTPUT);
num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_SRAM, sram_port_types_required);
/* 7. CCFF must have at least a clock, an input and an output ports*/
std::vector<enum e_circuit_model_port_type> ccff_port_types_required;
ccff_port_types_required.push_back(CIRCUIT_MODEL_PORT_CLOCK);
ccff_port_types_required.push_back(CIRCUIT_MODEL_PORT_INPUT);
ccff_port_types_required.push_back(CIRCUIT_MODEL_PORT_OUTPUT);
num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_CCFF, ccff_port_types_required);
/* 8. FF must have at least a clock, an input and an output ports*/
std::vector<enum e_circuit_model_port_type> ff_port_types_required;
ff_port_types_required.push_back(CIRCUIT_MODEL_PORT_CLOCK);
ff_port_types_required.push_back(CIRCUIT_MODEL_PORT_INPUT);
ff_port_types_required.push_back(CIRCUIT_MODEL_PORT_OUTPUT);
num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_FF, ff_port_types_required);
/* 9. LUT must have at least an input, an output and a SRAM ports*/
std::vector<enum e_circuit_model_port_type> lut_port_types_required;
lut_port_types_required.push_back(CIRCUIT_MODEL_PORT_SRAM);
lut_port_types_required.push_back(CIRCUIT_MODEL_PORT_INPUT);
lut_port_types_required.push_back(CIRCUIT_MODEL_PORT_OUTPUT);
num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_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, CIRCUIT_MODEL_MUX);
num_err += check_required_default_circuit_model(circuit_lib, CIRCUIT_MODEL_CHAN_WIRE);
num_err += check_required_default_circuit_model(circuit_lib, CIRCUIT_MODEL_WIRE);
/* If we have any errors, exit */
if (0 < num_err) {
VTR_LOG("Finished checking circuit library with %d errors!\n",
num_err);
exit(1);
}
VTR_LOG("Checking circuit library passed.\n");
return;
}

View File

@ -0,0 +1,48 @@
/* 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 <vector>
#include "circuit_types.h"
#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_circuit_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_circuit_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_ccff_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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,568 @@
/* IMPORTANT:
* The following preprocessing flags are added to
* avoid compilation error when this headers are included in more than 1 times
*/
#ifndef CIRCUIT_LIBRARY_H
#define CIRCUIT_LIBRARY_H
/*
* Notes in include header files in a head file
* Only include the neccessary header files
* that is required by the data types in the function/class declarations!
*/
/* Header files should be included in a sequence */
/* Standard header files required go first */
#include <string>
#include "vtr_geometry.h"
#include "vtr_vector.h"
#include "vtr_range.h"
#include "circuit_types.h"
#include "circuit_library_fwd.h"
/************************************************************************
* The class CircuitLibrary is a critical data structure for OpenFPGA
* It stores all the circuit-level details from XML architecture file
*
* It includes the following data:
*
* ------ Fundamental Information -----
* 1. model_ids_ : unique identifier to find a circuit model
* Use a strong id for search, to avoid illegal type casting
* 2. model_types_: types of the circuit model, see details in the definition of enum e_circuit_model_type
* 3. model_names_: unique names for each circuit models.
* It should be the same as user-defined Verilog modules, if it is not auto-generated
* 4. model_prefix_: the prefix of a circuit model when it is instanciated
* 5. verilog_netlist_: specified path and file name of Verilog netlist if a circuit model is not auto-generated
* 6. circuit_netlist_: specified path and file name of CIRCUIT netlist if a circuit model is not auto-generated
* 7. is_default_: indicate if the circuit model is the default one among all those in the same type
* 8. sub_models_: the sub circuit models included by a circuit model. It is a collection of unique circuit model ids
* found in the CircuitModelId of pass-gate/buffers/port-related circuit models.
*
* ------ Fast look-ups-----
* 1. model_lookup_: A multi-dimension vector to provide fast look-up on circuit models for users
* It classifies CircuitModelIds by their type and set the default model in the first element for each type.
* 2. model_port_lookup_: A multi-dimension vector to provide fast look-up on ports of circuit models for users
* It classifies Ports by their types
*
* ------ Verilog generation options -----
* 1. dump_structural_verilog_: if Verilog generator will output structural Verilog syntax for the circuit model
* 2. dump_explicit_port_map_: if Verilog generator will use explicit port mapping when instanciate the circuit model
*
* ------ Design technology information -----
* 1. design_tech_types_: the design technology [cmos|rram] for each circuit model
* 2. is_power_gated_: specify if the circuit model is power-gated (contain a input to turn on/off VDD and GND)
*
* ------ Buffer existence -----
* Use vectors to simplify the defition of buffer existence:
* index (low=0 to high) represents INPUT, OUTPUT, LUT_INPUT_BUF, LUT_INPUT_INV, LUT_INTER_BUFFER
* 1. buffer_existence_: specify if this circuit model has an buffer
* 2. buffer_model_name_: specify the name of circuit model for the buffer
* 3. buffer_model_id_: specify the id of circuit model for the buffer
*
* ------ Pass-gate-related parameters ------
* 1. pass_gate_logic_model_name_: specify the name of circuit model for the pass gate logic
* 2. pass_gate_logic_model_id_: specify the id of circuit model for the pass gate logic
*
* ------ Port information ------
* 1. port_ids_: unique id of ports belonging to a circuit model
* 1. port_model_ids_: unique id of the parent circuit model for the port
* 2. port_types_: types of ports belonging to a circuit model
* 3. port_sizes_: width of ports belonging to a circuit model
* 4. port_prefix_: prefix of a port when instance of a circuit model
* 5. port_lib_names_: port name in the standard cell library, only used when explicit_port_mapping is enabled
* 6. port_inv_prefix_: the prefix to be added for the inverted port. This is mainly used by SRAM ports, which have an coupled inverterd port
* 7. port_is_mode_select: specify if this port is used to select operating modes of the circuit model
* 8. port_is_global: specify if this port is a global signal shared by other circuit model
* 9. port_is_reset: specify if this port is a reset signal which needs special pulse widths in testbenches
* 10. port_is_set: specify if this port is a set signal which needs special pulse widths in testbenches
* 11. port_is_config_enable: specify if this port is a config_enable signal which needs special pulse widths in testbenches
* 12. port_is_prog: specify if this port is for FPGA programming use which needs special pulse widths in testbenches
* 13. port_tri_state_model_name: the name of circuit model linked to tri-state the port
* 14. port_tri_state_model_ids_: the Id of circuit model linked to tri-state the port
* 15. port_inv_model_names_: the name of inverter circuit model linked to the port
* 16. port_inv_model_ids_: the Id of inverter circuit model linked to the port
* 17. port_tri_state_map_: only applicable to inputs of LUTs, the tri-state map applied to each pin of this port
* 18. port_lut_frac_level_: only applicable to outputs of LUTs, indicate which level of outputs inside LUT multiplexing structure will be used
* 19. port_lut_output_mask_: only applicable to outputs of LUTs, indicate which output at an internal level of LUT multiplexing structure will be used
* 20. port_sram_orgz_: only applicable to SRAM ports, indicate how the SRAMs will be organized, either memory decoders or scan-chains
*
* ------ Delay information ------
* 1. delay_types_: type of pin-to-pin delay, either rising_edge of falling_edge
* 2. delay_in_port_names_: name of input ports that the pin-to-pin delay is linked to
* 3. delay_in_port_names_: name of output ports that the pin-to-pin delay is linked to
* 4. delay_values_: delay values of the pin-to-pin delay
*
* ------ Timing graph information: TODO: consider using tatum? ------
* Timing graph is allocated when delay information is made
* 1. edge_ids_ : ids of edges in the timing graph
* 2. port_in_edge_ids_: ids of input edges for each pin of a circuit port
* 3. port_out_edge_ids_: ids of output edges for each pin of a circuit port
* 4. edge_src_port_ids_: ids of source ports that each edge is connected to
* 5. edge_src_pin_ids_: ids of source pin that each edge is connected to
* 6. edge_sink_port_ids_: ids of sink ports that each edge is connected to
* 7. edge_sink_pin_ids_: ids of sink pin that each edge is connected to
* 8. edge_trise_: rising delay of the edge
* 9. edge_tfall_: falling delay of the edge
*
* ------ Buffer/Inverter-related parameters ------
* Note: only applicable to circuit models whose type is buffer or inverter
* 1. buffer_types_: type of the buffer, either buffer or inverter
* 2. buffer_location_maps_: location of the buffer, only applicable to LUTs
* 3. buffer_sizes_: size of buffer (transistor size for the first stage)
* 4. buffer_is_tapered_: specify if this buffer has multiple stages
* 5. buffer_num_levels: specify the number of levels of this buffer (if this is defined as multi-level buffer)
* 6. buffer_f_per_stage: specify the driving strength of the buffer by stage
*
* ------ Pass-gate-logic-related parameters ------
* Note: only applicable to circuit models whose type is pass-gate-logic
* 1. pass_gate_logic_types_: types of the pass-gate-logic, either transmission-gate or pass-transistor
* 2. pass_gate_logic_nmos_sizes_: size of NMOS transistor in the pass-gate-logic
* 3. pass_gate_logic_pmos_sizes_: size of PMOS transistor in the pass-gate-logic, only applicable for transmission-gates
*
* ------ Multiplexer-related parameters ------
* Note: only applicable to circuit models whose type is MUX
* 1. mux_structure_: specify the structure of a multiplexer, one-level, multi-level or tree-like
* 2. mux_num_levels_: specify the number of levels for a multiplexer
* 3. mux_add_const_input_: specify if this multiplexer has a constant input
* 4. mux_const_input_values_: specify the value of the constant input for this multiplexer (valid only when mux_add_const_input is true)
* 5. mux_use_local_encoder_: specify if the mux as a local encoder between SRAMs and multiplexing structure
* 6. mux_advanced_rram_design_: specify if the multiplexer will use advanced RRAM circuit design topology
*
* ------ LUT-related parameters ------
* Note: only applicable to circuit models whose type is LUT
* 1. lut_is_fracturable_: specify if this LUT is built with fracturable structure
*
* ------ RRAM-related parameters ------
* Note: only applicable to circuit models whose design technology is RRAM
* 1. rlrs: RRAM resistance in Low-Resistance State (LRS)
* 2. rhrs: RRAM resistance in High-Resistance State (HRS)
* The following transistor sizes are applicable for 4T1R programming structures
* 3. wprog_set_nmos: size of n-type programming transistor used to set a RRAM
* 4. wprog_set_pmos: size of p-type programming transistor used to set a RRAM
* 5. wprog_reset_nmos: size of n-type programming transistor used to reset a RRAM
* 6. wprog_reset_pmos: size of p-type programming transistor used to reset a RRAM
*
* ------ Metal wire-related parameters ------
* Note: only applicable to circuit models whose type is wires or channel wires
* 1. wire_types_: types of the metal wire for the model
* 2. wire_res_val_: resistance value of the metal wire for the circuit model
* 3. wire_cap_val_: capacitance value of the metal wire for the circuit model
* 4. wire_num_levels_: number of levels of the metal wire model for the circuit model
***********************************************************************/
class CircuitLibrary {
public: /* Types */
typedef vtr::vector<CircuitModelId, CircuitModelId>::const_iterator circuit_model_iterator;
typedef vtr::vector<CircuitModelId, std::string>::const_iterator circuit_model_string_iterator;
typedef vtr::vector<CircuitPortId, CircuitPortId>::const_iterator circuit_port_iterator;
typedef vtr::vector<CircuitEdgeId, CircuitEdgeId>::const_iterator circuit_edge_iterator;
/* Create range */
typedef vtr::Range<circuit_model_iterator> circuit_model_range;
typedef vtr::Range<circuit_port_iterator> circuit_port_range;
typedef vtr::Range<circuit_edge_iterator> circuit_edge_range;
/* local enumeration for buffer existence */
enum e_buffer_type: unsigned char{
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 models() const;
circuit_port_range ports() const;
std::vector<CircuitModelId> models_by_type(const enum e_circuit_model_type& type) const;
public: /* Public Accessors: Basic data query on Circuit Models*/
size_t num_models() const;
enum e_circuit_model_type model_type(const CircuitModelId& model_id) const;
std::string model_name(const CircuitModelId& model_id) const;
std::string model_prefix(const CircuitModelId& model_id) const;
std::string model_verilog_netlist(const CircuitModelId& model_id) const;
std::string model_circuit_netlist(const CircuitModelId& model_id) const;
bool model_is_default(const CircuitModelId& model_id) const;
bool dump_structural_verilog(const CircuitModelId& model_id) const;
bool dump_explicit_port_map(const CircuitModelId& model_id) const;
enum e_circuit_model_design_tech design_tech_type(const CircuitModelId& model_id) const;
bool is_power_gated(const CircuitModelId& model_id) const;
/* General buffer information */
bool is_input_buffered(const CircuitModelId& model_id) const;
bool is_output_buffered(const CircuitModelId& model_id) const;
/* LUT-related information */
bool is_lut_intermediate_buffered(const CircuitModelId& model_id) const;
bool is_lut_fracturable(const CircuitModelId& model_id) const;
CircuitModelId lut_input_buffer_model(const CircuitModelId& model_id) const;
CircuitModelId lut_input_inverter_model(const CircuitModelId& model_id) const;
CircuitModelId lut_intermediate_buffer_model(const CircuitModelId& model_id) const;
std::string lut_intermediate_buffer_location_map(const CircuitModelId& model_id) const;
/* Pass-gate-logic information */
CircuitModelId pass_gate_logic_model(const CircuitModelId& model_id) const;
enum e_circuit_model_pass_gate_logic_type pass_gate_logic_type(const CircuitModelId& model_id) const;
/* Multiplexer information */
enum e_circuit_model_structure mux_structure(const CircuitModelId& model_id) const;
size_t mux_num_levels(const CircuitModelId& model_id) const;
bool mux_add_const_input(const CircuitModelId& model_id) const;
size_t mux_const_input_value(const CircuitModelId& model_id) const;
bool mux_use_local_encoder(const CircuitModelId& model_id) const;
/* Gate information */
enum e_circuit_model_gate_type gate_type(const CircuitModelId& model_id) const;
/* Buffer information */
enum e_circuit_model_buffer_type buffer_type(const CircuitModelId& model_id) const;
size_t buffer_num_levels(const CircuitModelId& model_id) const;
CircuitModelId input_buffer_model(const CircuitModelId& model_id) const;
CircuitModelId output_buffer_model(const CircuitModelId& model_id) const;
/* Delay information */
size_t num_delay_info(const CircuitModelId& model_id) const;
public: /* Public Accessors: Basic data query on cirucit models' Circuit Ports*/
CircuitPortId model_port(const CircuitModelId& model_id, const std::string& name) const;
size_t num_model_ports(const CircuitModelId& model_id) const;
size_t num_model_ports_by_type(const CircuitModelId& model_id, const enum e_circuit_model_port_type& port_type, const bool& include_global_port) const;
std::vector<CircuitPortId> model_ports(const CircuitModelId& model_id) const;
std::vector<CircuitPortId> model_global_ports(const CircuitModelId& model_id, const bool& recursive) const;
std::vector<CircuitPortId> model_global_ports_by_type(const CircuitModelId& model_id,
const enum e_circuit_model_port_type& type,
const bool& recursive,
const std::vector<enum e_circuit_model_type>& ignore_model_types) const;
std::vector<CircuitPortId> model_global_ports_by_type(const CircuitModelId& model_id,
const std::vector<enum e_circuit_model_port_type>& type,
const bool& recursive,
const bool& ignore_config_memories) const;
std::vector<CircuitPortId> model_global_ports_by_type(const CircuitModelId& model_id,
const enum e_circuit_model_port_type& type,
const bool& recursive,
const bool& ignore_config_memories) const;
std::vector<CircuitPortId> model_ports_by_type(const CircuitModelId& model_id, const enum e_circuit_model_port_type& port_type) const;
std::vector<CircuitPortId> model_ports_by_type(const CircuitModelId& model_id, const enum e_circuit_model_port_type& port_type, const bool& include_global_port) const;
std::vector<CircuitPortId> model_input_ports(const CircuitModelId& model_id) const;
std::vector<CircuitPortId> model_output_ports(const CircuitModelId& model_id) const;
std::vector<size_t> pins(const CircuitPortId& circuit_port_id) const;
public: /* Public Accessors: Basic data query on Circuit Ports*/
bool is_input_port(const CircuitPortId& circuit_port_id) const;
bool is_output_port(const CircuitPortId& circuit_port_id) const;
enum e_circuit_model_port_type port_type(const CircuitPortId& circuit_port_id) const;
size_t port_size(const CircuitPortId& circuit_port_id) const;
std::string port_prefix(const CircuitPortId& circuit_port_id) const;
std::string port_lib_name(const CircuitPortId& circuit_port_id) const;
std::string port_inv_prefix(const CircuitPortId& circuit_port_id) const;
size_t port_default_value(const CircuitPortId& circuit_port_id) const;
bool port_is_mode_select(const CircuitPortId& circuit_port_id) const;
bool port_is_global(const CircuitPortId& circuit_port_id) const;
bool port_is_reset(const CircuitPortId& circuit_port_id) const;
bool port_is_set(const CircuitPortId& circuit_port_id) const;
bool port_is_config_enable(const CircuitPortId& circuit_port_id) const;
bool port_is_prog(const CircuitPortId& circuit_port_id) const;
size_t port_lut_frac_level(const CircuitPortId& circuit_port_id) const;
std::vector<size_t> port_lut_output_masks(const CircuitPortId& circuit_port_id) const;
std::string port_tri_state_map(const CircuitPortId& circuit_port_id) const;
CircuitModelId port_tri_state_model(const CircuitPortId& circuit_port_id) const;
std::string port_tri_state_model_name(const CircuitPortId& circuit_port_id) const;
CircuitModelId port_parent_model(const CircuitPortId& circuit_port_id) const;
std::string model_name(const CircuitPortId& port_id) const;
public: /* Public Accessors: Timing graph */
/* Get source/sink nodes and delay of edges */
std::vector<CircuitEdgeId> timing_edges_by_model(const CircuitModelId& model_id) const;
CircuitPortId timing_edge_src_port(const CircuitEdgeId& edge) const;
size_t timing_edge_src_pin(const CircuitEdgeId& edge) const;
CircuitPortId timing_edge_sink_port(const CircuitEdgeId& edge) const;
size_t timing_edge_sink_pin(const CircuitEdgeId& edge) const;
float timing_edge_delay(const CircuitEdgeId& edge, const enum circuit_model_delay_type& delay_type) const;
public: /* Public Accessors: Methods to find circuit model */
CircuitModelId model(const char* name) const;
CircuitModelId model(const std::string& name) const;
CircuitModelId default_model(const enum e_circuit_model_type& type) const;
public: /* Public Accessors: Timing graph */
CircuitEdgeId edge(const CircuitPortId& from_port, const size_t from_pin,
const CircuitPortId& to_port, const size_t to_pin);
public: /* Public Mutators */
CircuitModelId add_model(const enum e_circuit_model_type& type);
/* Fundamental information */
void set_model_name(const CircuitModelId& model_id, const std::string& name);
void set_model_prefix(const CircuitModelId& model_id, const std::string& prefix);
void set_model_verilog_netlist(const CircuitModelId& model_id, const std::string& verilog_netlist);
void set_model_circuit_netlist(const CircuitModelId& model_id, const std::string& circuit_netlist);
void set_model_is_default(const CircuitModelId& model_id, const bool& is_default);
/* Verilog generator options */
void set_model_dump_structural_verilog(const CircuitModelId& model_id, const bool& dump_structural_verilog);
void set_model_dump_explicit_port_map(const CircuitModelId& model_id, const bool& dump_explicit_port_map);
/* Design technology information */
void set_model_design_tech_type(const CircuitModelId& model_id, const enum e_circuit_model_design_tech& design_tech_type);
void set_model_is_power_gated(const CircuitModelId& model_id, const bool& is_power_gated);
/* Buffer existence */
void set_model_input_buffer(const CircuitModelId& model_id,
const bool& existence, const std::string& model_name);
void set_model_output_buffer(const CircuitModelId& model_id,
const bool& existence, const std::string& model_name);
void set_model_lut_input_buffer(const CircuitModelId& model_id,
const bool& existence, const std::string& model_name);
void set_model_lut_input_inverter(const CircuitModelId& model_id,
const bool& existence, const std::string& model_name);
void set_model_lut_intermediate_buffer(const CircuitModelId& model_id,
const bool& existence, const std::string& model_name);
void set_model_lut_intermediate_buffer_location_map(const CircuitModelId& model_id,
const std::string& location_map);
/* Pass-gate-related parameters */
void set_model_pass_gate_logic(const CircuitModelId& model_id, const std::string& model_name);
/* Port information */
CircuitPortId add_model_port(const CircuitModelId& model_id,
const enum e_circuit_model_port_type& port_type);
void set_port_size(const CircuitPortId& circuit_port_id,
const size_t& port_size);
void set_port_prefix(const CircuitPortId& circuit_port_id,
const std::string& port_prefix);
void set_port_lib_name(const CircuitPortId& circuit_port_id,
const std::string& lib_name);
void set_port_inv_prefix(const CircuitPortId& circuit_port_id,
const std::string& inv_prefix);
void set_port_default_value(const CircuitPortId& circuit_port_id,
const size_t& default_val);
void set_port_is_mode_select(const CircuitPortId& circuit_port_id,
const bool& is_mode_select);
void set_port_is_global(const CircuitPortId& circuit_port_id,
const bool& is_global);
void set_port_is_reset(const CircuitPortId& circuit_port_id,
const bool& is_reset);
void set_port_is_set(const CircuitPortId& circuit_port_id,
const bool& is_set);
void set_port_is_config_enable(const CircuitPortId& circuit_port_id,
const bool& is_config_enable);
void set_port_is_prog(const CircuitPortId& circuit_port_id,
const bool& is_prog);
void set_port_tri_state_model_name(const CircuitPortId& circuit_port_id,
const std::string& model_name);
void set_port_tri_state_model_id(const CircuitPortId& circuit_port_id,
const CircuitModelId& port_model_id);
void set_port_inv_model_name(const CircuitPortId& circuit_port_id,
const std::string& inv_model_name);
void set_port_inv_model_id(const CircuitPortId& circuit_port_id,
const CircuitModelId& inv_model_id);
void set_port_tri_state_map(const CircuitPortId& circuit_port_id,
const std::string& tri_state_map);
void set_port_lut_frac_level(const CircuitPortId& circuit_port_id,
const size_t& lut_frac_level);
void set_port_lut_output_mask(const CircuitPortId& circuit_port_id,
const std::vector<size_t>& lut_output_masks);
void set_port_sram_orgz(const CircuitPortId& circuit_port_id,
const enum e_sram_orgz& sram_orgz);
/* Delay information */
void add_delay_info(const CircuitModelId& model_id,
const enum circuit_model_delay_type& delay_type);
void set_delay_in_port_names(const CircuitModelId& model_id,
const enum circuit_model_delay_type& delay_type,
const std::string& in_port_names);
void set_delay_out_port_names(const CircuitModelId& model_id,
const enum circuit_model_delay_type& delay_type,
const std::string& out_port_names);
void set_delay_values(const CircuitModelId& model_id,
const enum circuit_model_delay_type& delay_type,
const std::string& delay_values);
/* Buffer/Inverter-related parameters */
void set_buffer_type(const CircuitModelId& model_id,
const enum e_circuit_model_buffer_type& buffer_type);
void set_buffer_size(const CircuitModelId& model_id,
const float& buffer_size);
void set_buffer_num_levels(const CircuitModelId& model_id,
const size_t& num_levels);
void set_buffer_f_per_stage(const CircuitModelId& model_id,
const size_t& f_per_stage);
/* Pass-gate-related parameters */
void set_pass_gate_logic_type(const CircuitModelId& model_id,
const enum e_circuit_model_pass_gate_logic_type& pass_gate_logic_type);
void set_pass_gate_logic_nmos_size(const CircuitModelId& model_id,
const float& nmos_size);
void set_pass_gate_logic_pmos_size(const CircuitModelId& model_id,
const float& pmos_size);
/* Multiplexer-related parameters */
void set_mux_structure(const CircuitModelId& model_id,
const enum e_circuit_model_structure& mux_structure);
void set_mux_num_levels(const CircuitModelId& model_id,
const size_t& num_levels);
void set_mux_const_input_value(const CircuitModelId& model_id,
const size_t& const_input_value);
void set_mux_use_local_encoder(const CircuitModelId& model_id,
const bool& use_local_encoder);
void set_mux_use_advanced_rram_design(const CircuitModelId& model_id,
const bool& use_advanced_rram_design);
/* LUT-related parameters */
void set_lut_is_fracturable(const CircuitModelId& model_id,
const bool& is_fracturable);
/* Gate-related parameters */
void set_gate_type(const CircuitModelId& model_id,
const enum e_circuit_model_gate_type& gate_type);
/* RRAM-related design technology information */
void set_rram_rlrs(const CircuitModelId& model_id,
const float& rlrs);
void set_rram_rhrs(const CircuitModelId& model_id,
const float& rhrs);
void set_rram_wprog_set_nmos(const CircuitModelId& model_id,
const float& wprog_set_nmos);
void set_rram_wprog_set_pmos(const CircuitModelId& model_id,
const float& wprog_set_pmos);
void set_rram_wprog_reset_nmos(const CircuitModelId& model_id,
const float& wprog_reset_nmos);
void set_rram_wprog_reset_pmos(const CircuitModelId& model_id,
const float& wprog_reset_pmos);
/* Wire parameters */
void set_wire_type(const CircuitModelId& model_id,
const enum e_wire_model_type& wire_type);
void set_wire_r(const CircuitModelId& model_id,
const float& r_val);
void set_wire_c(const CircuitModelId& model_id,
const float& c_val);
void set_wire_num_levels(const CircuitModelId& model_id,
const size_t& num_level);
private: /* Private Mutators: builders */
void set_model_buffer(const CircuitModelId& model_id, const enum e_buffer_type buffer_type, const bool& existence, const std::string& model_name);
void link_port_tri_state_model();
void link_port_inv_model();
void link_buffer_model(const CircuitModelId& model_id);
void link_pass_gate_logic_model(const CircuitModelId& model_id);
bool is_unique_submodel(const CircuitModelId& model_id, const CircuitModelId& submodel_id);
void build_model_timing_graph(const CircuitModelId& model_id);
void build_submodels();
public: /* Public Mutators: builders */
void build_model_links();
void build_timing_graphs();
public: /* Internal mutators: build timing graphs */
void add_edge(const CircuitModelId& model_id,
const CircuitPortId& from_port, const size_t& from_pin,
const CircuitPortId& to_port, const size_t& to_pin);
void set_edge_delay(const CircuitModelId& model_id,
const CircuitEdgeId& circuit_edge_id,
const enum circuit_model_delay_type& delay_type,
const float& delay_value);
/* validate the circuit_edge_id */
void set_timing_graph_delays(const CircuitModelId& model_id);
public: /* Internal mutators: build fast look-ups */
void build_model_lookup();
void build_model_port_lookup();
public: /* Public invalidators/validators */
bool valid_model_id(const CircuitModelId& model_id) const;
bool valid_circuit_port_id(const CircuitPortId& circuit_port_id) const;
bool valid_circuit_pin_id(const CircuitPortId& circuit_port_id, const size_t& pin_id) const;
private: /* Internal invalidators/validators */
/* Validators */
bool valid_edge_id(const CircuitEdgeId& edge_id) const;
bool valid_delay_type(const CircuitModelId& model_id, const enum circuit_model_delay_type& delay_type) const;
bool valid_circuit_edge_id(const CircuitEdgeId& circuit_edge_id) const;
bool valid_mux_const_input_value(const size_t& const_input_value) const;
/* Invalidators */
void invalidate_model_lookup() const;
void invalidate_model_port_lookup() const;
void invalidate_model_timing_graph();
private: /* Internal data */
/* Fundamental information */
vtr::vector<CircuitModelId, CircuitModelId> model_ids_;
vtr::vector<CircuitModelId, enum e_circuit_model_type> model_types_;
vtr::vector<CircuitModelId, std::string> model_names_;
vtr::vector<CircuitModelId, std::string> model_prefix_;
vtr::vector<CircuitModelId, std::string> model_verilog_netlists_;
vtr::vector<CircuitModelId, std::string> model_circuit_netlists_;
vtr::vector<CircuitModelId, bool> model_is_default_;
/* Submodules that a circuit model contains */
vtr::vector<CircuitModelId, std::vector<CircuitModelId>> sub_models_;
/* fast look-up for circuit models to categorize by types
* [type][num_ids]
* Important: we force the default circuit model in the first element for each type
*/
typedef std::vector<std::vector<CircuitModelId>> CircuitModelLookup;
mutable CircuitModelLookup model_lookup_; /* [model_type][model_ids] */
typedef vtr::vector<CircuitModelId, std::vector<std::vector<CircuitPortId>>> CircuitModelPortLookup;
mutable CircuitModelPortLookup model_port_lookup_; /* [model_id][port_type][port_ids] */
/* Verilog generator options */
vtr::vector<CircuitModelId, bool> dump_structural_verilog_;
vtr::vector<CircuitModelId, bool> dump_explicit_port_map_;
/* Design technology information */
vtr::vector<CircuitModelId, enum e_circuit_model_design_tech> design_tech_types_;
vtr::vector<CircuitModelId, bool> is_power_gated_;
/* Buffer existence */
vtr::vector<CircuitModelId, std::vector<bool>> buffer_existence_;
vtr::vector<CircuitModelId, std::vector<std::string>> buffer_model_names_;
vtr::vector<CircuitModelId, std::vector<CircuitModelId>> buffer_model_ids_;
vtr::vector<CircuitModelId, std::vector<std::string>> buffer_location_maps_;
/* Pass-gate-related parameters */
vtr::vector<CircuitModelId, std::string> pass_gate_logic_model_names_;
vtr::vector<CircuitModelId, CircuitModelId> pass_gate_logic_model_ids_;
/* Port information */
vtr::vector<CircuitPortId, CircuitPortId> port_ids_;
vtr::vector<CircuitPortId, CircuitModelId> port_model_ids_;
vtr::vector<CircuitPortId, enum e_circuit_model_port_type> port_types_;
vtr::vector<CircuitPortId, size_t> port_sizes_;
vtr::vector<CircuitPortId, std::string> port_prefix_;
vtr::vector<CircuitPortId, std::string> port_lib_names_;
vtr::vector<CircuitPortId, std::string> port_inv_prefix_;
vtr::vector<CircuitPortId, size_t> port_default_values_;
vtr::vector<CircuitPortId, bool> port_is_mode_select_;
vtr::vector<CircuitPortId, bool> port_is_global_;
vtr::vector<CircuitPortId, bool> port_is_reset_;
vtr::vector<CircuitPortId, bool> port_is_set_;
vtr::vector<CircuitPortId, bool> port_is_config_enable_;
vtr::vector<CircuitPortId, bool> port_is_prog_;
vtr::vector<CircuitPortId, std::string> port_tri_state_model_names_;
vtr::vector<CircuitPortId, CircuitModelId> port_tri_state_model_ids_;
vtr::vector<CircuitPortId, std::string> port_inv_model_names_;
vtr::vector<CircuitPortId, CircuitModelId> port_inv_model_ids_;
vtr::vector<CircuitPortId, std::string> port_tri_state_maps_;
vtr::vector<CircuitPortId, size_t> port_lut_frac_level_;
vtr::vector<CircuitPortId, std::vector<size_t>> port_lut_output_masks_;
vtr::vector<CircuitPortId, enum e_sram_orgz> port_sram_orgz_;
/* Timing graphs */
vtr::vector<CircuitEdgeId, CircuitEdgeId> edge_ids_;
vtr::vector<CircuitEdgeId, CircuitModelId> edge_parent_model_ids_;
vtr::vector<CircuitPortId, vtr::vector<size_t, CircuitEdgeId>> port_in_edge_ids_;
vtr::vector<CircuitPortId, vtr::vector<size_t, CircuitEdgeId>> port_out_edge_ids_;
vtr::vector<CircuitEdgeId, CircuitPortId> edge_src_port_ids_;
vtr::vector<CircuitEdgeId, size_t> edge_src_pin_ids_;
vtr::vector<CircuitEdgeId, CircuitPortId> edge_sink_port_ids_;
vtr::vector<CircuitEdgeId, size_t> edge_sink_pin_ids_;
vtr::vector<CircuitEdgeId, std::vector<float>> edge_timing_info_; /* x0 => trise, x1 => tfall */
/* Delay information */
vtr::vector<CircuitModelId, std::vector<enum circuit_model_delay_type>> delay_types_;
vtr::vector<CircuitModelId, std::vector<std::string>> delay_in_port_names_;
vtr::vector<CircuitModelId, std::vector<std::string>> delay_out_port_names_;
vtr::vector<CircuitModelId, std::vector<std::string>> delay_values_;
/* Buffer/Inverter-related parameters */
vtr::vector<CircuitModelId, enum e_circuit_model_buffer_type> buffer_types_;
vtr::vector<CircuitModelId, float> buffer_sizes_;
vtr::vector<CircuitModelId, size_t> buffer_num_levels_;
vtr::vector<CircuitModelId, size_t> buffer_f_per_stage_;
/* Pass-gate-related parameters */
vtr::vector<CircuitModelId, enum e_circuit_model_pass_gate_logic_type> pass_gate_logic_types_;
vtr::vector<CircuitModelId, vtr::Point<float>> pass_gate_logic_sizes_; /* x=> nmos_size; y => pmos_size */
/* Multiplexer-related parameters */
vtr::vector<CircuitModelId, enum e_circuit_model_structure> mux_structure_;
vtr::vector<CircuitModelId, size_t> mux_num_levels_;
vtr::vector<CircuitModelId, size_t> mux_const_input_values_;
vtr::vector<CircuitModelId, bool> mux_use_local_encoder_;
vtr::vector<CircuitModelId, bool> mux_use_advanced_rram_design_;
/* LUT-related parameters */
vtr::vector<CircuitModelId, bool> lut_is_fracturable_;
/* Gate-related parameters */
vtr::vector<CircuitModelId, enum e_circuit_model_gate_type> gate_types_;
/* RRAM-related design technology information */
vtr::vector<CircuitModelId, vtr::Point<float>> rram_res_; /* x => R_LRS, y => R_HRS */
vtr::vector<CircuitModelId, vtr::Point<float>> wprog_set_; /* x => wprog_set_nmos, y=> wprog_set_pmos */
vtr::vector<CircuitModelId, vtr::Point<float>> wprog_reset_; /* x => wprog_reset_nmos, y=> wprog_reset_pmos */
/* Wire parameters */
vtr::vector<CircuitModelId, enum e_wire_model_type> wire_types_;
vtr::vector<CircuitModelId, vtr::Point<float>> wire_rc_; /* x => wire_res_val, y=> wire_cap_val */
vtr::vector<CircuitModelId, size_t> wire_num_levels_;
};
#endif

View File

@ -0,0 +1,26 @@
/************************************************************************
* A header file for CircuitLibrary class, including critical data declaration
* Please include this file only for using any CircuitLibrary data structure
* Refer to circuit_library.h for more details
***********************************************************************/
/************************************************************************
* Create strong id for Circuit Models/Ports to avoid illegal type casting
***********************************************************************/
#ifndef CIRCUIT_LIBRARY_FWD_H
#define CIRCUIT_LIBRARY_FWD_H
#include "vtr_strong_id.h"
struct circuit_model_id_tag;
struct circuit_port_id_tag;
struct circuit_edge_id_tag;
typedef vtr::StrongId<circuit_model_id_tag> CircuitModelId;
typedef vtr::StrongId<circuit_port_id_tag> CircuitPortId;
typedef vtr::StrongId<circuit_edge_id_tag> CircuitEdgeId;
/* Short declaration of class */
class CircuitLibrary;
#endif

View File

@ -0,0 +1,113 @@
/* IMPORTANT:
* The following preprocessing flags are added to
* avoid compilation error when this headers are included in more than 1 times
*/
#ifndef CIRCUIT_TYPES_H
#define CIRCUIT_TYPES_H
/************************************************************************
* This file includes basic enumeration types for circuit models
***********************************************************************/
/*
* Notes in include header files in a head file
* Only include the neccessary header files
* that is required by the data types in the function/class declarations!
*/
/* Header files should be included in a sequence */
/* Standard header files required go first */
enum circuit_model_delay_type {
CIRCUIT_MODEL_DELAY_RISE,
CIRCUIT_MODEL_DELAY_FALL,
NUM_CIRCUIT_MODEL_DELAY_TYPES
};
/*Struct for a CIRCUIT model of a module*/
enum e_circuit_model_type {
CIRCUIT_MODEL_CHAN_WIRE,
CIRCUIT_MODEL_WIRE,
CIRCUIT_MODEL_MUX,
CIRCUIT_MODEL_LUT,
CIRCUIT_MODEL_FF,
CIRCUIT_MODEL_SRAM,
CIRCUIT_MODEL_HARDLOGIC,
CIRCUIT_MODEL_CCFF,
CIRCUIT_MODEL_IOPAD,
CIRCUIT_MODEL_INVBUF,
CIRCUIT_MODEL_PASSGATE,
CIRCUIT_MODEL_GATE,
NUM_CIRCUIT_MODEL_TYPES
};
/* Strings correspond to each port type */
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_TYPES> CIRCUIT_MODEL_TYPE_STRING = {{"CHAN_WIRE", "WIRE", "MUX", "LUT", "FF", "SRAM", "HARDLOGIC", "CCFF", "IOPAD", "INVBUF", "PASSGATE", "GATE"}};
enum e_circuit_model_design_tech {
CIRCUIT_MODEL_DESIGN_CMOS,
CIRCUIT_MODEL_DESIGN_RRAM,
NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES
};
enum e_circuit_model_structure {
CIRCUIT_MODEL_STRUCTURE_TREE,
CIRCUIT_MODEL_STRUCTURE_ONELEVEL,
CIRCUIT_MODEL_STRUCTURE_MULTILEVEL,
CIRCUIT_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_circuit_model_buffer_type {
CIRCUIT_MODEL_BUF_INV,
CIRCUIT_MODEL_BUF_BUF,
NUM_CIRCUIT_MODEL_BUF_TYPES
};
enum e_circuit_model_pass_gate_logic_type {
CIRCUIT_MODEL_PASS_GATE_TRANSMISSION,
CIRCUIT_MODEL_PASS_GATE_TRANSISTOR,
CIRCUIT_MODEL_PASS_GATE_RRAM, /* RRAM can be treated as a special type of pass-gate logic */
CIRCUIT_MODEL_PASS_GATE_STDCELL, /* Standard cell as a special type of pass-gate logic */
NUM_CIRCUIT_MODEL_PASS_GATE_TYPES
};
enum e_circuit_model_gate_type {
CIRCUIT_MODEL_GATE_AND,
CIRCUIT_MODEL_GATE_OR,
CIRCUIT_MODEL_GATE_MUX2,
NUM_CIRCUIT_MODEL_GATE_TYPES
};
enum e_wire_model_type {
WIRE_MODEL_PIE,
WIRE_MODEL_T,
NUM_WIRE_MODEL_TYPES
};
enum e_circuit_model_port_type {
CIRCUIT_MODEL_PORT_INPUT,
CIRCUIT_MODEL_PORT_OUTPUT,
CIRCUIT_MODEL_PORT_INOUT,
CIRCUIT_MODEL_PORT_CLOCK,
CIRCUIT_MODEL_PORT_SRAM,
CIRCUIT_MODEL_PORT_BL,
CIRCUIT_MODEL_PORT_BLB,
CIRCUIT_MODEL_PORT_WL,
CIRCUIT_MODEL_PORT_WLB,
NUM_CIRCUIT_MODEL_PORT_TYPES
};
/* Strings correspond to each port type */
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_PORT_TYPES> CIRCUIT_MODEL_PORT_TYPE_STRING = {{"INPUT", "OUTPUT", "INOUT", "CLOCK", "SRAM", "BL", "BLB", "WL", "WLB"}};
/* For SRAM */
enum e_sram_orgz {
CIRCUIT_SRAM_STANDALONE, /* SRAMs are organized and accessed as standalone elements */
CIRCUIT_SRAM_SCAN_CHAIN, /* SRAMs are organized and accessed by a scan-chain */
CIRCUIT_SRAM_MEMORY_BANK, /* SRAMs are organized and accessed by memory bank */
CIRCUIT_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

@ -0,0 +1,397 @@
#include <numeric>
#include <algorithm>
#include <limits>
#include "vtr_assert.h"
#include "device_port.h"
/* Basic Port member functions */
/* Constructor */
/* Default constructor */
BasicPort::BasicPort() {
/* By default we set an invalid port, which size is 0 */
lsb_ = 1;
msb_ = 0;
}
/* Quick constructor */
BasicPort::BasicPort(const char* name, const size_t& lsb, const size_t& msb) {
set_name(std::string(name));
set_width(lsb, msb);
}
BasicPort::BasicPort(const std::string& name, const size_t& lsb, const size_t& msb) {
set_name(name);
set_width(lsb, msb);
}
BasicPort::BasicPort(const char* name, const size_t& width) {
set_name(std::string(name));
set_width(width);
}
BasicPort::BasicPort(const std::string& name, const size_t& width) {
set_name(name);
set_width(width);
}
/* Copy constructor */
BasicPort::BasicPort(const BasicPort& basic_port) {
set(basic_port);
}
/* Accessors */
/* get the port width */
size_t BasicPort::get_width() const {
if (true == is_valid()) {
return msb_ - lsb_ + 1;
}
return 0; /* invalid port has a zero width */
}
/* get the LSB */
size_t BasicPort::get_msb() const {
return msb_;
}
/* get the LSB */
size_t BasicPort::get_lsb() const {
return lsb_;
}
/* get the name */
std::string BasicPort::get_name() const {
return name_;
}
/* Make a range of the pin indices */
std::vector<size_t> BasicPort::pins() const {
std::vector<size_t> pin_indices;
/* Return if the port is invalid */
if (false == is_valid()) {
return pin_indices; /* Return an empty vector */
}
/* For valid ports, create a vector whose length is the port width */
pin_indices.resize(get_width());
/* Fill in an incremental sequence */
std::iota(pin_indices.begin(), pin_indices.end(), get_lsb());
/* Ensure the last one is MSB */
VTR_ASSERT(get_msb() == pin_indices.back());
return pin_indices;
}
/* Check if a port can be merged with this port: their name should be the same */
bool BasicPort::mergeable(const BasicPort& portA) const {
return (0 == this->get_name().compare(portA.get_name()));
}
/* Check if a port is contained by this port:
* this function will check if the (LSB, MSB) of portA
* is contained by the (LSB, MSB) of this port
*/
bool BasicPort::contained(const BasicPort& portA) const {
return ( lsb_ <= portA.get_lsb() && portA.get_msb() <= msb_ );
}
/* Overloaded operators */
/* Two ports are the same only when:
* 1. port names are the same
* 2. LSBs are the same
* 3. MSBs are the same
*/
bool BasicPort::operator== (const BasicPort& portA) const {
if ( (0 == this->get_name().compare(portA.get_name()))
&& (this->get_lsb() == portA.get_lsb())
&& (this->get_msb() == portA.get_msb()) ) {
return true;
}
return false;
}
/* Mutators */
/* copy */
void BasicPort::set(const BasicPort& basic_port) {
name_ = basic_port.get_name();
lsb_ = basic_port.get_lsb();
msb_ = basic_port.get_msb();
return;
}
/* set the port LSB and MSB */
void BasicPort::set_name(const std::string& name) {
name_ = name;
return;
}
/* set the port LSB and MSB */
void BasicPort::set_width(const size_t& width) {
if (0 == width) {
make_invalid();
return;
}
lsb_ = 0;
msb_ = width - 1;
return;
}
/* set the port LSB and MSB */
void BasicPort::set_width(const size_t& lsb, const size_t& msb) {
/* If lsb and msb is invalid, we make a default port */
if (lsb > msb) {
make_invalid();
return;
}
set_lsb(lsb);
set_msb(msb);
return;
}
void BasicPort::set_lsb(const size_t& lsb) {
lsb_ = lsb;
return;
}
void BasicPort::set_msb(const size_t& msb) {
msb_ = msb;
return;
}
/* Increase the port width */
void BasicPort::expand(const size_t& width) {
if (0 == width) {
return; /* ignore zero-width port */
}
/* If current port is invalid, we do not combine */
if (0 == get_width()) {
lsb_ = 0;
msb_ = width;
return;
}
/* Increase MSB */
msb_ += width;
return;
}
/* Swap lsb and msb */
void BasicPort::revert() {
std::swap(lsb_, msb_);
return;
}
/* rotate: increase both lsb and msb by an offset */
bool BasicPort::rotate(const size_t& offset) {
/* If offset is 0, we do nothing */
if (0 == offset) {
return true;
}
/* If current width is 0, we set a width using the offset! */
if (0 == get_width()) {
set_width(offset);
return true;
}
/* check if leads to overflow:
* if limits - msb is larger than offset
*/
if ( (std::numeric_limits<size_t>::max() - msb_ < offset) ) {
return false;
}
/* Increase LSB and MSB */
lsb_ += offset;
msb_ += offset;
return true;
}
/* rotate: decrease both lsb and msb by an offset */
bool BasicPort::counter_rotate(const size_t& offset) {
/* If current port is invalid or offset is 0,
* we do nothing
*/
if ((0 == offset) || (0 == get_width())) {
return true;
}
/* check if leads to overflow:
* if limits is larger than offset
*/
if ( (std::numeric_limits<size_t>::min() + lsb_ < offset) ) {
return false;
}
/* decrease LSB and MSB */
lsb_ -= offset;
msb_ -= offset;
return true;
}
/* Reset to initial port */
void BasicPort::reset() {
make_invalid();
return;
}
/* Combine two ports */
void BasicPort::combine(const BasicPort& port) {
/* LSB follows the current LSB */
/* MSB increases */
VTR_ASSERT(0 < port.get_width() ); /* Make sure port is valid */
/* If current port is invalid, we do not combine */
if (0 == get_width()) {
return;
}
/* Increase MSB */
msb_ += port.get_width();
return;
}
/* A restricted combine function for two ports,
* Following conditions will be applied:
* 1. the two ports have the same name
* Note: you must run mergable() function first
* to make sure this assumption is valid
* 2. the new MSB will be the maximum MSB of the two ports
* 3. the new LSB will be the minimum LSB of the two ports
* 4. both ports should be valid!!!
*/
void BasicPort::merge(const BasicPort& portA) {
VTR_ASSERT(true == this->mergeable(portA));
VTR_ASSERT(true == this->is_valid() && true == portA.is_valid());
/* We skip merging if the portA is already contained by this port */
if (true == this->contained(portA)) {
return;
}
/* LSB follows the minium LSB of the two ports */
lsb_ = std::min((int)lsb_, (int)portA.get_lsb());
/* MSB follows the minium MSB of the two ports */
msb_ = std::max((int)msb_, (int)portA.get_msb());
return;
}
/* Internal functions */
/* Make a port to be invalid: msb < lsb */
void BasicPort::make_invalid() {
/* set a default invalid port */
lsb_ = 1;
msb_ = 0;
return;
}
/* check if port size is valid > 0 */
bool BasicPort::is_valid() const {
/* msb should be equal or greater than lsb, if this is a valid port */
if ( msb_ < lsb_ ) {
return false;
}
return true;
}
/* ConfPorts member functions */
/* Constructor */
/* Default constructor */
ConfPorts::ConfPorts() {
/* default port */
reserved_.reset();
regular_.reset();
}
/* copy */
ConfPorts::ConfPorts(const ConfPorts& conf_ports) {
set(conf_ports);
}
/* Accessors */
size_t ConfPorts::get_reserved_port_width() const {
return reserved_.get_width();
}
size_t ConfPorts::get_reserved_port_lsb() const {
return reserved_.get_lsb();
}
size_t ConfPorts::get_reserved_port_msb() const {
return reserved_.get_msb();
}
size_t ConfPorts::get_regular_port_width() const {
return regular_.get_width();
}
size_t ConfPorts::get_regular_port_lsb() const {
return regular_.get_lsb();
}
size_t ConfPorts::get_regular_port_msb() const {
return regular_.get_msb();
}
/* Mutators */
void ConfPorts::set(const ConfPorts& conf_ports) {
set_reserved_port(conf_ports.get_reserved_port_width());
set_regular_port(conf_ports.get_regular_port_lsb(), conf_ports.get_regular_port_msb());
return;
}
void ConfPorts::set_reserved_port(size_t width) {
reserved_.set_width(width);
return;
}
void ConfPorts::set_regular_port(size_t width) {
regular_.set_width(width);
return;
}
void ConfPorts::set_regular_port(size_t lsb, size_t msb) {
regular_.set_width(lsb, msb);
return;
}
void ConfPorts::set_regular_port_lsb(size_t lsb) {
regular_.set_lsb(lsb);
return;
}
void ConfPorts::set_regular_port_msb(size_t msb) {
regular_.set_msb(msb);
return;
}
/* Increase the port width of reserved port */
void ConfPorts::expand_reserved_port(size_t width) {
reserved_.expand(width);
return;
}
/* Increase the port width of regular port */
void ConfPorts::expand_regular_port(size_t width) {
regular_.expand(width);
return;
}
/* Increase the port width of both ports */
void ConfPorts::expand(size_t width) {
expand_reserved_port(width);
expand_regular_port(width);
}
/* rotate */
bool ConfPorts::rotate_regular_port(size_t offset) {
return regular_.rotate(offset);
}
/* counter rotate */
bool ConfPorts::counter_rotate_regular_port(size_t offset) {
return regular_.counter_rotate(offset);
}
/* Reset to initial port */
void ConfPorts::reset() {
reserved_.reset();
regular_.reset();
return;
}

View File

@ -0,0 +1,89 @@
/* IMPORTANT:
* The following preprocessing flags are added to
* avoid compilation error when this headers are included in more than 1 times
*/
#ifndef DEVICE_PORT_H
#define DEVICE_PORT_H
#include <string>
#include <vector>
/* A basic port */
class BasicPort {
public: /* Constructors */
BasicPort();
BasicPort(const char* name, const size_t& lsb, const size_t& msb);
BasicPort(const char* name, const size_t& width);
BasicPort(const std::string& name, const size_t& lsb, const size_t& msb);
BasicPort(const std::string& name, const size_t& width);
BasicPort(const BasicPort& basic_port); /* Copy constructor */
public: /* Overloaded operators */
bool operator== (const BasicPort& portA) const;
public: /* Accessors */
size_t get_width() const; /* get the port width */
size_t get_msb() const; /* get the LSB */
size_t get_lsb() const; /* get the LSB */
std::string get_name() const; /* get the name */
bool is_valid() const; /* check if port size is valid > 0 */
std::vector<size_t> pins() const; /* Make a range of the pin indices */
bool mergeable(const BasicPort& portA) const; /* Check if a port can be merged with this port */
bool contained(const BasicPort& portA) const; /* Check if a port is contained by this port */
public: /* Mutators */
void set(const BasicPort& basic_port); /* copy */
void set_name(const std::string& name); /* set the port LSB and MSB */
void set_width(const size_t& width); /* set the port LSB and MSB */
void set_width(const size_t& lsb, const size_t& msb); /* set the port LSB and MSB */
void set_lsb(const size_t& lsb);
void set_msb(const size_t& msb);
void expand(const size_t& width); /* Increase the port width */
void revert(); /* Swap lsb and msb */
bool rotate(const size_t& offset); /* rotate */
bool counter_rotate(const size_t& offset); /* counter rotate */
void reset(); /* Reset to initial port */
void combine(const BasicPort& port); /* Combine two ports */
void merge(const BasicPort& portA);
private: /* internal functions */
void make_invalid(); /* Make a port invalid */
private: /* Internal Data */
std::string name_; /* Name of this port */
size_t msb_; /* Most Significant Bit of this port */
size_t lsb_; /* Least Significant Bit of this port */
};
/* Configuration ports:
* 1. reserved configuration port, which is used by RRAM FPGA architecture
* 2. regular configuration port, which is used by any FPGA architecture
*/
class ConfPorts {
public: /* Constructors */
ConfPorts(); /* default port */
ConfPorts(const ConfPorts& conf_ports); /* copy */
public: /* Accessors */
size_t get_reserved_port_width() const;
size_t get_reserved_port_lsb() const;
size_t get_reserved_port_msb() const;
size_t get_regular_port_width() const;
size_t get_regular_port_lsb() const;
size_t get_regular_port_msb() const;
public: /* Mutators */
void set(const ConfPorts& conf_ports);
void set_reserved_port(size_t width);
void set_regular_port(size_t width);
void set_regular_port(size_t lsb, size_t msb);
void set_regular_port_lsb(size_t lsb);
void set_regular_port_msb(size_t msb);
void expand_reserved_port(size_t width); /* Increase the port width of reserved port */
void expand_regular_port(size_t width); /* Increase the port width of regular port */
void expand(size_t width); /* Increase the port width of both ports */
bool rotate_regular_port(size_t offset); /* rotate */
bool counter_rotate_regular_port(size_t offset); /* counter rotate */
void reset(); /* Reset to initial port */
private: /* Internal Data */
BasicPort reserved_;
BasicPort regular_;
};
/* TODO: create a class for BL and WL ports */
#endif

View File

@ -0,0 +1,22 @@
#ifndef DIRECT_TYPES_H
#define DIRECT_TYPES_H
/********************************************************************
* Define the types of point to point connection between CLBs
* These types are supplementary to the original VPR direct connections
* Here we extend to the cross-row and cross-column connections
********************************************************************/
enum e_point2point_interconnection_type {
NO_P2P,
P2P_DIRECT_COLUMN,
P2P_DIRECT_ROW,
NUM_POINT2POINT_INTERCONNECT_TYPE
};
enum e_point2point_interconnection_dir {
POSITIVE_DIR,
NEGATIVE_DIR,
NUM_POINT2POINT_INTERCONNECT_DIR
};
#endif

View File

@ -0,0 +1,331 @@
/**********************************************************
* MIT License
*
* Copyright (c) 2018 LNIS - The University of Utah
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
***********************************************************************/
/************************************************************************
* Filename: port_parser.cpp
* Created by: Xifan Tang
* Change history:
* +-------------------------------------+
* | Date | Author | Notes
* +-------------------------------------+
* | 2019/08/09 | Xifan Tang | Created
* +-------------------------------------+
***********************************************************************/
/************************************************************************
* Member functions for Port parsers
***********************************************************************/
#include "string.h"
#include "vtr_assert.h"
#include "vtr_geometry.h"
#include "string_token.h"
#include "port_parser.h"
/************************************************************************
* Member functions for PortParser class
***********************************************************************/
/************************************************************************
* Constructors
***********************************************************************/
PortParser::PortParser (const std::string& data) {
set_default_bracket();
set_default_delim();
set_data(data);
}
/************************************************************************
* Public Accessors
***********************************************************************/
/* Get the data string */
std::string PortParser::data() const {
return data_;
}
BasicPort PortParser::port() const {
return port_;
}
/************************************************************************
* Public Mutators
***********************************************************************/
void PortParser::set_data(const std::string& data) {
data_ = data;
parse();
return;
}
/************************************************************************
* Internal Mutators
***********************************************************************/
/* Parse the data */
void PortParser::parse() {
/* Create a tokenizer */
StringToken tokenizer(data_);
/* Split the data into <port_name> and <pin_string> */
std::vector<std::string> port_tokens = tokenizer.split(bracket_.x());
/* Make sure we have a port name! */
VTR_ASSERT_SAFE ((1 == port_tokens.size()) || (2 == port_tokens.size()));
/* Store the port name! */
port_.set_name(port_tokens[0]);
/* If we only have one token */
if (1 == port_tokens.size()) {
port_.set_width(0);
return; /* We can finish here */
}
/* Chomp the ']' */
tokenizer.set_data(port_tokens[1]);
std::vector<std::string> pin_tokens = tokenizer.split(bracket_.y());
/* Make sure we have a valid string! */
VTR_ASSERT_SAFE (1 == port_tokens.size());
/* Split the pin string now */
tokenizer.set_data(port_tokens[0]);
pin_tokens = tokenizer.split(delim_);
/* Check if we have LSB and MSB or just one */
if ( 1 == pin_tokens.size() ) {
/* Single pin */
port_.set_width(stoi(pin_tokens[0]), stoi(pin_tokens[0]));
} else if ( 2 == pin_tokens.size() ) {
/* A number of pin */
port_.set_width(stoi(pin_tokens[0]), stoi(pin_tokens[1]));
}
/* Re-order to ensure LSB <= MSB */
if (false == port_.is_valid()) {
port_.revert();
}
return;
}
void PortParser::set_default_bracket() {
bracket_.set_x('[');
bracket_.set_y(']');
return;
}
void PortParser::set_default_delim() {
delim_ = ':';
return;
}
/************************************************************************
* Member functions for MultiPortParser class
***********************************************************************/
/************************************************************************
* Constructors
***********************************************************************/
MultiPortParser::MultiPortParser (const std::string& data) {
set_default_delim();
set_data(data);
}
/************************************************************************
* Public Accessors
***********************************************************************/
/* Get the data string */
std::string MultiPortParser::data() const {
return data_;
}
std::vector<BasicPort> MultiPortParser::ports() const {
return ports_;
}
/************************************************************************
* Public Mutators
***********************************************************************/
void MultiPortParser::set_data(const std::string& data) {
data_ = data;
parse();
return;
}
/************************************************************************
* Internal Mutators
***********************************************************************/
/* Split the data line into fragments and parse one by one */
void MultiPortParser::parse() {
/* Clear content */
clear();
/* Create a tokenizer */
StringToken tokenizer(data_);
/* Split the data into <port_name> and <pin_string> */
std::vector<std::string> port_tokens = tokenizer.split(delim_);
/* Use PortParser for each token */
for (const auto& port : port_tokens) {
PortParser port_parser(port);
/* Get the port name, LSB and MSB */
ports_.push_back(port_parser.port());
}
return;
}
void MultiPortParser::set_default_delim() {
delim_ = ' ';
return;
}
void MultiPortParser::clear() {
ports_.clear();
return;
}
/************************************************************************
* Member functions for PortDelayParser class
***********************************************************************/
/************************************************************************
* Constructors
***********************************************************************/
PortDelayParser::PortDelayParser (const std::string& data) {
set_default_element_delim();
set_default_line_delim();
set_data(data);
}
/************************************************************************
* Public Accessors
***********************************************************************/
/* Get the data string */
std::string PortDelayParser::data() const {
return data_;
}
/* Get the size of delay matrix [height, width]*/
size_t PortDelayParser::height() const {
return delay_matrix_.dim_size(0);
}
size_t PortDelayParser::width() const {
return delay_matrix_.dim_size(1);
}
vtr::Point<size_t> PortDelayParser::delay_size() const {
vtr::Point<size_t> matrix_size(height(), width());
return matrix_size;
}
float PortDelayParser::delay(size_t x, size_t y) const {
/* Make sure x and y are in range */
VTR_ASSERT_SAFE( (x < width()) && (y < height()) );
return delay_matrix_[x][y];
}
/************************************************************************
* Public Mutators
***********************************************************************/
void PortDelayParser::set_data(const std::string& data) {
data_ = data;
parse();
return;
}
/************************************************************************
* Internal Mutators
***********************************************************************/
/* Split the data line into fragments and parse one by one */
void PortDelayParser::parse() {
/* Clear content */
clear();
/* Create a tokenizer */
StringToken delay_tokenizer(data_);
/* Ensure a clean start! Trim whitespace at the beginning and end of the string */
delay_tokenizer.trim();
/* Split the data into different lines */
std::vector<std::string> delay_lines = delay_tokenizer.split(line_delim_);
/* The number of lines is actually the height of delay matrix */
size_t matrix_height = delay_lines.size();
size_t matrix_width = 0;
/* Visit each line and split with element_delim */
for (const auto& line : delay_lines) {
/* Create a tokenizer for each line */
StringToken line_tokenizer(line);
std::vector<std::string> delay_elements = line_tokenizer.split(element_delim_);
/* Get maximum number of length, which is the width of delay matrix */
matrix_width = std::max(matrix_width, delay_elements.size());
}
/* Resize matrix */
delay_matrix_.resize({matrix_height, matrix_width});
/* Fill matrix */
for (const auto& line : delay_lines) {
/* Create a tokenizer for each line */
StringToken line_tokenizer(line);
std::vector<std::string> delay_elements = line_tokenizer.split(element_delim_);
/* Get maximum number of length, which is the width of delay matrix */
for (const auto& element : delay_elements) {
delay_matrix_[size_t(&line - &delay_lines[0])][size_t(&element - &delay_elements[0])] = stof(element);
}
}
return;
}
void PortDelayParser::set_default_element_delim() {
/* Ensure a clean start */
element_delim_.clear();
element_delim_.push_back(' ');
element_delim_.push_back('\t');
return;
}
void PortDelayParser::set_default_line_delim() {
/* Ensure a clean start */
line_delim_.clear();
line_delim_.push_back('\n');
line_delim_.push_back('\r');
return;
}
void PortDelayParser::clear() {
delay_matrix_.clear();
return;
}
/************************************************************************
* End of file : port_parser.cpp
***********************************************************************/

View File

@ -0,0 +1,112 @@
/* IMPORTANT:
* The following preprocessing flags are added to
* avoid compilation error when this headers are included in more than 1 times
*/
#ifndef PORT_PARSER_H
#define PORT_PARSER_H
/*
* Notes in include header files in a head file
* Only include the neccessary header files
* that is required by the data types in the function/class declarations!
*/
/* Header files should be included in a sequence */
/* Standard header files required go first */
#include <string>
#include <vector>
#include "vtr_ndmatrix.h"
#include "vtr_geometry.h"
#include "device_port.h"
#include "string_token.h"
/************************************************************************
* This file includes parsers for port definition in the architecture XML
* language. Note that it is also compatiable to Verilog syntax.
* It means we may reuse this for constructing a structural Verilog parser
***********************************************************************/
/************************************************************************
* Class PortParser: single port parser
* Supported port definition:
* 1. <port_name>[<LSB>:<MSB>]
* 2. <port_name>[<MSB>:<LSB>]
* 3. <port_name>[<single_pin_index>]
* 4. <port_name>[]
* 5. <port_name>
* In case 4 and 5, we will assign (-1,-1) for LSB and MSB
***********************************************************************/
class PortParser{
public : /* Constructors*/
PortParser (const std::string& data);
public : /* Public Accessors */
std::string data() const;
BasicPort port() const;
public : /* Public Mutators */
void set_data(const std::string& data);
private : /* Private Mutators */
void parse();
void set_default_bracket();
void set_default_delim();
private: /* Internal data */
std::string data_; /* Lines to be splited */
vtr::Point<char> bracket_;
char delim_;
BasicPort port_;
};
/************************************************************************
* MultiPortParser: a parser for multiple ports in one line
***********************************************************************/
class MultiPortParser {
public : /* Constructors*/
MultiPortParser (const std::string& data);
public : /* Public Accessors */
std::string data() const;
std::vector<BasicPort> ports() const;
public : /* Public Mutators */
void set_data(const std::string& data);
private : /* Private Mutators */
void parse();
void set_default_delim();
void clear();
private: /* Internal data */
std::string data_; /* Lines to be splited */
char delim_;
std::vector<BasicPort> ports_;
};
/************************************************************************
* PortDelayParser: a parser for 2D delay matrix
***********************************************************************/
class PortDelayParser {
public : /* Constructors*/
PortDelayParser (const std::string& data);
public : /* Public Accessors */
std::string data() const;
size_t height() const;
size_t width() const;
vtr::Point<size_t> delay_size() const;
float delay(size_t x, size_t y) const;
public : /* Public Mutators */
void set_data(const std::string& data);
private : /* Private Mutators */
void parse();
void set_default_element_delim();
void set_default_line_delim();
void clear();
private: /* Internal data */
std::string data_; /* Lines to be splited */
std::vector<char> element_delim_;
std::vector<char> line_delim_;
vtr::Matrix<float> delay_matrix_;
};
#endif
/************************************************************************
* End of file : port_parser.h
***********************************************************************/

View File

@ -0,0 +1,9 @@
#ifndef SIMULATION_SETTING_H
#define SIMULATION_SETTING_H
enum e_sim_accuracy_type {
SIM_ACCURACY_FRAC,
SIM_ACCURACY_ABS
};
#endif

View File

@ -0,0 +1,174 @@
/**********************************************************
* MIT License
*
* Copyright (c) 2018 LNIS - The University of Utah
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
***********************************************************************/
/************************************************************************
* Filename: string_token.cpp
* Created by: Xifan Tang
* Change history:
* +-------------------------------------+
* | Date | Author | Notes
* +-------------------------------------+
* | 2019/08/09 | Xifan Tang | Created
* +-------------------------------------+
***********************************************************************/
/************************************************************************
* Member functions for StringToken class
***********************************************************************/
#include "string.h"
#include "vtr_assert.h"
#include "string_token.h"
/************************************************************************
* Constructors
***********************************************************************/
StringToken::StringToken (const std::string& data) {
set_data(data);
}
/************************************************************************
* Public Accessors
***********************************************************************/
/* Get the data string */
std::string StringToken::data() const {
return data_;
}
/* Split the string using a given delim */
std::vector<std::string> StringToken::split(const std::string& delims) const {
/* Return vector */
std::vector<std::string> ret;
/* Get a writable char array */
char* tmp = new char[data_.size() + 1];
std::copy(data_.begin(), data_.end(), tmp);
tmp[data_.size()] = '\0';
/* Split using strtok */
char* result = strtok(tmp, delims.c_str());
while (NULL != result) {
std::string result_str(result);
/* Store the token */
ret.push_back(result_str);
/* Got to next */
result = strtok(NULL, delims.c_str());
}
/* Free the tmp */
delete[] tmp;
return ret;
}
/* Split the string using a given delim */
std::vector<std::string> StringToken::split(const char& delim) const {
/* Create delims */
std::string delims(1, delim);
return split(delims);
}
/* Split the string using a given delim */
std::vector<std::string> StringToken::split(const char* delim) const {
/* Create delims */
std::string delims(delim);
return split(delims);
}
/* Split the string using a given delim */
std::vector<std::string> StringToken::split(const std::vector<char>& delims) const {
/* Create delims */
std::string delims_str;
for (const auto& delim : delims) {
delims_str.push_back(delim);
}
return split(delims_str);
}
/* Split the string */
std::vector<std::string> StringToken::split() {
/* Add a default delim */
if (true == delims_.empty()) {
add_default_delim();
}
/* Create delims */
std::string delims;
for (const auto& delim : delims_) {
delims.push_back(delim);
}
return split(delims);
}
/************************************************************************
* Public Mutators
***********************************************************************/
void StringToken::set_data(const std::string& data) {
data_ = data;
return;
}
/* Add a delima to the list */
void StringToken::add_delim(const char& delim) {
delims_.push_back(delim);
}
/* Remove the string repeated at the beginning of string */
void StringToken::ltrim(const std::string& sensitive_word) {
size_t start = data_.find_first_not_of(sensitive_word);
data_ = (start == std::string::npos) ? "" : data_.substr(start);
return;
}
/* Remove the string repeated at the end of string */
void StringToken::rtrim(const std::string& sensitive_word) {
size_t end = data_.find_last_not_of(sensitive_word);
data_ = (end == std::string::npos) ? "" : data_.substr(0, end + 1);
return;
}
void StringToken::trim() {
rtrim(" ");
ltrim(" ");
return;
}
/************************************************************************
* Internal Mutators
***********************************************************************/
void StringToken::add_default_delim() {
VTR_ASSERT_SAFE(true == delims_.empty());
delims_.push_back(' ');
return;
}
/************************************************************************
* End of file : string_token.cpp
***********************************************************************/

View File

@ -0,0 +1,88 @@
/**********************************************************
* MIT License
*
* Copyright (c) 2018 LNIS - The University of Utah
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
***********************************************************************/
/************************************************************************
* Filename: string_token.h
* Created by: Xifan Tang
* Change history:
* +-------------------------------------+
* | Date | Author | Notes
* +-------------------------------------+
* | 2019/08/09 | Xifan Tang | Created
* +-------------------------------------+
***********************************************************************/
/* IMPORTANT:
* The following preprocessing flags are added to
* avoid compilation error when this headers are included in more than 1 times
*/
#ifndef STRING_TOKEN_H
#define STRING_TOKEN_H
/*
* Notes in include header files in a head file
* Only include the neccessary header files
* that is required by the data types in the function/class declarations!
*/
/* Header files should be included in a sequence */
/* Standard header files required go first */
#include <string>
#include <vector>
/************************************************************************
* This file includes a tokenizer for string objects
* It splits a string with given delima and return a vector of tokens
* It can accept different delima in splitting strings
***********************************************************************/
class StringToken {
public : /* Constructors*/
StringToken (const std::string& data);
public : /* Public Accessors */
std::string data() const;
std::vector<std::string> split(const std::string& delims) const;
std::vector<std::string> split(const char& delim) const;
std::vector<std::string> split(const char* delim) const;
std::vector<std::string> split(const std::vector<char>& delim) const;
std::vector<std::string> split();
public : /* Public Mutators */
void set_data(const std::string& data);
void add_delim(const char& delim);
void ltrim(const std::string& sensitive_word);
void rtrim(const std::string& sensitive_word);
void trim();
private : /* Private Mutators */
void add_default_delim();
private: /* Internal data */
std::string data_; /* Lines to be splited */
std::vector<char> delims_;
};
#endif
/************************************************************************
* End of file : string_token.h
***********************************************************************/

View File

@ -0,0 +1,48 @@
#ifndef TECHNOLOGY_LIBRARY_H
#define TECHNOLOGY_LIBRARY_H
/********************************************************************
* This file include the declaration of technology library
*******************************************************************/
/********************************************************************
* Types for technology library attributes
* Industrial library: the .lib file which define technology
* This is ubiquitous in commercial vendors
* For industry library, we allow users to define
* process corners.
* Academia library: the .pm file which define technology
* This is mainly used in PTM-like technology library
* PTM is the Predictive Technology Model provided by the Arizona
* State University (ASU). Available at ptm.asu.edu
*******************************************************************/
enum e_tech_lib_type {
TECH_LIB_INDUSTRY,
TECH_LIB_ACADEMIA
};
/********************************************************************
* Types of transistors which may be defined in a technology library
* We categorize the transistors in terms of their usage in FPGA architecture
* 1. NMOS transistor used in datapath logic
* 2. PMOS transistor used in datapath logic
* 3. NMOS transistor used in the I/O blocks
* 3. PMOS transistor used in the I/O blocks
*******************************************************************/
enum e_tech_lib_trans_type {
TECH_LIB_TRANS_NMOS,
TECH_LIB_TRANS_PMOS,
TECH_LIB_TRANS_IO_NMOS,
TECH_LIB_TRANS_IO_PMOS
};
/********************************************************************
* Process corners supported
*******************************************************************/
enum e_process_corner {
BEST_CORNER,
TYPICAL_CORNER,
WORST_CORNER
};
#endif

View File

@ -0,0 +1,20 @@
/********************************************************************
* Unit test functions to validate the correctness of
* 1. parser of data structures
* 2. writer of data structures
*******************************************************************/
#include "circuit_library.h"
#include "check_circuit_library.h"
#include "technology_library.h"
#include "simulation_setting.h"
#include "direct_types.h"
int main(int argc, const char** argv) {
/* Parse the circuit library from an XML file */
/* Check the circuit library */
/* Output the circuit library to an XML file*/
}

View File

@ -1,9 +1,6 @@
#Externally developed libraries
add_subdirectory(EXTERNAL)
# OpenFPGA-related libraries
add_subdirectory(libini)
# VTR developed libraries
# Only add warn flags for VPR internal libraries.
#add_compile_options(${WARN_FLAGS})