Merge branch 'refactoring' into dev

This commit is contained in:
tangxifan 2020-02-16 00:04:29 -07:00
commit 2035afc34b
22 changed files with 2520 additions and 1 deletions

View File

@ -2,6 +2,9 @@
* This file includes functions that handles the file outputting
* in OpenFPGA framework
*******************************************************************/
#include <sys/stat.h>
#include <algorithm>
/* Headers from vtrutil library */
#include "vtr_log.h"
@ -37,4 +40,114 @@ void check_file_stream(const char* fname,
}
}
/********************************************************************
* Format a directory path:
* 1. Replace "\" with "/"
* 2. add a "/" if the string does not end with a "/"
*******************************************************************/
std::string format_dir_path(const std::string& dir_path_to_format) {
std::string formatted_dir_path = dir_path_to_format;
char illegal_back_slash = '\\';
char legal_back_slash = '/';
#ifdef _WIN32
/* For windows OS, replace any '/' with '\' */
char illegal_back_slash = '/';
char legal_back_slash = '\\';
#endif
/* Replace "\" with "/" */
std::replace(formatted_dir_path.begin(), formatted_dir_path.end(), illegal_back_slash, legal_back_slash);
/* Add a back slash the string is not ended like this! */
if (legal_back_slash != formatted_dir_path.back()) {
formatted_dir_path.push_back(legal_back_slash);
}
return formatted_dir_path;
}
/********************************************************************
* Extract full file name from a full path of file
* For example: <dir_path>/<file_name>
* This function will return <file_name>
********************************************************************/
std::string find_path_file_name(const std::string& file_name) {
char back_slash = '/';
#ifdef _WIN32
/* For windows OS, replace any '/' with '\' */
char back_slash = '\\';
#endif
/* Find the last '/' in the string and return the left part */
size_t found = file_name.rfind(back_slash);
if (found != std::string::npos) {
return file_name.substr(found + 1);
}
/* Not found. The input is the file name! Return the original string */
return file_name;
}
/********************************************************************
* Extract full directory path from a full path of file
* For example: <dir_path>/<file_name>
* This function will return <dir_path>
********************************************************************/
std::string find_path_dir_name(const std::string& file_name) {
char back_slash = '/';
#ifdef _WIN32
/* For windows OS, replace any '/' with '\' */
char back_slash = '\\';
#endif
/* Find the last '/' in the string and return the left part */
size_t found = file_name.rfind(back_slash);
if (found != std::string::npos) {
return file_name.substr(0, found);
}
/* Not found, return an empty string */
return std::string();
}
/********************************************************************
* Create a directory with a given path
********************************************************************/
bool create_dir_path(const char* dir_path) {
/* Give up if the path is empty */
if (nullptr == dir_path) {
VTR_LOG_ERROR("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:
VTR_LOG("Succeed to create directory '%s'\n",
dir_path);
return true;
case -1:
if (EEXIST == errno) {
VTR_LOG_ERROR("Directory '%s' already exists. Will overwrite contents\n",
dir_path);
return true;
}
break;
default:
VTR_LOG_ERROR("Create directory '%s'...Failed!\n",
dir_path);
exit(1);
return false;
}
return false;
}
} /* namespace openfpga ends */

View File

@ -17,6 +17,14 @@ bool valid_file_stream(std::fstream& fp);
void check_file_stream(const char* fname,
std::fstream& fp);
std::string format_dir_path(const std::string& dir_path_to_format);
std::string find_path_file_name(const std::string& file_name);
std::string find_path_dir_name(const std::string& file_name);
bool create_dir_path(const char* dir_path);
} /* namespace openfpga ends */
#endif

View File

