Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support testbench template generation and I/O connection generation #1426

Merged
merged 7 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,83 @@ __ iverilog_website_

Show verbose log


.. _cmd_write_testbench_template:

write_testbench_template
~~~~~~~~~~~~~~~~~~~~~~~~

Write a template of testbench for a preconfigured FPGA fabric. See details in :ref:`fpga_verilog_testbench`.

.. warning:: The template testbench only contains an instance of FPGA fabric. Please do **NOT** directly use it in design verification without a proper modification!!!

.. option:: --file <string> or -f <string>

The file path to output the testbench file. For example, ``--file /temp/testbench_template.v``

.. option:: --top_module <string>

Specify the name of top-level module to be considered in the testbench. Please avoid reserved words, i.e., ``fpga_top`` or ``fpga_core. By default, it is ``top_tb``.

.. note:: Please use the reserved words ``fpga_top`` or ``fpga_core`` even when renaming is applied to the modules (See details in :ref:`openfpga_setup_commands_rename_modules`). Renaming will be applied automatically.

.. option:: --dut_module <string>

Specify the name of *Design Under Test* (DUT) module to be considered in the testbench. Can be either ``fpga_top`` or ``fpga_core. By default, it is ``fpga_top``.

.. note:: Please use the reserved words ``fpga_top`` or ``fpga_core`` even when renaming is applied to the modules (See details in :ref:`openfpga_setup_commands_rename_modules`). Renaming will be applied automatically.

.. option:: --explicit_port_mapping

Use explicit port mapping when writing the Verilog netlists

.. option:: --default_net_type <string>

Specify the default net type for the Verilog netlists. Currently, supported types are ``none`` and ``wire``. Default value: ``none``.

.. option:: --no_time_stamp

Do not print time stamp in Verilog netlists

.. option:: --verbose

Show verbose log

write_testbench_io_connection
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Write the I/O connection statements in Verilog for a preconfigured FPGA fabric mapped to a given design. See details in :ref:`fpga_verilog_testbench`.

.. warning:: The netlist may be included by the template testbench (see details in :ref:`cmd_write_testbench_template`). Please do **NOT** directly use it in design verification without a proper modification!!!

.. option:: --file <string> or -f <string>

The file path to output the netlist file. For example, ``--file /temp/testbench_io_conkt.v``

.. option:: --dut_module <string>

Specify the name of *Design Under Test* (DUT) module to be considered in the testbench. Can be either ``fpga_top`` or ``fpga_core. By default, it is ``fpga_top``.

.. note:: Please use the reserved words ``fpga_top`` or ``fpga_core`` even when renaming is applied to the modules (See details in :ref:`openfpga_setup_commands_rename_modules`). Renaming will be applied automatically.

