diff --git a/openfpga/src/base/openfpga_build_fabric.cpp b/openfpga/src/base/openfpga_build_fabric.cpp index 708bef124..b1a1fe118 100644 --- a/openfpga/src/base/openfpga_build_fabric.cpp +++ b/openfpga/src/base/openfpga_build_fabric.cpp @@ -76,8 +76,9 @@ int build_fabric(OpenfpgaContext& openfpga_ctx, VTR_LOG("\n"); openfpga_ctx.mutable_module_graph() = build_device_module_graph(openfpga_ctx.mutable_io_location_map(), - g_vpr_ctx.device(), + openfpga_ctx.mutable_decoder_lib(), const_cast(openfpga_ctx), + g_vpr_ctx.device(), cmd_context.option_enable(cmd, opt_compress_routing), cmd_context.option_enable(cmd, opt_duplicate_grid_pin), cmd_context.option_enable(cmd, opt_verbose)); diff --git a/openfpga/src/base/openfpga_context.h b/openfpga/src/base/openfpga_context.h index 2ea114410..8c025687f 100644 --- a/openfpga/src/base/openfpga_context.h +++ b/openfpga/src/base/openfpga_context.h @@ -10,6 +10,7 @@ #include "vpr_placement_annotation.h" #include "vpr_routing_annotation.h" #include "mux_library.h" +#include "decoder_library.h" #include "tile_direct.h" #include "module_manager.h" #include "netlist_manager.h" @@ -55,6 +56,7 @@ class OpenfpgaContext : public Context { const openfpga::VprRoutingAnnotation& vpr_routing_annotation() const { return vpr_routing_annotation_; } const openfpga::DeviceRRGSB& device_rr_gsb() const { return device_rr_gsb_; } const openfpga::MuxLibrary& mux_lib() const { return mux_lib_; } + const openfpga::DecoderLibrary& decoder_lib() const { return decoder_lib_; } const openfpga::TileDirect& tile_direct() const { return tile_direct_; } const openfpga::ModuleManager& module_graph() const { return module_graph_; } const openfpga::FlowManager& flow_manager() const { return flow_manager_; } @@ -72,6 +74,7 @@ class OpenfpgaContext : public Context { openfpga::VprRoutingAnnotation& mutable_vpr_routing_annotation() { return vpr_routing_annotation_; } openfpga::DeviceRRGSB& mutable_device_rr_gsb() { return device_rr_gsb_; } openfpga::MuxLibrary& mutable_mux_lib() { return mux_lib_; } + openfpga::DecoderLibrary& mutable_decoder_lib() { return decoder_lib_; } openfpga::TileDirect& mutable_tile_direct() { return tile_direct_; } openfpga::ModuleManager& mutable_module_graph() { return module_graph_; } openfpga::FlowManager& mutable_flow_manager() { return flow_manager_; } @@ -105,6 +108,9 @@ class OpenfpgaContext : public Context { /* Library of physical implmentation of routing multiplexers */ openfpga::MuxLibrary mux_lib_; + /* Library of physical implmentation of decoders */ + openfpga::DecoderLibrary decoder_lib_; + /* Inner/inter-column/row tile direct connections */ openfpga::TileDirect tile_direct_; diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index 74750fca5..bf82a1d7c 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -142,6 +142,20 @@ std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size, return subckt_name; } +/************************************************ + * Generate the module name of a decoder + * for frame-based memories + ***********************************************/ +std::string generate_frame_memory_decoder_subckt_name(const size_t& addr_size, + const size_t& data_size) { + std::string subckt_name = "frame_decoder"; + subckt_name += std::to_string(addr_size); + subckt_name += "to"; + subckt_name += std::to_string(data_size); + + return subckt_name; +} + /************************************************ * Generate the module name of a routing track wire ***********************************************/ diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h index 9896dddd4..d3cfb04f0 100644 --- a/openfpga/src/base/openfpga_naming.h +++ b/openfpga/src/base/openfpga_naming.h @@ -50,6 +50,9 @@ std::string generate_mux_branch_subckt_name(const CircuitLibrary& circuit_lib, std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size, const size_t& data_size); +std::string generate_frame_memory_decoder_subckt_name(const size_t& addr_size, + const size_t& data_size); + std::string generate_segment_wire_subckt_name(const std::string& wire_model_name, const size_t& segment_id); diff --git a/openfpga/src/base/openfpga_reserved_words.h b/openfpga/src/base/openfpga_reserved_words.h index be47315ba..c556a19b1 100644 --- a/openfpga/src/base/openfpga_reserved_words.h +++ b/openfpga/src/base/openfpga_reserved_words.h @@ -30,6 +30,12 @@ constexpr char* GRID_MUX_INSTANCE_PREFIX = "mux_"; constexpr char* SWITCH_BLOCK_MUX_INSTANCE_PREFIX = "mux_"; constexpr char* CONNECTION_BLOCK_MUX_INSTANCE_PREFIX = "mux_"; +/* Decoder naming constant strings */ +constexpr char* DECODER_ENABLE_PORT_NAME = "enable"; +constexpr char* DECODER_ADDRESS_PORT_NAME = "address"; +constexpr char* DECODER_DATA_PORT_NAME = "data"; +constexpr char* DECODER_DATA_INV_PORT_NAME = "data_inv"; + /* Inverted port naming */ constexpr char* INV_PORT_POSTFIX = "_inv"; diff --git a/openfpga/src/fabric/build_decoder_modules.cpp b/openfpga/src/fabric/build_decoder_modules.cpp index 06defc007..a2accae89 100644 --- a/openfpga/src/fabric/build_decoder_modules.cpp +++ b/openfpga/src/fabric/build_decoder_modules.cpp @@ -9,6 +9,7 @@ #include "vtr_assert.h" #include "vtr_time.h" +#include "openfpga_reserved_words.h" #include "openfpga_naming.h" #include "decoder_library_utils.h" #include "module_manager_utils.h" @@ -18,6 +19,61 @@ /* begin namespace openfpga */ namespace openfpga { +/*************************************************************************************** + * Create a module for a decoder with a given output size + * + * Data input + * | | ... | + * v v v + * +-----------+ + * / \ + * enable-->/ Decoder \ + * +-----------------+ + * | | | ... | | | + * v v v v v v + * Data Outputs + * + * The outputs are assumes to be one-hot codes (at most only one '1' exist) + * Considering this fact, there are only num_of_outputs conditions to be encoded. + * Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2)) + ***************************************************************************************/ +ModuleId build_frame_memory_decoder_module(ModuleManager& module_manager, + const DecoderLibrary& decoder_lib, + const DecoderId& decoder) { + /* Get the number of inputs */ + size_t addr_size = decoder_lib.addr_size(decoder); + size_t data_size = decoder_lib.data_size(decoder); + + /* Create a name for the local encoder */ + std::string module_name = generate_frame_memory_decoder_subckt_name(addr_size, data_size); + + /* Create a Verilog Module based on the circuit model, and add to module manager */ + ModuleId module_id = module_manager.add_module(module_name); + VTR_ASSERT(true == module_manager.valid_module_id(module_id)); + + /* Add enable port */ + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); + /* Add each input port */ + BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), addr_size); + module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT); + /* Add each output port */ + BasicPort data_port(std::string(DECODER_DATA_PORT_NAME), data_size); + module_manager.add_port(module_id, data_port, ModuleManager::MODULE_OUTPUT_PORT); + + /* Data port is registered. It should be outputted as + * output reg [lsb:msb] data + */ + module_manager.set_port_is_register(module_id, data_port.get_name(), true); + /* Add data_in port */ + if (true == decoder_lib.use_data_inv_port(decoder)) { + BasicPort data_inv_port(std::string(DECODER_DATA_INV_PORT_NAME), data_size); + module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT); + } + + return module_id; +} + /*************************************************************************************** * Create a module for a decoder with a given output size * @@ -44,7 +100,7 @@ void build_mux_local_decoder_module(ModuleManager& module_manager, size_t addr_size = decoder_lib.addr_size(decoder); size_t data_size = decoder_lib.data_size(decoder); - /* TODO: create a name for the local encoder */ + /* Create a name for the local encoder */ std::string module_name = generate_mux_local_decoder_subckt_name(addr_size, data_size); /* Create a Verilog Module based on the circuit model, and add to module manager */ @@ -67,7 +123,6 @@ void build_mux_local_decoder_module(ModuleManager& module_manager, module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT); } - /*************************************************************************************** * This function will generate all the unique Verilog modules of local decoders for * the multiplexers used in a FPGA fabric diff --git a/openfpga/src/fabric/build_decoder_modules.h b/openfpga/src/fabric/build_decoder_modules.h index 842aef8c4..bf18e47d4 100644 --- a/openfpga/src/fabric/build_decoder_modules.h +++ b/openfpga/src/fabric/build_decoder_modules.h @@ -5,6 +5,7 @@ * Include header files that are required by function declaration *******************************************************************/ #include "module_manager.h" +#include "decoder_library.h" #include "mux_library.h" #include "circuit_library.h" @@ -15,6 +16,10 @@ /* begin namespace openfpga */ namespace openfpga { +ModuleId build_frame_memory_decoder_module(ModuleManager& module_manager, + const DecoderLibrary& decoder_lib, + const DecoderId& decoder); + void build_mux_local_decoder_modules(ModuleManager& module_manager, const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib); diff --git a/openfpga/src/fabric/build_device_module.cpp b/openfpga/src/fabric/build_device_module.cpp index 9680285fa..1d65fef7c 100644 --- a/openfpga/src/fabric/build_device_module.cpp +++ b/openfpga/src/fabric/build_device_module.cpp @@ -27,8 +27,9 @@ namespace openfpga { * for a FPGA fabric *******************************************************************/ ModuleManager build_device_module_graph(IoLocationMap& io_location_map, - const DeviceContext& vpr_device_ctx, + DecoderLibrary& decoder_lib, const OpenfpgaContext& openfpga_ctx, + const DeviceContext& vpr_device_ctx, const bool& compress_routing, const bool& duplicate_grid_pin, const bool& verbose) { @@ -66,7 +67,9 @@ ModuleManager build_device_module_graph(IoLocationMap& io_location_map, build_wire_modules(module_manager, openfpga_ctx.arch().circuit_lib); /* Build memory modules */ - build_memory_modules(module_manager, openfpga_ctx.mux_lib(), + build_memory_modules(module_manager, + decoder_lib, + openfpga_ctx.mux_lib(), openfpga_ctx.arch().circuit_lib, openfpga_ctx.arch().config_protocol.type()); diff --git a/openfpga/src/fabric/build_device_module.h b/openfpga/src/fabric/build_device_module.h index b8f8c0ac8..75a9f982c 100644 --- a/openfpga/src/fabric/build_device_module.h +++ b/openfpga/src/fabric/build_device_module.h @@ -15,8 +15,9 @@ namespace openfpga { ModuleManager build_device_module_graph(IoLocationMap& io_location_map, - const DeviceContext& vpr_device_ctx, + DecoderLibrary& decoder_lib, const OpenfpgaContext& openfpga_ctx, + const DeviceContext& vpr_device_ctx, const bool& compress_routing, const bool& duplicate_grid_pin, const bool& verbose); diff --git a/openfpga/src/fabric/build_memory_modules.cpp b/openfpga/src/fabric/build_memory_modules.cpp index 299bf6d70..bbdb01fef 100644 --- a/openfpga/src/fabric/build_memory_modules.cpp +++ b/openfpga/src/fabric/build_memory_modules.cpp @@ -15,12 +15,14 @@ #include "mux_graph.h" #include "module_manager.h" #include "circuit_library_utils.h" +#include "decoder_library_utils.h" #include "module_manager_utils.h" #include "mux_utils.h" #include "openfpga_reserved_words.h" #include "openfpga_naming.h" +#include "build_decoder_modules.h" #include "build_memory_modules.h" /* begin namespace openfpga */ @@ -553,6 +555,178 @@ void build_memory_bank_module(ModuleManager& module_manager, add_module_global_ports_from_child_modules(module_manager, mem_module); } +/********************************************************************* + * Frame-based Memory organization + * + * EN Address Data + * | | | + * v v v + * +------------------------------------+ + * | Address Decoder | + * +------------------------------------+ + * | | | + * v v v + * +-------+ +-------+ +-------+ + * | SRAM | | SRAM | ... | SRAM | + * | [0] | | [1] | | [N-1] | + * +-------+ +-------+ +-------+ + * | | ... | + * v v v + * +------------------------------------+ + * | Multiplexer Configuration port | + * + ********************************************************************/ +static +void build_frame_memory_module(ModuleManager& module_manager, + DecoderLibrary& frame_decoder_lib, + const CircuitLibrary& circuit_lib, + const std::string& module_name, + const CircuitModelId& sram_model, + const size_t& num_mems) { + + /* Get the global ports required by the SRAM */ + std::vector global_port_types; + global_port_types.push_back(CIRCUIT_MODEL_PORT_CLOCK); + global_port_types.push_back(CIRCUIT_MODEL_PORT_INPUT); + std::vector sram_global_ports = circuit_lib.model_global_ports_by_type(sram_model, global_port_types, true, false); + /* Get the input ports from the SRAM */ + std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); + /* A SRAM cell with BL/WL should not have any input */ + VTR_ASSERT( 0 == sram_input_ports.size() ); + + /* Get the output ports from the SRAM */ + std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + + /* Get the BL/WL ports from the SRAM + * Here, we consider that the WL port will be EN signal of a SRAM + * and the BL port will be the data_in signal of a SRAM + */ + std::vector sram_bl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true); + std::vector sram_blb_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BLB, true); + std::vector sram_wl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WL, true); + std::vector sram_wlb_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLB, true); + + /* We do NOT expect any BLB port here!!! + * TODO: to suppor this, we need an inverter circuit model to be specified by users !!! + */ + VTR_ASSERT(1 == sram_bl_ports.size()); + VTR_ASSERT(1 == circuit_lib.port_size(sram_bl_ports[0])); + VTR_ASSERT(1 == sram_wl_ports.size()); + VTR_ASSERT(1 == circuit_lib.port_size(sram_wl_ports[0])); + VTR_ASSERT(0 == sram_blb_ports.size()); + + /* Create a module and add to the module manager */ + ModuleId mem_module = module_manager.add_module(module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); + + /* Find the specification of the decoder: + * Size of address port and data input + */ + size_t addr_size = find_mux_local_decoder_addr_size(num_mems); + /* Data input should match the WL (data_in) of a SRAM */ + size_t data_size = num_mems * circuit_lib.port_size(sram_bl_ports[0]); + bool use_data_inv = (0 < sram_blb_ports.size()); + + /* Search the decoder library + * If we find one, we use the module. + * Otherwise, we create one and add it to the decoder library + */ + DecoderId decoder_id = frame_decoder_lib.find_decoder(addr_size, data_size, true, true, use_data_inv); + if (DecoderId::INVALID() == decoder_id) { + decoder_id = frame_decoder_lib.add_decoder(addr_size, data_size, true, true, use_data_inv); + } + VTR_ASSERT(DecoderId::INVALID() != decoder_id); + + /* Create a module if not existed yet */ + std::string decoder_module_name = generate_frame_memory_decoder_subckt_name(addr_size, data_size); + ModuleId decoder_module = module_manager.find_module(decoder_module_name); + if (ModuleId::INVALID() == decoder_module) { + decoder_module = build_frame_memory_decoder_module(module_manager, + frame_decoder_lib, + decoder_id); + } + VTR_ASSERT(ModuleId::INVALID() != decoder_module); + + /* Add module ports */ + /* Input: Enable port */ + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + ModulePortId mem_en_port = module_manager.add_port(mem_module, en_port, ModuleManager::MODULE_INPUT_PORT); + + /* Input: Address port */ + BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), addr_size); + ModulePortId mem_addr_port = module_manager.add_port(mem_module, addr_port, ModuleManager::MODULE_INPUT_PORT); + + /* Input: Data port */ + BasicPort data_port(std::string(DECODER_DATA_PORT_NAME), data_size); + ModulePortId mem_data_port = module_manager.add_port(mem_module, data_port, ModuleManager::MODULE_INPUT_PORT); + + /* Add each output port: port width should match the number of memories */ + for (const auto& port : sram_output_ports) { + BasicPort output_port(circuit_lib.port_prefix(port), num_mems * circuit_lib.port_size(port)); + module_manager.add_port(mem_module, output_port, ModuleManager::MODULE_OUTPUT_PORT); + } + + /* Instanciate the decoder module here */ + VTR_ASSERT(0 == module_manager.num_instance(mem_module, decoder_module)); + module_manager.add_child_module(mem_module, decoder_module); + + /* Find the sram module in the module manager */ + ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model)); + + /* Build module nets */ + /* Wire enable port to decoder enable port */ + ModulePortId decoder_en_port = module_manager.find_module_port(decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); + add_module_bus_nets(module_manager, mem_module, + mem_module, 0, mem_en_port, + decoder_module, 0, decoder_en_port); + + /* Wire address port to decoder address port */ + ModulePortId decoder_addr_port = module_manager.find_module_port(decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + add_module_bus_nets(module_manager, mem_module, + mem_module, 0, mem_addr_port, + decoder_module, 0, decoder_addr_port); + + /* Instanciate each submodule */ + for (size_t i = 0; i < num_mems; ++i) { + /* Memory seed module instanciation */ + size_t sram_instance = module_manager.num_instance(mem_module, sram_mem_module); + module_manager.add_child_module(mem_module, sram_mem_module); + + /* Wire data_in port to SRAM BL port */ + ModulePortId sram_bl_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_lib_name(sram_bl_ports[0])); + add_module_bus_nets(module_manager, mem_module, + mem_module, 0, mem_data_port, + sram_mem_module, sram_instance, sram_bl_port); + + /* Wire decoder data_out port to sram WL ports */ + ModulePortId sram_wl_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_lib_name(sram_wl_ports[0])); + ModulePortId decoder_data_port = module_manager.find_module_port(decoder_module, std::string(DECODER_DATA_PORT_NAME)); + ModuleNetId wl_net = module_manager.create_module_net(mem_module); + /* Source node of the input net is the input of memory module */ + module_manager.add_module_net_source(mem_module, wl_net, decoder_module, 0, decoder_data_port, sram_instance); + module_manager.add_module_net_sink(mem_module, wl_net, sram_mem_module, sram_instance, sram_wl_port, 0); + + /* Optional: Wire decoder data_out inverted port to sram WLB ports */ + if (true == use_data_inv) { + ModulePortId sram_wlb_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_lib_name(sram_wlb_ports[0])); + ModulePortId decoder_data_inv_port = module_manager.find_module_port(decoder_module, std::string(DECODER_DATA_INV_PORT_NAME)); + ModuleNetId wlb_net = module_manager.create_module_net(mem_module); + /* Source node of the input net is the input of memory module */ + module_manager.add_module_net_source(mem_module, wlb_net, decoder_module, 0, decoder_data_inv_port, sram_instance); + module_manager.add_module_net_sink(mem_module, wlb_net, sram_mem_module, sram_instance, sram_wlb_port, 0); + } + + /* Wire inputs of parent module to outputs of child modules */ + add_module_output_nets_to_mem_modules(module_manager, mem_module, circuit_lib, sram_output_ports, sram_mem_module, i, sram_instance); + } + + /* 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, mem_module); +} + /********************************************************************* * Generate Verilog modules for the memories that are used @@ -566,6 +740,7 @@ void build_memory_bank_module(ModuleManager& module_manager, ********************************************************************/ static void build_memory_module(ModuleManager& module_manager, + DecoderLibrary& arch_decoder_lib, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const std::string& module_name, @@ -574,7 +749,7 @@ void build_memory_module(ModuleManager& module_manager, switch (sram_orgz_type) { case CONFIG_MEM_STANDALONE: build_memory_standalone_module(module_manager, circuit_lib, - module_name, sram_model, num_mems); + module_name, sram_model, num_mems); break; case CONFIG_MEM_SCAN_CHAIN: build_memory_chain_module(module_manager, circuit_lib, @@ -584,8 +759,13 @@ void build_memory_module(ModuleManager& module_manager, build_memory_bank_module(module_manager, circuit_lib, module_name, sram_model, num_mems); break; + case CONFIG_MEM_FRAME_BASED: + build_frame_memory_module(module_manager, arch_decoder_lib, circuit_lib, + module_name, sram_model, num_mems); + break; default: - VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid SRAM organization!\n"); + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid configurable memory organization!\n"); exit(1); } } @@ -606,6 +786,7 @@ void build_memory_module(ModuleManager& module_manager, ********************************************************************/ static void build_mux_memory_module(ModuleManager& module_manager, + DecoderLibrary& arch_decoder_lib, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& mux_model, @@ -626,7 +807,8 @@ void build_mux_memory_module(ModuleManager& module_manager, std::vector sram_models = find_circuit_sram_models(circuit_lib, mux_model); VTR_ASSERT( 1 == sram_models.size() ); - build_memory_module(module_manager, circuit_lib, sram_orgz_type, module_name, sram_models[0], num_config_bits); + build_memory_module(module_manager, arch_decoder_lib, + circuit_lib, sram_orgz_type, module_name, sram_models[0], num_config_bits); break; } case CIRCUIT_MODEL_DESIGN_RRAM: @@ -659,6 +841,7 @@ void build_mux_memory_module(ModuleManager& module_manager, * memory-bank organization for the memories. ********************************************************************/ void build_memory_modules(ModuleManager& module_manager, + DecoderLibrary& arch_decoder_lib, const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type) { @@ -676,7 +859,8 @@ void build_memory_modules(ModuleManager& module_manager, continue; } /* Create a Verilog module for the memories used by the multiplexer */ - build_mux_memory_module(module_manager, circuit_lib, sram_orgz_type, mux_model, mux_graph); + build_mux_memory_module(module_manager, arch_decoder_lib, + circuit_lib, sram_orgz_type, mux_model, mux_graph); } /* Create the memory circuits for non-MUX circuit models. @@ -708,7 +892,8 @@ void build_memory_modules(ModuleManager& module_manager, std::string module_name = generate_memory_module_name(circuit_lib, model, sram_models[0], std::string(MEMORY_MODULE_POSTFIX)); /* Create a Verilog module for the memories used by the circuit model */ - build_memory_module(module_manager, circuit_lib, sram_orgz_type, module_name, sram_models[0], num_mems); + build_memory_module(module_manager, arch_decoder_lib, + circuit_lib, sram_orgz_type, module_name, sram_models[0], num_mems); } } diff --git a/openfpga/src/fabric/build_memory_modules.h b/openfpga/src/fabric/build_memory_modules.h index 2728d1d81..3551426a2 100644 --- a/openfpga/src/fabric/build_memory_modules.h +++ b/openfpga/src/fabric/build_memory_modules.h @@ -4,6 +4,7 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ +#include "decoder_library.h" #include "circuit_library.h" #include "mux_library.h" #include "module_manager.h" @@ -16,6 +17,7 @@ namespace openfpga { void build_memory_modules(ModuleManager& module_manager, + DecoderLibrary& arch_decoder_lib, const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type); diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index b1408dcad..44e13c65a 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -1227,6 +1227,66 @@ size_t find_module_num_config_bits_from_child_modules(ModuleManager& module_mana return num_config_bits; } +/******************************************************************** + * Add a bus of nets to a module (cur_module_id) + * Note: + * - both src and des module should exist in the module manager + * - src_module should be the cur_module or a child of it + * - des_module should be the cur_module or a child of it + * - src_instance should be valid and des_instance should be valid as well + * - src port size should match the des port size + *******************************************************************/ +void add_module_bus_nets(ModuleManager& module_manager, + const ModuleId& cur_module_id, + const ModuleId& src_module_id, + const size_t& src_instance_id, + const ModulePortId& src_module_port_id, + const ModuleId& des_module_id, + const size_t& des_instance_id, + const ModulePortId& des_module_port_id) { + + VTR_ASSERT(true == module_manager.valid_module_id(cur_module_id)); + VTR_ASSERT(true == module_manager.valid_module_id(src_module_id)); + VTR_ASSERT(true == module_manager.valid_module_id(des_module_id)); + + VTR_ASSERT(true == module_manager.valid_module_port_id(src_module_id, src_module_port_id)); + VTR_ASSERT(true == module_manager.valid_module_port_id(des_module_id, des_module_port_id)); + + if (src_module_id == cur_module_id) { + VTR_ASSERT(0 == src_instance_id); + } else { + VTR_ASSERT(src_instance_id < module_manager.num_instance(cur_module_id, src_module_id)); + } + + if (des_module_id == cur_module_id) { + VTR_ASSERT(0 == des_instance_id); + } else { + VTR_ASSERT(des_instance_id < module_manager.num_instance(cur_module_id, des_module_id)); + } + + const BasicPort& src_port = module_manager.module_port(src_module_id, src_module_port_id); + const BasicPort& des_port = module_manager.module_port(des_module_id, des_module_port_id); + + if (src_port.get_width() != des_port.get_width()) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Unmatched port size: src_port is %lu while des_port is %lu!\n"); + exit(1); + } + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < src_port.pins().size(); ++pin_id) { + ModuleNetId net = module_manager.module_instance_port_net(cur_module_id, + src_module_id, src_instance_id, + src_module_port_id, src_port.pins()[pin_id]); + if (ModuleNetId::INVALID() == net) { + net = module_manager.create_module_net(cur_module_id); + } + /* Configure the net source */ + module_manager.add_module_net_source(cur_module_id, net, src_module_id, src_instance_id, src_module_port_id, src_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink(cur_module_id, net, des_module_id, des_instance_id, des_module_port_id, des_port.pins()[pin_id]); + } +} /******************************************************************** * TODO: diff --git a/openfpga/src/utils/module_manager_utils.h b/openfpga/src/utils/module_manager_utils.h index fcc95b8ba..0ecdfd282 100644 --- a/openfpga/src/utils/module_manager_utils.h +++ b/openfpga/src/utils/module_manager_utils.h @@ -129,6 +129,15 @@ size_t find_module_num_config_bits_from_child_modules(ModuleManager& module_mana const CircuitModelId& sram_model, const e_config_protocol_type& sram_orgz_type); +void add_module_bus_nets(ModuleManager& module_manager, + const ModuleId& cur_module_id, + const ModuleId& src_module_id, + const size_t& src_instance_id, + const ModulePortId& src_module_port_id, + const ModuleId& des_module_id, + const size_t& des_instance_id, + const ModulePortId& des_module_port_id); + } /* end namespace openfpga */ #endif