@ -10,6 +10,7 @@
#include "mux_library.h"
#include "tile_direct.h"
#include "module_manager.h"
#include "openfpga_flow_manager.h"
#include "device_rr_gsb.h"
/********************************************************************
@ -50,6 +51,7 @@ class OpenfpgaContext : public Context {
const openfpga::MuxLibrary& mux_lib() const { return mux_lib_; }
const openfpga::TileDirect& tile_direct() const { return tile_direct_; }
const openfpga::ModuleManager& module_graph() const { return module_graph_; }
const openfpga::FlowManager& flow_manager() const { return flow_manager_; }
public: /* Public mutators */
openfpga::Arch& mutable_arch() { return arch_; }
openfpga::VprDeviceAnnotation& mutable_vpr_device_annotation() { return vpr_device_annotation_; }
@ -60,6 +62,7 @@ class OpenfpgaContext : public Context {
openfpga::MuxLibrary& mutable_mux_lib() { return mux_lib_; }
openfpga::TileDirect& mutable_tile_direct() { return tile_direct_; }
openfpga::ModuleManager& mutable_module_graph() { return module_graph_; }
openfpga::FlowManager& mutable_flow_manager() { return flow_manager_; }
private: /* Internal data */
/* Data structure to store information from read_openfpga_arch library */
openfpga::Arch arch_;
@ -87,6 +90,9 @@ class OpenfpgaContext : public Context {
/* Fabric module graph */
openfpga::ModuleManager module_graph_;
/* Flow status */
openfpga::FlowManager flow_manager_;
};
#endif

View File

@ -0,0 +1,26 @@
/******************************************************************************
* Memember functions for data structure FlowManager
******************************************************************************/
#include "vtr_assert.h"
#include "openfpga_flow_manager.h"
/* begin namespace openfpga */
namespace openfpga {
/**************************************************
* Public Accessors
*************************************************/
bool FlowManager::compress_routing() const {
return compress_routing_;
}
/******************************************************************************
* Private Mutators
******************************************************************************/
void FlowManager::set_compress_routing(const bool& enabled) {
compress_routing_ = enabled;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,28 @@
#ifndef FLOW_MANAGER_H
#define FLOW_MANAGER_H
/********************************************************************
* Include header files required by the data structure definition
*******************************************************************/
/* Begin namespace openfpga */
namespace openfpga {
/********************************************************************
* FlowManager aims to resolve the dependency between OpenFPGA functional
* code blocks
* It can provide flags for downstream modules about if the data structures
* they require have already been constructed
*
*******************************************************************/
class FlowManager {
public: /* Public accessors */
bool compress_routing() const;
public: /* Public mutators */
void set_compress_routing(const bool& enabled);
private: /* Internal Data */
bool compress_routing_;
};
} /* End namespace openfpga*/
#endif

View File

@ -135,7 +135,7 @@ void add_openfpga_setup_commands(openfpga::Shell<OpenfpgaContext>& shell) {
shell.set_command_execute_function(shell_cmd_build_fabric_id, build_fabric);
/* The 'build_fabric' command should NOT be executed before 'link_openfpga_arch' */
std::vector<ShellCommandId> cmd_dependency_build_fabric;
cmd_dependency_lut_truth_table_fixup.push_back(shell_cmd_link_openfpga_arch_id);
cmd_dependency_build_fabric.push_back(shell_cmd_link_openfpga_arch_id);
shell.set_command_dependency(shell_cmd_build_fabric_id, cmd_dependency_build_fabric);
}

View File

@ -0,0 +1,50 @@
/********************************************************************
* This file includes functions to compress the hierachy of routing architecture
*******************************************************************/
/* Headers from vtrutil library */
#include "vtr_time.h"
#include "vtr_log.h"
#include "verilog_api.h"
#include "openfpga_verilog.h"
/* Include global variables of VPR */
#include "globals.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* A wrapper function to call the fabric_verilog function of FPGA-Verilog
*******************************************************************/
void write_fabric_verilog(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping");
CommandOptionId opt_include_timing = cmd.option("include_timing");
CommandOptionId opt_include_signal_init = cmd.option("include_signal_init");
CommandOptionId opt_support_icarus_simulator = cmd.option("support_icarus_simulator");
CommandOptionId opt_verbose = cmd.option("verbose");
/* This is an intermediate data structure which is designed to modularize the FPGA-Verilog
* Keep it independent from any other outside data structures
*/
FabricVerilogOption options;
options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir));
options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping));
options.set_include_timing(cmd_context.option_enable(cmd, opt_include_timing));
options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init));
options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
options.set_compress_routing(openfpga_ctx.flow_manager().compress_routing());
fpga_fabric_verilog(openfpga_ctx.module_graph(),
openfpga_ctx.arch().circuit_lib,
openfpga_ctx.mux_lib(),
g_vpr_ctx.device().grid,
openfpga_ctx.device_rr_gsb(),
options);
}
} /* end namespace openfpga */

View File

