diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.cpp b/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.cpp index 373a46117..3a0a7d91a 100644 --- a/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.cpp +++ b/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.cpp @@ -92,6 +92,25 @@ std::vector find_circuit_regular_sram_ports(const CircuitLibrary& return regular_sram_ports; } +/******************************************************************** + * Find mode select sram ports of a circuit model + *******************************************************************/ +std::vector find_circuit_mode_select_sram_ports(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { + std::vector sram_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_SRAM, true); + std::vector mode_select_sram_ports; + + for (const auto& port : sram_ports) { + if (false == circuit_lib.port_is_mode_select(port)) { + continue; + } + mode_select_sram_ports.push_back(port); + } + + return mode_select_sram_ports; +} + + /******************************************************************** * Find the number of shared configuration bits for a ReRAM circuit * TODO: this function is subjected to be changed due to ReRAM-based SRAM cell design!!! diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.h b/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.h index 2fa705c25..03485a014 100644 --- a/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.h +++ b/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.h @@ -17,6 +17,9 @@ std::vector find_circuit_sram_models(const CircuitLibrary& circu std::vector find_circuit_regular_sram_ports(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); +std::vector find_circuit_mode_select_sram_ports(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model); + size_t find_circuit_num_shared_config_bits(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const e_sram_orgz& sram_orgz_type); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp index ea1b034ad..52e73c6c0 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp @@ -12,10 +12,12 @@ #include "spice_types.h" #include "circuit_library.h" +#include "circuit_library_utils.h" #include "module_manager.h" #include "fpga_x2p_naming.h" #include "fpga_x2p_pbtypes_utils.h" +#include "fpga_x2p_mem_utils.h" #include "module_manager_utils.h" @@ -397,3 +399,233 @@ void add_primitive_pb_type_module_nets(ModuleManager& module_manager, } } +/******************************************************************** + * Add the port-to-port connection between a logic module + * and a memory module + * Create nets to wire SRAM ports between logic module and memory module + * + * The information about SRAM ports of logic module are stored in the + * mem_output_bus_ports, where element [0] denotes the SRAM port while + * element [1] denotes the SRAMb port + * + * +---------+ +--------+ + * | | regular SRAM port | | + * | Logic |-----------------------+ | Memory | + * | Module | mode-select SRAM port |->| Module | + * | |-----------------------+ | | + * +---------+ +--------+ + * + * There could be multiple SRAM ports of logic module, which are wired to + * the SRAM ports of memory module + * + * Note: this function SHOULD be called after the pb_type_module is created + * and its child module (logic_module and memory_module) is created! + * + * Note: this function only handle either SRAM or SRAMb ports. + * So, this function may be called twice to complete the wiring + *******************************************************************/ +static +void add_module_nets_between_logic_and_memory_sram_ports(ModuleManager& module_manager, + const ModuleId& parent_module, + const ModuleId& logic_module, + const size_t& logic_instance_id, + const ModuleId& memory_module, + const size_t& memory_instance_id, + const std::vector& logic_module_sram_port_ids, + const ModulePortId& mem_module_sram_port_id) { + /* Find mem_output_bus ports in logic module */ + std::vector logic_module_sram_ports; + for (const ModulePortId& logic_module_sram_port_id : logic_module_sram_port_ids) { + logic_module_sram_ports.push_back(module_manager.module_port(logic_module, logic_module_sram_port_id)); + } + + /* Create a list of virtual ports to align with the SRAM port of logic module + * Physical ports: + * + * logic_module_sram_port[0] logic_module_sram_port[1] + * + * LSB[0]------------>MSB[0] LSB------------------>MSB + * + * memory_sram_port + * LSBY---------------------------------------------->MSBY + * + * Virtual ports: + * mem_module_sram_port[0] mem_module_sram_port[1] + * LSBY--------------->MSBX MSBX+1------------------>MSBY + * + */ + BasicPort mem_module_port = module_manager.module_port(memory_module, mem_module_sram_port_id); + std::vector virtual_mem_module_ports; + + /* Create a counter for the LSB of virtual ports */ + size_t port_lsb = 0; + for (const BasicPort& logic_module_sram_port : logic_module_sram_ports) { + BasicPort virtual_port; + virtual_port.set_name(mem_module_port.get_name()); + virtual_port.set_width(port_lsb, port_lsb + logic_module_sram_port.get_width() - 1); + virtual_mem_module_ports.push_back(virtual_port); + port_lsb = virtual_port.get_msb() + 1; + } + /* port_lsb should be aligned with the MSB of memory_sram_port */ + VTR_ASSERT(port_lsb == mem_module_port.get_msb() + 1); + + /* Wire port to port */ + for (size_t port_index = 0; port_index < logic_module_sram_ports.size(); ++port_index) { + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < logic_module_sram_ports[port_index].pins().size(); ++pin_id) { + ModuleNetId net = module_manager.create_module_net(parent_module); + /* Add net source */ + module_manager.add_module_net_source(parent_module, net, logic_module, logic_instance_id, logic_module_sram_port_ids[port_index], logic_module_sram_ports[port_index].pins()[pin_id]); + /* Add net sink */ + module_manager.add_module_net_sink(parent_module, net, memory_module, memory_instance_id, mem_module_sram_port_id, virtual_mem_module_ports[port_index].pins()[pin_id]); + } + } +} + +/******************************************************************** + * Add the port-to-port connection between a logic module + * and a memory module + * Create nets to wire SRAM ports between logic module and memory module + * + * + * +---------+ +--------+ + * | | SRAM ports | | + * | Logic |----------------------->| Memory | + * | Module | SRAMb ports | Module | + * | |----------------------->| | + * +---------+ +--------+ + * + * Note: this function SHOULD be called after the pb_type_module is created + * and its child module (logic_module and memory_module) is created! + * + *******************************************************************/ +void add_module_nets_between_logic_and_memory_sram_bus(ModuleManager& module_manager, + const ModuleId& parent_module, + const ModuleId& logic_module, + const size_t& logic_instance_id, + const ModuleId& memory_module, + const size_t& memory_instance_id, + const CircuitLibrary& circuit_lib, + const CircuitModelId& logic_model) { + + /* Connect SRAM port */ + /* Find SRAM ports in the circuit model for logic module */ + std::vector logic_model_sram_port_names; + /* Regular sram port goes first */ + for (CircuitPortId regular_sram_port : find_circuit_regular_sram_ports(circuit_lib, logic_model)) { + logic_model_sram_port_names.push_back(circuit_lib.port_lib_name(regular_sram_port)); + } + /* Mode-select sram port goes first */ + for (CircuitPortId mode_select_sram_port : find_circuit_mode_select_sram_ports(circuit_lib, logic_model)) { + logic_model_sram_port_names.push_back(circuit_lib.port_lib_name(mode_select_sram_port)); + } + /* Find the port ids in the memory */ + std::vector logic_module_sram_port_ids; + for (const std::string& logic_model_sram_port_name : logic_model_sram_port_names) { + /* Skip non-exist ports */ + if (ModulePortId::INVALID() == module_manager.find_module_port(logic_module, logic_model_sram_port_name)) { + continue; + } + logic_module_sram_port_ids.push_back(module_manager.find_module_port(logic_module, logic_model_sram_port_name)); + } + + /* Get the SRAM port name of memory model */ + /* TODO: this should be a constant expression and it should be the same for all the memory module! */ + std::string memory_model_sram_port_name = generate_configuration_chain_data_out_name(); + /* Find the corresponding ports in memory module */ + ModulePortId mem_module_sram_port_id = module_manager.find_module_port(memory_module, memory_model_sram_port_name); + + /* Do wiring only when we have sram ports */ + if ( (false == logic_module_sram_port_ids.empty()) + || (ModulePortId::INVALID() == mem_module_sram_port_id) ) { + add_module_nets_between_logic_and_memory_sram_ports(module_manager, parent_module, + logic_module, logic_instance_id, + memory_module, memory_instance_id, + logic_module_sram_port_ids, mem_module_sram_port_id); + } + + /* Connect SRAMb port */ + /* Find SRAM ports in the circuit model for logic module */ + std::vector logic_model_sramb_port_names; + /* Regular sram port goes first */ + for (CircuitPortId regular_sram_port : find_circuit_regular_sram_ports(circuit_lib, logic_model)) { + logic_model_sramb_port_names.push_back(circuit_lib.port_lib_name(regular_sram_port) + std::string("_inv")); + } + /* Mode-select sram port goes first */ + for (CircuitPortId mode_select_sram_port : find_circuit_mode_select_sram_ports(circuit_lib, logic_model)) { + logic_model_sramb_port_names.push_back(circuit_lib.port_lib_name(mode_select_sram_port) + std::string("_inv")); + } + /* Find the port ids in the memory */ + std::vector logic_module_sramb_port_ids; + for (const std::string& logic_model_sramb_port_name : logic_model_sramb_port_names) { + /* Skip non-exist ports */ + if (ModulePortId::INVALID() == module_manager.find_module_port(logic_module, logic_model_sramb_port_name)) { + continue; + } + logic_module_sramb_port_ids.push_back(module_manager.find_module_port(logic_module, logic_model_sramb_port_name)); + } + + /* Get the SRAM port name of memory model */ + std::string memory_model_sramb_port_name = generate_configuration_chain_inverted_data_out_name(); + /* Find the corresponding ports in memory module */ + ModulePortId mem_module_sramb_port_id = module_manager.find_module_port(memory_module, memory_model_sramb_port_name); + + /* Do wiring only when we have sramb ports */ + if ( (false == logic_module_sramb_port_ids.empty()) + || (ModulePortId::INVALID() == mem_module_sramb_port_id) ) { + add_module_nets_between_logic_and_memory_sram_ports(module_manager, parent_module, + logic_module, logic_instance_id, + memory_module, memory_instance_id, + logic_module_sramb_port_ids, mem_module_sramb_port_id); + } +} + +/******************************************************************** + * TODO: + * Add the port-to-port connection between a logic module + * and a memory module inside a primitive module + * + * Create nets to wire the control signals of memory module to + * the configuration ports of primitive module + * + * Primitive module + * +----------------------------+ + * | +--------+ | + * config | | | | + * ports --->|--------------->| Memory | | + * | | Module | | + * | | | | + * | +--------+ | + * +----------------------------+ + * The detailed config ports really depend on the type + * of SRAM organization. + * + * Note: this function SHOULD be called after the pb_type_module is created + * and its child module (logic_module and memory_module) is created! + *******************************************************************/ + +/******************************************************************** + * TODO: + * Add the port-to-port connection between a logic module + * and a memory module inside a primitive module + * + * Create nets to wire the formal verification ports of + * primitive module to SRAM ports of logic module + * + * Primitive module + * + * formal_port_sram + * +-----------------------------------------------+ + * | ^ | + * | +---------+ | +--------+ | + * | | | SRAM | | | | + * | | Logic |--------+--->| Memory | | + * | | Module | SRAMb | Module | | + * | | |--------+--->| | | + * | +---------+ | +--------+ | + * | v | + * +-----------------------------------------------+ + * formal_port_sramb + * + *******************************************************************/ + diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h index 4bfa2125c..e67127fcd 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h @@ -55,4 +55,14 @@ void add_primitive_pb_type_module_nets(ModuleManager& module_manager, const size_t& child_instance_id, const CircuitLibrary& circuit_lib, t_pb_type* cur_pb_type); + +void add_module_nets_between_logic_and_memory_sram_bus(ModuleManager& module_manager, + const ModuleId& parent_module, + const ModuleId& logic_module, + const size_t& logic_instance_id, + const ModuleId& memory_module, + const size_t& memory_instance_id, + const CircuitLibrary& circuit_lib, + const CircuitModelId& logic_model); + #endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp index 9151fafc7..95360ccf8 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp @@ -156,11 +156,26 @@ void print_verilog_primitive_block(std::fstream& fp, /* Add nets to connect the logic model ports to pb_type ports */ add_primitive_pb_type_module_nets(module_manager, primitive_module, logic_module, logic_instance_id, circuit_lib, primitive_pb_graph_node->pb_type); - /* TODO: add the associated memory module as a child of primitive module */ + /* Add the associated memory module as a child of primitive module */ + std::string memory_module_name = generate_memory_module_name(circuit_lib, primitive_model, sram_model, std::string(verilog_mem_posfix)); + ModuleId memory_module = module_manager.find_module(memory_module_name); - /* TODO: Add nets to connect regular and mode-select SRAM ports to the SRAM port of memory module */ - - /* TODO: write the verilog module */ + /* If there is no memory module required, we can skip the assocated net addition */ + if (ModuleId::INVALID() != memory_module) { + size_t memory_instance_id = module_manager.num_instance(primitive_module, memory_module); + /* Add the memory module as a child of primitive module */ + module_manager.add_child_module(primitive_module, memory_module); + + /* Add nets to connect regular and mode-select SRAM ports to the SRAM port of memory module */ + add_module_nets_between_logic_and_memory_sram_bus(module_manager, primitive_module, + logic_module, logic_instance_id, + memory_module, memory_instance_id, + circuit_lib, primitive_model); + /* TODO: Add nets to connect configuration ports from memory module to primitive module */ + /* TODO: Add nets to connect formal verification ports from memory module to primitive module */ + } + + /* Write the verilog module */ write_verilog_module_to_file(fp, module_manager, primitive_module, use_explicit_mapping); /* Add an empty line as a splitter */