From 36a4da863c51e3b5c6349f414210ab4f6498cef6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 20 Sep 2021 16:05:36 -0700 Subject: [PATCH] [Engine] Support WLR port in OpenFPGA architecture file and fabric generator --- .../libarchopenfpga/src/circuit_types.h | 3 +- .../src/openfpga_reserved_words.h | 3 + openfpga/src/base/openfpga_naming.cpp | 6 +- openfpga/src/fabric/build_decoder_modules.cpp | 12 +++ openfpga/src/fabric/build_memory_modules.cpp | 18 ++++- .../src/fabric/build_top_module_memory.cpp | 18 +++-- .../fabric/build_top_module_memory_bank.cpp | 73 +++++++++++++++++-- openfpga/src/mux_lib/decoder_library.cpp | 15 +++- openfpga/src/mux_lib/decoder_library.h | 9 ++- openfpga/src/utils/decoder_library_utils.cpp | 4 +- openfpga/src/utils/memory_utils.cpp | 3 +- openfpga/src/utils/module_manager_utils.cpp | 40 ++++++---- 12 files changed, 165 insertions(+), 39 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/circuit_types.h b/libopenfpga/libarchopenfpga/src/circuit_types.h index 3a2604a42..12b881db0 100644 --- a/libopenfpga/libarchopenfpga/src/circuit_types.h +++ b/libopenfpga/libarchopenfpga/src/circuit_types.h @@ -101,10 +101,11 @@ enum e_circuit_model_port_type { CIRCUIT_MODEL_PORT_BLB, CIRCUIT_MODEL_PORT_WL, CIRCUIT_MODEL_PORT_WLB, + CIRCUIT_MODEL_PORT_WLR, NUM_CIRCUIT_MODEL_PORT_TYPES }; /* Strings correspond to each port type */ -constexpr std::array CIRCUIT_MODEL_PORT_TYPE_STRING = {{"input", "output", "inout", "clock", "sram", "bl", "blb", "wl", "wlb"}}; +constexpr std::array CIRCUIT_MODEL_PORT_TYPE_STRING = {{"input", "output", "inout", "clock", "sram", "bl", "blb", "wl", "wlb", "wlr"}}; enum e_circuit_model_delay_type { CIRCUIT_MODEL_DELAY_RISE, diff --git a/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h b/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h index 732247178..af151a7a5 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h @@ -33,6 +33,7 @@ constexpr char* CONNECTION_BLOCK_MEM_INSTANCE_PREFIX = "mem_"; constexpr char* MEMORY_MODULE_POSTFIX = "_mem"; constexpr char* MEMORY_BL_PORT_NAME = "bl"; constexpr char* MEMORY_WL_PORT_NAME = "wl"; +constexpr char* MEMORY_WLR_PORT_NAME = "wlr"; /* Multiplexer naming constant strings */ constexpr char* MUX_BASIS_MODULE_POSTFIX = "_basis"; @@ -48,6 +49,8 @@ constexpr char* DECODER_DATA_OUT_PORT_NAME = "data_out"; constexpr char* DECODER_DATA_OUT_INV_PORT_NAME = "data_out_inv"; constexpr char* DECODER_BL_ADDRESS_PORT_NAME = "bl_address"; constexpr char* DECODER_WL_ADDRESS_PORT_NAME = "wl_address"; +constexpr char* DECODER_READBACK_PORT_NAME = "readback"; +constexpr char* DECODER_DATA_READ_ENABLE_PORT_NAME = "data_out_ren"; /* Inverted port naming */ constexpr char* INV_PORT_POSTFIX = "_inv"; diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index c898066b3..3dab1ca7f 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -719,9 +719,11 @@ std::string generate_sram_port_name(const e_config_protocol_type& sram_orgz_type */ if (CIRCUIT_MODEL_PORT_BL == port_type) { port_name = std::string(MEMORY_BL_PORT_NAME); - } else { - VTR_ASSERT( CIRCUIT_MODEL_PORT_WL == port_type ); + } else if (CIRCUIT_MODEL_PORT_WL == port_type) { port_name = std::string(MEMORY_WL_PORT_NAME); + } else { + VTR_ASSERT( CIRCUIT_MODEL_PORT_WLR == port_type ); + port_name = std::string(MEMORY_WLR_PORT_NAME); } break; case CONFIG_MEM_FRAME_BASED: diff --git a/openfpga/src/fabric/build_decoder_modules.cpp b/openfpga/src/fabric/build_decoder_modules.cpp index 949058ba8..fe18212e7 100644 --- a/openfpga/src/fabric/build_decoder_modules.cpp +++ b/openfpga/src/fabric/build_decoder_modules.cpp @@ -184,6 +184,18 @@ ModuleId build_wl_memory_decoder_module(ModuleManager& module_manager, module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT); } + /* Add readback port */ + if (true == decoder_lib.use_readback(decoder)) { + BasicPort readback_port(std::string(DECODER_READBACK_PORT_NAME), 1); + module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT); + } + + /* Add data read-enable port */ + if (true == decoder_lib.use_readback(decoder)) { + BasicPort data_ren_port(std::string(DECODER_DATA_READ_ENABLE_PORT_NAME), data_size); + module_manager.add_port(module_id, data_ren_port, ModuleManager::MODULE_OUTPUT_PORT); + } + return module_id; } diff --git a/openfpga/src/fabric/build_memory_modules.cpp b/openfpga/src/fabric/build_memory_modules.cpp index 8a354da75..a8f7fceb4 100644 --- a/openfpga/src/fabric/build_memory_modules.cpp +++ b/openfpga/src/fabric/build_memory_modules.cpp @@ -366,12 +366,15 @@ void build_memory_flatten_module(ModuleManager& module_manager, /* Get the BL/WL ports from the SRAM */ std::vector sram_bl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true); std::vector sram_wl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WL, true); + /* Optional: Get the WLR ports from the SRAM */ + std::vector sram_wlr_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR, true); /* 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); - /* Ensure that we have only 1 BL, 1 WL and 2 output ports*/ + /* Ensure that we have only 1 BL, 1 WL and 2 output ports, as well as an optional WLR*/ VTR_ASSERT(1 == sram_bl_ports.size()); VTR_ASSERT(1 == sram_wl_ports.size()); + VTR_ASSERT(2 > sram_wlr_ports.size()); VTR_ASSERT(2 == sram_output_ports.size()); /* Create a module and add to the module manager */ @@ -389,6 +392,12 @@ void build_memory_flatten_module(ModuleManager& module_manager, BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), num_mems); ModulePortId mem_wl_port = module_manager.add_port(mem_module, wl_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort wlr_port(std::string(MEMORY_WLR_PORT_NAME), num_mems); + ModulePortId mem_wlr_port = ModulePortId::INVALID(); + if (!sram_wlr_ports.empty()) { + mem_wlr_port = module_manager.add_port(mem_module, wlr_port, ModuleManager::MODULE_INPUT_PORT); + } + /* Add each output port: port width should match the number of memories */ for (size_t iport = 0; iport < sram_output_ports.size(); ++iport) { std::string port_name; @@ -419,6 +428,9 @@ void build_memory_flatten_module(ModuleManager& module_manager, for (const CircuitPortId& port : sram_wl_ports) { add_module_input_nets_to_mem_modules(module_manager, mem_module, mem_wl_port, circuit_lib, port, sram_mem_module, i, sram_mem_instance); } + for (const CircuitPortId& port : sram_wlr_ports) { + add_module_input_nets_to_mem_modules(module_manager, mem_module, mem_wlr_port, circuit_lib, port, sram_mem_module, i, sram_mem_instance); + } /* Wire outputs of child module to outputs of parent module */ add_module_output_nets_to_mem_modules(module_manager, mem_module, circuit_lib, sram_output_ports, sram_mem_module, i, sram_mem_instance); } @@ -644,9 +656,9 @@ void build_frame_memory_module(ModuleManager& module_manager, * 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, false, use_data_inv); + DecoderId decoder_id = frame_decoder_lib.find_decoder(addr_size, data_size, true, false, use_data_inv, false); if (DecoderId::INVALID() == decoder_id) { - decoder_id = frame_decoder_lib.add_decoder(addr_size, data_size, true, false, use_data_inv); + decoder_id = frame_decoder_lib.add_decoder(addr_size, data_size, true, false, use_data_inv, false); } VTR_ASSERT(DecoderId::INVALID() != decoder_id); diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index bcc093062..c9ee2b722 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -870,6 +870,12 @@ void add_top_module_sram_ports(ModuleManager& module_manager, BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); + /* Optional: If we have WLR port, we should add a read-back port */ + if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR).empty()) { + BasicPort readback_port(std::string(DECODER_READBACK_PORT_NAME), config_protocol.num_regions()); + module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT); + } + /* Data input should be dependent on the number of configuration regions*/ BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), config_protocol.num_regions()); module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); @@ -1056,9 +1062,9 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag * Otherwise, we create one and add it to the decoder library */ DecoderId bl_decoder_id = decoder_lib.find_decoder(bl_addr_size, num_bls, - true, true, false); + true, true, false, false); if (DecoderId::INVALID() == bl_decoder_id) { - bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false); + bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false, false); } VTR_ASSERT(DecoderId::INVALID() != bl_decoder_id); @@ -1084,9 +1090,9 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag * Otherwise, we create one and add it to the decoder library */ DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls, - true, false, false); + true, false, false, false); if (DecoderId::INVALID() == wl_decoder_id) { - wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false); + wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false, false); } VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id); @@ -1533,9 +1539,9 @@ void add_top_module_nets_cmos_memory_frame_decoder_config_bus(ModuleManager& mod /* Search the decoder library and try to find one * If not found, create a new module and add it to the module manager */ - DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false); + DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false, false); if (DecoderId::INVALID() == decoder_id) { - decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false); + decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false, false); } VTR_ASSERT(DecoderId::INVALID() != decoder_id); diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index c1bfac4b2..7c60a03d8 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -137,6 +137,16 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma /* Data in port should match the number of configuration regions */ VTR_ASSERT(din_port_info.get_width() == module_manager.regions(top_module).size()); + /* Find readback port from the top-level module */ + ModulePortId readback_port = module_manager.find_module_port(top_module, std::string(DECODER_READBACK_PORT_NAME)); + BasicPort readback_port_info; + + /* Readback port if available, should be a 1-bit port */ + if (readback_port) { + readback_port_info = module_manager.module_port(top_module, readback_port); + VTR_ASSERT(readback_port_info.get_width() == 1); + } + /* Find BL and WL address port from the top-level module */ ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); @@ -168,9 +178,9 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma * Otherwise, we create one and add it to the decoder library */ DecoderId bl_decoder_id = decoder_lib.find_decoder(bl_addr_size, num_bls, - true, true, false); + true, true, false, false); if (DecoderId::INVALID() == bl_decoder_id) { - bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false); + bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false, false); } VTR_ASSERT(DecoderId::INVALID() != bl_decoder_id); @@ -196,9 +206,9 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma * Otherwise, we create one and add it to the decoder library */ DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls, - true, false, false); + true, false, false, readback_port != ModulePortId::INVALID()); if (DecoderId::INVALID() == wl_decoder_id) { - wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false); + wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false, readback_port != ModulePortId::INVALID()); } VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id); @@ -264,7 +274,13 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma BasicPort wl_decoder_en_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_en_port); ModulePortId wl_decoder_addr_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, bl_decoder_addr_port); + BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_addr_port); + + ModulePortId wl_decoder_readback_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_READBACK_PORT_NAME)); + BasicPort wl_decoder_readback_port_info; + if (wl_decoder_readback_port) { + wl_decoder_readback_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_readback_port); + } /* Top module Enable port -> WL Decoder Enable port */ add_module_bus_nets(module_manager, @@ -278,6 +294,14 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma top_module, 0, wl_addr_port, wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_addr_port); + /* Top module readback port -> WL Decoder readback port */ + if (wl_decoder_readback_port) { + add_module_bus_nets(module_manager, + top_module, + top_module, 0, readback_port, + wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_readback_port); + } + /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric * The distribution is a matrix which contains the starting index of BL/WL for each column or row @@ -391,6 +415,45 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma } } + /************************************************************** + * Optional: Add nets from WLR data out to each configurable child + */ + ModulePortId wl_decoder_data_ren_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_READ_ENABLE_PORT_NAME)); + BasicPort wl_decoder_data_ren_port_info; + if (wl_decoder_data_ren_port) { + wl_decoder_data_ren_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_data_ren_port); + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the WL port */ + ModulePortId child_wlr_port = module_manager.find_module_port(child_module, std::string(MEMORY_WLR_PORT_NAME)); + BasicPort child_wlr_port_info = module_manager.module_port(child_module, child_wlr_port); + + size_t cur_wlr_index = 0; + + for (const size_t& sink_wlr_pin : child_wlr_port_info.pins()) { + size_t wlr_pin_id = wl_start_index_per_tile[coord.y()] + cur_wlr_index; + VTR_ASSERT(wlr_pin_id < wl_decoder_data_ren_port_info.pins().size()); + + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + wl_decoder_module, curr_wl_decoder_instance_id, + wl_decoder_data_ren_port, + wl_decoder_data_ren_port_info.pins()[wlr_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_wlr_port, sink_wlr_pin); + + cur_wlr_index++; + } + } + } + /************************************************************** * Add the BL and WL decoders to the end of configurable children list * Note: this MUST be done after adding all the module nets to other regular configurable children diff --git a/openfpga/src/mux_lib/decoder_library.cpp b/openfpga/src/mux_lib/decoder_library.cpp index a7c4a8840..8d6017f40 100644 --- a/openfpga/src/mux_lib/decoder_library.cpp +++ b/openfpga/src/mux_lib/decoder_library.cpp @@ -47,6 +47,11 @@ bool DecoderLibrary::use_data_inv_port(const DecoderId& decoder) const { return use_data_inv_port_[decoder]; } +bool DecoderLibrary::use_readback(const DecoderId& decoder) const { + VTR_ASSERT_SAFE(valid_decoder_id(decoder)); + return use_readback_[decoder]; +} + /* Find a decoder to the library, with the specification. * If found, return the id of decoder. * If not found, return an invalid id of decoder @@ -61,13 +66,15 @@ DecoderId DecoderLibrary::find_decoder(const size_t& addr_size, const size_t& data_size, const bool& use_enable, const bool& use_data_in, - const bool& use_data_inv_port) const { + const bool& use_data_inv_port, + const bool& use_readback) const { for (auto decoder : decoders()) { if ( (addr_size == addr_sizes_[decoder]) && (data_size == data_sizes_[decoder]) && (use_enable == use_enable_[decoder]) && (use_data_in == use_data_in_[decoder]) - && (use_data_inv_port == use_data_inv_port_[decoder]) ) { + && (use_data_inv_port == use_data_inv_port_[decoder]) + && (use_readback == use_readback_[decoder]) ) { return decoder; } } @@ -92,7 +99,8 @@ DecoderId DecoderLibrary::add_decoder(const size_t& addr_size, const size_t& data_size, const bool& use_enable, const bool& use_data_in, - const bool& use_data_inv_port) { + const bool& use_data_inv_port, + const bool& use_readback) { DecoderId decoder = DecoderId(decoder_ids_.size()); /* Push to the decoder list */ decoder_ids_.push_back(decoder); @@ -102,6 +110,7 @@ DecoderId DecoderLibrary::add_decoder(const size_t& addr_size, use_enable_.push_back(use_enable); use_data_in_.push_back(use_data_in); use_data_inv_port_.push_back(use_data_inv_port); + use_readback_.push_back(use_readback); return decoder; } diff --git a/openfpga/src/mux_lib/decoder_library.h b/openfpga/src/mux_lib/decoder_library.h index 397308db5..7340f4375 100644 --- a/openfpga/src/mux_lib/decoder_library.h +++ b/openfpga/src/mux_lib/decoder_library.h @@ -50,6 +50,8 @@ class DecoderLibrary { bool use_data_in(const DecoderId& decoder) const; /* Get the flag if a decoder includes a data_inv port which is an inversion of the regular data output port */ bool use_data_inv_port(const DecoderId& decoder) const; + /* Get the flag if a decoder includes a readback port which enables readback from configurable memories */ + bool use_readback(const DecoderId& decoder) const; /* Find a decoder to the library, with the specification. * If found, return the id of decoder. * If not found, return an invalid id of decoder @@ -64,7 +66,8 @@ class DecoderLibrary { const size_t& data_size, const bool& use_enable, const bool& use_data_in, - const bool& use_data_inv_port) const; + const bool& use_data_inv_port, + const bool& use_readback) const; public: /* Public validators */ /* valid ids */ @@ -76,7 +79,8 @@ class DecoderLibrary { const size_t& data_size, const bool& use_enable, const bool& use_data_in, - const bool& use_data_inv_port); + const bool& use_data_inv_port, + const bool& use_readback); private: /* Internal Data */ vtr::vector decoder_ids_; @@ -85,6 +89,7 @@ class DecoderLibrary { vtr::vector use_enable_; vtr::vector use_data_in_; vtr::vector use_data_inv_port_; + vtr::vector use_readback_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/utils/decoder_library_utils.cpp b/openfpga/src/utils/decoder_library_utils.cpp index 502620661..b44bb106c 100644 --- a/openfpga/src/utils/decoder_library_utils.cpp +++ b/openfpga/src/utils/decoder_library_utils.cpp @@ -112,11 +112,11 @@ DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib, const size_t data_size) { size_t addr_size = find_mux_local_decoder_addr_size(data_size); - DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, false, false, true); + DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, false, false, true, false); if (DecoderId::INVALID() == decoder_id) { /* Add the decoder */ - return decoder_lib.add_decoder(addr_size, data_size, false, false, true); + return decoder_lib.add_decoder(addr_size, data_size, false, false, true, false); } /* There is already a decoder in the library, return the decoder id */ diff --git a/openfpga/src/utils/memory_utils.cpp b/openfpga/src/utils/memory_utils.cpp index bcca022ab..8e2038b06 100644 --- a/openfpga/src/utils/memory_utils.cpp +++ b/openfpga/src/utils/memory_utils.cpp @@ -330,7 +330,8 @@ std::vector generate_sram_port_names(const CircuitLibrary& circuit_ std::vector ports_to_search; ports_to_search.push_back(CIRCUIT_MODEL_PORT_BL); ports_to_search.push_back(CIRCUIT_MODEL_PORT_WL); - /* Try to find a BL/WL/BLB/WLB port and update the port types/module port types to be added */ + ports_to_search.push_back(CIRCUIT_MODEL_PORT_WLR); + /* Try to find a BL/WL/WLR port and update the port types/module port types to be added */ for (const auto& port_to_search : ports_to_search) { std::vector found_port = circuit_lib.model_ports_by_type(sram_model, port_to_search); if (0 == found_port.size()) { diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 421e7b95f..4c25c3a4a 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -195,6 +195,7 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager, port_type2type_map[CIRCUIT_MODEL_PORT_BLB] = ModuleManager::MODULE_INPUT_PORT; port_type2type_map[CIRCUIT_MODEL_PORT_WL] = ModuleManager::MODULE_INPUT_PORT; port_type2type_map[CIRCUIT_MODEL_PORT_WLB] = ModuleManager::MODULE_INPUT_PORT; + port_type2type_map[CIRCUIT_MODEL_PORT_WLR] = ModuleManager::MODULE_INPUT_PORT; port_type2type_map[CIRCUIT_MODEL_PORT_OUTPUT] = ModuleManager::MODULE_OUTPUT_PORT; /* Input ports (ignore all the global ports when searching the circuit_lib */ @@ -390,8 +391,9 @@ void add_pb_sram_ports_to_module_manager(ModuleManager& module_manager, for (const std::string& sram_port_name : sram_port_names) { /* Add generated ports to the ModuleManager */ BasicPort sram_port(sram_port_name, sram_port_size); - /* For WL ports, we need to fine-tune it */ - if (CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(circuit_lib.model_port(sram_model, sram_port_name))) { + /* For WL and WLR ports, we need to fine-tune it */ + if ( (CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(circuit_lib.model_port(sram_model, sram_port_name))) + || (CIRCUIT_MODEL_PORT_WLR == circuit_lib.port_type(circuit_lib.model_port(sram_model, sram_port_name))) ) { sram_port.set_width(find_memory_wl_decoder_data_size(num_config_bits, sram_port_size)); } module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); @@ -885,7 +887,7 @@ void add_module_nets_between_logic_and_memory_sram_bus(ModuleManager& module_man * | | | * +------------+----------------------+ * | - * WL + * WL/WLR * * Note: * - This function will do the connection for only one type of the port, @@ -900,15 +902,16 @@ void add_module_nets_cmos_flatten_memory_config_bus(ModuleManager& module_manage /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; - ModuleId net_src_module_id; - size_t net_src_instance_id; - ModulePortId net_src_port_id; - /* Find the port name of parent module */ std::string src_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - net_src_module_id = parent_module; - net_src_instance_id = 0; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + ModuleId net_src_module_id = parent_module; + size_t net_src_instance_id = 0; + ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + + /* We may not be able to find WLR port, return now */ + if (!net_src_port_id) { + return; + } /* Get the pin id for source port */ BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); @@ -1025,7 +1028,7 @@ void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manage * | | | * +------------+----------------------+ * | - * WL<0> + * WL<0>/WLR<0> * * +--------+ +--------+ +--------+ * | Memory | | Memory | ... | Memory | @@ -1036,7 +1039,7 @@ void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manage * | | | * +------------+----------------------+ * | - * WL<1> + * WL<1>/WLR<1> * *********************************************************************/ void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manager, @@ -1055,6 +1058,11 @@ void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manage ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); ModulePortId net_bl_port_id = module_manager.find_module_port(net_src_module_id, bl_port_name); + /* We may not be able to find WLR port, return now */ + if (!net_src_port_id) { + return; + } + /* Get the pin id for source port */ BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); BasicPort net_bl_port = module_manager.module_port(net_src_module_id, net_bl_port_id); @@ -1300,9 +1308,9 @@ void add_module_nets_cmos_memory_frame_decoder_config_bus(ModuleManager& module_ /* Search the decoder library and try to find one * If not found, create a new module and add it to the module manager */ - DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false); + DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false, false); if (DecoderId::INVALID() == decoder_id) { - decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false); + decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false, false); } VTR_ASSERT(DecoderId::INVALID() != decoder_id); @@ -1519,6 +1527,8 @@ void add_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, + sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); break; case CONFIG_MEM_FRAME_BASED: add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, parent_module); @@ -1580,6 +1590,8 @@ void add_pb_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); add_module_nets_cmos_memory_bank_wl_config_bus(module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + add_module_nets_cmos_memory_bank_wl_config_bus(module_manager, parent_module, + sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); break; case CONFIG_MEM_MEMORY_BANK: add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module,