@ -0,0 +1,23 @@
#ifndef OPENFPGA_VERILOG_H
#define OPENFPGA_VERILOG_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "command.h"
#include "command_context.h"
#include "openfpga_context.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void write_fabric_verilog(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,51 @@
/********************************************************************
* Add commands to the OpenFPGA shell interface,
* in purpose of generate Verilog netlists modeling the full FPGA fabric
* This is one of the core engine of openfpga, including:
* - generate_fabric_verilog : generate Verilog netlists about FPGA fabric
* - generate_fabric_verilog_testbench : TODO: generate Verilog testbenches
*******************************************************************/
#include "openfpga_verilog.h"
#include "openfpga_verilog_command.h"
/* begin namespace openfpga */
namespace openfpga {
void add_openfpga_verilog_commands(openfpga::Shell<OpenfpgaContext>& shell) {
/* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */
const ShellCommandId& shell_cmd_build_fabric_id = shell.command(std::string("build_fabric"));
/* Add a new class of commands */
ShellCommandClassId openfpga_verilog_cmd_class = shell.add_command_class("FPGA-Verilog");
/********************************
* Command 'wirte_fabric_verilog'
*/
Command shell_cmd_write_fabric_verilog("write_fabric_verilog");
/* Add an option '--file' in short '-f'*/
CommandOptionId fabric_verilog_output_opt = shell_cmd_write_fabric_verilog.add_option("file", true, "Specify the output directory for Verilog netlists");
shell_cmd_write_fabric_verilog.set_option_short_name(fabric_verilog_output_opt, "f");
shell_cmd_write_fabric_verilog.set_option_require_value(fabric_verilog_output_opt, openfpga::OPT_STRING);
/* Add an option '--explicit_port_mapping' */
shell_cmd_write_fabric_verilog.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists");
/* Add an option '--include_timing' */
shell_cmd_write_fabric_verilog.add_option("include_timing", false, "Enable timing annotation in Verilog netlists");
/* Add an option '--include_signal_init' */
shell_cmd_write_fabric_verilog.add_option("include_signal_init", false, "Initialize all the signals in Verilog netlists");
/* Add an option '--support_icarus_simulator' */
shell_cmd_write_fabric_verilog.add_option("support_icarus_simulator", false, "Fine-tune Verilog netlists to support icarus simulator");
/* Add an option '--verbose' */
shell_cmd_write_fabric_verilog.add_option("verbose", false, "Enable verbose output");
/* Add command 'write_fabric_verilog' to the Shell */
ShellCommandId shell_cmd_write_fabric_verilog_id = shell.add_command(shell_cmd_write_fabric_verilog, "generate Verilog netlists modeling full FPGA fabric");
shell.set_command_class(shell_cmd_write_fabric_verilog_id, openfpga_verilog_cmd_class);
shell.set_command_execute_function(shell_cmd_write_fabric_verilog_id, write_fabric_verilog);
/* The 'build_fabric' command should NOT be executed before 'link_openfpga_arch' */
std::vector<ShellCommandId> cmd_dependency_write_fabric_verilog;
cmd_dependency_write_fabric_verilog.push_back(shell_cmd_build_fabric_id);
shell.set_command_dependency(shell_cmd_write_fabric_verilog_id, cmd_dependency_write_fabric_verilog);
}
} /* end namespace openfpga */

View File

@ -0,0 +1,21 @@
#ifndef OPENFPGA_VERILOG_COMMAND_H
#define OPENFPGA_VERILOG_COMMAND_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "shell.h"
#include "openfpga_context.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void add_openfpga_verilog_commands(openfpga::Shell<OpenfpgaContext>& shell);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,116 @@
/********************************************************************
* This file include top-level function of FPGA-Verilog
********************************************************************/
/* Headers from vtrutil library */
#include "vtr_log.h"
#include "vtr_assert.h"
#include "vtr_time.h"
#include "circuit_library_utils.h"
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "device_rr_gsb.h"
#include "verilog_constants.h"
#include "verilog_auxiliary_netlists.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"
/* Header file for this source file */
#include "verilog_api.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* 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 fpga_fabric_verilog(const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const DeviceGrid& grids,
const DeviceRRGSB& device_rr_gsb,
const FabricVerilogOption& options) {
vtr::ScopedStartFinishTimer timer("Write Verilog netlists for FPGA fabric\n");
std::string src_dir_path = format_dir_path(options.output_directory());
/* Create directories */
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());
/* Print Verilog files containing preprocessing flags */
print_verilog_preprocessing_flags_netlist(std::string(src_dir_path),
options);
print_verilog_simulation_preprocessing_flags(std::string(src_dir_path),
options);
/* 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 == compress_routing) {
// print_verilog_unique_routing_modules(module_manager, device_rr_gsb,
// src_dir_path, rr_dir_path,
// dump_explicit_verilog);
//} else {
// VTR_ASSERT(false == compress_routing);
// print_verilog_flatten_routing_modules(module_manager, device_rr_gsb,
// src_dir_path, rr_dir_path,
// dump_explicit_verilog);
//}
/* Generate grids */
//print_verilog_grids(module_manager,
// src_dir_path, lb_dir_path,
// dump_explicit_verilog);
/* Generate FPGA fabric */
//print_verilog_top_module(module_manager,
// std::string(vpr_setup.FileNameOpts.ArchFile),
// src_dir_path,
// dump_explicit_verilog);
/* Given a brief stats on how many Verilog modules have been written to files */
VTR_LOGV(options.verbose_output(),
"Outputted %lu Verilog modules in total\n",
module_manager.num_modules());
}
} /* end namespace openfpga */

View File

