[Tool] Add a new command 'write_preconfigured_testbench'

This commit is contained in:
tangxifan 2021-06-08 21:53:51 -06:00
parent d2495a4e47
commit d2275b971d
5 changed files with 155 additions and 0 deletions

View File

@ -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 */

View File

@ -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

View File

@ -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<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& 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<OpenfpgaContext>& 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<OpenfpgaContext>& 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<ShellCommandId> 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 */

View File

@ -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 */

View File

@ -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 */