diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_module_graph.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_module_graph.cpp index 36b23e401..d4196672d 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_module_graph.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_module_graph.cpp @@ -14,6 +14,7 @@ #include "build_decoder_modules.h" #include "build_mux_modules.h" #include "build_lut_modules.h" +#include "build_wire_modules.h" #include "build_module_graph.h" /******************************************************************** @@ -90,7 +91,8 @@ ModuleManager build_device_module_graph(const t_vpr_setup& vpr_setup, /* Build LUT modules */ build_lut_modules(module_manager, arch.spice->circuit_lib); - /* TODO: Build wire modules */ + /* Build wire modules */ + build_wire_modules(module_manager, arch.spice->circuit_lib, L_segment_vec); /* TODO: Build memory modules */ diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_wire_modules.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_wire_modules.cpp new file mode 100644 index 000000000..020329e63 --- /dev/null +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_wire_modules.cpp @@ -0,0 +1,134 @@ +/*********************************************** + * This file includes functions to generate + * Verilog submodules for wires. + **********************************************/ +#include +#include + +#include "util.h" +#include "vtr_assert.h" + +/* Device-level header files */ +#include "module_manager.h" +#include "module_manager_utils.h" +#include "physical_types.h" +#include "vpr_types.h" + +/* FPGA-X2P context header files */ +#include "spice_types.h" +#include "fpga_x2p_naming.h" +#include "fpga_x2p_utils.h" + +/* FPGA-Verilog context header files */ +#include "verilog_global.h" +#include "build_wire_modules.h" + +/******************************************************************** + * Print a Verilog module of a regular wire segment + * Regular wire, which is 1-input and 1-output + * This type of wires are used in the local routing architecture + * +------+ + * input --->| wire |---> output + * +------+ + * + *******************************************************************/ +static +void build_wire_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& wire_model) { + /* Find the input port, output port*/ + std::vector input_ports = circuit_lib.model_ports_by_type(wire_model, SPICE_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type(wire_model, SPICE_MODEL_PORT_OUTPUT, true); + std::vector global_ports = circuit_lib.model_global_ports_by_type(wire_model, SPICE_MODEL_PORT_INPUT, true, true); + + /* Makre sure the port size is what we want */ + VTR_ASSERT (1 == input_ports.size()); + VTR_ASSERT (1 == output_ports.size()); + VTR_ASSERT (1 == circuit_lib.port_size(input_ports[0])); + VTR_ASSERT (1 == circuit_lib.port_size(output_ports[0])); + + /* Create a Verilog Module based on the circuit model, and add to module manager */ + add_circuit_model_to_module_manager(module_manager, circuit_lib, wire_model); +} + +/******************************************************************** + * Build module of a routing track wire segment + * Routing track wire, which is 1-input and dual output + * This type of wires are used in the global routing architecture. + * One of the output is wired to another Switch block multiplexer, + * while the mid-output is wired to a Connection block multiplexer. + * + * | CLB | + * +------------+ + * ^ + * | + * +------------------------------+ + * | Connection block multiplexer | + * +------------------------------+ + * ^ + * | mid-output +-------------- + * +--------------------+ | + * input --->| Routing track wire |--------->| Switch Block + * +--------------------+ output | + * +-------------- + * + *******************************************************************/ +static +void build_routing_wire_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const CircuitModelId& wire_model, + const std::string& wire_subckt_name) { + /* Find the input port, output port*/ + std::vector input_ports = circuit_lib.model_ports_by_type(wire_model, SPICE_MODEL_PORT_INPUT, true); + std::vector output_ports = circuit_lib.model_ports_by_type(wire_model, SPICE_MODEL_PORT_OUTPUT, true); + + /* Make sure the port size is what we want */ + VTR_ASSERT (1 == input_ports.size()); + VTR_ASSERT (1 == output_ports.size()); + VTR_ASSERT (1 == circuit_lib.port_size(input_ports[0])); + VTR_ASSERT (1 == circuit_lib.port_size(output_ports[0])); + + /* Create a Verilog Module based on the circuit model, and add to module manager */ + ModuleId wire_module = add_circuit_model_to_module_manager(module_manager, circuit_lib, wire_model, wire_subckt_name); + + /* Add a mid-output port to the module */ + BasicPort module_mid_output_port(generate_segment_wire_mid_output_name(circuit_lib.port_lib_name(output_ports[0])), circuit_lib.port_size(output_ports[0])); + module_manager.add_port(wire_module, module_mid_output_port, ModuleManager::MODULE_OUTPUT_PORT); +} + +/******************************************************************** + * This function will only create wire modules with a number of + * ports that are defined by users. + * It will NOT insert any internal logic, which should be handled + * by Verilog/SPICE writers + *******************************************************************/ +void build_wire_modules(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + std::vector routing_segments) { + /* Print Verilog models for regular wires*/ + for (const auto& wire_model : circuit_lib.models_by_type(SPICE_MODEL_WIRE)) { + /* Bypass user-defined circuit models */ + if ( (!circuit_lib.model_spice_netlist(wire_model).empty()) + && (!circuit_lib.model_verilog_netlist(wire_model).empty()) ) { + continue; + } + build_wire_module(module_manager, circuit_lib, wire_model); + } + + for (const auto& seg : routing_segments) { + VTR_ASSERT( CircuitModelId::INVALID() != seg.circuit_model); + VTR_ASSERT( SPICE_MODEL_CHAN_WIRE == circuit_lib.model_type(seg.circuit_model)); + /* Bypass user-defined circuit models */ + if ( (!circuit_lib.model_spice_netlist(seg.circuit_model).empty()) + && (!circuit_lib.model_verilog_netlist(seg.circuit_model).empty()) ) { + continue; + } + /* Give a unique name for subckt of wire_model of segment, + * circuit_model name is unique, and segment id is unique as well + */ + std::string segment_wire_subckt_name = generate_segment_wire_subckt_name(circuit_lib.model_name(seg.circuit_model), &seg - &routing_segments[0]); + + /* Print a Verilog module */ + build_routing_wire_module(module_manager, circuit_lib, seg.circuit_model, segment_wire_subckt_name); + } +} diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_wire_modules.h b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_wire_modules.h new file mode 100644 index 000000000..a68eb22b0 --- /dev/null +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_wire_modules.h @@ -0,0 +1,20 @@ +/*********************************************** + * Header file for verilog_wire.cpp + **********************************************/ + +#ifndef BUILD_WIRE_MODULES_H +#define BUILD_WIRE_MODULES_H + +/* Include other header files which are dependency on the function declared below */ +#include +#include "physical_types.h" +#include "vpr_types.h" + +#include "circuit_library.h" +#include "module_manager.h" + +void build_wire_modules(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + std::vector routing_segments); + +#endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_wire.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_wire.cpp index 4506aa106..b8b9443bc 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_wire.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_wire.cpp @@ -54,22 +54,23 @@ void print_verilog_wire_module(ModuleManager& module_manager, VTR_ASSERT (1 == circuit_lib.port_size(output_ports[0])); /* 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, wire_model); + ModuleId wire_module = module_manager.find_module(circuit_lib.model_name(wire_model)); + VTR_ASSERT(true == module_manager.valid_module_id(wire_module)); /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, module_id); + print_verilog_module_declaration(fp, module_manager, wire_module); /* Finish dumping ports */ /* Print the internal logic of Verilog module */ /* Find the input port of the module */ - ModulePortId module_input_port_id = module_manager.find_module_port(module_id, circuit_lib.port_lib_name(input_ports[0])); + ModulePortId module_input_port_id = module_manager.find_module_port(wire_module, circuit_lib.port_lib_name(input_ports[0])); VTR_ASSERT(ModulePortId::INVALID() != module_input_port_id); - BasicPort module_input_port = module_manager.module_port(module_id, module_input_port_id); + BasicPort module_input_port = module_manager.module_port(wire_module, module_input_port_id); /* Find the output port of the module */ - ModulePortId module_output_port_id = module_manager.find_module_port(module_id, circuit_lib.port_lib_name(output_ports[0])); + ModulePortId module_output_port_id = module_manager.find_module_port(wire_module, circuit_lib.port_lib_name(output_ports[0])); VTR_ASSERT(ModulePortId::INVALID() != module_output_port_id); - BasicPort module_output_port = module_manager.module_port(module_id, module_output_port_id); + BasicPort module_output_port = module_manager.module_port(wire_module, module_output_port_id); /* Print wire declaration for the inputs and outputs */ fp << generate_verilog_port(VERILOG_PORT_WIRE, module_input_port) << ";" << std::endl; @@ -130,26 +131,28 @@ void print_verilog_routing_wire_module(ModuleManager& module_manager, VTR_ASSERT (1 == circuit_lib.port_size(output_ports[0])); /* 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, wire_model, wire_subckt_name); + ModuleId wire_module = module_manager.find_module(wire_subckt_name); + VTR_ASSERT(true == module_manager.valid_module_id(wire_module)); /* Add a mid-output port to the module */ BasicPort module_mid_output_port(generate_segment_wire_mid_output_name(circuit_lib.port_lib_name(output_ports[0])), circuit_lib.port_size(output_ports[0])); - module_manager.add_port(module_id, module_mid_output_port, ModuleManager::MODULE_OUTPUT_PORT); + ModulePortId module_mid_output_port_id = module_manager.find_module_port(wire_module, module_mid_output_port.get_name()); + VTR_ASSERT(ModulePortId::INVALID() != module_mid_output_port_id); /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, module_id); + print_verilog_module_declaration(fp, module_manager, wire_module); /* Finish dumping ports */ /* Print the internal logic of Verilog module */ /* Find the input port of the module */ - ModulePortId module_input_port_id = module_manager.find_module_port(module_id, circuit_lib.port_lib_name(input_ports[0])); + ModulePortId module_input_port_id = module_manager.find_module_port(wire_module, circuit_lib.port_lib_name(input_ports[0])); VTR_ASSERT(ModulePortId::INVALID() != module_input_port_id); - BasicPort module_input_port = module_manager.module_port(module_id, module_input_port_id); + BasicPort module_input_port = module_manager.module_port(wire_module, module_input_port_id); /* Find the output port of the module */ - ModulePortId module_output_port_id = module_manager.find_module_port(module_id, circuit_lib.port_lib_name(output_ports[0])); + ModulePortId module_output_port_id = module_manager.find_module_port(wire_module, circuit_lib.port_lib_name(output_ports[0])); VTR_ASSERT(ModulePortId::INVALID() != module_output_port_id); - BasicPort module_output_port = module_manager.module_port(module_id, module_output_port_id); + BasicPort module_output_port = module_manager.module_port(wire_module, module_output_port_id); /* Print wire declaration for the inputs and outputs */ fp << generate_verilog_port(VERILOG_PORT_WIRE, module_input_port) << ";" << std::endl;