@ -0,0 +1,34 @@
#ifndef VERILOG_API_H
#define VERILOG_API_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include <vector>
#include "vpr_types.h"
#include "mux_library.h"
#include "circuit_library.h"
#include "device_grid.h"
#include "device_rr_gsb.h"
#include "module_manager.h"
#include "verilog_options.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void fpga_fabric_verilog(const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const DeviceGrid& grids,
const DeviceRRGSB& device_rr_gsb,
const FabricVerilogOption& options);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,200 @@
/********************************************************************
* This file includes functions that are used to generate Verilog files
* or code blocks, with a focus on
* `include user-defined or auto-generated netlists in Verilog format
*******************************************************************/
#include <fstream>
/* Headers from vtrutil library */
#include "vtr_assert.h"
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "openfpga_naming.h"
#include "circuit_library_utils.h"
#include "verilog_constants.h"
#include "verilog_writer_utils.h"
#include "verilog_auxiliary_netlists.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Local constant variables
*******************************************************************/
constexpr char* TOP_INCLUDE_NETLIST_FILE_NAME_POSTFIX = "_include_netlists.v";
/********************************************************************
* Print a file that includes all the netlists that have been generated
* and user-defined.
* Some netlists are open to compile under specific preprocessing flags
*******************************************************************/
void print_include_netlists(const std::string& src_dir,
const std::string& circuit_name,
const std::string& reference_benchmark_file,
const CircuitLibrary& circuit_lib) {
std::string verilog_fname = src_dir + circuit_name + std::string(TOP_INCLUDE_NETLIST_FILE_NAME_POSTFIX);
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
/* Validate the file stream */
check_file_stream(verilog_fname.c_str(), fp);
/* Print the title */
print_verilog_file_header(fp, std::string("Netlist Summary"));
/* Print preprocessing flags */
print_verilog_comment(fp, std::string("------ Include defines: preproc flags -----"));
print_verilog_include_netlist(fp, std::string(src_dir + std::string(DEFINES_VERILOG_FILE_NAME)));
fp << std::endl;
print_verilog_comment(fp, std::string("------ Include simulation defines -----"));
print_verilog_include_netlist(fp, src_dir + std::string(DEFINES_VERILOG_SIMULATION_FILE_NAME));
fp << std::endl;
/* Include all the user-defined netlists */
for (const std::string& user_defined_netlist : find_circuit_library_unique_verilog_netlists(circuit_lib)) {
print_verilog_include_netlist(fp, user_defined_netlist);
}
/* Include all the primitive modules */
print_verilog_include_netlist(fp, src_dir + std::string(DEFAULT_SUBMODULE_DIR_NAME) + std::string(SUBMODULE_VERILOG_FILE_NAME));
fp << std::endl;
/* Include all the CLB, heterogeneous block modules */
print_verilog_include_netlist(fp, src_dir + std::string(DEFAULT_LB_DIR_NAME) + std::string(LOGIC_BLOCK_VERILOG_FILE_NAME));
fp << std::endl;
/* Include all the routing architecture modules */
print_verilog_include_netlist(fp, src_dir + std::string(DEFAULT_RR_DIR_NAME) + std::string(ROUTING_VERILOG_FILE_NAME));
fp << std::endl;
/* Include FPGA top module */
print_verilog_include_netlist(fp, src_dir + generate_fpga_top_netlist_name(std::string(VERILOG_NETLIST_FILE_POSTFIX)));
fp << std::endl;
/* Include reference benchmark netlist only when auto-check flag is enabled */
print_verilog_preprocessing_flag(fp, std::string(AUTOCHECKED_SIMULATION_FLAG));
fp << "\t";
print_verilog_include_netlist(fp, std::string(reference_benchmark_file));
print_verilog_endif(fp);
fp << std::endl;
/* Include formal verification netlists only when formal verification flag is enable */
print_verilog_preprocessing_flag(fp, std::string(VERILOG_FORMAL_VERIFICATION_PREPROC_FLAG));
fp << "\t";
print_verilog_include_netlist(fp, src_dir + circuit_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX));
/* Include formal verification testbench only when formal simulation flag is enabled */
fp << "\t";
print_verilog_preprocessing_flag(fp, std::string(FORMAL_SIMULATION_FLAG));
fp << "\t\t";
print_verilog_include_netlist(fp, src_dir + circuit_name + std::string(RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX));
fp << "\t";
print_verilog_endif(fp);
print_verilog_endif(fp);
fp << std::endl;
/* Include top-level testbench only when auto-check flag is enabled */
print_verilog_preprocessing_flag(fp, std::string(AUTOCHECKED_SIMULATION_FLAG));
fp << "\t";
print_verilog_include_netlist(fp, src_dir + circuit_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX));
print_verilog_endif(fp);
fp << std::endl;
/* Close the file stream */
fp.close();
}
/********************************************************************
* Print a Verilog file containing preprocessing flags
* which are used enable/disable some features in FPGA Verilog modules
*******************************************************************/
void print_verilog_preprocessing_flags_netlist(const std::string& src_dir,
const FabricVerilogOption& fpga_verilog_opts) {
std::string verilog_fname = src_dir + std::string(DEFINES_VERILOG_FILE_NAME);
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
/* Validate the file stream */
check_file_stream(verilog_fname.c_str(), fp);
/* Print the title */
print_verilog_file_header(fp, std::string("Preprocessing flags to enable/disable features in FPGA Verilog modules"));
/* To enable timing */
if (true == fpga_verilog_opts.include_timing()) {
print_verilog_define_flag(fp, std::string(VERILOG_TIMING_PREPROC_FLAG), 1);
fp << std::endl;
}
/* To enable timing */
if (true == fpga_verilog_opts.include_signal_init()) {
print_verilog_define_flag(fp, std::string(VERILOG_SIGNAL_INIT_PREPROC_FLAG), 1);
fp << std::endl;
}
/* To enable formal verfication flag */
if (true == fpga_verilog_opts.print_formal_verification_top_netlist()) {
print_verilog_define_flag(fp, std::string(VERILOG_FORMAL_VERIFICATION_PREPROC_FLAG), 1);
fp << std::endl;
}
/* To enable functional verfication with Icarus */
if (true == fpga_verilog_opts.support_icarus_simulator()) {
print_verilog_define_flag(fp, std::string(ICARUS_SIMULATOR_FLAG), 1);
fp << std::endl;
}
/* Close the file stream */
fp.close();
}
/********************************************************************
* Print a Verilog file containing simulation-related preprocessing flags
*******************************************************************/
void print_verilog_simulation_preprocessing_flags(const std::string& src_dir,
const FabricVerilogOption& fpga_verilog_opts) {
std::string verilog_fname = src_dir + std::string(DEFINES_VERILOG_SIMULATION_FILE_NAME);
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
/* Validate the file stream */
check_file_stream(verilog_fname.c_str(), fp);
/* Print the title */
print_verilog_file_header(fp, std::string("Preprocessing flags to enable/disable simulation features"));
/* To enable manualy checked simulation */
if (true == fpga_verilog_opts.print_top_testbench()) {
print_verilog_define_flag(fp, std::string(INITIAL_SIMULATION_FLAG), 1);
fp << std::endl;
}
/* To enable auto-checked simulation */
if (true == fpga_verilog_opts.print_autocheck_top_testbench()) {
print_verilog_define_flag(fp, std::string(AUTOCHECKED_SIMULATION_FLAG), 1);
fp << std::endl;
}
/* To enable pre-configured FPGA simulation */
if (true == fpga_verilog_opts.print_formal_verification_top_netlist()) {
print_verilog_define_flag(fp, std::string(FORMAL_SIMULATION_FLAG), 1);
fp << std::endl;
}
/* Close the file stream */
fp.close();
}
} /* end namespace openfpga */

