refactored all the new functions to new source files, ready to delete legacy codes
This commit is contained in:
parent
13f964ea72
commit
0daf170e45
|
@ -13,6 +13,7 @@
|
|||
#include <vector>
|
||||
|
||||
/* 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<CircuitPortId> global_ports = find_circuit_library_global_ports(Arch.spice->circuit_lib);
|
||||
/* TODO: the critical path delay unit should be explicit! */
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/********************************************************************
|
||||
* Most utilized functions in FPGA X2P framework
|
||||
*******************************************************************/
|
||||
#include <sys/stat.h>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -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<size_t> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ std::string find_path_file_name(const std::string& file_name);
|
|||
|
||||
std::vector<size_t> 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();
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
/********************************************************************
|
||||
* This file include top-level function of FPGA-Verilog
|
||||
********************************************************************/
|
||||
/* Standard header files */
|
||||
#include <ctime>
|
||||
|
||||
/* 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<ConfigBitId>& fabric_bitstream,
|
||||
const MuxLibrary& mux_lib,
|
||||
const std::vector<t_logical_block>& L_logical_blocks,
|
||||
const vtr::Point<size_t>& device_size,
|
||||
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
||||
const std::vector<t_block>& 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<CircuitPortId> 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);
|
||||
}
|
||||
|
|
@ -1,12 +1,29 @@
|
|||
#ifndef VERILOG_API_H
|
||||
#define VERILOG_API_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#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<ConfigBitId>& fabric_bitstream,
|
||||
const MuxLibrary& mux_lib,
|
||||
const std::vector<t_logical_block>& L_logical_blocks,
|
||||
const vtr::Point<size_t>& device_size,
|
||||
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
||||
const std::vector<t_block>& 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<ConfigBitId>& fabric_bitstream,
|
||||
|
|
|
@ -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());
|
||||
*/
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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! */
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#define VERILOG_SUBMODULE_UTILS_H
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue