diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index 6cfb9879a..5ac0a49e0 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -122,7 +122,7 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx, /******************************************************************** * A wrapper function to call the full testbench generator of FPGA-Verilog *******************************************************************/ -int write_full_testbench(OpenfpgaContext& openfpga_ctx, +int write_full_testbench(const OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); @@ -170,5 +170,45 @@ int write_full_testbench(OpenfpgaContext& openfpga_ctx, options); } +/******************************************************************** + * A wrapper function to call the preconfigured wrapper generator of FPGA-Verilog + *******************************************************************/ +int write_preconfigured_fabric_wrapper(const OpenfpgaContext& openfpga_ctx, + const Command& cmd, const CommandContext& cmd_context) { + + CommandOptionId opt_output_dir = cmd.option("file"); + 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_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_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_print_formal_verification_top_netlist(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_fabric_wrapper(openfpga_ctx.module_graph(), + openfpga_ctx.bitstream_manager(), + g_vpr_ctx.atom(), + g_vpr_ctx.placement(), + pin_constraints, + openfpga_ctx.io_location_map(), + openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.vpr_netlist_annotation(), + openfpga_ctx.arch().circuit_lib, + openfpga_ctx.arch().config_protocol, + options); +} } /* end namespace openfpga */ diff --git a/openfpga/src/base/openfpga_verilog.h b/openfpga/src/base/openfpga_verilog.h index 20ce5d858..f755bf0bb 100644 --- a/openfpga/src/base/openfpga_verilog.h +++ b/openfpga/src/base/openfpga_verilog.h @@ -21,9 +21,12 @@ int write_fabric_verilog(OpenfpgaContext& openfpga_ctx, int write_verilog_testbench(OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); -int write_full_testbench(OpenfpgaContext& openfpga_ctx, +int write_full_testbench(const OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); +int write_preconfigured_fabric_wrapper(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 431eac47f..6a3c7c415 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -123,9 +123,9 @@ ShellCommandId add_openfpga_write_verilog_testbench_command(openfpga::Shell& shell, @@ -133,46 +133,88 @@ ShellCommandId add_openfpga_write_full_testbench_command(openfpga::Shell& dependent_cmds) { Command shell_cmd("write_full_testbench"); - /* Add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for HDL netlists"); + /* 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 '--bitstream'*/ - CommandOptionId bitstream_opt = shell_cmd.add_option("bitstream", true, "Specify the bitstream to be loaded in the testbench"); + /* add an option '--bitstream'*/ + CommandOptionId bitstream_opt = shell_cmd.add_option("bitstream", true, "specify the bitstream to be loaded in the testbench"); shell_cmd.set_option_require_value(bitstream_opt, openfpga::OPT_STRING); - /* Add an option '--fabric_netlist_file_path'*/ - CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "Specify the file path to the fabric HDL netlist"); + /* add an option '--fabric_netlist_file_path'*/ + CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "specify the file path to the fabric hdl netlist"); shell_cmd.set_option_require_value(fabric_netlist_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"); + /* 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"); + /* 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 '--fast_configuration' */ - shell_cmd.add_option("fast_configuration", false, "Reduce the period of configuration by skip certain data points"); + /* add an option '--fast_configuration' */ + shell_cmd.add_option("fast_configuration", false, "reduce the period of configuration by skip certain data points"); - /* Add an option '--explicit_port_mapping' */ - shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists"); + /* add an option '--explicit_port_mapping' */ + shell_cmd.add_option("explicit_port_mapping", false, "use explicit port mapping in verilog netlists"); - /* Add an option '--include_signal_init' */ - shell_cmd.add_option("include_signal_init", false, "Initialize all the signals in Verilog testbenches"); + /* add an option '--include_signal_init' */ + shell_cmd.add_option("include_signal_init", false, "initialize all the signals in verilog testbenches"); - /* Add an option '--verbose' */ - shell_cmd.add_option("verbose", false, "Enable verbose output"); + /* 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 full testbenches for an FPGA fabric"); + /* add command to the shell */ + ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate full testbenches for an fpga fabric"); shell.set_command_class(shell_cmd_id, cmd_class_id); shell.set_command_execute_function(shell_cmd_id, write_full_testbench); - /* Add command dependency to the Shell */ + /* add command dependency to the shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + +/******************************************************************** + * - add a command to shell environment: write preconfigured fabric wrapper + * - add associated options + * - add command dependency + *******************************************************************/ +static +ShellCommandId add_openfpga_write_preconfigured_fabric_wrapper_command(openfpga::Shell& shell, + const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds) { + Command shell_cmd("write_preconfigured_fabric_wrapper"); + + /* 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 '--fabric_netlist_file_path'*/ + CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "specify the file path to the fabric hdl netlist"); + shell_cmd.set_option_require_value(fabric_netlist_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 '--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 a wrapper for a pre-configured fpga fabric"); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, write_preconfigured_fabric_wrapper); + + /* add command dependency to the shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); return shell_cmd_id; @@ -214,6 +256,17 @@ void add_openfpga_verilog_commands(openfpga::Shell& shell) { add_openfpga_write_full_testbench_command(shell, openfpga_verilog_cmd_class, full_testbench_dependent_cmds); + + /******************************** + * Command 'write_preconfigured_fabric_wrapper' + */ + /* The command 'write_preconfigured_fabric_wrapper' should NOT be executed before 'build_fabric' */ + std::vector preconfig_wrapper_dependent_cmds; + preconfig_wrapper_dependent_cmds.push_back(build_fabric_cmd_id); + add_openfpga_write_preconfigured_fabric_wrapper_command(shell, + openfpga_verilog_cmd_class, + preconfig_wrapper_dependent_cmds); + } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index fa0980eea..d7628570e 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -313,4 +313,49 @@ int fpga_verilog_full_testbench(const ModuleManager &module_manager, return status; } +/******************************************************************** + * A top-level function of FPGA-Verilog which focuses on full testbench generation + * This function will generate + * - A wrapper module, which encapsulate the FPGA module in a Verilog module which have the same port as the input benchmark + ********************************************************************/ +int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, + const AtomContext &atom_ctx, + const PlacementContext &place_ctx, + const PinConstraints& pin_constraints, + const IoLocationMap &io_location_map, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const CircuitLibrary &circuit_lib, + const ConfigProtocol &config_protocol, + const VerilogTestbenchOption &options) { + + vtr::ScopedStartFinishTimer timer("Write a wrapper module 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); + + /* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */ + std::string formal_verification_top_netlist_file_path = src_dir_path + netlist_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX); + status = print_verilog_preconfig_top_module(module_manager, bitstream_manager, + config_protocol, + circuit_lib, fabric_global_port_info, + atom_ctx, place_ctx, + pin_constraints, + io_location_map, + netlist_annotation, + netlist_name, + formal_verification_top_netlist_file_path, + options.explicit_port_mapping()); + + return status; +} + + } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index f3f0b8321..f8665a0e8 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -72,6 +72,19 @@ int fpga_verilog_full_testbench(const ModuleManager& module_manager, const ConfigProtocol& config_protocol, const VerilogTestbenchOption& options); +int fpga_verilog_preconfigured_fabric_wrapper(const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, + const AtomContext &atom_ctx, + const PlacementContext &place_ctx, + const PinConstraints& pin_constraints, + const IoLocationMap &io_location_map, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const CircuitLibrary &circuit_lib, + const ConfigProtocol &config_protocol, + const VerilogTestbenchOption &options); + + } /* end namespace openfpga */ #endif