diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index 1c792d26d..44eb2c8cd 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -146,23 +146,9 @@ std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size, * 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 bit-line decoder - * for memories - ***********************************************/ -std::string generate_bl_memory_decoder_subckt_name(const size_t& addr_size, - const size_t& data_size) { - std::string subckt_name = "bl_decoder"; +std::string generate_memory_decoder_subckt_name(const size_t& addr_size, + const size_t& data_size) { + std::string subckt_name = "decoder"; subckt_name += std::to_string(addr_size); subckt_name += "to"; subckt_name += std::to_string(data_size); @@ -174,9 +160,9 @@ std::string generate_bl_memory_decoder_subckt_name(const size_t& addr_size, * Generate the module name of a word-line decoder * for memories ***********************************************/ -std::string generate_wl_memory_decoder_subckt_name(const size_t& addr_size, - const size_t& data_size) { - std::string subckt_name = "wl_decoder"; +std::string generate_memory_decoder_with_data_in_subckt_name(const size_t& addr_size, + const size_t& data_size) { + std::string subckt_name = "decoder_with_data_in_"; subckt_name += std::to_string(addr_size); subckt_name += "to"; subckt_name += std::to_string(data_size); diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h index 534bf2a78..3634be27a 100644 --- a/openfpga/src/base/openfpga_naming.h +++ b/openfpga/src/base/openfpga_naming.h @@ -50,14 +50,11 @@ 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_memory_decoder_subckt_name(const size_t& addr_size, + const size_t& data_size); -std::string generate_bl_memory_decoder_subckt_name(const size_t& addr_size, - const size_t& data_size); - -std::string generate_wl_memory_decoder_subckt_name(const size_t& addr_size, - const size_t& data_size); +std::string generate_memory_decoder_with_data_in_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/fabric/build_decoder_modules.cpp b/openfpga/src/fabric/build_decoder_modules.cpp index fb8a29e5c..eecb31344 100644 --- a/openfpga/src/fabric/build_decoder_modules.cpp +++ b/openfpga/src/fabric/build_decoder_modules.cpp @@ -45,7 +45,7 @@ ModuleId build_frame_memory_decoder_module(ModuleManager& module_manager, 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); + std::string module_name = generate_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); @@ -100,7 +100,7 @@ ModuleId build_bl_memory_decoder_module(ModuleManager& module_manager, size_t data_size = decoder_lib.data_size(decoder); /* Create a name for the local encoder */ - std::string module_name = generate_bl_memory_decoder_subckt_name(addr_size, data_size); + std::string module_name = generate_memory_decoder_with_data_in_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); @@ -158,7 +158,7 @@ ModuleId build_wl_memory_decoder_module(ModuleManager& module_manager, size_t data_size = decoder_lib.data_size(decoder); /* Create a name for the local encoder */ - std::string module_name = generate_wl_memory_decoder_subckt_name(addr_size, data_size); + std::string module_name = generate_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); diff --git a/openfpga/src/fabric/build_memory_modules.cpp b/openfpga/src/fabric/build_memory_modules.cpp index 72d1315ad..e3c8a0c03 100644 --- a/openfpga/src/fabric/build_memory_modules.cpp +++ b/openfpga/src/fabric/build_memory_modules.cpp @@ -554,14 +554,14 @@ 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, true, use_data_inv); + DecoderId decoder_id = frame_decoder_lib.find_decoder(addr_size, data_size, true, false, use_data_inv); if (DecoderId::INVALID() == decoder_id) { - decoder_id = frame_decoder_lib.add_decoder(addr_size, data_size, true, true, use_data_inv); + decoder_id = frame_decoder_lib.add_decoder(addr_size, data_size, true, false, 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); + std::string decoder_module_name = generate_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, diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 278a33f2d..0de55ca4e 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -545,7 +545,7 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag VTR_ASSERT(DecoderId::INVALID() != bl_decoder_id); /* Create a module if not existed yet */ - std::string bl_decoder_module_name = generate_bl_memory_decoder_subckt_name(bl_addr_size, num_bls); + std::string bl_decoder_module_name = generate_memory_decoder_with_data_in_subckt_name(bl_addr_size, num_bls); ModuleId bl_decoder_module = module_manager.find_module(bl_decoder_module_name); if (ModuleId::INVALID() == bl_decoder_module) { /* BL decoder has the same ports as the frame-based decoders @@ -572,7 +572,7 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id); /* Create a module if not existed yet */ - std::string wl_decoder_module_name = generate_bl_memory_decoder_subckt_name(wl_addr_size, num_wls); + std::string wl_decoder_module_name = generate_memory_decoder_subckt_name(wl_addr_size, num_wls); ModuleId wl_decoder_module = module_manager.find_module(wl_decoder_module_name); if (ModuleId::INVALID() == wl_decoder_module) { /* BL decoder has the same ports as the frame-based decoders diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index 1be2025b3..a9c5b6ec7 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -374,12 +374,12 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc case CONFIG_MEM_MEMORY_BANK: { size_t cur_mem_index = 0; /* Find BL address port size */ - ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(MEMORY_BL_PORT_NAME)); + 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(MEMORY_WL_PORT_NAME)); + 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()); diff --git a/openfpga/src/fpga_verilog/verilog_decoders.cpp b/openfpga/src/fpga_verilog/verilog_decoders.cpp index 64568515c..6e6025ea6 100644 --- a/openfpga/src/fpga_verilog/verilog_decoders.cpp +++ b/openfpga/src/fpga_verilog/verilog_decoders.cpp @@ -262,7 +262,7 @@ void print_verilog_arch_decoder_module(std::fstream& fp, VTR_ASSERT(true == valid_file_stream(fp)); /* Create a name for the decoder */ - std::string module_name = generate_frame_memory_decoder_subckt_name(addr_size, data_size); + std::string module_name = generate_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.find_module(module_name); @@ -377,6 +377,132 @@ void print_verilog_arch_decoder_module(std::fstream& fp, print_verilog_module_end(fp, module_name); } +/*************************************************************************************** + * Create a Verilog module for a decoder with data_in used as a configuration protocol + * in FPGA architecture + * + * Address + * | | ... | + * v v v + * +-----------+ + * Enable->/ \<-data_in + * / Decoder \ + * +-----------------+ + * | | | ... | | | + * v v v v v v + * Data output + * + * The outputs are assumes to be one-hot codes (at most only one '1' exist) + * Only the data output at the address bit will show data_in + * + * The decoder has an enable signal which is active at logic '1'. + * When activated, the decoder will output decoding results to the data output port + * Otherwise, the data output port will be always all-zero + ***************************************************************************************/ +static +void print_verilog_arch_decoder_with_data_in_module(std::fstream& fp, + const 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); + VTR_ASSERT(true == decoder_lib.use_data_in(decoder)); + + /* Validate the FILE handler */ + VTR_ASSERT(true == valid_file_stream(fp)); + + /* Create a name for the decoder */ + std::string module_name = generate_memory_decoder_with_data_in_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.find_module(module_name); + VTR_ASSERT(true == module_manager.valid_module_id(module_id)); + /* Find module ports */ + /* Enable port */ + ModulePortId enable_port_id = module_manager.find_module_port(module_id, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort enable_port = module_manager.module_port(module_id, enable_port_id); + /* Address port */ + ModulePortId addr_port_id = module_manager.find_module_port(module_id, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort addr_port = module_manager.module_port(module_id, addr_port_id); + /* Find data-in port*/ + ModulePortId din_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort din_port = module_manager.module_port(module_id, din_port_id); + /* Find each output port */ + ModulePortId data_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort data_port = module_manager.module_port(module_id, data_port_id); + /* Data port is registered. It should be outputted as + * output reg [lsb:msb] data + */ + BasicPort data_inv_port(std::string(DECODER_DATA_OUT_INV_PORT_NAME), data_size); + if (true == decoder_lib.use_data_inv_port(decoder)) { + ModulePortId data_inv_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_OUT_INV_PORT_NAME)); + data_inv_port = module_manager.module_port(module_id, data_inv_port_id); + } + + /* dump module definition + ports */ + print_verilog_module_declaration(fp, module_manager, module_id); + /* Finish dumping ports */ + + print_verilog_comment(fp, std::string("----- BEGIN Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----")); + + /* Print the truth table of this decoder */ + /* Internal logics */ + /* Early exit: Corner case for data size = 1 the logic is very simple: + * data = addr; + * data_inv = ~data_inv + */ + if (1 == data_size) { + fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); + fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port); + fp << ") begin" << std::endl; + fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) begin" << std::endl; + fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, din_port) << ";" << std::endl; + fp << "\t" << "end else begin" << std::endl; + fp << "\t\t" << generate_verilog_port_constant_values(data_port, std::vector(1, 0)) << ";" << std::endl; + fp << "\t" << "end" << std::endl; + fp << "end" << std::endl; + + /* Depend on if the inverted data output port is needed or not */ + if (true == decoder_lib.use_data_inv_port(decoder)) { + print_verilog_wire_connection(fp, data_inv_port, addr_port, true); + } + + print_verilog_comment(fp, std::string("----- END Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----")); + + /* Put an end to the Verilog module */ + print_verilog_module_end(fp, module_name); + return; + } + + /* Only the selected data output bit will be set to the value of data_in, + * other data output bits will be '0' + */ + fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); + fp << ", " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port); + fp << ", " << generate_verilog_port(VERILOG_PORT_CONKT, din_port); + fp << ") begin" << std::endl; + + fp << "\t" << generate_verilog_port_constant_values(data_port, ito1hot_vec(data_size, data_size)) << ";" << std::endl; + + fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) begin" << std::endl; + fp << "\t\t" << data_port.get_name().c_str() << "[" << addr_port.get_name().c_str() << "]"; + fp << " = " << generate_verilog_port(VERILOG_PORT_CONKT, din_port) << ";" << std::endl; + + fp << "\t" << "end" << std::endl; + + fp << "end" << std::endl; + + if (true == decoder_lib.use_data_inv_port(decoder)) { + print_verilog_wire_connection(fp, data_inv_port, data_port, true); + } + + print_verilog_comment(fp, std::string("----- END Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----")); + + /* Put an end to the Verilog module */ + print_verilog_module_end(fp, module_name); +} + /*************************************************************************************** * This function will generate all the unique Verilog modules of decoders for * configuration protocols in a FPGA fabric @@ -407,7 +533,11 @@ void print_verilog_submodule_arch_decoders(const ModuleManager& module_manager, /* Generate Verilog modules for the found unique local encoders */ for (const auto& decoder : decoder_lib.decoders()) { - print_verilog_arch_decoder_module(fp, module_manager, decoder_lib, decoder); + if (true == decoder_lib.use_data_in(decoder)) { + print_verilog_arch_decoder_with_data_in_module(fp, module_manager, decoder_lib, decoder); + } else { + print_verilog_arch_decoder_module(fp, module_manager, decoder_lib, decoder); + } } /* Close the file stream */ diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index e741e16ee..670074d74 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -116,7 +116,7 @@ void print_verilog_top_testbench_memory_bank_port(std::fstream& fp, /* Print the address port for the Bit-Line decoder here */ print_verilog_comment(fp, std::string("---- Address port for Bit-Line decoder -----")); ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, - std::string(MEMORY_BL_PORT_NAME)); + std::string(DECODER_BL_ADDRESS_PORT_NAME)); BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); fp << generate_verilog_port(VERILOG_PORT_REG, bl_addr_port) << ";" << std::endl; @@ -124,7 +124,7 @@ void print_verilog_top_testbench_memory_bank_port(std::fstream& fp, /* Print the address port for the Word-Line decoder here */ print_verilog_comment(fp, std::string("---- Address port for Word-Line decoder -----")); ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, - std::string(MEMORY_WL_PORT_NAME)); + std::string(DECODER_WL_ADDRESS_PORT_NAME)); BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); fp << generate_verilog_port(VERILOG_PORT_REG, wl_addr_port) << ";" << std::endl; @@ -711,13 +711,13 @@ void print_verilog_top_testbench_load_bitstream_task_memory_bank(std::fstream& f BasicPort en_port = module_manager.module_port(top_module, en_port_id); ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, - std::string(MEMORY_BL_PORT_NAME)); + std::string(DECODER_BL_ADDRESS_PORT_NAME)); BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); BasicPort bl_addr_value = bl_addr_port; bl_addr_value.set_name(std::string(MEMORY_BL_PORT_NAME) + std::string("_val")); ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, - std::string(MEMORY_WL_PORT_NAME)); + std::string(DECODER_WL_ADDRESS_PORT_NAME)); BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); BasicPort wl_addr_value = wl_addr_port; wl_addr_value.set_name(std::string(MEMORY_WL_PORT_NAME) + std::string("_val")); @@ -1176,12 +1176,12 @@ void print_verilog_top_testbench_memory_bank_bitstream(std::fstream& fp, * We should give dummy values */ ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, - std::string(MEMORY_BL_PORT_NAME)); + std::string(DECODER_BL_ADDRESS_PORT_NAME)); BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); std::vector initial_bl_addr_values(bl_addr_port.get_width(), 0); ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, - std::string(MEMORY_WL_PORT_NAME)); + std::string(DECODER_WL_ADDRESS_PORT_NAME)); BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); std::vector initial_wl_addr_values(wl_addr_port.get_width(), 0); @@ -1196,8 +1196,12 @@ void print_verilog_top_testbench_memory_bank_bitstream(std::fstream& fp, print_verilog_comment(fp, "----- Address port default input -----"); fp << "\t\t"; fp << generate_verilog_port_constant_values(bl_addr_port, initial_bl_addr_values); + fp << ";"; + fp << std::endl; + fp << generate_verilog_port_constant_values(wl_addr_port, initial_wl_addr_values); fp << ";"; + fp << std::endl; print_verilog_comment(fp, "----- Data-input port default input -----"); fp << "\t\t"; @@ -1312,6 +1316,7 @@ void print_verilog_top_testbench_frame_decoder_bitstream(std::fstream& fp, fp << "\t\t"; fp << generate_verilog_port_constant_values(addr_port, initial_addr_values); fp << ";"; + fp << std::endl; print_verilog_comment(fp, "----- Data-input port default input -----"); fp << "\t\t"; diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index ec871368a..0fe16987c 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -960,14 +960,14 @@ 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, true, false); + DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false); if (DecoderId::INVALID() == decoder_id) { - decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, true, false); + decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false); } 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); + std::string decoder_module_name = generate_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,