From 5368485bd6e17cd2f961fa1088db8473819a4f8b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 31 May 2020 12:44:38 -0600 Subject: [PATCH] keep bug fixing for memory bank configuration protocol. Reduce number of BL/WLs at the top-level --- openfpga/src/fabric/build_top_module.cpp | 3 +- .../src/fabric/build_top_module_memory.cpp | 25 ++++++++---- openfpga/src/fabric/build_top_module_memory.h | 3 +- .../fpga_bitstream/build_fabric_bitstream.cpp | 39 +++++++++++++++---- .../fpga_verilog/verilog_top_testbench.cpp | 19 --------- openfpga/src/utils/decoder_library_utils.cpp | 11 ++++-- openfpga/src/utils/decoder_library_utils.h | 2 +- 7 files changed, 61 insertions(+), 41 deletions(-) diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 7b05a5676..762ba66f0 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -395,7 +395,8 @@ void build_top_module(ModuleManager& module_manager, if (0 < module_manager.configurable_children(top_module).size()) { add_top_module_nets_memory_config_bus(module_manager, decoder_lib, top_module, - sram_orgz_type, circuit_lib.design_tech_type(sram_model)); + sram_orgz_type, circuit_lib.design_tech_type(sram_model), + module_num_config_bits); } } diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 0de55ca4e..568646d57 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -510,7 +510,8 @@ void add_top_module_sram_ports(ModuleManager& module_manager, static void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, - const ModuleId& top_module) { + const ModuleId& top_module, + const size_t& num_config_bits) { /* Find Enable port from the top-level module */ ModulePortId en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port_info = module_manager.module_port(top_module, en_port); @@ -529,8 +530,8 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag /* Find the number of BLs and WLs required to access each memory bit */ size_t bl_addr_size = bl_addr_port_info.get_width(); size_t wl_addr_size = wl_addr_port_info.get_width(); - size_t num_bls = find_memory_decoder_data_size(bl_addr_size); - size_t num_wls = find_memory_decoder_data_size(wl_addr_size); + size_t num_bls = find_memory_decoder_data_size(num_config_bits); + size_t num_wls = find_memory_decoder_data_size(num_config_bits); /* Add the BL decoder module * Search the decoder library @@ -704,6 +705,12 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag cur_wl_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 + */ + module_manager.add_configurable_child(top_module, bl_decoder_module, 0); + module_manager.add_configurable_child(top_module, wl_decoder_module, 0); } /********************************************************************* @@ -754,7 +761,8 @@ static void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type) { + const e_config_protocol_type& sram_orgz_type, + const size_t& num_config_bits) { switch (sram_orgz_type) { case CONFIG_MEM_STANDALONE: add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, @@ -767,8 +775,7 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, break; } case CONFIG_MEM_MEMORY_BANK: - /* TODO */ - add_top_module_nets_cmos_memory_bank_config_bus(module_manager, decoder_lib, parent_module); + add_top_module_nets_cmos_memory_bank_config_bus(module_manager, decoder_lib, parent_module, num_config_bits); break; case CONFIG_MEM_FRAME_BASED: add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, parent_module); @@ -816,12 +823,14 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech) { + const e_circuit_model_design_tech& mem_tech, + const size_t& num_config_bits) { switch (mem_tech) { case CIRCUIT_MODEL_DESIGN_CMOS: add_top_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, parent_module, - sram_orgz_type); + sram_orgz_type, + num_config_bits); break; case CIRCUIT_MODEL_DESIGN_RRAM: /* TODO: */ diff --git a/openfpga/src/fabric/build_top_module_memory.h b/openfpga/src/fabric/build_top_module_memory.h index a912845b2..b67389790 100644 --- a/openfpga/src/fabric/build_top_module_memory.h +++ b/openfpga/src/fabric/build_top_module_memory.h @@ -45,7 +45,8 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech); + const e_circuit_model_design_tech& mem_tech, + const size_t& num_config_bits); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index a9c5b6ec7..a69594f48 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -93,6 +93,7 @@ static void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamManager& bitstream_manager, const ConfigBlockId& parent_block, const ModuleManager& module_manager, + const ModuleId& top_module, const ModuleId& parent_module, const size_t& bl_addr_size, const size_t& wl_addr_size, @@ -105,8 +106,17 @@ void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamMana * we dive to the next level first! */ if (0 < bitstream_manager.block_children(parent_block).size()) { - for (size_t child_id = 0; child_id < module_manager.configurable_children(parent_module).size(); ++child_id) { - ModuleId child_module = module_manager.configurable_children(parent_module)[child_id]; + /* For top module, we will skip the two decoders at the end of the configurable children list */ + std::vector configurable_children = module_manager.configurable_children(parent_module); + + size_t num_configurable_children = configurable_children.size(); + if (parent_module == top_module) { + VTR_ASSERT(2 <= configurable_children.size()); + num_configurable_children -= 2; + } + + for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { + ModuleId child_module = configurable_children[child_id]; size_t child_instance = module_manager.configurable_child_instances(parent_module)[child_id]; /* Get the instance name and ensure it is not empty */ std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); @@ -114,12 +124,12 @@ void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamMana /* Find the child block that matches the instance name! */ ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); /* We must have one valid block id! */ - if (true != bitstream_manager.valid_block_id(child_block)) + if (true != bitstream_manager.valid_block_id(child_block)) VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); /* Go recursively */ rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, child_block, - module_manager, child_module, + module_manager, top_module, child_module, bl_addr_size, wl_addr_size, num_bls, num_wls, cur_mem_index, @@ -376,18 +386,31 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc /* Find BL address port size */ 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); - size_t num_bls = find_memory_decoder_data_size(bl_addr_port_info.get_width()); /* Find WL address port size */ ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); - size_t num_wls = find_memory_decoder_data_size(wl_addr_port_info.get_width()); + + /* Find BL and WL decoders which are the last two configurable children*/ + std::vector configurable_children = module_manager.configurable_children(top_module); + VTR_ASSERT(2 <= configurable_children.size()); + ModuleId bl_decoder_module = configurable_children[configurable_children.size() - 2]; + VTR_ASSERT(0 == module_manager.configurable_child_instances(top_module)[configurable_children.size() - 2]); + ModuleId wl_decoder_module = configurable_children[configurable_children.size() - 1]; + VTR_ASSERT(0 == module_manager.configurable_child_instances(top_module)[configurable_children.size() - 1]); + + ModulePortId bl_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort bl_port_info = module_manager.module_port(bl_decoder_module, bl_port); + + ModulePortId wl_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort wl_port_info = module_manager.module_port(wl_decoder_module, wl_port); rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, top_block, - module_manager, top_module, + module_manager, top_module, top_module, bl_addr_port_info.get_width(), wl_addr_port_info.get_width(), - num_bls, num_wls, + bl_port_info.get_width(), + wl_port_info.get_width(), cur_mem_index, fabric_bitstream); break; } diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 670074d74..5c05d666f 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1245,25 +1245,6 @@ void print_verilog_top_testbench_memory_bank_bitstream(std::fstream& fp, fp << ");" << std::endl; } - /* Disable the address and din */ - fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME); - fp << "(" << bl_addr_port.get_width() << "'b"; - std::vector all_zero_bl_addr(bl_addr_port.get_width(), 0); - for (const size_t& addr_bit : all_zero_bl_addr) { - fp << addr_bit; - } - - fp << ", "; - fp << wl_addr_port.get_width() << "'b"; - std::vector all_zero_wl_addr(wl_addr_port.get_width(), 0); - for (const size_t& addr_bit : all_zero_wl_addr) { - fp << addr_bit; - } - - fp << ", "; - fp <<"1'b0"; - fp << ");" << std::endl; - /* Raise the flag of configuration done when bitstream loading is complete */ BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; diff --git a/openfpga/src/utils/decoder_library_utils.cpp b/openfpga/src/utils/decoder_library_utils.cpp index 8fd7e2208..f4db14ba7 100644 --- a/openfpga/src/utils/decoder_library_utils.cpp +++ b/openfpga/src/utils/decoder_library_utils.cpp @@ -74,11 +74,16 @@ size_t find_mux_local_decoder_addr_size(const size_t& data_size) { * ***************************************************************************************/ size_t find_memory_decoder_addr_size(const size_t& num_mems) { - return find_mux_local_decoder_addr_size((size_t)std::ceil(std::sqrt((float)num_mems))); + return find_mux_local_decoder_addr_size(find_memory_decoder_data_size(num_mems)); } -size_t find_memory_decoder_data_size(const size_t& num_addr) { - return (size_t)std::pow(2., num_addr); +/*************************************************************************************** + * Find the size of data lines (BLs and WLs) for a memory decoder to access a memory array + * As the memory cells are organized in an array with shared bit lines and word lines, + * the number of data lines will be a square root of the number of memory cells. + ***************************************************************************************/ +size_t find_memory_decoder_data_size(const size_t& num_mems) { + return (size_t)std::ceil(std::sqrt((float)num_mems)); } /*************************************************************************************** diff --git a/openfpga/src/utils/decoder_library_utils.h b/openfpga/src/utils/decoder_library_utils.h index f7f06f733..aa25d0df2 100644 --- a/openfpga/src/utils/decoder_library_utils.h +++ b/openfpga/src/utils/decoder_library_utils.h @@ -15,7 +15,7 @@ size_t find_mux_local_decoder_addr_size(const size_t& data_size); size_t find_memory_decoder_addr_size(const size_t& num_mems); -size_t find_memory_decoder_data_size(const size_t& num_addr); +size_t find_memory_decoder_data_size(const size_t& num_mems); DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib, const size_t data_size);