2020-02-12 18:53:23 -06:00
|
|
|
/********************************************************************
|
|
|
|
* This function includes the module builders for essential logic gates
|
|
|
|
* which are the leaf circuit model in the circuit library
|
|
|
|
*******************************************************************/
|
|
|
|
|
|
|
|
/* Headers from vtrutil library */
|
2022-10-06 19:08:50 -05:00
|
|
|
#include "build_essential_modules.h"
|
|
|
|
|
|
|
|
#include "module_manager_utils.h"
|
|
|
|
#include "openfpga_naming.h"
|
2020-02-12 18:53:23 -06:00
|
|
|
#include "vtr_assert.h"
|
|
|
|
#include "vtr_log.h"
|
|
|
|
#include "vtr_time.h"
|
|
|
|
|
|
|
|
/* begin namespace openfpga */
|
|
|
|
namespace openfpga {
|
|
|
|
|
|
|
|
/************************************************
|
2022-10-06 19:08:50 -05:00
|
|
|
* Build a module of inverter or buffer
|
|
|
|
* or tapered buffer to a file
|
2020-02-12 18:53:23 -06:00
|
|
|
***********************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
static void build_invbuf_module(ModuleManager& module_manager,
|
|
|
|
const CircuitLibrary& circuit_lib,
|
|
|
|
const CircuitModelId& circuit_model) {
|
2020-02-12 18:53:23 -06:00
|
|
|
/* Find the input port, output port and global inputs*/
|
2022-10-06 19:08:50 -05:00
|
|
|
std::vector<CircuitPortId> input_ports = circuit_lib.model_ports_by_type(
|
|
|
|
circuit_model, CIRCUIT_MODEL_PORT_INPUT, true);
|
|
|
|
std::vector<CircuitPortId> output_ports = circuit_lib.model_ports_by_type(
|
|
|
|
circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true);
|
|
|
|
std::vector<CircuitPortId> global_ports =
|
|
|
|
circuit_lib.model_global_ports_by_type(
|
|
|
|
circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true);
|
2020-02-12 18:53:23 -06:00
|
|
|
|
|
|
|
/* Make sure:
|
2022-10-06 19:08:50 -05:00
|
|
|
* There is only 1 input port and 1 output port,
|
2020-02-12 18:53:23 -06:00
|
|
|
* each size of which is 1
|
|
|
|
*/
|
2022-10-06 19:08:50 -05:00
|
|
|
VTR_ASSERT((1 == input_ports.size()) &&
|
|
|
|
(1 == circuit_lib.port_size(input_ports[0])));
|
|
|
|
VTR_ASSERT((1 == output_ports.size()) &&
|
|
|
|
(1 == circuit_lib.port_size(output_ports[0])));
|
2020-02-12 18:53:23 -06:00
|
|
|
|
|
|
|
/* TODO: move the check codes to check_circuit_library.h */
|
2022-10-06 19:08:50 -05:00
|
|
|
/* If the circuit model is power-gated, we need to find at least one global
|
|
|
|
* config_enable signals */
|
|
|
|
if (true == circuit_lib.is_power_gated(circuit_model)) {
|
2020-02-12 18:53:23 -06:00
|
|
|
/* Check all the ports we have are good for a power-gated circuit model */
|
|
|
|
size_t num_err = 0;
|
|
|
|
/* We need at least one global port */
|
2022-10-06 19:08:50 -05:00
|
|
|
if (0 == global_ports.size()) {
|
2020-02-12 18:53:23 -06:00
|
|
|
num_err++;
|
|
|
|
}
|
|
|
|
/* All the global ports should be config_enable */
|
|
|
|
for (const auto& port : global_ports) {
|
|
|
|
if (false == circuit_lib.port_is_config_enable(port)) {
|
|
|
|
num_err++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Report errors if there are any */
|
|
|
|
if (0 < num_err) {
|
2022-10-06 19:08:50 -05:00
|
|
|
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
|
|
|
"Inverter/buffer circuit model '%s' is power-gated. At "
|
|
|
|
"least one config-enable global port is required!\n",
|
|
|
|
circuit_lib.model_name(circuit_model).c_str());
|
2020-02-12 18:53:23 -06:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Create a Verilog Module based on the circuit model, and add to module
|
|
|
|
* manager */
|
|
|
|
ModuleId module_id = add_circuit_model_to_module_manager(
|
|
|
|
module_manager, circuit_lib, circuit_model);
|
2020-02-12 18:53:23 -06:00
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(module_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************
|
|
|
|
* Build a module of a pass-gate,
|
|
|
|
* either transmission-gate or pass-transistor
|
|
|
|
***********************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
static void build_passgate_module(ModuleManager& module_manager,
|
|
|
|
const CircuitLibrary& circuit_lib,
|
|
|
|
const CircuitModelId& circuit_model) {
|
2020-02-12 18:53:23 -06:00
|
|
|
/* Find the input port, output port*/
|
2022-10-06 19:08:50 -05:00
|
|
|
std::vector<CircuitPortId> input_ports = circuit_lib.model_ports_by_type(
|
|
|
|
circuit_model, CIRCUIT_MODEL_PORT_INPUT, true);
|
|
|
|
std::vector<CircuitPortId> output_ports = circuit_lib.model_ports_by_type(
|
|
|
|
circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true);
|
|
|
|
std::vector<CircuitPortId> global_ports =
|
|
|
|
circuit_lib.model_global_ports_by_type(
|
|
|
|
circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true);
|
2020-02-12 18:53:23 -06:00
|
|
|
|
|
|
|
switch (circuit_lib.pass_gate_logic_type(circuit_model)) {
|
2022-10-06 19:08:50 -05:00
|
|
|
case CIRCUIT_MODEL_PASS_GATE_TRANSMISSION:
|
|
|
|
/* Make sure:
|
|
|
|
* There is only 3 input port (in, sel, selb),
|
|
|
|
* each size of which is 1
|
|
|
|
*/
|
|
|
|
VTR_ASSERT(3 == input_ports.size());
|
|
|
|
for (const auto& input_port : input_ports) {
|
|
|
|
VTR_ASSERT(1 == circuit_lib.port_size(input_port));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CIRCUIT_MODEL_PASS_GATE_TRANSISTOR:
|
|
|
|
/* Make sure:
|
|
|
|
* There is only 2 input port (in, sel),
|
|
|
|
* each size of which is 1
|
|
|
|
*/
|
|
|
|
VTR_ASSERT(2 == input_ports.size());
|
|
|
|
for (const auto& input_port : input_ports) {
|
|
|
|
VTR_ASSERT(1 == circuit_lib.port_size(input_port));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
|
|
|
"Invalid topology for circuit model '%s'!\n",
|
|
|
|
circuit_lib.model_name(circuit_model).c_str());
|
|
|
|
exit(1);
|
2020-02-12 18:53:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure:
|
2022-10-06 19:08:50 -05:00
|
|
|
* There is only 1 output port,
|
2020-02-12 18:53:23 -06:00
|
|
|
* each size of which is 1
|
|
|
|
*/
|
2022-10-06 19:08:50 -05:00
|
|
|
VTR_ASSERT((1 == output_ports.size()) &&
|
|
|
|
(1 == circuit_lib.port_size(output_ports[0])));
|
2020-02-12 18:53:23 -06:00
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Create a Verilog Module based on the circuit model, and add to module
|
|
|
|
* manager */
|
|
|
|
ModuleId module_id = add_circuit_model_to_module_manager(
|
|
|
|
module_manager, circuit_lib, circuit_model);
|
2020-02-12 18:53:23 -06:00
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(module_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************
|
|
|
|
* Build a module of a logic gate
|
|
|
|
* which are standard cells
|
2022-10-06 19:08:50 -05:00
|
|
|
* Supported gate types:
|
|
|
|
* 1. N-input AND
|
2020-02-12 18:53:23 -06:00
|
|
|
* 2. N-input OR
|
|
|
|
* 3. 2-input MUX
|
|
|
|
***********************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
static void build_gate_module(ModuleManager& module_manager,
|
|
|
|
const CircuitLibrary& circuit_lib,
|
|
|
|
const CircuitModelId& circuit_model) {
|
2020-02-12 18:53:23 -06:00
|
|
|
/* Find the input port, output port*/
|
2022-10-06 19:08:50 -05:00
|
|
|
std::vector<CircuitPortId> input_ports = circuit_lib.model_ports_by_type(
|
|
|
|
circuit_model, CIRCUIT_MODEL_PORT_INPUT, true);
|
|
|
|
std::vector<CircuitPortId> output_ports = circuit_lib.model_ports_by_type(
|
|
|
|
circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true);
|
|
|
|
std::vector<CircuitPortId> global_ports =
|
|
|
|
circuit_lib.model_global_ports_by_type(
|
|
|
|
circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true);
|
2020-02-12 18:53:23 -06:00
|
|
|
|
|
|
|
/* Make sure:
|
2022-10-06 19:08:50 -05:00
|
|
|
* There is only 1 output port,
|
2020-02-12 18:53:23 -06:00
|
|
|
* each size of which is 1
|
|
|
|
*/
|
2022-10-06 19:08:50 -05:00
|
|
|
VTR_ASSERT((1 == output_ports.size()) &&
|
|
|
|
(1 == circuit_lib.port_size(output_ports[0])));
|
2020-02-12 18:53:23 -06:00
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Create a Verilog Module based on the circuit model, and add to module
|
|
|
|
* manager */
|
|
|
|
ModuleId module_id = add_circuit_model_to_module_manager(
|
|
|
|
module_manager, circuit_lib, circuit_model);
|
2020-02-12 18:53:23 -06:00
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(module_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************
|
|
|
|
* Generate the modules for essential gates
|
|
|
|
* include inverters, buffers, transmission-gates,
|
|
|
|
* etc.
|
|
|
|
***********************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
void build_essential_modules(ModuleManager& module_manager,
|
2020-02-12 18:53:23 -06:00
|
|
|
const CircuitLibrary& circuit_lib) {
|
2022-10-06 19:08:50 -05:00
|
|
|
vtr::ScopedStartFinishTimer timer(
|
|
|
|
"Build essential (inverter/buffer/logic gate) modules");
|
2020-02-12 18:53:23 -06:00
|
|
|
|
|
|
|
for (const auto& circuit_model : circuit_lib.models()) {
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Add essential modules upon on demand: only when it is not yet in the
|
|
|
|
* module library */
|
|
|
|
ModuleId module =
|
|
|
|
module_manager.find_module(circuit_lib.model_name(circuit_model));
|
2020-02-12 18:53:23 -06:00
|
|
|
if (true == module_manager.valid_module_id(module)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CIRCUIT_MODEL_INVBUF == circuit_lib.model_type(circuit_model)) {
|
|
|
|
build_invbuf_module(module_manager, circuit_lib, circuit_model);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (CIRCUIT_MODEL_PASSGATE == circuit_lib.model_type(circuit_model)) {
|
|
|
|
build_passgate_module(module_manager, circuit_lib, circuit_model);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (CIRCUIT_MODEL_GATE == circuit_lib.model_type(circuit_model)) {
|
|
|
|
build_gate_module(module_manager, circuit_lib, circuit_model);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
* Register all the user-defined modules in the module manager
|
|
|
|
* Walk through the circuit library and add user-defined circuit models
|
|
|
|
* to the module_manager
|
|
|
|
********************************************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
void build_user_defined_modules(ModuleManager& module_manager,
|
2020-02-12 18:53:23 -06:00
|
|
|
const CircuitLibrary& circuit_lib) {
|
|
|
|
vtr::ScopedStartFinishTimer timer("Build user-defined modules");
|
|
|
|
|
|
|
|
/* Iterate over Verilog modules */
|
|
|
|
for (const auto& model : circuit_lib.models()) {
|
|
|
|
/* We only care about user-defined models */
|
2022-10-06 19:08:50 -05:00
|
|
|
if ((true == circuit_lib.model_verilog_netlist(model).empty()) &&
|
|
|
|
(true == circuit_lib.model_spice_netlist(model).empty())) {
|
2020-02-12 18:53:23 -06:00
|
|
|
continue;
|
|
|
|
}
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Skip Routing channel wire models because they need a different name. Do
|
|
|
|
* it later */
|
2020-02-12 18:53:23 -06:00
|
|
|
if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Reach here, the model requires a user-defined Verilog netlist,
|
|
|
|
* Register it in the module_manager
|
2020-02-12 18:53:23 -06:00
|
|
|
*/
|
|
|
|
add_circuit_model_to_module_manager(module_manager, circuit_lib, model);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************
|
2022-10-06 19:08:50 -05:00
|
|
|
* This function will build a constant generator modules
|
2020-02-12 18:53:23 -06:00
|
|
|
* and add it to the module manager
|
|
|
|
* It could be either
|
|
|
|
* 1. VDD or 2. GND
|
|
|
|
* Each module will have only one output port
|
|
|
|
********************************************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
static void build_constant_generator_module(ModuleManager& module_manager,
|
|
|
|
const size_t& const_value) {
|
|
|
|
ModuleId const_module =
|
|
|
|
module_manager.add_module(generate_const_value_module_name(const_value));
|
2020-02-12 18:53:23 -06:00
|
|
|
/* Add one output port */
|
2022-10-06 19:08:50 -05:00
|
|
|
BasicPort const_output_port(
|
|
|
|
generate_const_value_module_output_port_name(const_value), 1);
|
|
|
|
module_manager.add_port(const_module, const_output_port,
|
|
|
|
ModuleManager::MODULE_OUTPUT_PORT);
|
2020-07-04 23:33:54 -05:00
|
|
|
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Specify the usage of this module
|
2020-07-04 23:33:54 -05:00
|
|
|
* 1: VDD
|
|
|
|
* 0: GND
|
|
|
|
*/
|
|
|
|
if (1 == const_value) {
|
|
|
|
module_manager.set_module_usage(const_module, ModuleManager::MODULE_VDD);
|
|
|
|
} else {
|
|
|
|
VTR_ASSERT(0 == const_value);
|
|
|
|
module_manager.set_module_usage(const_module, ModuleManager::MODULE_VSS);
|
|
|
|
}
|
2020-02-12 18:53:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************
|
2022-10-06 19:08:50 -05:00
|
|
|
* This function will add two constant generator modules
|
2020-02-12 18:53:23 -06:00
|
|
|
* to the module manager
|
|
|
|
* 1. VDD
|
|
|
|
* 2. GND
|
|
|
|
********************************************************************/
|
|
|
|
void build_constant_generator_modules(ModuleManager& module_manager) {
|
|
|
|
vtr::ScopedStartFinishTimer timer("Build constant generator modules");
|
|
|
|
|
|
|
|
/* VDD */
|
|
|
|
build_constant_generator_module(module_manager, 1);
|
|
|
|
|
|
|
|
/* GND */
|
|
|
|
build_constant_generator_module(module_manager, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************
|
2022-10-06 19:08:50 -05:00
|
|
|
* This function will rename the ports of primitive modules
|
2020-02-12 18:53:23 -06:00
|
|
|
* using lib_name instead of prefix
|
2022-10-06 19:08:50 -05:00
|
|
|
* Primitive modules are defined as those modules in the module manager
|
2020-02-12 18:53:23 -06:00
|
|
|
* which have user defined netlists
|
|
|
|
********************************************************************/
|
2022-10-06 19:08:50 -05:00
|
|
|
void rename_primitive_module_port_names(ModuleManager& module_manager,
|
2020-02-12 18:53:23 -06:00
|
|
|
const CircuitLibrary& circuit_lib) {
|
|
|
|
for (const CircuitModelId& model : circuit_lib.models()) {
|
|
|
|
/* We only care about user-defined models */
|
2022-10-06 19:08:50 -05:00
|
|
|
if ((true == circuit_lib.model_verilog_netlist(model).empty()) &&
|
|
|
|
(true == circuit_lib.model_spice_netlist(model).empty())) {
|
2020-09-25 15:54:51 -05:00
|
|
|
/* Exception circuit models as primitive cells
|
|
|
|
* - Inverter, buffer, pass-gate logic, logic gate
|
|
|
|
* which should be renamed even when auto-generated
|
|
|
|
*/
|
2022-10-06 19:08:50 -05:00
|
|
|
if ((CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) &&
|
|
|
|
(CIRCUIT_MODEL_PASSGATE != circuit_lib.model_type(model)) &&
|
|
|
|
(CIRCUIT_MODEL_GATE != circuit_lib.model_type(model))) {
|
2020-09-25 15:54:51 -05:00
|
|
|
continue;
|
|
|
|
}
|
2020-02-12 18:53:23 -06:00
|
|
|
}
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Skip Routing channel wire models because they need a different name. Do
|
|
|
|
* it later */
|
2020-02-12 18:53:23 -06:00
|
|
|
if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Find the module in module manager */
|
|
|
|
ModuleId module = module_manager.find_module(circuit_lib.model_name(model));
|
|
|
|
/* We must find one! */
|
|
|
|
VTR_ASSERT(true == module_manager.valid_module_id(module));
|
|
|
|
|
|
|
|
/* Rename all the ports to use lib_name! */
|
|
|
|
for (const CircuitPortId& model_port : circuit_lib.model_ports(model)) {
|
2022-10-06 19:08:50 -05:00
|
|
|
/* Find the module port in module manager. We used prefix when creating
|
|
|
|
* the ports */
|
|
|
|
ModulePortId module_port = module_manager.find_module_port(
|
|
|
|
module, circuit_lib.port_prefix(model_port));
|
2020-02-12 18:53:23 -06:00
|
|
|
/* We must find one! */
|
2022-10-06 19:08:50 -05:00
|
|
|
VTR_ASSERT(true ==
|
|
|
|
module_manager.valid_module_port_id(module, module_port));
|
2020-02-12 18:53:23 -06:00
|
|
|
/* Name it with lib_name */
|
2022-10-06 19:08:50 -05:00
|
|
|
module_manager.set_module_port_name(
|
|
|
|
module, module_port, circuit_lib.port_lib_name(model_port));
|
2020-02-12 18:53:23 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* end namespace openfpga */
|