diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index 5ac0a49e0..f62c9da71 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -180,6 +180,7 @@ int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + 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 @@ -190,6 +191,7 @@ int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist)); options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); + options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator)); options.set_print_formal_verification_top_netlist(true); /* If pin constraints are enabled by command options, read the file */ @@ -211,4 +213,42 @@ int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, options); } +/******************************************************************** + * A wrapper function to call the preconfigured testbench generator of FPGA-Verilog + *******************************************************************/ +int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context) { + + CommandOptionId opt_output_dir = cmd.option("file"); + CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); + CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); + CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); + 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 + */ + VerilogTestbenchOption options; + options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); + options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); + options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); + options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); + options.set_print_preconfig_top_testbench(true); + + /* If pin constraints are enabled by command options, read the file */ + PinConstraints pin_constraints; + if (true == cmd_context.option_enable(cmd, opt_pcf)) { + pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); + } + + return fpga_verilog_preconfigured_testbench(openfpga_ctx.module_graph(), + g_vpr_ctx.atom(), + pin_constraints, + openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.vpr_netlist_annotation(), + openfpga_ctx.simulation_setting(), + options); +} + + } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_verilog.h b/openfpga/src/base/openfpga_verilog.h index f755bf0bb..d7c0b5404 100644 --- a/openfpga/src/base/openfpga_verilog.h +++ b/openfpga/src/base/openfpga_verilog.h @@ -27,6 +27,9 @@ int write_full_testbench(const OpenfpgaContext& openfpga_ctx, int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); +int write_preconfigured_testbench(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index 6a3c7c415..f9d4acc65 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -206,6 +206,9 @@ ShellCommandId add_openfpga_write_preconfigured_fabric_wrapper_command(openfpga: /* add an option '--explicit_port_mapping' */ shell_cmd.add_option("explicit_port_mapping", false, "use explicit port mapping in verilog netlists"); + /* Add an option '--support_icarus_simulator' */ + shell_cmd.add_option("support_icarus_simulator", false, "Fine-tune Verilog testbenches to support icarus simulator"); + /* add an option '--verbose' */ shell_cmd.add_option("verbose", false, "enable verbose output"); @@ -220,6 +223,48 @@ ShellCommandId add_openfpga_write_preconfigured_fabric_wrapper_command(openfpga: return shell_cmd_id; } +/******************************************************************** + * - Add a command to Shell environment: write preconfigured testbench + * - Add associated options + * - Add command dependency + *******************************************************************/ +static +ShellCommandId add_openfpga_write_preconfigured_testbench_command(openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { + Command shell_cmd("write_preconfigured_testbench"); + + /* Add an option '--file' in short '-f'*/ + CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for HDL netlists"); + shell_cmd.set_option_short_name(output_opt, "f"); + shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); + + /* Add an option '--pin_constraints_file in short '-pcf' */ + CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "Specify the file path to the pin constraints"); + shell_cmd.set_option_short_name(pcf_opt, "pcf"); + shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING); + + /* Add an option '--reference_benchmark_file_path'*/ + CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "Specify the file path to the reference Verilog netlist"); + shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING); + + /* Add an option '--explicit_port_mapping' */ + shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists"); + + /* Add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "Enable verbose output"); + + /* Add command to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate testbenches for a preconfigured FPGA fabric"); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, write_preconfigured_testbench); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + void add_openfpga_verilog_commands(openfpga::Shell& shell) { /* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */ const ShellCommandId& build_fabric_cmd_id = shell.command(std::string("build_fabric")); @@ -267,6 +312,16 @@ void add_openfpga_verilog_commands(openfpga::Shell& shell) { openfpga_verilog_cmd_class, preconfig_wrapper_dependent_cmds); + /******************************** + * Command 'write_preconfigured_testbench' + */ + /* The command 'write_preconfigured_testbench' should NOT be executed before 'build_fabric' */ + std::vector preconfig_testbench_dependent_cmds; + preconfig_testbench_dependent_cmds.push_back(build_fabric_cmd_id); + add_openfpga_write_preconfigured_testbench_command(shell, + openfpga_verilog_cmd_class, + preconfig_testbench_dependent_cmds); + } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index d7628570e..3c1624c1a 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -357,5 +357,55 @@ int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manage return status; } +/******************************************************************** + * A top-level function of FPGA-Verilog which focuses on fabric Verilog generation + * This function will generate + * - 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. + ********************************************************************/ +int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager, + const AtomContext &atom_ctx, + const PinConstraints& pin_constraints, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const SimulationSetting &simulation_setting, + const VerilogTestbenchOption &options) { + + vtr::ScopedStartFinishTimer timer("Write Verilog testbenches for a preconfigured FPGA fabric\n"); + + std::string src_dir_path = format_dir_path(options.output_directory()); + + std::string netlist_name = atom_ctx.nlist.netlist_name(); + + int status = CMD_EXEC_SUCCESS; + + /* Create directories */ + create_directory(src_dir_path); + + /* Output preprocessing flags for HDL simulations */ + print_verilog_simulation_preprocessing_flags(std::string(src_dir_path), + options); + + /* Generate top-level testbench using random vectors */ + std::string random_top_testbench_file_path = src_dir_path + netlist_name + std::string(RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); + print_verilog_random_top_testbench(netlist_name, + random_top_testbench_file_path, + atom_ctx, + netlist_annotation, + module_manager, + fabric_global_port_info, + pin_constraints, + simulation_setting, + options.explicit_port_mapping()); + + /* Generate a Verilog file including all the netlists that have been generated */ + print_verilog_testbench_include_netlists(src_dir_path, + netlist_name, + options.fabric_netlist_file_path(), + options.reference_benchmark_file_path()); + + return status; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index f8665a0e8..da6685f3b 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -84,6 +84,13 @@ int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manage const ConfigProtocol &config_protocol, const VerilogTestbenchOption &options); +int fpga_verilog_preconfigured_testbench(const ModuleManager &module_manager, + const AtomContext &atom_ctx, + const PinConstraints& pin_constraints, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const SimulationSetting &simulation_setting, + const VerilogTestbenchOption &options); } /* end namespace openfpga */