From b082e60c103c815d9946fa741fd8e67c50043cec Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 29 Sep 2019 18:20:56 -0600 Subject: [PATCH] start refactoring instanciation of memory modules --- .../vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp | 16 ++ .../vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h | 4 + .../fpga_x2p/base/module_manager_utils.cpp | 148 ++++++++++++++++++ .../SRC/fpga_x2p/base/module_manager_utils.h | 7 + .../vpr/SRC/fpga_x2p/base/rr_blocks_utils.cpp | 6 +- .../SRC/fpga_x2p/verilog/verilog_memory.cpp | 41 +++-- .../SRC/fpga_x2p/verilog/verilog_routing.c | 17 +- 7 files changed, 222 insertions(+), 17 deletions(-) diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp index b63ee1f48..d39d4961a 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp @@ -332,6 +332,22 @@ std::string generate_configuration_chain_tail_name() { return std::string("ccff_tail"); } +/********************************************************************* + * Generate the memory output port name of a configuration chain + * TODO: This could be replaced as a constexpr string + *********************************************************************/ +std::string generate_configuration_chain_data_out_name() { + return std::string("mem_out"); +} + +/********************************************************************* + * Generate the inverted memory output port name of a configuration chain + * TODO: This could be replaced as a constexpr string + *********************************************************************/ +std::string generate_configuration_chain_inverted_data_out_name() { + return std::string("mem_outb"); +} + /********************************************************************* * Generate the addr port (input) for a local decoder of a multiplexer * TODO: This could be replaced as a constexpr string diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h index 91488b24f..6d7f9c88c 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h @@ -76,6 +76,10 @@ std::string generate_configuration_chain_head_name(); std::string generate_configuration_chain_tail_name(); +std::string generate_configuration_chain_data_out_name(); + +std::string generate_configuration_chain_inverted_data_out_name(); + std::string generate_mux_local_decoder_addr_port_name(); std::string generate_mux_local_decoder_data_port_name(); 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 1aa0c9024..e442b0223 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 @@ -209,3 +209,151 @@ void add_sram_ports_to_module_manager(ModuleManager& module_manager, module_manager.add_port(module_id, module_port, module_port_types[iport]); } } + +/********************************************************************* + * Create a port-to-port map for a CMOS memory module + * + * Configuration Chain + * ------------------- + * + * config_bus (head) config_bus (tail) + * | ^ + * v | + * +-------------------------------------+ + * | CMOS-based Memory Module | + * +-------------------------------------+ + * | | + * v v + * sram_out sram_outb + * + * + * Memory bank + * ----------- + * + * config_bus (BL) config_bus (WL) + * | | + * v v + * +-------------------------------------+ + * | CMOS-based Memory Module | + * +-------------------------------------+ + * | | + * v v + * sram_out sram_outb + * + **********************************************************************/ +static +std::map generate_cmos_mem_module_port2port_map(const ModuleManager& module_manager, + const ModuleId& mem_module, + const std::vector& config_bus_ports, + const std::vector& mem_output_bus_ports, + const e_sram_orgz& sram_orgz_type) { + std::map port2port_name_map; + + switch (sram_orgz_type) { + case SPICE_SRAM_STANDALONE: + /* Nothing to do */ + break; + case SPICE_SRAM_SCAN_CHAIN: { + /* Link the head port of the memory module: + * the LSB of config bus port is the head port index + */ + VTR_ASSERT( 1 == config_bus_ports.size() ); + BasicPort head_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_lsb(), config_bus_ports[0].get_lsb()); + port2port_name_map[generate_configuration_chain_head_name()] = head_port; + + /* Link the tail port of the memory module: + * the MSB of config bus port is the tail port index + */ + BasicPort tail_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_msb(), config_bus_ports[0].get_msb()); + port2port_name_map[generate_configuration_chain_tail_name()] = tail_port; + + /* Link the SRAM output ports of the memory module */ + VTR_ASSERT( 2 == mem_output_bus_ports.size() ); + port2port_name_map[generate_configuration_chain_data_out_name()] = mem_output_bus_ports[0]; + port2port_name_map[generate_configuration_chain_inverted_data_out_name()] = mem_output_bus_ports[1]; + break; + } + case SPICE_SRAM_MEMORY_BANK: + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s,[LINE%d])Invalid type of SRAM organization!\n", + __FILE__, __LINE__); + exit(1); + } + + return port2port_name_map; +} + +/********************************************************************* + * Create a port-to-port map for a ReRAM-based memory module + * Memory bank + * ----------- + * + * config_bus (BL) config_bus (WL) + * | | + * v v + * +-------------------------------------+ + * | ReRAM-based Memory Module | + * +-------------------------------------+ + * | | + * v v + * Mem_out Mem_outb + **********************************************************************/ +static +std::map generate_rram_mem_module_port2port_map(const ModuleManager& module_manager, + const ModuleId& mem_module, + const e_sram_orgz& sram_orgz_type) { + std::map port2port_name_map; + + switch (sram_orgz_type) { + case SPICE_SRAM_STANDALONE: + /* Not supported */ + break; + case SPICE_SRAM_SCAN_CHAIN: + /* TODO: to be supported */ + break; + case SPICE_SRAM_MEMORY_BANK: + /* TODO: link BL/WL/Reserved Ports to the inputs of a memory module */ + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s,[LINE%d])Invalid type of SRAM organization!\n", + __FILE__, __LINE__); + exit(1); + } + + return port2port_name_map; +} + +/********************************************************************* + * Create a port-to-port map for a memory module + * The content of the port-to-port map will depend not only + * the design technology of the memory cells but also the + * configuration styles of FPGA fabric. + * Here we will branch on the design technology + **********************************************************************/ +std::map generate_mem_module_port2port_map(const ModuleManager& module_manager, + const ModuleId& mem_module, + const std::vector& config_bus_ports, + const std::vector& mem_output_bus_ports, + const e_spice_model_design_tech& mem_design_tech, + const e_sram_orgz& sram_orgz_type) { + std::map port2port_name_map; + + switch (mem_design_tech) { + case SPICE_MODEL_DESIGN_CMOS: + port2port_name_map = generate_cmos_mem_module_port2port_map(module_manager, mem_module, config_bus_ports, mem_output_bus_ports, sram_orgz_type); + break; + case SPICE_MODEL_DESIGN_RRAM: + port2port_name_map = generate_rram_mem_module_port2port_map(module_manager, mem_module, sram_orgz_type); + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s,[LINE%d])Invalid type of memory design technology !\n", + __FILE__, __LINE__); + exit(1); + } + + return port2port_name_map; +} 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 17d395cdb..bee3e7ff8 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 @@ -38,5 +38,12 @@ void add_sram_ports_to_module_manager(ModuleManager& module_manager, const e_sram_orgz sram_orgz_type, const size_t& port_size); +std::map generate_mem_module_port2port_map(const ModuleManager& module_manager, + const ModuleId& mem_module, + const std::vector& config_bus_ports, + const std::vector& mem_output_bus_ports, + const e_spice_model_design_tech& mem_design_tech, + const e_sram_orgz& sram_orgz_type); + #endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks_utils.cpp index a078ed535..197da9c8b 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks_utils.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks_utils.cpp @@ -77,10 +77,14 @@ size_t find_switch_block_number_of_muxes(const RRGSB& rr_gsb) { if (OUT_PORT != rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) { continue; } - /* Check if this node is driven by a multiplexer */ + /* Check if this node is just a passing wire */ if (true == rr_gsb.is_sb_node_passing_wire(side_manager.get_side(), itrack)) { continue; } + /* Check if this node has more than 2 drivers */ + if (2 > rr_gsb.get_chan_node(side_manager.get_side(), itrack)->num_drive_rr_nodes) { + continue; + } /* This means we need a multiplexer, update the counter */ num_muxes++; } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.cpp index 61090aaab..09c2501f3 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.cpp @@ -155,6 +155,8 @@ void print_verilog_memory_chain_module(ModuleManager& module_manager, VTR_ASSERT( 1 == sram_input_ports.size() ); /* Get the output ports from the SRAM */ std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, SPICE_MODEL_PORT_OUTPUT, true); + /* Should have only 1 or 2 output port */ + VTR_ASSERT( (1 == sram_output_ports.size()) || ( 2 == sram_output_ports.size()) ); /* Add module ports: the ports come from the SRAM modules */ /* Add each global port */ @@ -180,8 +182,15 @@ void print_verilog_memory_chain_module(ModuleManager& module_manager, circuit_lib.port_size(sram_output_ports[0])); module_manager.add_port(module_id, chain_tail_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_lib_name(port), num_mems); + for (size_t iport = 0; iport < sram_output_ports.size(); ++iport) { + std::string port_name; + if (0 == iport) { + port_name = generate_configuration_chain_data_out_name(); + } else { + VTR_ASSERT( 1 == iport); + port_name = generate_configuration_chain_inverted_data_out_name(); + } + BasicPort output_port(port_name, num_mems); module_manager.add_port(module_id, output_port, ModuleManager::MODULE_OUTPUT_PORT); } @@ -202,9 +211,16 @@ void print_verilog_memory_chain_module(ModuleManager& module_manager, port2port_name_map[circuit_lib.port_lib_name(port)] = instance_input_port; } /* Map instance outputs [i] to SRAM module input */ - for (const auto& port : sram_output_ports) { - BasicPort instance_output_port(circuit_lib.port_lib_name(port), i, i); - port2port_name_map[circuit_lib.port_lib_name(port)] = instance_output_port; + for (size_t iport = 0; iport < sram_output_ports.size(); ++iport) { + std::string port_name; + if (0 == iport) { + port_name = generate_configuration_chain_data_out_name(); + } else { + VTR_ASSERT( 1 == iport); + port_name = generate_configuration_chain_inverted_data_out_name(); + } + BasicPort instance_output_port(port_name, i, i); + port2port_name_map[circuit_lib.port_lib_name(sram_output_ports[iport])] = instance_output_port; } /* Output an instance of the module */ @@ -223,11 +239,11 @@ void print_verilog_memory_chain_module(ModuleManager& module_manager, BasicPort first_ccff_input_port(circuit_lib.port_lib_name(sram_input_ports[0]), 0, 0); print_verilog_wire_connection(fp, first_ccff_input_port, chain_head_port, false); - BasicPort last_ccff_output_port(circuit_lib.port_lib_name(sram_output_ports[0]), num_mems - 1, num_mems - 1); + BasicPort last_ccff_output_port(generate_configuration_chain_data_out_name(), num_mems - 1, num_mems - 1); print_verilog_wire_connection(fp, chain_tail_port, last_ccff_output_port, false); - BasicPort chain_output_port(circuit_lib.port_lib_name(sram_output_ports[0]), 1, num_mems - 1); - BasicPort chain_input_port(circuit_lib.port_lib_name(sram_input_ports[0]), 0, num_mems - 2); + BasicPort chain_output_port(generate_configuration_chain_data_out_name(), 0, num_mems - 2); + BasicPort chain_input_port(circuit_lib.port_lib_name(sram_input_ports[0]), 1, num_mems - 1); print_verilog_wire_connection(fp, chain_input_port, chain_output_port, false); /* Put an end to the Verilog module */ @@ -433,6 +449,10 @@ void print_verilog_mux_memory_module(ModuleManager& module_manager, std::fstream& fp, const CircuitModelId& mux_model, const MuxGraph& mux_graph) { + /* Find the actual number of configuration bits, based on the mux graph + * Due to the use of local decoders inside mux, this may be + */ + size_t num_config_bits = find_mux_num_config_bits(circuit_lib, mux_model, mux_graph, sram_orgz_type); /* Multiplexers built with different technology is in different organization */ switch (circuit_lib.design_tech_type(mux_model)) { case SPICE_MODEL_DESIGN_CMOS: { @@ -445,10 +465,7 @@ void print_verilog_mux_memory_module(ModuleManager& module_manager, std::vector sram_models = find_circuit_sram_models(circuit_lib, mux_model); VTR_ASSERT( 1 == sram_models.size() ); - /* Find the number of SRAMs in the module, this is also the port width */ - size_t num_mems = mux_graph.num_memory_bits(); - - print_verilog_memory_module(module_manager, circuit_lib, sram_orgz_type, fp, module_name, sram_models[0], num_mems); + print_verilog_memory_module(module_manager, circuit_lib, sram_orgz_type, fp, module_name, sram_models[0], num_config_bits); break; } case SPICE_MODEL_DESIGN_RRAM: diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c index 8ed8eb209..d08f5eb15 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c @@ -66,7 +66,8 @@ void print_verilog_switch_block_local_sram_wires(std::fstream& fp, const size_t& port_size) { size_t local_port_size = port_size; if (SPICE_SRAM_SCAN_CHAIN == sram_orgz_type) { - local_port_size = find_switch_block_number_of_muxes(rr_gsb); + /* Plus 1 for the wire size to connect to the tail of the configuration chain */ + local_port_size = find_switch_block_number_of_muxes(rr_gsb) + 1; } print_verilog_local_sram_wires(fp, circuit_lib, sram_model, sram_orgz_type, local_port_size); } @@ -2449,9 +2450,17 @@ void print_verilog_unique_switch_box_mux(ModuleManager& module_manager, /* Create port-to-port map */ std::map mem_port2port_name_map; - /* TODO: Link input port to Switch block configuration bus */ - - /* TODO: Link output port to MUX configuration port */ + /* TODO: Make the port2port map generation more generic!!! */ + std::vector config_ports; + config_ports.push_back(BasicPort(generate_local_config_bus_port_name(), mux_instance_id - 1, mux_instance_id)); + std::vector mem_output_ports; + mem_output_ports.push_back(mux_config_port); + mem_output_ports.push_back(mux_config_inv_port); + mem_port2port_name_map = generate_mem_module_port2port_map(module_manager, mem_module, + config_ports, + mem_output_ports, + circuit_lib.design_tech_type(mux_model), + cur_sram_orgz_info->type); /* Print an instance of the MUX Module */ print_verilog_comment(fp, std::string("----- BEGIN Instanciation of memory cells for a routing multiplexer -----"));