.. option:: --pin_constraints_file <string> or -pcf <string>

Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml``
Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`.

.. option:: --bus_group_file <string> or -bgf <string>

Specify the *Bus Group File* (BGF) if you want to group pins to buses. For example, ``-bgf bus_group.xml``
Strongly recommend when input HDL contains bus ports. See detailed file format about :ref:`file_format_bus_group_file`.

.. option:: --no_time_stamp

Do not print time stamp in Verilog netlists

.. option:: --verbose

Show verbose log

write_mock_fpga_wrapper
~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
147 changes: 147 additions & 0 deletions openfpga/src/base/openfpga_verilog_command_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,131 @@ ShellCommandId add_write_preconfigured_fabric_wrapper_command_template(
return shell_cmd_id;
}

/********************************************************************
* - add a command to shell environment: write a template of testbench
* - add associated options
* - add command dependency
*******************************************************************/
template <class T>
ShellCommandId add_write_testbench_template_command_template(
openfpga::Shell<T>& shell, const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds, const bool& hidden) {
Command shell_cmd("write_testbench_template");

/* add an option '--file' in short '-f'*/
CommandOptionId output_opt = shell_cmd.add_option(
"file", true, "specify the file path to output the content");
shell_cmd.set_option_short_name(output_opt, "f");
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);

/* add an option '--top_module'*/
CommandOptionId top_module_opt =
shell_cmd.add_option("top_module", false,
"specify the top-level module name to be used in the "
"testbench. Please avoid reserved words, i.e., "
"fpga_top or fpga_core. By default, it is top_tb.");
shell_cmd.set_option_require_value(top_module_opt, openfpga::OPT_STRING);

/* add an option '--dut_module'*/
CommandOptionId dut_module_opt = shell_cmd.add_option(
"dut_module", false,
"specify the module name of DUT to be used in the testbench. Can be either "
"fpga_top or fpga_core. By default, it is fpga_top.");
shell_cmd.set_option_require_value(dut_module_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 '--default_net_type' */
CommandOptionId default_net_type_opt = shell_cmd.add_option(
"default_net_type", false,
"Set the default net type for Verilog netlists. Default value is 'none'");
shell_cmd.set_option_require_value(default_net_type_opt,
openfpga::OPT_STRING);

/* Add an option '--no_time_stamp' */
shell_cmd.add_option("no_time_stamp", false,
"Do not print a time stamp in the output files");

/* 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 template of testbench for a pre-configured fpga fabric",
hidden);
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id,
write_testbench_template_template<T>);

/* 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 testbench io connection
* - add associated options
* - add command dependency
*******************************************************************/
template <class T>
ShellCommandId add_write_testbench_io_connection_command_template(
openfpga::Shell<T>& shell, const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds, const bool& hidden) {
Command shell_cmd("write_testbench_io_connection");

/* add an option '--file' in short '-f'*/
CommandOptionId output_opt = shell_cmd.add_option(
"file", true, "specify the file path to output the content");
shell_cmd.set_option_short_name(output_opt, "f");
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);

/* add an option '--dut_module'*/
CommandOptionId dut_module_opt = shell_cmd.add_option(
"dut_module", false,
"specify the module name of DUT to be used in the testbench. Can be either "
"fpga_top or fpga_core. By default, it is fpga_top.");
shell_cmd.set_option_require_value(dut_module_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 '--bus_group_file in short '-bgf' */
CommandOptionId bgf_opt = shell_cmd.add_option(
"bus_group_file", false, "specify the file path to the group pins to bus");
shell_cmd.set_option_short_name(bgf_opt, "bgf");
shell_cmd.set_option_require_value(bgf_opt, openfpga::OPT_STRING);

/* Add an option '--no_time_stamp' */
shell_cmd.add_option("no_time_stamp", false,
"Do not print a time stamp in the output files");

/* 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 file to describe the connection to I/Os of a "
"pre-configured fpga fabric",
hidden);
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id,
write_testbench_io_connection_template<T>);

/* 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 mock fpga wrapper
* - add associated options
Expand Down Expand Up @@ -525,6 +650,28 @@ void add_verilog_command_templates(openfpga::Shell<T>& shell,
shell, openfpga_verilog_cmd_class, preconfig_wrapper_dependent_cmds,
hidden);

/********************************
* Command 'write_testbench_template'
*/
/* The command 'write_testbench_template' should NOT be executed
* before 'build_fabric' */
std::vector<ShellCommandId> testbench_template_dependent_cmds;
testbench_template_dependent_cmds.push_back(build_fabric_cmd_id);
add_write_testbench_template_command_template<T>(
shell, openfpga_verilog_cmd_class, testbench_template_dependent_cmds,
hidden);

/********************************
* Command 'write_testbench_io_connection'
*/
/* The command 'write_testbench_io_connection' should NOT be executed
* before 'build_fabric' */
std::vector<ShellCommandId> testbench_io_conkt_dependent_cmds;
testbench_io_conkt_dependent_cmds.push_back(build_fabric_cmd_id);
add_write_testbench_io_connection_command_template<T>(
shell, openfpga_verilog_cmd_class, testbench_io_conkt_dependent_cmds,
hidden);

/********************************
* Command 'write_mock_fpga_wrapper'
*/
Expand Down
92 changes: 92 additions & 0 deletions openfpga/src/base/openfpga_verilog_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,98 @@ int write_preconfigured_fabric_wrapper_template(
openfpga_ctx.arch().config_protocol, options);
}

/********************************************************************
* A wrapper function to call the testbench template generator of
*FPGA-Verilog
*******************************************************************/
template <class T>
int write_testbench_template_template(const T& openfpga_ctx, const Command& cmd,
const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_top_module = cmd.option("top_module");
CommandOptionId opt_dut_module = cmd.option("dut_module");
CommandOptionId opt_explicit_port_mapping =
cmd.option("explicit_port_mapping");
CommandOptionId opt_default_net_type = cmd.option("default_net_type");
CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp");
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_explicit_port_mapping(
cmd_context.option_enable(cmd, opt_explicit_port_mapping));
options.set_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));

if (true == cmd_context.option_enable(cmd, opt_default_net_type)) {
options.set_default_net_type(
cmd_context.option_value(cmd, opt_default_net_type));
}

if (true == cmd_context.option_enable(cmd, opt_dut_module)) {
options.set_dut_module(cmd_context.option_value(cmd, opt_dut_module));
}

if (true == cmd_context.option_enable(cmd, opt_top_module)) {
options.set_top_module(cmd_context.option_value(cmd, opt_top_module));
}

return fpga_verilog_template_testbench(
openfpga_ctx.module_graph(), openfpga_ctx.io_name_map(),
openfpga_ctx.module_name_map(), options);
}

/********************************************************************
* A wrapper function to call the testbench I/O connection generator of
*FPGA-Verilog
*******************************************************************/
template <class T>
int write_testbench_io_connection_template(const T& openfpga_ctx,
const Command& cmd,
const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_dut_module = cmd.option("dut_module");
CommandOptionId opt_pcf = cmd.option("pin_constraints_file");
CommandOptionId opt_bgf = cmd.option("bus_group_file");
CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp");
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_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));

if (true == cmd_context.option_enable(cmd, opt_dut_module)) {
options.set_dut_module(cmd_context.option_value(cmd, opt_dut_module));
}

/* 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());
}

/* If bug group file are enabled by command options, read the file */
BusGroup bus_group;
if (true == cmd_context.option_enable(cmd, opt_bgf)) {
bus_group =
read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str());
}

return fpga_verilog_testbench_io_connection(
openfpga_ctx.module_graph(), g_vpr_ctx.atom(), g_vpr_ctx.placement(),
pin_constraints, bus_group, openfpga_ctx.io_location_map(),
openfpga_ctx.module_name_map(), openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.vpr_netlist_annotation(), options);
}

/********************************************************************
* A wrapper function to call the mock fpga wrapper generator of
*FPGA-Verilog
Expand Down
Loading
Loading