View File

@ -0,0 +1,31 @@
#ifndef VERILOG_AUXILIARY_NETLISTS_H
#define VERILOG_AUXILIARY_NETLISTS_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "circuit_library.h"
#include "verilog_options.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void print_include_netlists(const std::string& src_dir,
const std::string& circuit_name,
const std::string& reference_benchmark_file,
const CircuitLibrary& circuit_lib);
void print_verilog_preprocessing_flags_netlist(const std::string& src_dir,
const FabricVerilogOption& fpga_verilog_opts);
void print_verilog_simulation_preprocessing_flags(const std::string& src_dir,
const FabricVerilogOption& fpga_verilog_opts);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,44 @@
#ifndef VERILOG_CONSTANTS_H
#define VERILOG_CONSTANTS_H
/* global parameters for dumping synthesizable verilog */
constexpr char* VERILOG_NETLIST_FILE_POSTFIX = ".v";
constexpr float VERILOG_SIM_TIMESCALE = 1e-9; // Verilog Simulation time scale (minimum time unit) : 1ns
constexpr char* VERILOG_TIMING_PREPROC_FLAG = "ENABLE_TIMING"; // the flag to enable timing definition during compilation
constexpr char* VERILOG_SIGNAL_INIT_PREPROC_FLAG = "ENABLE_SIGNAL_INITIALIZATION"; // the flag to enable signal initialization during compilation
constexpr char* VERILOG_FORMAL_VERIFICATION_PREPROC_FLAG = "ENABLE_FORMAL_VERIFICATION"; // the flag to enable formal verification during compilation
constexpr char* INITIAL_SIMULATION_FLAG = "INITIAL_SIMULATION"; // the flag to enable initial functional verification
constexpr char* AUTOCHECKED_SIMULATION_FLAG = "AUTOCHECKED_SIMULATION"; // the flag to enable autochecked functional verification
constexpr char* FORMAL_SIMULATION_FLAG = "FORMAL_SIMULATION"; // the flag to enable formal functional verification
constexpr char* DEFAULT_LB_DIR_NAME = "lb/";
constexpr char* DEFAULT_RR_DIR_NAME = "routing/";
constexpr char* DEFAULT_SUBMODULE_DIR_NAME = "sub_module/";
constexpr char* MODELSIM_SIMULATION_TIME_UNIT = "ms";
// Icarus variables and flag
constexpr char* ICARUS_SIMULATOR_FLAG = "ICARUS_SIMULATOR"; // the flag to enable specific Verilog code in testbenches
// End of Icarus variables and flag
constexpr char* VERILOG_TOP_POSTFIX = "_top.v";
constexpr char* FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX = "_top_formal_verification.v";
constexpr char* TOP_TESTBENCH_VERILOG_FILE_POSTFIX = "_top_tb.v"; /* !!! must be consist with the modelsim_testbench_module_postfix */
constexpr char* AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX = "_autocheck_top_tb.v"; /* !!! must be consist with the modelsim_autocheck_testbench_module_postfix */
constexpr char* RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX = "_formal_random_top_tb.v";
constexpr char* DEFINES_VERILOG_FILE_NAME = "fpga_defines.v";
constexpr char* DEFINES_VERILOG_SIMULATION_FILE_NAME = "define_simulation.v";
constexpr char* SUBMODULE_VERILOG_FILE_NAME = "sub_module.v";
constexpr char* LOGIC_BLOCK_VERILOG_FILE_NAME = "logic_blocks.v";
constexpr char* LUTS_VERILOG_FILE_NAME = "luts.v";
constexpr char* ROUTING_VERILOG_FILE_NAME = "routing.v";
constexpr char* MUXES_VERILOG_FILE_NAME = "muxes.v";
constexpr char* LOCAL_ENCODER_VERILOG_FILE_NAME = "local_encoder.v";
constexpr char* MEMORIES_VERILOG_FILE_NAME = "memories.v";
constexpr char* WIRES_VERILOG_FILE_NAME = "wires.v";
constexpr char* ESSENTIALS_VERILOG_FILE_NAME = "inv_buf_passgate.v";
constexpr char* CONFIG_PERIPHERAL_VERILOG_FILE_NAME = "config_peripherals.v";
constexpr char* USER_DEFINED_TEMPLATE_VERILOG_FILE_NAME = "user_defined_templates.v";
#endif

