From 0daf170e45741a7a9ab60ce746b0d1829f28fe6f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 4 Dec 2019 15:38:42 -0700 Subject: [PATCH] refactored all the new functions to new source files, ready to delete legacy codes --- vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_api.c | 17 ++ .../vpr/SRC/fpga_x2p/base/fpga_x2p_utils.cpp | 45 +++- .../vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h | 2 + .../vpr/SRC/fpga_x2p/verilog/verilog_api.cpp | 234 ++++++++++++++++++ .../vpr/SRC/fpga_x2p/verilog/verilog_api.h | 17 ++ .../vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp | 2 - .../vpr/SRC/fpga_x2p/verilog/verilog_lut.cpp | 4 - .../SRC/fpga_x2p/verilog/verilog_memory.cpp | 3 +- .../vpr/SRC/fpga_x2p/verilog/verilog_mux.cpp | 4 +- .../fpga_x2p/verilog/verilog_submodule.cpp | 97 ++++++++ .../verilog/verilog_submodule_utils.cpp | 115 +++++++++ .../verilog/verilog_submodule_utils.h | 11 + .../SRC/fpga_x2p/verilog/verilog_submodules.c | 116 +-------- .../SRC/fpga_x2p/verilog/verilog_submodules.h | 11 + .../vpr/SRC/fpga_x2p/verilog/verilog_utils.h | 2 + .../vpr/SRC/fpga_x2p/verilog/verilog_wire.cpp | 4 - 16 files changed, 552 insertions(+), 132 deletions(-) create mode 100644 vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.cpp create mode 100644 vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule.cpp diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_api.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_api.c index edff64348..1dcd1238b 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_api.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_api.c @@ -13,6 +13,7 @@ #include /* Include vpr structs*/ +#include "vtr_assert.h" #include "util.h" #include "physical_types.h" #include "vpr_types.h" @@ -137,9 +138,22 @@ void vpr_fpga_x2p_tool_suites(t_vpr_setup vpr_setup, /* Xifan TANG: Synthesizable verilog dumping */ if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_syn_verilog) { + /* Old function to deprecatd vpr_fpga_verilog(module_manager, bitstream_manager, fabric_bitstream, mux_lib, L_logical_blocks, device_size, grids, L_blocks, vpr_setup, Arch, vpr_setup.FileNameOpts.CircuitName); + */ + /* Create a local SRAM organization info + * TODO: This should be deprecated in future */ + VTR_ASSERT(NULL != Arch.sram_inf.verilog_sram_inf_orgz); /* Check !*/ + t_spice_model* sram_verilog_model = Arch.sram_inf.verilog_sram_inf_orgz->spice_model; + /* initialize the SRAM organization information struct */ + t_sram_orgz_info* sram_verilog_orgz_info = alloc_one_sram_orgz_info(); + init_sram_orgz_info(sram_verilog_orgz_info, Arch.sram_inf.verilog_sram_inf_orgz->type, sram_verilog_model, nx + 2, ny + 2); + + vpr_fpga_verilog(module_manager, bitstream_manager, fabric_bitstream, mux_lib, + L_logical_blocks, device_size, grids, L_blocks, device_rr_gsb, + vpr_setup, Arch, std::string(vpr_setup.FileNameOpts.CircuitName), sram_verilog_orgz_info); } @@ -154,6 +168,9 @@ void vpr_fpga_x2p_tool_suites(t_vpr_setup vpr_setup, sdc_options.set_generate_sdc_pnr(TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_sdc_pnr); sdc_options.set_generate_sdc_analysis(TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_sdc_analysis); + /* Create directory to contain the SDC files */ + create_dir_path(sdc_options.sdc_dir().c_str()); + if (true == sdc_options.generate_sdc()) { std::vector global_ports = find_circuit_library_global_ports(Arch.spice->circuit_lib); /* TODO: the critical path delay unit should be explicit! */ diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.cpp index 1f49526f0..d158568f7 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.cpp @@ -1,6 +1,7 @@ /******************************************************************** * Most utilized functions in FPGA X2P framework *******************************************************************/ +#include #include #include @@ -54,8 +55,8 @@ std::string find_path_file_name(const std::string& file_name) { if (found != std::string::npos) { return file_name.substr(found + 1); } - /* Not found, return an empty string */ - return std::string(); + /* Not found. The input is the file name! Return the original string */ + return file_name; } /******************************************************************** @@ -133,3 +134,43 @@ std::vector my_itobin_vec(const size_t& in_int, const size_t& bin_len) { return ret; } +/******************************************************************** + * Create a directory with a given path + ********************************************************************/ +bool create_dir_path(const char* dir_path) { + /* Give up if the path is empty */ + if (NULL == dir_path) { + vpr_printf(TIO_MESSAGE_INFO, + "dir_path is empty and nothing is created.\n"); + return false; + } + + /* Try to create a directory */ + int ret = mkdir(dir_path, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH); + + /* Analyze the return flag and output status */ + switch (ret) { + case 0: + vpr_printf(TIO_MESSAGE_INFO, + "Create directory(%s)...successfully.\n", + dir_path); + return true; + case -1: + if (EEXIST == errno) { + vpr_printf(TIO_MESSAGE_WARNING, + "Directory(%s) already exists. Will overwrite contents\n", + dir_path); + return true; + } + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "Create directory(%s)...Failed!\n", + dir_path); + exit(1); + return false; + } + + return false; +} + diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h index 4ad93fc2b..119b68f99 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h @@ -20,6 +20,8 @@ std::string find_path_file_name(const std::string& file_name); std::vector my_itobin_vec(const size_t& in_int, const size_t& bin_len); +bool create_dir_path(const char* dir_path); + /* Old functions */ char* my_gettime(); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.cpp new file mode 100644 index 000000000..3dd850153 --- /dev/null +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.cpp @@ -0,0 +1,234 @@ +/******************************************************************** + * This file include top-level function of FPGA-Verilog + ********************************************************************/ +/* Standard header files */ +#include + +/* External library header files */ +#include "util.h" +#include "vtr_assert.h" +#include "circuit_library_utils.h" + +/* FPGA-X2P header files */ +#include "fpga_x2p_utils.h" +#include "rr_blocks.h" + +/* FPGA-Verilog header files */ +#include "verilog_global.h" +#include "verilog_submodules.h" +#include "verilog_routing.h" +#include "verilog_submodules.h" +#include "verilog_grid.h" +#include "verilog_routing.h" +#include "verilog_top_module.h" +#include "verilog_top_testbench.h" +#include "verilog_formal_random_top_testbench.h" +#include "verilog_preconfig_top_module.h" +#include "simulation_info_writer.h" +#include "verilog_auxiliary_netlists.h" + +/* Header file for this source file */ +#include "verilog_api.h" + +/******************************************************************** + * Top-level function of FPGA-Verilog + * This function will generate + * 1. primitive modules required by the full fabric + * which are LUTs, routing multiplexer, logic gates, transmission-gates etc. + * 2. Routing modules, which are Switch Blocks (SBs) and Connection Blocks (CBs) + * 3. Logic block modules, which are Configuration Logic Blocks (CLBs) + * 4. FPGA module, which are the full FPGA fabric with configuration protocol + * 5. A wrapper module, which encapsulate the FPGA module in a Verilog module which have the same port as the input benchmark + * 6. Testbench, where a FPGA module is configured with a bitstream and then driven by input vectors + * 7. Pre-configured testbench, which can skip the configuration phase and pre-configure the FPGA module. This testbench is created for quick verification and formal verification purpose. + * 8. Verilog netlist including preprocessing flags and all the Verilog netlists that have been generated + ********************************************************************/ +void vpr_fpga_verilog(ModuleManager& module_manager, + const BitstreamManager& bitstream_manager, + const std::vector& fabric_bitstream, + const MuxLibrary& mux_lib, + const std::vector& L_logical_blocks, + const vtr::Point& device_size, + const std::vector>& L_grids, + const std::vector& L_blocks, + const DeviceRRGSB& L_device_rr_gsb, + const t_vpr_setup& vpr_setup, + const t_arch& Arch, + const std::string& circuit_name, + t_sram_orgz_info* sram_verilog_orgz_info) { + /* Start time count */ + clock_t t_start = clock(); + + /* 0. basic units: inverter, buffers and pass-gate logics, */ + /* Check if the routing architecture we support*/ + if (UNI_DIRECTIONAL != vpr_setup.RoutingArch.directionality) { + vpr_printf(TIO_MESSAGE_ERROR, + "FPGA-Verilog only supports uni-directional routing architecture!\n"); + exit(1); + } + + /* We don't support mrFPGA */ +#ifdef MRFPGA_H + if (is_mrFPGA) { + vpr_printf(TIO_MESSAGE_ERROR, + "FPGA-Verilog does not support mrFPGA!\n"); + exit(1); + } +#endif + + /* Verilog generator formally starts*/ + vpr_printf(TIO_MESSAGE_INFO, + "\nFPGA-Verilog starts...\n"); + + /* Format the directory paths */ + std::string chomped_parent_dir = find_path_dir_name(circuit_name); + std::string chomped_circuit_name = find_path_file_name(circuit_name); + + std::string verilog_dir_formatted; + if (NULL != vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.syn_verilog_dump_dir) { + verilog_dir_formatted = format_dir_path(std::string(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.syn_verilog_dump_dir)); + } else { + verilog_dir_formatted = format_dir_path(format_dir_path(chomped_parent_dir) + std::string(default_verilog_dir_name)); + } + + /* Create directories */ + create_dir_path(verilog_dir_formatted.c_str()); + + /* SRC directory to contain all the netlists */ + std::string src_dir_path = format_dir_path(verilog_dir_formatted + std::string(default_src_dir_name)); + create_dir_path(src_dir_path.c_str()); + + /* Sub directory under SRC directory to contain all the primitive block netlists */ + std::string submodule_dir_path = src_dir_path + std::string(default_submodule_dir_name); + create_dir_path(submodule_dir_path.c_str()); + + /* Sub directory under SRC directory to contain all the logic block netlists */ + std::string lb_dir_path = src_dir_path + std::string(default_lb_dir_name); + create_dir_path(lb_dir_path.c_str()); + + /* Sub directory under SRC directory to contain all the routing block netlists */ + std::string rr_dir_path = src_dir_path + std::string(default_rr_dir_name); + create_dir_path(rr_dir_path.c_str()); + + /* Ensure all the SRAM port is using the correct circuit model */ + config_circuit_models_sram_port_to_default_sram_model(Arch.spice->circuit_lib, Arch.sram_inf.verilog_sram_inf_orgz->circuit_model); + + /* Print Verilog files containing preprocessing flags */ + print_verilog_preprocessing_flags_netlist(std::string(src_dir_path), + vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts); + + print_verilog_simulation_preprocessing_flags(std::string(src_dir_path), + vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts); + + /* Generate primitive Verilog modules, which are corner stones of FPGA fabric + * Note that this function MUST be called before Verilog generation of + * core logic (i.e., logic blocks and routing resources) !!! + * This is because that this function will add the primitive Verilog modules to + * the module manager. + * Without the modules in the module manager, core logic generation is not possible!!! + */ + print_verilog_submodules(module_manager, mux_lib, sram_verilog_orgz_info, src_dir_path.c_str(), submodule_dir_path.c_str(), + Arch, vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts); + + /* Generate routing blocks */ + if (TRUE == vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy) { + print_verilog_unique_routing_modules(module_manager, L_device_rr_gsb, + vpr_setup.RoutingArch, + src_dir_path, rr_dir_path, + TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog); + } else { + VTR_ASSERT(FALSE == vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy); + print_verilog_flatten_routing_modules(module_manager, L_device_rr_gsb, + vpr_setup.RoutingArch, + src_dir_path, rr_dir_path, + TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog); + } + + /* Generate grids */ + print_verilog_grids(module_manager, + src_dir_path, lb_dir_path, + TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog); + + /* Generate FPGA fabric */ + print_verilog_top_module(module_manager, + std::string(vpr_setup.FileNameOpts.ArchFile), + src_dir_path, + TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog); + + /* Collect global ports from the circuit library + * TODO: move outside this function + */ + std::vector global_ports = find_circuit_library_global_ports(Arch.spice->circuit_lib); + + /* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */ + if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_formal_verification_top_netlist) { + std::string formal_verification_top_netlist_file_path = src_dir_path + chomped_circuit_name + + std::string(formal_verification_verilog_file_postfix); + print_verilog_preconfig_top_module(module_manager, bitstream_manager, + Arch.spice->circuit_lib, global_ports, L_logical_blocks, + device_size, L_grids, L_blocks, + std::string(chomped_circuit_name), formal_verification_top_netlist_file_path, + std::string(src_dir_path)); + + /* Generate top-level testbench using random vectors */ + std::string random_top_testbench_file_path = src_dir_path + chomped_circuit_name + + std::string(random_top_testbench_verilog_file_postfix); + print_verilog_random_top_testbench(chomped_circuit_name, random_top_testbench_file_path, + src_dir_path, L_logical_blocks, + vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, Arch.spice->spice_params); + } + + /* Generate exchangeable files which contains simulation settings */ + if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_simulation_ini) { + std::string simulation_ini_file_name; + if (NULL != vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.simulation_ini_path) { + simulation_ini_file_name = std::string(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.simulation_ini_path); + } + print_verilog_simulation_info(simulation_ini_file_name, + format_dir_path(chomped_parent_dir), + chomped_circuit_name, + src_dir_path, + bitstream_manager.bits().size(), + Arch.spice->spice_params.meas_params.sim_num_clock_cycle, + Arch.spice->spice_params.stimulate_params.prog_clock_freq, + Arch.spice->spice_params.stimulate_params.op_clock_freq); + } + + /* Generate full testbench for verification, including configuration phase and operating phase */ + if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_autocheck_top_testbench) { + std::string autocheck_top_testbench_file_path = src_dir_path + chomped_circuit_name + + std::string(autocheck_top_testbench_verilog_file_postfix); + print_verilog_top_testbench(module_manager, bitstream_manager, fabric_bitstream, + sram_verilog_orgz_info->type, + Arch.spice->circuit_lib, global_ports, + L_logical_blocks, device_size, L_grids, L_blocks, + chomped_circuit_name, + autocheck_top_testbench_file_path, + src_dir_path, + Arch.spice->spice_params); + } + + /* Generate a Verilog file including all the netlists that have been generated */ + std::string ref_verilog_benchmark_file_name; + if (NULL != vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.reference_verilog_benchmark_file) { + ref_verilog_benchmark_file_name = std::string(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.reference_verilog_benchmark_file); + } + print_include_netlists(src_dir_path, + chomped_circuit_name, + ref_verilog_benchmark_file_name, + Arch.spice->circuit_lib); + + /* Given a brief stats on how many Verilog modules have been written to files */ + vpr_printf(TIO_MESSAGE_INFO, + "Outputted %lu Verilog modules in total\n", + module_manager.num_modules()); + + /* End time count */ + clock_t t_end = clock(); + + float run_time_sec = (float)(t_end - t_start) / CLOCKS_PER_SEC; + vpr_printf(TIO_MESSAGE_INFO, + "FPGA-Verilog took %g seconds\n", + run_time_sec); +} + diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.h index 95358f85c..a23175e0e 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.h @@ -1,12 +1,29 @@ #ifndef VERILOG_API_H #define VERILOG_API_H +#include #include #include "vpr_types.h" #include "mux_library.h" +#include "rr_blocks.h" #include "module_manager.h" #include "bitstream_manager.h" +void vpr_fpga_verilog(ModuleManager& module_manager, + const BitstreamManager& bitstream_manager, + const std::vector& fabric_bitstream, + const MuxLibrary& mux_lib, + const std::vector& L_logical_blocks, + const vtr::Point& device_size, + const std::vector>& L_grids, + const std::vector& L_blocks, + const DeviceRRGSB& L_device_rr_gsb, + const t_vpr_setup& vpr_setup, + const t_arch& Arch, + const std::string& circuit_name, + t_sram_orgz_info* sram_verilog_orgz_info); + +/* TODO: Old function to be deprecated */ void vpr_fpga_verilog(ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const std::vector& fabric_bitstream, 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 401484e30..fb1cdc75f 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_grid.cpp @@ -262,9 +262,7 @@ void print_verilog_grid(ModuleManager& module_manager, fp.close(); /* Add fname to the linked list */ - /* TODO: add it when it is ready grid_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(grid_verilog_subckt_file_path_head, verilog_fname.c_str()); - */ } /***************************************************************************** diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_lut.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_lut.cpp index 5a0232b5c..08fd812a8 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_lut.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_lut.cpp @@ -71,10 +71,6 @@ void print_verilog_submodule_luts(ModuleManager& module_manager, fp.close(); /* Add fname to the linked list */ - /* Add it when the Verilog generation is refactored submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_fname.c_str()); - */ - - return; } 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 ee0b63e9f..31ac06cac 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.cpp @@ -187,8 +187,7 @@ void print_verilog_submodule_memories(ModuleManager& module_manager, /* Close the file stream */ fp.close(); - /* Add fname to the linked list + /* Add fname to the linked list */ submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_fname.c_str()); - */ } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_mux.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_mux.cpp index a52018ff3..caa8c1a00 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_mux.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_mux.cpp @@ -1279,9 +1279,7 @@ void print_verilog_submodule_muxes(ModuleManager& module_manager, try_update_sram_orgz_info_reserved_blwl(cur_sram_orgz_info, mux_lib.max_mux_size(), mux_lib.max_mux_size()); - /* TODO: Add fname to the linked list when debugging is finished */ - /* + /* Add fname to the linked list when debugging is finished */ submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_fname.c_str()); - */ } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule.cpp new file mode 100644 index 000000000..eaeb0115a --- /dev/null +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule.cpp @@ -0,0 +1,97 @@ +/********************************************************************* + * This file includes top-level function to generate Verilog primitive modules + * and print them to files + ********************************************************************/ +/* Standard header files */ + +/* External library header files */ +#include "util.h" + +/* FPGA-Verilog header files */ +#include "verilog_global.h" +#include "verilog_utils.h" +#include "verilog_submodule_utils.h" +#include "verilog_essential_gates.h" +#include "verilog_decoders.h" +#include "verilog_mux.h" +#include "verilog_lut.h" +#include "verilog_wire.h" +#include "verilog_memory.h" + +/* Header file for this source file */ +#include "verilog_submodules.h" + +/********************************************************************* + * Top-level function to generate primitive modules: + * 1. Logic gates: AND/OR, inverter, buffer and transmission-gate/pass-transistor + * 2. Routing multiplexers + * 3. Local encoders for routing multiplexers + * 4. Wires + * 5. Configuration memory blocks + * 6. Verilog template + ********************************************************************/ +void print_verilog_submodules(ModuleManager& module_manager, + const MuxLibrary& mux_lib, + t_sram_orgz_info* cur_sram_orgz_info, + const char* verilog_dir, + const char* submodule_dir, + const t_arch& Arch, + const t_syn_verilog_opts& fpga_verilog_opts) { + + /* Register all the user-defined modules in the module manager + * This should be done prior to other steps in this function, + * because they will be instanciated by other primitive modules + */ + vpr_printf(TIO_MESSAGE_INFO, + "Registering user-defined modules...\n"); + + add_user_defined_verilog_modules(module_manager, Arch.spice->circuit_lib); + + print_verilog_submodule_essentials(module_manager, + std::string(verilog_dir), + std::string(submodule_dir), + Arch.spice->circuit_lib); + + /* Routing multiplexers */ + vpr_printf(TIO_MESSAGE_INFO, + "Generating modules for routing multiplexers...\n"); + + /* NOTE: local decoders generation must go before the MUX generation!!! + * because local decoders modules will be instanciated in the MUX modules + */ + print_verilog_submodule_mux_local_decoders(module_manager, mux_lib, Arch.spice->circuit_lib, + std::string(verilog_dir), std::string(submodule_dir)); + print_verilog_submodule_muxes(module_manager, mux_lib, Arch.spice->circuit_lib, cur_sram_orgz_info, + std::string(verilog_dir), std::string(submodule_dir), + fpga_verilog_opts.dump_explicit_verilog); + + + /* LUTes */ + vpr_printf(TIO_MESSAGE_INFO, + "Generating modules for LUTs...\n"); + print_verilog_submodule_luts(module_manager, Arch.spice->circuit_lib, std::string(verilog_dir), std::string(submodule_dir), + fpga_verilog_opts.dump_explicit_verilog); + + /* Hard wires */ + print_verilog_submodule_wires(module_manager, Arch.spice->circuit_lib, std::string(verilog_dir), std::string(submodule_dir)); + + /* 4. Memories */ + vpr_printf(TIO_MESSAGE_INFO, + "Generating modules for configuration memory blocks...\n"); + print_verilog_submodule_memories(module_manager, mux_lib, Arch.spice->circuit_lib, + std::string(verilog_dir), std::string(submodule_dir), + fpga_verilog_opts.dump_explicit_verilog); + + /* 5. Dump template for all the modules */ + if (TRUE == fpga_verilog_opts.print_user_defined_template) { + print_verilog_submodule_templates(module_manager, Arch.spice->circuit_lib, std::string(verilog_dir), std::string(submodule_dir)); + } + + /* Create a header file to include all the subckts */ + vpr_printf(TIO_MESSAGE_INFO, + "Generating header file for basic submodules...\n"); + dump_verilog_subckt_header_file(submodule_verilog_subckt_file_path_head, + submodule_dir, + submodule_verilog_file_name); +} + diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_utils.cpp index 3ddf25c03..5a9838b3c 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_utils.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_utils.cpp @@ -14,6 +14,7 @@ /* FPGA-X2P context header files */ #include "fpga_x2p_utils.h" +#include "module_manager_utils.h" /* FPGA-Verilog context header files */ #include "verilog_global.h" @@ -119,3 +120,117 @@ void print_verilog_submodule_signal_init(std::fstream& fp, fp << "`endif" << std::endl; } +/********************************************************************* + * Register all the user-defined modules in the module manager + * Walk through the circuit library and add user-defined circuit models + * to the module_manager + ********************************************************************/ +void add_user_defined_verilog_modules(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib) { + /* Iterate over Verilog modules */ + for (const auto& model : circuit_lib.models()) { + /* We only care about user-defined models */ + if (true == circuit_lib.model_verilog_netlist(model).empty()) { + continue; + } + /* Skip Routing channel wire models because they need a different name. Do it later */ + if (SPICE_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) { + continue; + } + /* Reach here, the model requires a user-defined Verilog netlist, + * Try to find it in the module manager + * If not found, register it in the module_manager + */ + ModuleId module_id = module_manager.find_module(circuit_lib.model_name(model)); + if (ModuleId::INVALID() == module_id) { + add_circuit_model_to_module_manager(module_manager, circuit_lib, model); + } + } +} + +/********************************************************************* + * Print a template for a user-defined circuit model + * The template will include just the port declaration of the Verilog module + * The template aims to help user to write Verilog codes with a guaranteed + * module definition, which can be correctly instanciated (with correct + * port mapping) in the FPGA fabric + ********************************************************************/ +static +void print_one_verilog_template_module(const ModuleManager& module_manager, + std::fstream& fp, + const std::string& module_name) { + /* Ensure a valid file handler*/ + check_file_handler(fp); + + print_verilog_comment(fp, std::string("----- Template Verilog module for " + module_name + " -----")); + + /* Find the module in module manager, which should be already registered */ + /* TODO: routing channel wire model may have a different name! */ + ModuleId template_module = module_manager.find_module(module_name); + VTR_ASSERT(ModuleId::INVALID() != template_module); + + /* dump module definition + ports */ + print_verilog_module_declaration(fp, module_manager, template_module); + /* Finish dumping ports */ + + print_verilog_comment(fp, std::string("----- Internal logic should start here -----")); + + /* Add some empty lines as placeholders for the internal logic*/ + fp << std::endl << std::endl; + + print_verilog_comment(fp, std::string("----- Internal logic should end here -----")); + + /* Put an end to the Verilog module */ + print_verilog_module_end(fp, module_name); + + /* Add an empty line as a splitter */ + fp << std::endl; +} + +/********************************************************************* + * Print a template of all the submodules that are user-defined + * The template will include just the port declaration of the submodule + * The template aims to help user to write Verilog codes with a guaranteed + * module definition, which can be correctly instanciated (with correct + * port mapping) in the FPGA fabric + ********************************************************************/ +void print_verilog_submodule_templates(const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const std::string& verilog_dir, + const std::string& submodule_dir) { + std::string verilog_fname(submodule_dir + user_defined_template_verilog_file_name); + + /* Create the file stream */ + std::fstream fp; + fp.open(verilog_fname, std::fstream::out | std::fstream::trunc); + + check_file_handler(fp); + + /* Print out debugging information for if the file is not opened/created properly */ + vpr_printf(TIO_MESSAGE_INFO, + "Creating template for user-defined Verilog modules (%s)...\n", + verilog_fname.c_str()); + + print_verilog_file_header(fp, "Template for user-defined Verilog modules"); + + print_verilog_include_defines_preproc_file(fp, verilog_dir); + + /* Output essential models*/ + for (const auto& model : circuit_lib.models()) { + /* Focus on user-defined modules, which must have a Verilog netlist defined */ + if (circuit_lib.model_verilog_netlist(model).empty()) { + continue; + } + /* Skip Routing channel wire models because they need a different name. Do it later */ + if (SPICE_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) { + continue; + } + /* Print a Verilog template for the circuit model */ + print_one_verilog_template_module(module_manager, fp, circuit_lib.model_name(model)); + } + + /* close file stream */ + fp.close(); + + /* No need to add the template to the subckt include files! */ +} diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_utils.h index 8d93deaaf..91f0828f8 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodule_utils.h @@ -9,6 +9,9 @@ #define VERILOG_SUBMODULE_UTILS_H #include +#include +#include "module_manager.h" +#include "circuit_library.h" void print_verilog_submodule_timing(std::fstream& fp, const CircuitLibrary& circuit_lib, @@ -18,4 +21,12 @@ void print_verilog_submodule_signal_init(std::fstream& fp, const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); +void add_user_defined_verilog_modules(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib); + +void print_verilog_submodule_templates(const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const std::string& verilog_dir, + const std::string& submodule_dir); + #endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodules.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodules.c index a792ed4ae..695c41b3c 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodules.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodules.c @@ -49,6 +49,7 @@ #include "verilog_lut.h" #include "verilog_memory.h" #include "verilog_wire.h" +#include "verilog_submodule_utils.h" #include "verilog_submodules.h" @@ -3078,121 +3079,6 @@ void dump_verilog_submodule_memories(t_sram_orgz_info* cur_sram_orgz_info, return; } -/********************************************************************* - * Register all the user-defined modules in the module manager - * Walk through the circuit library and add user-defined circuit models - * to the module_manager - ********************************************************************/ -static -void add_user_defined_verilog_modules(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib) { - /* Iterate over Verilog modules */ - for (const auto& model : circuit_lib.models()) { - /* We only care about user-defined models */ - if (true == circuit_lib.model_verilog_netlist(model).empty()) { - continue; - } - /* Skip Routing channel wire models because they need a different name. Do it later */ - if (SPICE_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) { - continue; - } - /* Reach here, the model requires a user-defined Verilog netlist, - * Try to find it in the module manager - * If not found, register it in the module_manager - */ - ModuleId module_id = module_manager.find_module(circuit_lib.model_name(model)); - if (ModuleId::INVALID() == module_id) { - add_circuit_model_to_module_manager(module_manager, circuit_lib, model); - } - } -} - -/* Print a template for a user-defined circuit model - * The template will include just the port declaration of the Verilog module - * The template aims to help user to write Verilog codes with a guaranteed - * module definition, which can be correctly instanciated (with correct - * port mapping) in the FPGA fabric - */ -static -void print_one_verilog_template_module(const ModuleManager& module_manager, - std::fstream& fp, - const std::string& module_name) { - /* Ensure a valid file handler*/ - check_file_handler(fp); - - print_verilog_comment(fp, std::string("----- Template Verilog module for " + module_name + " -----")); - - /* Find the module in module manager, which should be already registered */ - /* TODO: routing channel wire model may have a different name! */ - ModuleId template_module = module_manager.find_module(module_name); - VTR_ASSERT(ModuleId::INVALID() != template_module); - - /* dump module definition + ports */ - print_verilog_module_declaration(fp, module_manager, template_module); - /* Finish dumping ports */ - - print_verilog_comment(fp, std::string("----- Internal logic should start here -----")); - - /* Add some empty lines as placeholders for the internal logic*/ - fp << std::endl << std::endl; - - print_verilog_comment(fp, std::string("----- Internal logic should end here -----")); - - /* Put an end to the Verilog module */ - print_verilog_module_end(fp, module_name); - - /* Add an empty line as a splitter */ - fp << std::endl; -} - -/* Print a template of all the submodules that are user-defined - * The template will include just the port declaration of the submodule - * The template aims to help user to write Verilog codes with a guaranteed - * module definition, which can be correctly instanciated (with correct - * port mapping) in the FPGA fabric - */ -static -void print_verilog_submodule_templates(const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const std::string& verilog_dir, - const std::string& submodule_dir) { - std::string verilog_fname(submodule_dir + user_defined_template_verilog_file_name); - - /* Create the file stream */ - std::fstream fp; - fp.open(verilog_fname, std::fstream::out | std::fstream::trunc); - - check_file_handler(fp); - - /* Print out debugging information for if the file is not opened/created properly */ - vpr_printf(TIO_MESSAGE_INFO, - "Creating template for user-defined Verilog modules (%s)...\n", - verilog_fname.c_str()); - - print_verilog_file_header(fp, "Template for user-defined Verilog modules"); - - print_verilog_include_defines_preproc_file(fp, verilog_dir); - - /* Output essential models*/ - for (const auto& model : circuit_lib.models()) { - /* Focus on user-defined modules, which must have a Verilog netlist defined */ - if (circuit_lib.model_verilog_netlist(model).empty()) { - continue; - } - /* Skip Routing channel wire models because they need a different name. Do it later */ - if (SPICE_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) { - continue; - } - /* Print a Verilog template for the circuit model */ - print_one_verilog_template_module(module_manager, fp, circuit_lib.model_name(model)); - } - - /* close file stream */ - fp.close(); - - /* No need to add the template to the subckt include files! */ -} - /********************************************************************* * Dump verilog files of submodules to be used in FPGA components : * 1. MUXes diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodules.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodules.h index 3d6a30e99..1e8bcbaa3 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodules.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_submodules.h @@ -1,9 +1,19 @@ #ifndef VERILOG_SUBMODULES_H #define VERILOG_SUBMODULES_H +#include "vpr_types.h" #include "module_manager.h" #include "mux_library.h" +void print_verilog_submodules(ModuleManager& module_manager, + const MuxLibrary& mux_lib, + t_sram_orgz_info* cur_sram_orgz_info, + const char* verilog_dir, + const char* submodule_dir, + const t_arch& Arch, + const t_syn_verilog_opts& fpga_verilog_opts); + +/* TODO: Old function to be deprecated */ void dump_verilog_submodules(ModuleManager& module_manager, const MuxLibrary& mux_lib, t_sram_orgz_info* cur_sram_orgz_info, @@ -12,4 +22,5 @@ void dump_verilog_submodules(ModuleManager& module_manager, t_arch Arch, t_det_routing_arch* routing_arch, t_syn_verilog_opts fpga_verilog_opts); + #endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_utils.h index 30a4d8863..789aec66e 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_utils.h @@ -1,6 +1,8 @@ #ifndef VERILOG_UTILS_H #define VERILOG_UTILS_H +#include "vpr_types.h" + void init_list_include_verilog_netlists(t_spice* spice); void init_include_user_defined_verilog_netlists(t_spice spice); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_wire.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_wire.cpp index 1efe6d6cb..6c52c6e84 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_wire.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_wire.cpp @@ -128,9 +128,5 @@ void print_verilog_submodule_wires(ModuleManager& module_manager, fp.close(); /* Add fname to the linked list */ - /* Uncomment this when it is ready to be plugged in - */ submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_fname.c_str()); - - return; }