add lut module generation and simplify Verilog generation codes
This commit is contained in:
parent
f002f7e30f
commit
81093f0db6
|
@ -0,0 +1,402 @@
|
|||
/********************************************************************
|
||||
* This file include functions that create modules for
|
||||
* the Look-Up Tables (LUTs)
|
||||
********************************************************************/
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "util.h"
|
||||
#include "spice_types.h"
|
||||
|
||||
#include "fpga_x2p_naming.h"
|
||||
#include "circuit_library_utils.h"
|
||||
#include "module_manager.h"
|
||||
#include "module_manager_utils.h"
|
||||
|
||||
#include "build_module_graph_utils.h"
|
||||
#include "build_lut_modules.h"
|
||||
|
||||
/********************************************************************
|
||||
* Build a module for a LUT circuit model
|
||||
* This function supports both single-output and fracturable LUTs
|
||||
* The module will be organized in a connected graph of the following instances:
|
||||
* 1. Multiplexer used inside LUT
|
||||
* 2. Input buffers
|
||||
* 3. Input inverters
|
||||
* 4. Output buffers.
|
||||
* 6. AND/OR gates to tri-state LUT inputs
|
||||
********************************************************************/
|
||||
static
|
||||
void build_lut_module(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& lut_model) {
|
||||
/* Get the global ports required by LUT
|
||||
* Note that this function will only add global ports from LUT circuit model definition itself
|
||||
* We should NOT go recursively here.
|
||||
* The global ports of sub module will be handled by another function !!!
|
||||
* add_module_global_ports_from_child_modules(module_manager, lut_module);
|
||||
*/
|
||||
std::vector<CircuitPortId> lut_global_ports = circuit_lib.model_global_ports_by_type(lut_model, SPICE_MODEL_PORT_INPUT, false, true);
|
||||
/* Get the input ports from the mux */
|
||||
std::vector<CircuitPortId> lut_input_ports = circuit_lib.model_ports_by_type(lut_model, SPICE_MODEL_PORT_INPUT, true);
|
||||
/* Get the output ports from the mux */
|
||||
std::vector<CircuitPortId> lut_output_ports = circuit_lib.model_ports_by_type(lut_model, SPICE_MODEL_PORT_OUTPUT, true);
|
||||
|
||||
/* Classify SRAM ports into two categories: regular (not for mode select) and mode-select */
|
||||
std::vector<CircuitPortId> lut_regular_sram_ports = find_circuit_regular_sram_ports(circuit_lib, lut_model);
|
||||
std::vector<CircuitPortId> lut_mode_select_sram_ports = find_circuit_mode_select_sram_ports(circuit_lib, lut_model);
|
||||
|
||||
/***********************************************
|
||||
* Model Port Sanity Check
|
||||
***********************************************/
|
||||
/* Make sure that the number of ports and sizes of ports are what we want */
|
||||
if (false == circuit_lib.is_lut_fracturable(lut_model)) {
|
||||
/* Single-output LUTs:
|
||||
* We should have only 1 input port, 1 output port and 1 SRAM port
|
||||
*/
|
||||
VTR_ASSERT (1 == lut_input_ports.size());
|
||||
VTR_ASSERT (1 == lut_output_ports.size());
|
||||
VTR_ASSERT (1 == lut_regular_sram_ports.size());
|
||||
VTR_ASSERT (0 == lut_mode_select_sram_ports.size());
|
||||
} else {
|
||||
VTR_ASSERT (true == circuit_lib.is_lut_fracturable(lut_model));
|
||||
/* Fracturable LUT:
|
||||
* We should have only 1 input port, a few output ports (fracturable outputs)
|
||||
* and two SRAM ports
|
||||
*/
|
||||
VTR_ASSERT (1 == lut_input_ports.size());
|
||||
VTR_ASSERT (1 <= lut_output_ports.size());
|
||||
VTR_ASSERT (1 == lut_regular_sram_ports.size());
|
||||
VTR_ASSERT (1 == lut_mode_select_sram_ports.size());
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Module Port addition
|
||||
***********************************************/
|
||||
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||
ModuleId lut_module = module_manager.add_module(circuit_lib.model_name(lut_model));
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(lut_module));
|
||||
/* Add module ports */
|
||||
/* Add each global port */
|
||||
for (const auto& port : lut_global_ports) {
|
||||
/* Configure each global port */
|
||||
BasicPort global_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||
module_manager.add_port(lut_module, global_port, ModuleManager::MODULE_GLOBAL_PORT);
|
||||
}
|
||||
/* Add each input port */
|
||||
for (const auto& port : lut_input_ports) {
|
||||
BasicPort input_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||
module_manager.add_port(lut_module, input_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
/* Set the port to be wire-connection */
|
||||
module_manager.set_port_is_wire(lut_module, input_port.get_name(), true);
|
||||
}
|
||||
/* Add each output port */
|
||||
for (const auto& port : lut_output_ports) {
|
||||
BasicPort output_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||
module_manager.add_port(lut_module, output_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||
/* Set the port to be wire-connection */
|
||||
module_manager.set_port_is_wire(lut_module, output_port.get_name(), true);
|
||||
}
|
||||
/* Add each regular (not mode select) SRAM port */
|
||||
for (const auto& port : lut_regular_sram_ports) {
|
||||
BasicPort mem_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||
module_manager.add_port(lut_module, mem_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
BasicPort mem_inv_port(std::string(circuit_lib.port_lib_name(port) + "_inv"), circuit_lib.port_size(port));
|
||||
module_manager.add_port(lut_module, mem_inv_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
}
|
||||
|
||||
/* Add each mode-select SRAM port */
|
||||
for (const auto& port : lut_mode_select_sram_ports) {
|
||||
BasicPort mem_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||
module_manager.add_port(lut_module, mem_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
BasicPort mem_inv_port(std::string(circuit_lib.port_lib_name(port) + "_inv"), circuit_lib.port_size(port));
|
||||
module_manager.add_port(lut_module, mem_inv_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Child module addition: Model-select gates
|
||||
***********************************************/
|
||||
/* Module nets after the mode-selection circuit, this could include LUT inputs */
|
||||
std::vector<ModuleNetId> mode_selected_nets;
|
||||
/* Instanciate mode selecting circuit: AND/OR gate
|
||||
* By following the tri-state map of LUT input port
|
||||
* The wiring of input ports will be organized as follows
|
||||
*
|
||||
* LUT input
|
||||
* |
|
||||
* v
|
||||
* +----------+
|
||||
* | mode |
|
||||
* | selector |
|
||||
* +----------+
|
||||
* | mode_selected_nets
|
||||
* v
|
||||
* +-----------------+------------+
|
||||
* | |
|
||||
* v v
|
||||
* +----------+ +---------+
|
||||
* | Inverter | | Buffer |
|
||||
* +----------+ +---------+
|
||||
* | inverter_output_net | buffered_output_net
|
||||
* v v
|
||||
* +--------------------------------------+
|
||||
* | LUT Multiplexing Structure |
|
||||
* +--------------------------------------+
|
||||
*/
|
||||
/* Get the tri-state port map for the input ports*/
|
||||
std::string tri_state_map = circuit_lib.port_tri_state_map(lut_input_ports[0]);
|
||||
size_t mode_select_port_lsb = 0;
|
||||
for (const auto& pin : circuit_lib.pins(lut_input_ports[0])) {
|
||||
ModulePortId lut_module_input_port_id = module_manager.find_module_port(lut_module, circuit_lib.port_lib_name(lut_input_ports[0]));
|
||||
VTR_ASSERT(true == module_manager.valid_module_port_id(lut_module, lut_module_input_port_id));
|
||||
|
||||
/* Create a module net for the connection */
|
||||
ModuleNetId net = module_manager.create_module_net(lut_module);
|
||||
/* Set the source of the net to an lut input port */
|
||||
module_manager.add_module_net_source(lut_module, net, lut_module, 0, lut_module_input_port_id, pin);
|
||||
|
||||
/* For an empty tri-state map or a '-' sign in tri-state map, we can short-wire mode select_output_ports */
|
||||
if (tri_state_map.empty() || ('-' == tri_state_map[pin]) ) {
|
||||
/* Update the output nets of the mode-select layer */
|
||||
mode_selected_nets.push_back(net);
|
||||
continue; /* Finish here */
|
||||
}
|
||||
|
||||
e_spice_model_gate_type required_gate_type = NUM_SPICE_MODEL_GATE_TYPES;
|
||||
/* Reach here, it means that we need a circuit for mode selection */
|
||||
if ('0' == tri_state_map[pin]) {
|
||||
/* We need a 2-input AND gate, in order to tri-state the input
|
||||
* Detailed circuit is as follow:
|
||||
* +---------+
|
||||
* SRAM --->| 2-input |----> mode_select_output_port
|
||||
* LUT input--->| AND |
|
||||
* +---------+
|
||||
* When SRAM is set to logic 0, the LUT input is tri-stated
|
||||
* When SRAM is set to logic 1, the LUT input is effective to the downstream circuits
|
||||
*/
|
||||
required_gate_type = SPICE_MODEL_GATE_AND;
|
||||
} else {
|
||||
VTR_ASSERT ('1' == tri_state_map[pin]);
|
||||
/* We need a 2-input OR gate, in order to tri-state the input
|
||||
* Detailed circuit is as follow:
|
||||
* +---------+
|
||||
* SRAM --->| 2-input |----> mode_select_output_port
|
||||
* LUT input--->| OR |
|
||||
* +---------+
|
||||
* When SRAM is set to logic 1, the LUT input is tri-stated
|
||||
* When SRAM is set to logic 0, the LUT input is effective to the downstream circuits
|
||||
*/
|
||||
required_gate_type = SPICE_MODEL_GATE_OR;
|
||||
}
|
||||
/* Get the circuit model of the gate */
|
||||
CircuitModelId gate_model = circuit_lib.port_tri_state_model(lut_input_ports[0]);
|
||||
/* Check this is the gate we want ! */
|
||||
VTR_ASSERT (required_gate_type == circuit_lib.gate_type(gate_model));
|
||||
|
||||
/* Prepare for the gate instanciation */
|
||||
/* Get the input ports from the gate */
|
||||
std::vector<CircuitPortId> gate_input_ports = circuit_lib.model_ports_by_type(gate_model, SPICE_MODEL_PORT_INPUT, true);
|
||||
/* Get the output ports from the gate */
|
||||
std::vector<CircuitPortId> gate_output_ports = circuit_lib.model_ports_by_type(gate_model, SPICE_MODEL_PORT_OUTPUT, true);
|
||||
/* Check the port sizes and width:
|
||||
* we should have only 2 input ports, each of which has a size of 1
|
||||
* we should have only 1 output port, each of which has a size of 1
|
||||
*/
|
||||
VTR_ASSERT (2 == gate_input_ports.size());
|
||||
VTR_ASSERT (1 == gate_output_ports.size());
|
||||
/* Find the module id of gate_model in the module manager */
|
||||
ModuleId gate_module = module_manager.find_module(circuit_lib.model_name(gate_model));
|
||||
/* We must have a valid id */
|
||||
VTR_ASSERT (true == module_manager.valid_module_id(gate_module));
|
||||
size_t gate_instance = module_manager.num_instance(lut_module, gate_module);
|
||||
module_manager.add_child_module(lut_module, gate_module);
|
||||
|
||||
/* Create a port-to-port net connection:
|
||||
* Input[0] of the gate is wired to a SRAM mode-select port
|
||||
* Input[1] of the gate is wired to the input port of LUT
|
||||
* Output[0] of the gate is wired to the mode_select_output_port
|
||||
*/
|
||||
/* Create a module net for the connection */
|
||||
ModuleNetId gate_sram_net = module_manager.create_module_net(lut_module);
|
||||
|
||||
/* Find the module port id of the SRAM port of LUT module */
|
||||
ModulePortId lut_module_mode_select_port_id = module_manager.find_module_port(lut_module, circuit_lib.port_lib_name(lut_mode_select_sram_ports[0]));
|
||||
VTR_ASSERT(true == module_manager.valid_module_port_id(lut_module, lut_module_mode_select_port_id));
|
||||
/* Set the source of the net to an mode-select SRAM port of the LUT module */
|
||||
module_manager.add_module_net_source(lut_module, gate_sram_net, lut_module, 0, lut_module_mode_select_port_id, mode_select_port_lsb);
|
||||
|
||||
/* Find the module port id of the SRAM port of LUT module */
|
||||
ModulePortId gate_module_input0_port_id = module_manager.find_module_port(gate_module, circuit_lib.port_lib_name(gate_input_ports[0]));
|
||||
VTR_ASSERT(true == module_manager.valid_module_port_id(gate_module, gate_module_input0_port_id));
|
||||
/* Set the sink of the net to an input[0] port of the gate module */
|
||||
VTR_ASSERT(1 == module_manager.module_port(gate_module, gate_module_input0_port_id).get_width());
|
||||
for (const size_t& gate_pin : module_manager.module_port(gate_module, gate_module_input0_port_id).pins()) {
|
||||
module_manager.add_module_net_sink(lut_module, gate_sram_net, gate_module, gate_instance, gate_module_input0_port_id, gate_pin);
|
||||
}
|
||||
|
||||
/* Use the existing net to connect to the input[1] port of the gate module */
|
||||
ModulePortId gate_module_input1_port_id = module_manager.find_module_port(gate_module, circuit_lib.port_lib_name(gate_input_ports[1]));
|
||||
VTR_ASSERT(true == module_manager.valid_module_port_id(gate_module, gate_module_input1_port_id));
|
||||
VTR_ASSERT(1 == module_manager.module_port(gate_module, gate_module_input1_port_id).get_width());
|
||||
for (const size_t& gate_pin : module_manager.module_port(gate_module, gate_module_input1_port_id).pins()) {
|
||||
module_manager.add_module_net_sink(lut_module, net, gate_module, gate_instance, gate_module_input1_port_id, gate_pin);
|
||||
}
|
||||
|
||||
/* Create a module net for the output connection */
|
||||
ModuleNetId gate_output_net = module_manager.create_module_net(lut_module);
|
||||
ModulePortId gate_module_output_port_id = module_manager.find_module_port(gate_module, circuit_lib.port_lib_name(gate_output_ports[0]));
|
||||
VTR_ASSERT(true == module_manager.valid_module_port_id(gate_module, gate_module_output_port_id));
|
||||
BasicPort gate_module_output_port = module_manager.module_port(gate_module, gate_module_output_port_id);
|
||||
VTR_ASSERT(1 == gate_module_output_port.get_width());
|
||||
module_manager.add_module_net_source(lut_module, gate_output_net, gate_module, gate_instance, gate_module_output_port_id, gate_module_output_port.get_lsb());
|
||||
|
||||
/* Update the output nets of the mode-select layer */
|
||||
mode_selected_nets.push_back(gate_output_net);
|
||||
|
||||
/* update the lsb of mode select port size */
|
||||
mode_select_port_lsb++;
|
||||
}
|
||||
|
||||
/* Sanitity check */
|
||||
if ( true == circuit_lib.is_lut_fracturable(lut_model) ) {
|
||||
if (mode_select_port_lsb != circuit_lib.port_size(lut_mode_select_sram_ports[0])) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"(FILE:%s,LINE[%d]) Circuit model LUT (name=%s) has a unmatched tri-state map (%s) implied by mode_port size(%d)!\n",
|
||||
__FILE__, __LINE__,
|
||||
circuit_lib.model_name(lut_model).c_str(),
|
||||
tri_state_map.c_str(),
|
||||
circuit_lib.port_size(lut_mode_select_sram_ports[0]));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Child module addition: Input inverters
|
||||
***********************************************/
|
||||
/* Find the circuit model of the input inverter */
|
||||
CircuitModelId input_inverter_model = circuit_lib.lut_input_inverter_model(lut_model);
|
||||
VTR_ASSERT( CircuitModelId::INVALID() != input_inverter_model );
|
||||
|
||||
std::vector<ModuleNetId> lut_mux_sram_inv_nets;
|
||||
/* Now we need to add inverters by instanciating the modules */
|
||||
for (size_t pin = 0; pin < circuit_lib.port_size(lut_input_ports[0]); ++pin) {
|
||||
ModuleNetId lut_mux_sram_inv_net = add_inverter_buffer_child_module_and_nets(module_manager, lut_module,
|
||||
circuit_lib, input_inverter_model,
|
||||
mode_selected_nets[pin]);
|
||||
/* Update the net vector */
|
||||
lut_mux_sram_inv_nets.push_back(lut_mux_sram_inv_net);
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Child module addition: Input buffers
|
||||
***********************************************/
|
||||
/* Add buffers to mode_select output ports */
|
||||
/* Find the circuit model of the input inverter */
|
||||
CircuitModelId input_buffer_model = circuit_lib.lut_input_buffer_model(lut_model);
|
||||
VTR_ASSERT( CircuitModelId::INVALID() != input_buffer_model );
|
||||
|
||||
std::vector<ModuleNetId> lut_mux_sram_nets;
|
||||
/* Now we need to add inverters by instanciating the modules and add module nets */
|
||||
for (size_t pin = 0; pin < circuit_lib.port_size(lut_input_ports[0]); ++pin) {
|
||||
ModuleNetId lut_mux_sram_net = add_inverter_buffer_child_module_and_nets(module_manager, lut_module,
|
||||
circuit_lib, input_buffer_model,
|
||||
mode_selected_nets[pin]);
|
||||
/* Update the net vector */
|
||||
lut_mux_sram_nets.push_back(lut_mux_sram_net);
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Child module addition: LUT MUX
|
||||
***********************************************/
|
||||
/* Find the name of LUT MUX: no need to provide a mux size, just give an invalid number (=-1) */
|
||||
std::string lut_mux_module_name = generate_mux_subckt_name(circuit_lib, lut_model, size_t(-1), std::string(""));
|
||||
/* Find the module id of LUT MUX in the module manager */
|
||||
ModuleId lut_mux_module = module_manager.find_module(lut_mux_module_name);
|
||||
/* We must have a valid id */
|
||||
VTR_ASSERT (ModuleId::INVALID() != lut_mux_module);
|
||||
/* Instanciate a LUT MUX as child module */
|
||||
size_t lut_mux_instance = module_manager.num_instance(lut_module, lut_mux_module);
|
||||
module_manager.add_child_module(lut_module, lut_mux_module);
|
||||
|
||||
/* TODO: Build module nets to connect
|
||||
* 1. SRAM ports of LUT MUX module to output ports of input buffer
|
||||
* 2. Inverted SRAM ports of LUT MUX module to output ports of input inverters
|
||||
* 3. Data input of LUT MUX module to SRAM port of LUT
|
||||
* 4. Data output of LUT MUX module to output ports of LUT
|
||||
*/
|
||||
ModulePortId lut_mux_sram_port_id = module_manager.find_module_port(lut_mux_module, circuit_lib.port_lib_name(lut_regular_sram_ports[0]));
|
||||
BasicPort lut_mux_sram_port = module_manager.module_port(lut_mux_module, lut_mux_sram_port_id);
|
||||
VTR_ASSERT(lut_mux_sram_port.get_width() == lut_mux_sram_nets.size());
|
||||
/* Wire the port to lut_mux_sram_net */
|
||||
for (const size_t& pin : lut_mux_sram_port.pins()) {
|
||||
module_manager.add_module_net_sink(lut_module, lut_mux_sram_nets[pin], lut_mux_module, lut_mux_instance, lut_mux_sram_port_id, pin);
|
||||
}
|
||||
|
||||
ModulePortId lut_mux_sram_inv_port_id = module_manager.find_module_port(lut_mux_module, std::string(circuit_lib.port_lib_name(lut_regular_sram_ports[0]) + "_inv"));
|
||||
BasicPort lut_mux_sram_inv_port = module_manager.module_port(lut_mux_module, lut_mux_sram_inv_port_id);
|
||||
VTR_ASSERT(lut_mux_sram_inv_port.get_width() == lut_mux_sram_inv_nets.size());
|
||||
/* Wire the port to lut_mux_sram_net */
|
||||
for (const size_t& pin : lut_mux_sram_inv_port.pins()) {
|
||||
module_manager.add_module_net_sink(lut_module, lut_mux_sram_inv_nets[pin], lut_mux_module, lut_mux_instance, lut_mux_sram_inv_port_id, pin);
|
||||
}
|
||||
|
||||
/* lut_module
|
||||
* +------------
|
||||
* | +------
|
||||
* sram -->|---->| (lut_mux_input_port)
|
||||
* | ^ | LUT MUX
|
||||
* | | |
|
||||
* |
|
||||
* net
|
||||
*/
|
||||
ModulePortId lut_sram_port_id = module_manager.find_module_port(lut_module, circuit_lib.port_lib_name(lut_regular_sram_ports[0]));
|
||||
BasicPort lut_sram_port = module_manager.module_port(lut_module, lut_sram_port_id);
|
||||
ModulePortId lut_mux_input_port_id = module_manager.find_module_port(lut_mux_module, circuit_lib.port_lib_name(lut_input_ports[0]));
|
||||
BasicPort lut_mux_input_port = module_manager.module_port(lut_mux_module, lut_mux_input_port_id);
|
||||
VTR_ASSERT(lut_mux_input_port.get_width() == lut_sram_port.get_width());
|
||||
/* Wire the port to lut_mux_sram_net */
|
||||
for (size_t pin_id = 0; pin_id < lut_mux_input_port.pins().size(); ++pin_id) {
|
||||
ModuleNetId net = module_manager.create_module_net(lut_module);
|
||||
module_manager.add_module_net_source(lut_module, net, lut_module, 0, lut_sram_port_id, lut_sram_port.pins()[pin_id]);
|
||||
module_manager.add_module_net_sink(lut_module, net, lut_mux_module, lut_mux_instance, lut_mux_input_port_id, lut_mux_input_port.pins()[pin_id]);
|
||||
}
|
||||
|
||||
for (const auto& port : lut_output_ports) {
|
||||
ModulePortId lut_output_port_id = module_manager.find_module_port(lut_module, circuit_lib.port_lib_name(port));
|
||||
BasicPort lut_output_port = module_manager.module_port(lut_module, lut_output_port_id);
|
||||
ModulePortId lut_mux_output_port_id = module_manager.find_module_port(lut_mux_module, circuit_lib.port_lib_name(port));
|
||||
BasicPort lut_mux_output_port = module_manager.module_port(lut_mux_module, lut_mux_output_port_id);
|
||||
VTR_ASSERT(lut_mux_output_port.get_width() == lut_output_port.get_width());
|
||||
/* Wire the port to lut_mux_sram_net */
|
||||
for (size_t pin_id = 0; pin_id < lut_output_port.pins().size(); ++pin_id) {
|
||||
ModuleNetId net = module_manager.create_module_net(lut_module);
|
||||
module_manager.add_module_net_source(lut_module, net, lut_mux_module, lut_mux_instance, lut_mux_output_port_id, lut_mux_output_port.pins()[pin_id]);
|
||||
module_manager.add_module_net_sink(lut_module, net, lut_module, 0, lut_output_port_id, lut_output_port.pins()[pin_id]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add global ports to the pb_module:
|
||||
* This is a much easier job after adding sub modules (instances),
|
||||
* we just need to find all the global ports from the child modules and build a list of it
|
||||
*/
|
||||
add_module_global_ports_from_child_modules(module_manager, lut_module);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Print Verilog modules for the Look-Up Tables (LUTs)
|
||||
* in the circuit library
|
||||
********************************************************************/
|
||||
void build_lut_modules(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
|
||||
/* Search for each LUT circuit model */
|
||||
for (const auto& lut_model : circuit_lib.models()) {
|
||||
/* Bypas non-LUT modules */
|
||||
if (SPICE_MODEL_LUT != circuit_lib.model_type(lut_model)) {
|
||||
continue;
|
||||
}
|
||||
build_lut_module(module_manager, circuit_lib, lut_model);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/********************************************************************
|
||||
* Header file for build_lut_modules.cpp
|
||||
********************************************************************/
|
||||
#ifndef BUILD_LUT_MODULES_H
|
||||
#define BUILD_LUT_MODULES_H
|
||||
|
||||
#include "circuit_library.h"
|
||||
#include "module_manager.h"
|
||||
|
||||
void build_lut_modules(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib);
|
||||
|
||||
#endif
|
|
@ -13,6 +13,7 @@
|
|||
#include "build_essential_modules.h"
|
||||
#include "build_decoder_modules.h"
|
||||
#include "build_mux_modules.h"
|
||||
#include "build_lut_modules.h"
|
||||
#include "build_module_graph.h"
|
||||
|
||||
/********************************************************************
|
||||
|
@ -86,7 +87,8 @@ ModuleManager build_device_module_graph(const t_vpr_setup& vpr_setup,
|
|||
/* Build multiplexer modules */
|
||||
build_mux_modules(module_manager, mux_lib, arch.spice->circuit_lib);
|
||||
|
||||
/* TODO: Build LUT modules */
|
||||
/* Build LUT modules */
|
||||
build_lut_modules(module_manager, arch.spice->circuit_lib);
|
||||
|
||||
/* TODO: Build wire modules */
|
||||
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/********************************************************************
|
||||
* This file includes most utilized functions that are used to
|
||||
* build module graphs
|
||||
********************************************************************/
|
||||
#include <vector>
|
||||
#include "vtr_assert.h"
|
||||
|
||||
#include "build_module_graph_utils.h"
|
||||
|
||||
/********************************************************************
|
||||
* Find input port of a buffer/inverter module
|
||||
********************************************************************/
|
||||
ModulePortId find_inverter_buffer_module_port(const ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model_id,
|
||||
const e_spice_model_port_type& port_type) {
|
||||
/* We must have a valid module id */
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(module_id));
|
||||
/* Check the type of model */
|
||||
VTR_ASSERT(SPICE_MODEL_INVBUF == circuit_lib.model_type(model_id));
|
||||
|
||||
/* Add module nets to wire to the buffer module */
|
||||
/* To match the context, Buffer should have only 2 non-global ports: 1 input port and 1 output port */
|
||||
std::vector<CircuitPortId> model_ports = circuit_lib.model_ports_by_type(model_id, port_type, true);
|
||||
VTR_ASSERT(1 == model_ports.size());
|
||||
|
||||
/* Find the input and output module ports */
|
||||
ModulePortId module_port_id = module_manager.find_module_port(module_id, circuit_lib.port_lib_name(model_ports[0]));
|
||||
VTR_ASSERT(true == module_manager.valid_module_port_id(module_id, module_port_id));
|
||||
|
||||
return module_port_id;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Add inverter/buffer module to a parent module
|
||||
* and complete the wiring to the input port of inverter/buffer
|
||||
* This function will return the wire created for the output port of inverter/buffer
|
||||
*
|
||||
* parent_module
|
||||
* +-----------------------------------------------------------------
|
||||
* |
|
||||
* | input_net output_net
|
||||
* | | |
|
||||
* | v +---------------+ v
|
||||
* | src_module_port --------->| child_module |-------->
|
||||
* | +---------------+
|
||||
*
|
||||
********************************************************************/
|
||||
ModuleNetId add_inverter_buffer_child_module_and_nets(ModuleManager& module_manager,
|
||||
const ModuleId& parent_module,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model_id,
|
||||
const ModuleNetId& input_net) {
|
||||
/* We must have a valid module id */
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(parent_module));
|
||||
|
||||
std::string module_name = circuit_lib.model_name(model_id);
|
||||
ModuleId child_module = module_manager.find_module(module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(child_module));
|
||||
|
||||
ModulePortId module_input_port_id = find_inverter_buffer_module_port(module_manager, child_module, circuit_lib, model_id, SPICE_MODEL_PORT_INPUT);
|
||||
ModulePortId module_output_port_id = find_inverter_buffer_module_port(module_manager, child_module, circuit_lib, model_id, SPICE_MODEL_PORT_OUTPUT);
|
||||
|
||||
/* Port size should be 1 ! */
|
||||
VTR_ASSERT(1 == module_manager.module_port(child_module, module_input_port_id).get_width());
|
||||
VTR_ASSERT(1 == module_manager.module_port(child_module, module_output_port_id).get_width());
|
||||
|
||||
/* Instanciate a child module */
|
||||
size_t child_instance = module_manager.num_instance(parent_module, child_module);
|
||||
module_manager.add_child_module(parent_module, child_module);
|
||||
|
||||
/* Use the net to connect to the input net of buffer */
|
||||
module_manager.add_module_net_sink(parent_module, input_net, child_module, child_instance, module_input_port_id, 0);
|
||||
|
||||
/* Create a net to bridge the input inverter and LUT MUX */
|
||||
ModuleNetId output_net = module_manager.create_module_net(parent_module);
|
||||
module_manager.add_module_net_source(parent_module, output_net, child_module, child_instance, module_output_port_id, 0);
|
||||
|
||||
return output_net;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/********************************************************************
|
||||
* Header file for build_module_graph_utils.cpp
|
||||
********************************************************************/
|
||||
#ifndef BUILD_MODULE_GRAPH_UTILS_H
|
||||
#define BUILD_MODULE_GRAPH_UTILS_H
|
||||
|
||||
#include "module_manager.h"
|
||||
#include "circuit_library.h"
|
||||
|
||||
ModulePortId find_inverter_buffer_module_port(const ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model_id,
|
||||
const e_spice_model_port_type& port_type);
|
||||
|
||||
ModuleNetId add_inverter_buffer_child_module_and_nets(ModuleManager& module_manager,
|
||||
const ModuleId& parent_module,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& model_id,
|
||||
const ModuleNetId& input_net);
|
||||
|
||||
#endif
|
|
@ -20,324 +20,10 @@
|
|||
#include "fpga_x2p_utils.h"
|
||||
|
||||
/* FPGA-Verilog context header files */
|
||||
#include "verilog_global.h"
|
||||
#include "verilog_writer_utils.h"
|
||||
#include "verilog_submodule_utils.h"
|
||||
#include "verilog_module_writer.h"
|
||||
#include "verilog_lut.h"
|
||||
|
||||
/********************************************************************
|
||||
* Print a Verilog module for a LUT circuit model
|
||||
* This function supports both single-output and fracturable LUTs
|
||||
* The Verilog module will be organized in structural Verilog codes.
|
||||
* It will instanciate:
|
||||
* 1. Multiplexer used inside LUT
|
||||
* 2. Input buffers
|
||||
* 3. Input inverters
|
||||
* 4. Output buffers.
|
||||
* 6. AND/OR gates to tri-state LUT inputs
|
||||
********************************************************************/
|
||||
static
|
||||
void print_verilog_submodule_lut(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
std::fstream& fp,
|
||||
const CircuitModelId& circuit_model) {
|
||||
/* Ensure a valid file handler*/
|
||||
check_file_handler(fp);
|
||||
|
||||
/* Get the global ports required by MUX (and any submodules) */
|
||||
std::vector<CircuitPortId> lut_global_ports = circuit_lib.model_global_ports_by_type(circuit_model, SPICE_MODEL_PORT_INPUT, true, true);
|
||||
/* Get the input ports from the mux */
|
||||
std::vector<CircuitPortId> lut_input_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_INPUT, true);
|
||||
/* Get the output ports from the mux */
|
||||
std::vector<CircuitPortId> lut_output_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_OUTPUT, true);
|
||||
|
||||
/* Classify SRAM ports into two categories: regular (not for mode select) and mode-select */
|
||||
std::vector<CircuitPortId> lut_regular_sram_ports;
|
||||
std::vector<CircuitPortId> lut_mode_select_sram_ports;
|
||||
|
||||
{ /* Create a code block to keep some variables in local */
|
||||
/* Get the sram ports from the mux */
|
||||
std::vector<CircuitPortId> lut_sram_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_SRAM, true);
|
||||
for (const auto& port : lut_sram_ports) {
|
||||
/* Bypass mode_select ports */
|
||||
if (true == circuit_lib.port_is_mode_select(port)) {
|
||||
lut_mode_select_sram_ports.push_back(port);
|
||||
continue;
|
||||
}
|
||||
VTR_ASSERT_SAFE (false == circuit_lib.port_is_mode_select(port));
|
||||
lut_regular_sram_ports.push_back(port);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure that the number of ports and sizes of ports are what we want */
|
||||
if (false == circuit_lib.is_lut_fracturable(circuit_model)) {
|
||||
/* Single-output LUTs:
|
||||
* We should have only 1 input port, 1 output port and 1 SRAM port
|
||||
*/
|
||||
VTR_ASSERT (1 == lut_input_ports.size());
|
||||
VTR_ASSERT (1 == lut_output_ports.size());
|
||||
VTR_ASSERT (1 == lut_regular_sram_ports.size());
|
||||
VTR_ASSERT (0 == lut_mode_select_sram_ports.size());
|
||||
} else {
|
||||
VTR_ASSERT (true == circuit_lib.is_lut_fracturable(circuit_model));
|
||||
/* Fracturable LUT:
|
||||
* We should have only 1 input port, a few output ports (fracturable outputs)
|
||||
* and two SRAM ports
|
||||
*/
|
||||
VTR_ASSERT (1 == lut_input_ports.size());
|
||||
VTR_ASSERT (1 <= lut_output_ports.size());
|
||||
VTR_ASSERT (1 == lut_regular_sram_ports.size());
|
||||
VTR_ASSERT (1 == lut_mode_select_sram_ports.size());
|
||||
}
|
||||
|
||||
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||
ModuleId module_id = module_manager.add_module(circuit_lib.model_name(circuit_model));
|
||||
VTR_ASSERT(ModuleId::INVALID() != module_id);
|
||||
/* Add module ports */
|
||||
/* Add each global port */
|
||||
for (const auto& port : lut_global_ports) {
|
||||
/* Configure each global port */
|
||||
BasicPort global_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||
module_manager.add_port(module_id, global_port, ModuleManager::MODULE_GLOBAL_PORT);
|
||||
}
|
||||
/* Add each input port */
|
||||
for (const auto& port : lut_input_ports) {
|
||||
BasicPort input_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||
module_manager.add_port(module_id, input_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
/* Set the port to be wire-connection */
|
||||
module_manager.set_port_is_wire(module_id, input_port.get_name(), true);
|
||||
}
|
||||
/* Add each output port */
|
||||
for (const auto& port : lut_output_ports) {
|
||||
BasicPort output_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||
module_manager.add_port(module_id, output_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||
/* Set the port to be wire-connection */
|
||||
module_manager.set_port_is_wire(module_id, output_port.get_name(), true);
|
||||
}
|
||||
/* Add each regular (not mode select) SRAM port */
|
||||
for (const auto& port : lut_regular_sram_ports) {
|
||||
BasicPort mem_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||
module_manager.add_port(module_id, mem_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
BasicPort mem_inv_port(std::string(circuit_lib.port_lib_name(port) + "_inv"), circuit_lib.port_size(port));
|
||||
module_manager.add_port(module_id, mem_inv_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
}
|
||||
|
||||
/* Add each mode-select SRAM port */
|
||||
for (const auto& port : lut_mode_select_sram_ports) {
|
||||
BasicPort mem_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||
module_manager.add_port(module_id, mem_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
BasicPort mem_inv_port(std::string(circuit_lib.port_lib_name(port) + "_inv"), circuit_lib.port_size(port));
|
||||
module_manager.add_port(module_id, mem_inv_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
}
|
||||
|
||||
/* dump module definition + ports */
|
||||
print_verilog_module_declaration(fp, module_manager, module_id);
|
||||
|
||||
/* Print local wires for mode selector */
|
||||
/* Local wires for the output of mode selector */
|
||||
BasicPort mode_select_output_port(std::string(circuit_lib.port_lib_name(lut_input_ports[0]) + "_mode"), circuit_lib.port_size(lut_input_ports[0]));
|
||||
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, mode_select_output_port) << ";" << std::endl;
|
||||
/* Local wires for the output of input inverters */
|
||||
BasicPort inverted_input_port(std::string(circuit_lib.port_lib_name(lut_input_ports[0]) + "_b"), circuit_lib.port_size(lut_input_ports[0]));
|
||||
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, inverted_input_port) << ";" << std::endl;
|
||||
/* Local wires for the output of input buffers */
|
||||
BasicPort buffered_input_port(std::string(circuit_lib.port_lib_name(lut_input_ports[0]) + "_buf"), circuit_lib.port_size(lut_input_ports[0]));
|
||||
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, buffered_input_port) << ";" << std::endl;
|
||||
|
||||
/* Instanciate mode selecting circuit: AND/OR gate
|
||||
* By following the tri-state map of LUT input port
|
||||
* The wiring of input ports will be organized as follows
|
||||
*
|
||||
* LUT input
|
||||
* |
|
||||
* v
|
||||
* +----------+
|
||||
* | mode |
|
||||
* | selector |
|
||||
* +----------+
|
||||
* | mode_select_output_port
|
||||
* +-----------------+------------+
|
||||
* | |
|
||||
* +----------+ +---------+
|
||||
* | Inverter | | Buffer |
|
||||
* +----------+ +---------+
|
||||
* | inverter_input_port | buffered_input_port
|
||||
* v v
|
||||
* +--------------------------------------+
|
||||
* | LUT Multiplexing Structure |
|
||||
* +--------------------------------------+
|
||||
*/
|
||||
print_verilog_comment(fp, std::string("---- BEGIN Instanciation of model-select gates -----"));
|
||||
/* Get the tri-state port map for the input ports*/
|
||||
std::string tri_state_map = circuit_lib.port_tri_state_map(lut_input_ports[0]);
|
||||
size_t mode_select_port_lsb = 0;
|
||||
for (const auto& pin : circuit_lib.pins(lut_input_ports[0])) {
|
||||
BasicPort cur_mode_select_output_port(mode_select_output_port.get_name(), pin, pin);
|
||||
BasicPort cur_input_port(circuit_lib.port_lib_name(lut_input_ports[0]), pin, pin);
|
||||
/* For an empty tri-state map or a '-' sign in tri-state map, we can short-wire mode select_output_ports */
|
||||
if (tri_state_map.empty() || ('-' == tri_state_map[pin]) ) {
|
||||
print_verilog_wire_connection(fp, cur_mode_select_output_port, cur_input_port, false);
|
||||
continue; /* Finish here */
|
||||
}
|
||||
/* Reach here, it means that we need a circuit for mode selection */
|
||||
BasicPort cur_lut_mode_select_sram_port(circuit_lib.port_lib_name(lut_mode_select_sram_ports[0]), mode_select_port_lsb, mode_select_port_lsb);
|
||||
enum e_spice_model_gate_type required_gate_type;
|
||||
if ('0' == tri_state_map[pin]) {
|
||||
/* We need a 2-input AND gate, in order to tri-state the input
|
||||
* Detailed circuit is as follow:
|
||||
* +---------+
|
||||
* SRAM --->| 2-input |----> mode_select_output_port
|
||||
* LUT input--->| AND |
|
||||
* +---------+
|
||||
* When SRAM is set to logic 0, the LUT input is tri-stated
|
||||
* When SRAM is set to logic 1, the LUT input is effective to the downstream circuits
|
||||
*/
|
||||
required_gate_type = SPICE_MODEL_GATE_AND;
|
||||
} else {
|
||||
VTR_ASSERT ('1' == tri_state_map[pin]);
|
||||
/* We need a 2-input OR gate, in order to tri-state the input
|
||||
* Detailed circuit is as follow:
|
||||
* +---------+
|
||||
* SRAM --->| 2-input |----> mode_select_output_port
|
||||
* LUT input--->| OR |
|
||||
* +---------+
|
||||
* When SRAM is set to logic 1, the LUT input is tri-stated
|
||||
* When SRAM is set to logic 0, the LUT input is effective to the downstream circuits
|
||||
*/
|
||||
required_gate_type = SPICE_MODEL_GATE_OR;
|
||||
}
|
||||
/* Get the circuit model of the gate */
|
||||
CircuitModelId gate_model = circuit_lib.port_tri_state_model(lut_input_ports[0]);
|
||||
/* Check this is the gate we want ! */
|
||||
VTR_ASSERT (required_gate_type == circuit_lib.gate_type(gate_model));
|
||||
|
||||
/* Prepare for the gate instanciation */
|
||||
/* Get the input ports from the gate */
|
||||
std::vector<CircuitPortId> gate_input_ports = circuit_lib.model_ports_by_type(gate_model, SPICE_MODEL_PORT_INPUT, true);
|
||||
/* Get the output ports from the gate */
|
||||
std::vector<CircuitPortId> gate_output_ports = circuit_lib.model_ports_by_type(gate_model, SPICE_MODEL_PORT_OUTPUT, true);
|
||||
/* Check the port sizes and width:
|
||||
* we should have only 2 input ports, each of which has a size of 1
|
||||
* we should have only 1 output port, each of which has a size of 1
|
||||
*/
|
||||
VTR_ASSERT (2 == gate_input_ports.size());
|
||||
for (const auto& port : gate_input_ports) {
|
||||
VTR_ASSERT (1 == circuit_lib.port_size(port));
|
||||
}
|
||||
VTR_ASSERT (1 == gate_output_ports.size());
|
||||
for (const auto& port : gate_output_ports) {
|
||||
VTR_ASSERT (1 == circuit_lib.port_size(port));
|
||||
}
|
||||
/* Find the module id of gate_model in the module manager */
|
||||
ModuleId gate_module_id = module_manager.find_module(circuit_lib.model_name(gate_model));
|
||||
/* We must have a valid id */
|
||||
VTR_ASSERT (ModuleId::INVALID() != gate_module_id);
|
||||
/* Create a port-to-port map:
|
||||
* Input[0] of the gate is wired to a SRAM mode-select port
|
||||
* Input[1] of the gate is wired to the input port of LUT
|
||||
* Output[0] of the gate is wired to the mode_select_output_port
|
||||
*/
|
||||
std::map<std::string, BasicPort> port2port_name_map;
|
||||
port2port_name_map[circuit_lib.port_lib_name(gate_input_ports[0])] = cur_lut_mode_select_sram_port;
|
||||
port2port_name_map[circuit_lib.port_lib_name(gate_input_ports[1])] = cur_input_port;
|
||||
port2port_name_map[circuit_lib.port_lib_name(gate_output_ports[0])] = cur_mode_select_output_port;
|
||||
|
||||
/* Instanciate the gate */
|
||||
print_verilog_module_instance(fp, module_manager, module_id, gate_module_id, port2port_name_map, circuit_lib.dump_explicit_port_map(circuit_model));
|
||||
/* IMPORTANT: this update MUST be called after the instance outputting!!!!
|
||||
* update the module manager with the relationship between the parent and child modules
|
||||
*/
|
||||
module_manager.add_child_module(module_id, gate_module_id);
|
||||
/* update the lsb of mode select port size */
|
||||
mode_select_port_lsb++;
|
||||
}
|
||||
print_verilog_comment(fp, std::string("---- END Instanciation of model-select gates -----"));
|
||||
/* Sanitity check */
|
||||
if ( true == circuit_lib.is_lut_fracturable(circuit_model) ) {
|
||||
if (mode_select_port_lsb != circuit_lib.port_size(lut_mode_select_sram_ports[0])) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"(FILE:%s,LINE[%d]) Circuit model LUT (name=%s) has a unmatched tri-state map (%s) implied by mode_port size(%d)!\n",
|
||||
__FILE__, __LINE__,
|
||||
circuit_lib.model_name(circuit_model).c_str(),
|
||||
tri_state_map.c_str(),
|
||||
circuit_lib.port_size(lut_mode_select_sram_ports[0]));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a blank-line splitter */
|
||||
fp << std::endl;
|
||||
|
||||
/* Add inverters to mode_select output ports */
|
||||
print_verilog_comment(fp, std::string("---- BEGIN Instanciation of an input inverters modules -----"));
|
||||
/* Find the circuit model of the input inverter */
|
||||
CircuitModelId input_inverter_model = circuit_lib.lut_input_inverter_model(circuit_model);
|
||||
VTR_ASSERT( CircuitModelId::INVALID() != input_inverter_model );
|
||||
/* Now we need to add inverters by instanciating the modules */
|
||||
for (const auto& pin : circuit_lib.pins(lut_input_ports[0])) {
|
||||
/* Input of inverter is the output of mode select circuits */
|
||||
BasicPort inverter_instance_input_port(mode_select_output_port.get_name(), pin, pin);
|
||||
/* Output of inverter is the inverted input port */
|
||||
BasicPort inverter_instance_output_port(inverted_input_port.get_name(), pin, pin);
|
||||
|
||||
print_verilog_buffer_instance(fp, module_manager, circuit_lib, module_id, input_inverter_model, inverter_instance_input_port, inverter_instance_output_port);
|
||||
}
|
||||
print_verilog_comment(fp, std::string("---- END Instanciation of an input inverters modules -----"));
|
||||
|
||||
/* Add buffers to mode_select output ports */
|
||||
print_verilog_comment(fp, std::string("---- BEGIN Instanciation of an input buffer modules -----"));
|
||||
/* Find the circuit model of the input inverter */
|
||||
CircuitModelId input_buffer_model = circuit_lib.lut_input_buffer_model(circuit_model);
|
||||
VTR_ASSERT( CircuitModelId::INVALID() != input_buffer_model );
|
||||
/* Now we need to add inverters by instanciating the modules */
|
||||
for (const auto& pin : circuit_lib.pins(lut_input_ports[0])) {
|
||||
/* Input of inverter is the output of mode select circuits */
|
||||
BasicPort buffer_instance_input_port(mode_select_output_port.get_name(), pin, pin);
|
||||
/* Output of inverter is the inverted input port */
|
||||
BasicPort buffer_instance_output_port(buffered_input_port.get_name(), pin, pin);
|
||||
|
||||
print_verilog_buffer_instance(fp, module_manager, circuit_lib, module_id, input_buffer_model, buffer_instance_input_port, buffer_instance_output_port);
|
||||
}
|
||||
print_verilog_comment(fp, std::string("---- END Instanciation of an input buffer modules -----"));
|
||||
|
||||
/* Instanciate the multiplexing structure for the LUT */
|
||||
print_verilog_comment(fp, std::string("---- BEGIN Instanciation of LUT multiplexer module -----"));
|
||||
/* Find the name of LUT MUX: no need to provide a mux size, just give an invalid number (=-1) */
|
||||
std::string lut_mux_module_name = generate_mux_subckt_name(circuit_lib, circuit_model, size_t(-1), std::string(""));
|
||||
/* Find the module id of LUT MUX in the module manager */
|
||||
ModuleId lut_mux_module_id = module_manager.find_module(lut_mux_module_name);
|
||||
/* We must have a valid id */
|
||||
VTR_ASSERT (ModuleId::INVALID() != lut_mux_module_id);
|
||||
/* Create a port-to-port map:
|
||||
* Input of the LUT MUX is wired to a regular SRAM port of LUT
|
||||
* Outputs of the LUT MUX is wired to the output ports of LUT by name
|
||||
* SRAM of the LUT MUX is wired to the buffered input port of LUT
|
||||
* SRAM_inv of the LUT MUX is wired to the inverted input port of LUT
|
||||
*/
|
||||
std::map<std::string, BasicPort> port2port_name_map;
|
||||
port2port_name_map[circuit_lib.port_lib_name(lut_input_ports[0])] = BasicPort(circuit_lib.port_lib_name(lut_regular_sram_ports[0]), circuit_lib.port_size(lut_regular_sram_ports[0]));
|
||||
/* Skip the output ports, if we do not need a new name for the port of instance */
|
||||
port2port_name_map[circuit_lib.port_lib_name(lut_regular_sram_ports[0])] = buffered_input_port;
|
||||
/* TODO: be more flexible in naming !!! */
|
||||
port2port_name_map[std::string(circuit_lib.port_lib_name(lut_regular_sram_ports[0]) + "_inv")] = inverted_input_port;
|
||||
|
||||
/* Instanciate the gate */
|
||||
print_verilog_module_instance(fp, module_manager, module_id, lut_mux_module_id, port2port_name_map, circuit_lib.dump_explicit_port_map(circuit_model));
|
||||
/* IMPORTANT: this update MUST be called after the instance outputting!!!!
|
||||
* update the module manager with the relationship between the parent and child modules
|
||||
*/
|
||||
module_manager.add_child_module(module_id, lut_mux_module_id);
|
||||
|
||||
/* Print timing info */
|
||||
print_verilog_submodule_timing(fp, circuit_lib, circuit_model);
|
||||
|
||||
/* Print signal initialization */
|
||||
print_verilog_submodule_signal_init(fp, circuit_lib, circuit_model);
|
||||
|
||||
/* Put an end to the Verilog module */
|
||||
print_verilog_module_end(fp, circuit_lib.model_name(circuit_model));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Print Verilog modules for the Look-Up Tables (LUTs)
|
||||
* in the circuit library
|
||||
|
@ -366,13 +52,16 @@ void print_verilog_submodule_luts(ModuleManager& module_manager,
|
|||
print_verilog_include_defines_preproc_file(fp, verilog_dir);
|
||||
|
||||
/* Search for each LUT circuit model */
|
||||
for (const auto& circuit_model : circuit_lib.models()) {
|
||||
for (const auto& lut_model : circuit_lib.models()) {
|
||||
/* Bypass user-defined and non-LUT modules */
|
||||
if ( (!circuit_lib.model_verilog_netlist(circuit_model).empty())
|
||||
|| (SPICE_MODEL_LUT != circuit_lib.model_type(circuit_model)) ) {
|
||||
if ( (!circuit_lib.model_verilog_netlist(lut_model).empty())
|
||||
|| (SPICE_MODEL_LUT != circuit_lib.model_type(lut_model)) ) {
|
||||
continue;
|
||||
}
|
||||
print_verilog_submodule_lut(module_manager, circuit_lib, fp, circuit_model);
|
||||
/* Find the module id */
|
||||
ModuleId lut_module = module_manager.find_module(circuit_lib.model_name(lut_model));
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(lut_module));
|
||||
write_verilog_module_to_file(fp, module_manager, lut_module, circuit_lib.dump_explicit_port_map(lut_model));
|
||||
}
|
||||
|
||||
/* Close the file handler */
|
||||
|
|
Loading…
Reference in New Issue