View File

@ -0,0 +1,101 @@
/******************************************************************************
* Memember functions for data structure FabricVerilogOption
******************************************************************************/
#include "vtr_assert.h"
#include "verilog_options.h"
/* begin namespace openfpga */
namespace openfpga {
/**************************************************
* Public Accessors
*************************************************/
std::string FabricVerilogOption::output_directory() const {
return output_directory_;
}
bool FabricVerilogOption::support_icarus_simulator() const {
return support_icarus_simulator_;
}
bool FabricVerilogOption::include_timing() const {
return include_timing_;
}
bool FabricVerilogOption::include_signal_init() const {
return include_signal_init_;
}
bool FabricVerilogOption::explicit_port_mapping() const {
return explicit_port_mapping_;
}
bool FabricVerilogOption::compress_routing() const {
return compress_routing_;
}
bool FabricVerilogOption::print_top_testbench() const {
return print_top_testbench_;
}
bool FabricVerilogOption::print_formal_verification_top_netlist() const {
return print_formal_verification_top_netlist_;
}
bool FabricVerilogOption::print_autocheck_top_testbench() const {
return false == reference_verilog_file_path_.empty();
}
std::string FabricVerilogOption::reference_verilog_file_path() const {
return reference_verilog_file_path_;
}
bool FabricVerilogOption::verbose_output() const {
return verbose_output_;
}
/******************************************************************************
* Private Mutators
******************************************************************************/
void FabricVerilogOption::set_output_directory(const std::string& output_dir) {
output_directory_ = output_dir;
}
void FabricVerilogOption::set_support_icarus_simulator(const bool& enabled) {
support_icarus_simulator_ = enabled;
}
void FabricVerilogOption::set_include_timing(const bool& enabled) {
include_timing_ = enabled;
}
void FabricVerilogOption::set_include_signal_init(const bool& enabled) {
include_signal_init_ = enabled;
}
void FabricVerilogOption::set_explicit_port_mapping(const bool& enabled) {
explicit_port_mapping_ = enabled;
}
void FabricVerilogOption::set_compress_routing(const bool& enabled) {
compress_routing_ = enabled;
}
void FabricVerilogOption::set_print_top_testbench(const bool& enabled) {
print_top_testbench_ = enabled;
}
void FabricVerilogOption::set_print_formal_verification_top_netlist(const bool& enabled) {
print_formal_verification_top_netlist_ = enabled;
}
void FabricVerilogOption::set_print_autocheck_top_testbench(const std::string& reference_verilog_file_path) {
reference_verilog_file_path_ = reference_verilog_file_path;
}
void FabricVerilogOption::set_verbose_output(const bool& enabled) {
verbose_output_ = enabled;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,59 @@
#ifndef VERILOG_OPTIONS_H
#define VERILOG_OPTIONS_H
/********************************************************************
* Include header files required by the data structure definition
*******************************************************************/
#include <string>
/* Begin namespace openfpga */
namespace openfpga {
/********************************************************************
* FlowManager aims to resolve the dependency between OpenFPGA functional
* code blocks
* It can provide flags for downstream modules about if the data structures
* they require have already been constructed
*
*******************************************************************/
class FabricVerilogOption {
public: /* Public accessors */
std::string output_directory() const;
bool support_icarus_simulator() const;
bool include_timing() const;
bool include_signal_init() const;
bool explicit_port_mapping() const;
bool compress_routing() const;
bool print_top_testbench() const;
bool print_formal_verification_top_netlist() const;
bool print_autocheck_top_testbench() const;
std::string reference_verilog_file_path() const;
bool verbose_output() const;
public: /* Public mutators */
void set_output_directory(const std::string& output_dir);
void set_support_icarus_simulator(const bool& enabled);
void set_include_timing(const bool& enabled);
void set_include_signal_init(const bool& enabled);
void set_explicit_port_mapping(const bool& enabled);
void set_compress_routing(const bool& enabled);
void set_print_top_testbench(const bool& enabled);
void set_print_formal_verification_top_netlist(const bool& enabled);
void set_print_autocheck_top_testbench(const std::string& reference_verilog_file_path);
void set_verbose_output(const bool& enabled);
private: /* Internal Data */
std::string output_directory_;
bool support_icarus_simulator_;
bool include_signal_init_;
bool include_timing_;
bool explicit_port_mapping_;
bool compress_routing_;
bool print_top_testbench_;
bool print_formal_verification_top_netlist_;
/* print_autocheck_top_testbench will be enabled when reference file path is not empty */
std::string reference_verilog_file_path_;
bool verbose_output_;
};
} /* End namespace openfpga*/
#endif

View File

@ -0,0 +1,16 @@
#ifndef VERILOG_PORT_TYPES_H
#define VERILOG_PORT_TYPES_H
enum e_dump_verilog_port_type {
VERILOG_PORT_INPUT,
VERILOG_PORT_OUTPUT,
VERILOG_PORT_INOUT,
VERILOG_PORT_WIRE,
VERILOG_PORT_REG,
VERILOG_PORT_CONKT,
NUM_VERILOG_PORT_TYPES
};
constexpr std::array<const char*, NUM_VERILOG_PORT_TYPES> VERILOG_PORT_TYPE_STRING = {{"input", "output", "inout", "wire", "reg", ""}}; /* string version of enum e_verilog_port_type */
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,187 @@
/************************************************
* Header file for verilog_writer_utils.cpp
* Include function declaration for most frequently
* used Verilog writers
***********************************************/
#ifndef VERILOG_WRITER_UTILS_H
#define VERILOG_WRITER_UTILS_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <fstream>
#include <vector>
#include <string>
#include "openfpga_port.h"
#include "verilog_port_types.h"
#include "module_manager.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
/* Tips: for naming your function in this header/source file
* If a function outputs to a file, its name should begin with "print_verilog"
* If a function creates a string without outputting to a file, its name should begin with "generate_verilog"
* Please show respect to this naming convention, in order to keep a clean header/source file
* as well maintain a easy way to identify the functions
*/
void print_verilog_file_header(std::fstream& fp,
const std::string& usage);
void print_verilog_include_netlist(std::fstream& fp,
const std::string& netlist_name);
void print_verilog_define_flag(std::fstream& fp,
const std::string& flag_name,
const int& flag_value);
void print_verilog_include_defines_preproc_file(std::fstream& fp,
const std::string& verilog_dir);
void print_verilog_comment(std::fstream& fp,
const std::string& comment);
void print_verilog_preprocessing_flag(std::fstream& fp,
const std::string& preproc_flag);
void print_verilog_endif(std::fstream& fp);
void print_verilog_module_definition(std::fstream& fp,
const ModuleManager& module_manager, const ModuleId& module_id);
void print_verilog_module_ports(std::fstream& fp,
const ModuleManager& module_manager, const ModuleId& module_id);
void print_verilog_module_declaration(std::fstream& fp,
const ModuleManager& module_manager, const ModuleId& module_id);
void print_verilog_module_instance(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& module_id,
const std::string& instance_name,
const std::map<std::string, BasicPort>& port2port_name_map,
const bool& use_explicit_port_map);
void print_verilog_module_instance(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& parent_module_id, const ModuleId& child_module_id,
const std::map<std::string, BasicPort>& port2port_name_map,
const bool& use_explicit_port_map);
void print_verilog_module_end(std::fstream& fp,
const std::string& module_name);
std::string generate_verilog_port(const enum e_dump_verilog_port_type& dump_port_type,
const BasicPort& port_info);
bool two_verilog_ports_mergeable(const BasicPort& portA,
const BasicPort& portB);
BasicPort merge_two_verilog_ports(const BasicPort& portA,
const BasicPort& portB);
std::vector<BasicPort> combine_verilog_ports(const std::vector<BasicPort>& ports);
std::string generate_verilog_ports(const std::vector<BasicPort>& merged_ports);
BasicPort generate_verilog_bus_port(const std::vector<BasicPort>& input_ports,
const std::string& bus_port_name);
std::string generate_verilog_local_wire(const BasicPort& output_port,
const std::vector<BasicPort>& input_ports);
std::string generate_verilog_constant_values(const std::vector<size_t>& const_values);
std::string generate_verilog_port_constant_values(const BasicPort& output_port,
const std::vector<size_t>& const_values);
void print_verilog_wire_constant_values(std::fstream& fp,
const BasicPort& output_port,
const std::vector<size_t>& const_values);
void print_verilog_deposit_wire_constant_values(std::fstream& fp,
const BasicPort& output_port,
const std::vector<size_t>& const_values);
void print_verilog_force_wire_constant_values(std::fstream& fp,
const BasicPort& output_port,
const std::vector<size_t>& const_values);
void print_verilog_wire_connection(std::fstream& fp,
const BasicPort& output_port,
const BasicPort& input_port,
const bool& inverted);
void print_verilog_register_connection(std::fstream& fp,
const BasicPort& output_port,
const BasicPort& input_port,
const bool& inverted);
void print_verilog_buffer_instance(std::fstream& fp,
ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const ModuleId& parent_module_id,
const CircuitModelId& buffer_model,
const BasicPort& instance_input_port,
const BasicPort& instance_output_port);
void print_verilog_local_sram_wires(std::fstream& fp,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_config_protocol_type sram_orgz_type,
const size_t& port_size);
void print_verilog_local_config_bus(std::fstream& fp,
const std::string& prefix,
const e_config_protocol_type& sram_orgz_type,
const size_t& instance_id,
const size_t& num_conf_bits);
void print_verilog_mux_config_bus(std::fstream& fp,
const CircuitLibrary& circuit_lib,
const CircuitModelId& mux_model,
const e_config_protocol_type& sram_orgz_type,
const size_t& mux_size,
const size_t& mux_instance_id,
const size_t& num_reserved_conf_bits,
const size_t& num_conf_bits);
void print_verilog_formal_verification_mux_sram_ports_wiring(std::fstream& fp,
const CircuitLibrary& circuit_lib,
const CircuitModelId& mux_model,
const size_t& mux_size,
const size_t& mux_instance_id,
const size_t& num_conf_bits,
const BasicPort& fm_config_bus);
void print_verilog_pulse_stimuli(std::fstream& fp,
const BasicPort& port,
const size_t& initial_value,
const float& pulse_width,
const size_t& flip_value);
void print_verilog_pulse_stimuli(std::fstream& fp,
const BasicPort& port,
const size_t& initial_value,
const std::vector<float>& pulse_widths,
const std::vector<size_t>& flip_values,
const std::string& wait_condition);
void print_verilog_clock_stimuli(std::fstream& fp,
const BasicPort& port,
const size_t& initial_value,
const float& pulse_width,
const std::string& wait_condition);
void print_verilog_netlist_include_header_file(const std::vector<std::string>& netlists_to_be_included,
const char* subckt_dir,
const char* header_file_name);
} /* end namespace openfpga */
#endif

View File

@ -12,6 +12,7 @@
/* Header file from openfpga */
#include "vpr_command.h"
#include "openfpga_setup_command.h"
#include "openfpga_verilog_command.h"
#include "basic_command.h"
#include "openfpga_title.h"
@ -52,6 +53,9 @@ int main(int argc, char** argv) {
/* Add openfpga setup commands */
openfpga::add_openfpga_setup_commands(shell);
/* Add openfpga verilog commands */
openfpga::add_openfpga_verilog_commands(shell);
/* Add basic commands: exit, help, etc.
* Note:
* This MUST be the last command group to be added!

View File

@ -21,5 +21,9 @@ lut_truth_table_fixup #--verbose
# - Enable pin duplication on grid modules
build_fabric --compress_routing --duplicate_grid_pin --verbose
# Write the Verilog netlit for FPGA fabric
# - Enable the use of explicit port mapping in Verilog netlist
write_fabric_verilog --file /var/tmp/xtang/openfpga_test_src --explicit_port_mapping --include_timing --include_signal_init --support_icarus_simulator --verbose
# Finish and exit OpenFPGA
exit