diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_mem_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_mem_utils.cpp index f95f99a88..265330f40 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_mem_utils.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_mem_utils.cpp @@ -39,9 +39,7 @@ * **********************************************************************/ static -std::map generate_cmos_mem_module_port2port_map(const ModuleManager& module_manager, - const ModuleId& mem_module, - const BasicPort& config_bus, +std::map generate_cmos_mem_module_port2port_map(const BasicPort& config_bus, const std::vector& mem_output_bus_ports, const e_sram_orgz& sram_orgz_type) { std::map port2port_name_map; @@ -100,9 +98,7 @@ std::map generate_cmos_mem_module_port2port_map(const Mo * Mem_out Mem_outb **********************************************************************/ static -std::map generate_rram_mem_module_port2port_map(const ModuleManager& module_manager, - const ModuleId& mem_module, - const BasicPort& config_bus, +std::map generate_rram_mem_module_port2port_map(const BasicPort& config_bus, const std::vector& mem_output_bus_ports, const e_sram_orgz& sram_orgz_type) { std::map port2port_name_map; @@ -152,9 +148,7 @@ std::map generate_rram_mem_module_port2port_map(const Mo * 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 BasicPort& config_bus, +std::map generate_mem_module_port2port_map(const BasicPort& config_bus, const std::vector& mem_output_bus_ports, const e_spice_model_design_tech& mem_design_tech, const e_sram_orgz& sram_orgz_type) { @@ -162,10 +156,10 @@ std::map generate_mem_module_port2port_map(const ModuleM switch (mem_design_tech) { case SPICE_MODEL_DESIGN_CMOS: - port2port_name_map = generate_cmos_mem_module_port2port_map(module_manager, mem_module, config_bus, mem_output_bus_ports, sram_orgz_type); + port2port_name_map = generate_cmos_mem_module_port2port_map(config_bus, 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, config_bus, mem_output_bus_ports, sram_orgz_type); + port2port_name_map = generate_rram_mem_module_port2port_map(config_bus, mem_output_bus_ports, sram_orgz_type); break; default: vpr_printf(TIO_MESSAGE_ERROR, @@ -215,7 +209,6 @@ void update_cmos_mem_module_config_bus(const e_sram_orgz& sram_orgz_type, **********************************************************************/ static void update_rram_mem_module_config_bus(const e_sram_orgz& sram_orgz_type, - const size_t& num_config_bits, BasicPort& config_bus) { switch (sram_orgz_type) { case SPICE_SRAM_STANDALONE: @@ -261,7 +254,7 @@ void update_mem_module_config_bus(const e_sram_orgz& sram_orgz_type, update_cmos_mem_module_config_bus(sram_orgz_type, num_config_bits, config_bus); break; case SPICE_MODEL_DESIGN_RRAM: - update_rram_mem_module_config_bus(sram_orgz_type, num_config_bits, config_bus); + update_rram_mem_module_config_bus(sram_orgz_type, config_bus); break; default: vpr_printf(TIO_MESSAGE_ERROR, diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_mem_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_mem_utils.h index 831aca5a8..fef569c5a 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_mem_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_mem_utils.h @@ -10,9 +10,7 @@ #include "spice_types.h" #include "module_manager.h" -std::map generate_mem_module_port2port_map(const ModuleManager& module_manager, - const ModuleId& mem_module, - const BasicPort& config_bus, +std::map generate_mem_module_port2port_map(const BasicPort& config_bus, const std::vector& mem_output_bus_ports, const e_spice_model_design_tech& mem_design_tech, const e_sram_orgz& sram_orgz_type); 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 3c41111e3..fa87405d9 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 @@ -673,12 +673,12 @@ std::string generate_mux_sram_port_name(const CircuitLibrary& circuit_lib, } /********************************************************************* - * Generate the netlist name of a physical block + * Generate the netlist name of a grid block **********************************************************************/ -std::string generate_physical_block_netlist_name(const std::string& block_name, - const bool& is_block_io, - const e_side& io_side, - const std::string& postfix) { +std::string generate_grid_block_netlist_name(const std::string& block_name, + const bool& is_block_io, + const e_side& io_side, + const std::string& postfix) { /* Add the name of physical block */ std::string module_name(block_name); @@ -694,15 +694,69 @@ std::string generate_physical_block_netlist_name(const std::string& block_name, } /********************************************************************* - * Generate the module name of a physical block + * Generate the module name of a grid block **********************************************************************/ -std::string generate_physical_block_module_name(const std::string& prefix, - const std::string& block_name, - const bool& is_block_io, - const e_side& io_side) { +std::string generate_grid_block_module_name(const std::string& prefix, + const std::string& block_name, + const bool& is_block_io, + const e_side& io_side) { std::string module_name(prefix); - module_name += generate_physical_block_netlist_name(block_name, is_block_io, io_side, std::string()); + module_name += generate_grid_block_netlist_name(block_name, is_block_io, io_side, std::string()); + + return module_name; +} + +/********************************************************************* + * Generate the module name of a physical block + * To ensure a unique name for each physical block inside the graph of complex blocks + * (pb_graph_nodes), this function trace backward to the top-level node + * in the graph and add the name of these parents + * The final name will be in the following format: + * __ ... + * + * TODO: to make sure the length of this name does not exceed the size of + * chars in a line of a file!!! + **********************************************************************/ +std::string generate_physical_block_module_name(const std::string& prefix, + t_pb_type* physical_pb_type) { + std::string module_name(physical_pb_type->name); + + t_pb_type* parent_pb_type = physical_pb_type; + + /* Backward trace until we meet the top-level pb_type */ + while (1) { + /* If there is no parent mode, this is a top-level pb_type, quit the loop here */ + t_mode* parent_mode = parent_pb_type->parent_mode; + if (NULL == parent_mode) { + break; + } + + /* Add the mode name to the module name */ + module_name = std::string("mode[") + std::string(parent_mode->name) + std::string("]_") + module_name; + + /* Backtrace to the upper level */ + parent_pb_type = parent_mode->parent_pb_type; + + /* If there is no parent pb_type, this is a top-level pb_type, quit the loop here */ + if (NULL == parent_pb_type) { + break; + } + + /* Add the current pb_type name to the module name */ + module_name = std::string(parent_pb_type->name) + std::string("_") + module_name; + } + + /* Exception for top-level pb_type: add an virtual mode name (same name as the pb_type) + * This is to follow the naming convention as non top-level pb_types + * In addition, the name can be really unique, being different than the grid blocks + */ + if (NULL == physical_pb_type->parent_mode) { + module_name += std::string("_mode[") + std::string(physical_pb_type->name) + std::string("]"); + } + + /* Add the prefix */ + module_name = prefix + module_name; return module_name; } 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 8673de395..7d65a9605 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 @@ -130,14 +130,17 @@ std::string generate_mux_sram_port_name(const CircuitLibrary& circuit_lib, const size_t& mux_instance_id, const e_spice_model_port_type& port_type); -std::string generate_physical_block_netlist_name(const std::string& block_name, - const bool& is_block_io, - const e_side& io_side, - const std::string& postfix); +std::string generate_grid_block_netlist_name(const std::string& block_name, + const bool& is_block_io, + const e_side& io_side, + const std::string& postfix); + +std::string generate_grid_block_module_name(const std::string& prefix, + const std::string& block_name, + const bool& is_block_io, + const e_side& io_side); std::string generate_physical_block_module_name(const std::string& prefix, - const std::string& block_name, - const bool& is_block_io, - const e_side& io_side); + t_pb_type* physical_pb_type); #endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp index 5b103a726..f7105a104 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp @@ -26,6 +26,88 @@ #include "verilog_writer_utils.h" #include "verilog_grid.h" +/******************************************************************** + * Print Verilog modules of a LUT as a primitive node in the + * pb_graph_node graph + * This function will instanciate the LUT Verilog module + * generated in the print_verilog_submodule_luts() + * + * Verilog module structure: + * + * Primitive LUT + * +---------------------------------------+ + * | | + * | +---------+ +---------+ | + * in |----->| |--->| |<------|configuration lines + * | | LUT_MUX |... | LUT_MEM | | + * out|<-----| |--->| | | + * | +---------+ +---------+ | + * | | + * +---------------------------------------+ + * + *******************************************************************/ +static +void print_verilog_primitive_lut(std::fstream& fp, + ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + t_sram_orgz_info* cur_sram_orgz_info, + t_pb_graph_node* lut_pb_graph_node, + const e_side& io_side, + const bool& use_explicit_mapping) { + /* Ensure a valid file handler */ + check_file_handler(fp); + + /* Ensure a valid pb_graph_node */ + if (NULL == lut_pb_graph_node) { + vpr_printf(TIO_MESSAGE_ERROR, + "(File:%s,[LINE%d]) Invalid lut_pb_graph_node!\n", + __FILE__, __LINE__); + exit(1); + } + + /* Find the circuit model id linked to the pb_graph_node */ + CircuitModelId& lut_model = lut_pb_graph_node->pb_type->circuit_model; + + /* The circuit model must be a LUT */ + VTR_ASSERT(SPICE_MODEL_LUT == circuit_lib.model_type(lut_model)); + + /* Generate the module name for this primitive pb_graph_node*/ + std::string lut_module_name_prefix(grid_verilog_file_name_prefix); + /* Add side string to the name if it is valid */ + if (NUM_SIDES != io_side) { + Side side_manager(io_side); + lut_module_name_prefix += std::string(side_manager.to_string()); + lut_module_name_prefix += std::string("_"); + } + std::string lut_module_name = generate_physical_block_module_name(lut_module_name_prefix, lut_pb_graph_node->pb_type); + + /* TODO: Create a module of the primitive LUT + * and register it to module manager + */ + ModuleId lut_module = module_manager.add_module(lut_module_name); + VTR_ASSERT(ModuleId::INVALID() != lut_module); + + /* TODO: find the global ports required by the primitive LUT */ + + /* TODO: Print the module definition for the top-level Verilog module of physical block */ + print_verilog_module_declaration(fp, module_manager, lut_module); + /* Finish printing ports */ + + /* TODO: Create local wires as configuration bus */ + + /* TODO: Create a bus wire for the inputs of the LUT */ + + /* TODO: Instanciate LUT MUX module */ + + /* TODO: Instanciate associated memory module for the LUT */ + + /* Print an end to the Verilog module */ + print_verilog_module_end(fp, module_manager.module_name(lut_module)); + + /* Add an empty line as a splitter */ + fp << std::endl; +} + /******************************************************************** * Print Verilog modules of physical blocks inside a grid (CLB, I/O. etc.) * This function will traverse the graph of complex logic block (t_pb_graph_node) @@ -48,6 +130,7 @@ void print_verilog_physical_blocks_rec(std::fstream& fp, const MuxLibrary& mux_lib, t_sram_orgz_info* cur_sram_orgz_info, t_pb_graph_node* physical_pb_graph_node, + const e_side& io_side, const bool& use_explicit_mapping) { /* Check the file handler*/ check_file_handler(fp); @@ -75,6 +158,7 @@ void print_verilog_physical_blocks_rec(std::fstream& fp, print_verilog_physical_blocks_rec(fp, module_manager, circuit_lib, mux_lib, cur_sram_orgz_info, &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][ipb][0]), + io_side, use_explicit_mapping); } } @@ -84,12 +168,11 @@ void print_verilog_physical_blocks_rec(std::fstream& fp, /* Branch on the type of this physical pb_type, different Verilog modules are generated */ switch (physical_pb_type->class_type) { case LUT_CLASS: - /* TODO: refactor this function - dump_verilog_pb_primitive_verilog_model(cur_sram_orgz_info, fp, formatted_subckt_prefix, - cur_pb_graph_node, pb_type_index, - cur_pb_type->spice_model, - my_bool_to_boolean(is_explicit_mapping)); - */ + print_verilog_primitive_lut(fp, module_manager, circuit_lib, + cur_sram_orgz_info, + physical_pb_graph_node, + io_side, + use_explicit_mapping); break; case LATCH_CLASS: VTR_ASSERT(0 == physical_pb_type->num_modes); @@ -119,9 +202,19 @@ void print_verilog_physical_blocks_rec(std::fstream& fp, return; } - /* TODO: Generate the name of the Verilog module for this pb_type */ + /* Generate the name of the Verilog module for this pb_type */ + std::string pb_module_name_prefix(grid_verilog_file_name_prefix); + /* Add side string to the name if it is valid */ + if (NUM_SIDES != io_side) { + Side side_manager(io_side); + pb_module_name_prefix += std::string(side_manager.to_string()); + pb_module_name_prefix += std::string("_"); + } + std::string pb_module_name = generate_physical_block_module_name(pb_module_name_prefix, physical_pb_type); - /* TODO: Register the Verilog module in module manager */ + /* Register the Verilog module in module manager */ + ModuleId pb_module = module_manager.add_module(pb_module_name); + VTR_ASSERT(ModuleId::INVALID() != pb_module); /* TODO: Add ports to the Verilog module */ @@ -130,7 +223,9 @@ void print_verilog_physical_blocks_rec(std::fstream& fp, /* TODO: Count SRAM ports from the sub-modules under this Verilog module */ /* TODO: Count formal verification ports from the sub-modules under this Verilog module */ - /* TODO: Print Verilog module declaration */ + /* Print Verilog module declaration */ + print_verilog_module_declaration(fp, module_manager, pb_module); + /* Comment lines */ print_verilog_comment(fp, std::string("----- BEGIN Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----")); @@ -157,12 +252,14 @@ void print_verilog_physical_blocks_rec(std::fstream& fp, */ /* Print an end to the Verilog module */ - print_verilog_comment(fp, std::string("----- BEGIN Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----")); + print_verilog_module_end(fp, module_manager.module_name(pb_module)); - return; + print_verilog_comment(fp, std::string("----- END Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----")); + + /* Add an empty line as a splitter */ + fp << std::endl; } - /***************************************************************************** * This function will create a Verilog file and print out a Verilog netlist * for a type of physical block @@ -189,10 +286,10 @@ void print_verilog_grid(ModuleManager& module_manager, /* Give a name to the Verilog netlist */ /* Create the file name for Verilog */ std::string verilog_fname(subckt_dir - + generate_physical_block_netlist_name(std::string(phy_block_type->name), - IO_TYPE == phy_block_type, - border_side, - std::string(verilog_netlist_file_postfix)) + + generate_grid_block_netlist_name(std::string(phy_block_type->name), + IO_TYPE == phy_block_type, + border_side, + std::string(verilog_netlist_file_postfix)) ); /* TODO: remove the bak file when the file is ready */ verilog_fname += ".bak"; @@ -222,30 +319,26 @@ void print_verilog_grid(ModuleManager& module_manager, print_verilog_include_defines_preproc_file(fp, verilog_dir); /* TODO: Print Verilog modules for all the pb_types/pb_graph_nodes */ - for (int iz = 0; iz < phy_block_type->capacity; ++iz) { - /* ONLY output one Verilog module (which is unique), others are the same */ - if (0 < iz) { - continue; - } - /* TODO: use a Depth-First Search Algorithm to print the sub-modules - * Note: DFS is the right way. Do NOT use BFS. - * DFS can guarantee that all the sub-modules can be registered properly - * to its parent in module manager - */ - print_verilog_comment(fp, std::string("---- BEGIN Sub-module of physical block:" + std::string(phy_block_type->name) + " ----")); + /* TODO: use a Depth-First Search Algorithm to print the sub-modules + * Note: DFS is the right way. Do NOT use BFS. + * DFS can guarantee that all the sub-modules can be registered properly + * to its parent in module manager + */ + print_verilog_comment(fp, std::string("---- BEGIN Sub-module of physical block:" + std::string(phy_block_type->name) + " ----")); - /* Print Verilog modules starting from the top-level pb_type/pb_graph_node, and traverse the graph in a recursive way */ - print_verilog_physical_blocks_rec(fp, module_manager, circuit_lib, mux_lib, - cur_sram_orgz_info, - phy_block_type->pb_graph_head, - use_explicit_mapping); + /* Print Verilog modules starting from the top-level pb_type/pb_graph_node, and traverse the graph in a recursive way */ + print_verilog_physical_blocks_rec(fp, module_manager, circuit_lib, mux_lib, + cur_sram_orgz_info, + phy_block_type->pb_graph_head, + border_side, + use_explicit_mapping); - print_verilog_comment(fp, std::string("---- END Sub-module of physical block:" + std::string(phy_block_type->name) + " ----")); - } + print_verilog_comment(fp, std::string("---- END Sub-module of physical block:" + std::string(phy_block_type->name) + " ----")); /* TODO: Create a Verilog Module for the top-level physical block, and add to module manager */ - std::string module_name = generate_physical_block_module_name(std::string(grid_verilog_file_name_prefix), phy_block_type->name, IO_TYPE == phy_block_type, border_side); + std::string module_name = generate_grid_block_module_name(std::string(grid_verilog_file_name_prefix), phy_block_type->name, IO_TYPE == phy_block_type, border_side); ModuleId module_id = module_manager.add_module(module_name); + VTR_ASSERT(ModuleId::INVALID() != module_id); /* TODO: Add ports to the module */ 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 9cebf20ac..8c92880d6 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c @@ -2617,8 +2617,7 @@ void print_verilog_unique_switch_box_mux(ModuleManager& module_manager, 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_bus, + mem_port2port_name_map = generate_mem_module_port2port_map(config_bus, mem_output_ports, circuit_lib.design_tech_type(mux_model), cur_sram_orgz_info->type); @@ -3786,8 +3785,7 @@ void print_verilog_connection_box_mux(ModuleManager& module_manager, 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_bus, + mem_port2port_name_map = generate_mem_module_port2port_map(config_bus, mem_output_ports, circuit_lib.design_tech_type(mux_model), cur_sram_orgz_info->type);