From 75e9e98e5d1ca20f66dba364a8f92d6c9b0c79cd Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Nov 2023 16:06:48 -0700 Subject: [PATCH 1/7] [core] add two new commands to output testbench parts --- .../base/openfpga_verilog_command_template.h | 140 +++++++++++++ openfpga/src/base/openfpga_verilog_template.h | 94 +++++++++ openfpga/src/fpga_verilog/verilog_api.cpp | 44 ++++ .../verilog_preconfig_top_module.cpp | 175 +--------------- .../verilog_preconfig_top_module.h | 4 +- .../verilog_preconfig_top_module_utils.cpp | 194 ++++++++++++++++++ .../verilog_preconfig_top_module_utils.h | 44 ++++ .../verilog_template_testbench.cpp | 138 +++++++++++++ .../fpga_verilog/verilog_template_testbench.h | 45 ++++ .../verilog_testbench_options.cpp | 16 ++ .../fpga_verilog/verilog_testbench_options.h | 3 + 11 files changed, 724 insertions(+), 173 deletions(-) create mode 100644 openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.cpp create mode 100644 openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.h create mode 100644 openfpga/src/fpga_verilog/verilog_template_testbench.cpp create mode 100644 openfpga/src/fpga_verilog/verilog_template_testbench.h diff --git a/openfpga/src/base/openfpga_verilog_command_template.h b/openfpga/src/base/openfpga_verilog_command_template.h index fa40faff92..160ce809f5 100644 --- a/openfpga/src/base/openfpga_verilog_command_template.h +++ b/openfpga/src/base/openfpga_verilog_command_template.h @@ -265,6 +265,124 @@ 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 +ShellCommandId add_write_testbench_template_command_template( + openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id, + const std::vector& 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); + + /* 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 +ShellCommandId add_write_testbench_io_connection_command_template( + openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id, + const std::vector& 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); + + /* 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 @@ -525,6 +643,28 @@ void add_verilog_command_templates(openfpga::Shell& 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 testbench_template_dependent_cmds; + testbench_template_dependent_cmds.push_back(build_fabric_cmd_id); + add_write_testbench_template_command_template( + 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 testbench_io_conkt_dependent_cmds; + testbench_io_conkt_dependent_cmds.push_back(build_fabric_cmd_id); + add_write_testbench_io_connection_command_template( + shell, openfpga_verilog_cmd_class, testbench_io_conkt_dependent_cmds, + hidden); + /******************************** * Command 'write_mock_fpga_wrapper' */ diff --git a/openfpga/src/base/openfpga_verilog_template.h b/openfpga/src/base/openfpga_verilog_template.h index 783ab7f7d7..0f59239485 100644 --- a/openfpga/src/base/openfpga_verilog_template.h +++ b/openfpga/src/base/openfpga_verilog_template.h @@ -217,6 +217,100 @@ 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 +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_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.bitstream_manager(), + g_vpr_ctx.atom(), g_vpr_ctx.placement(), pin_constraints, bus_group, + openfpga_ctx.io_location_map(), openfpga_ctx.io_name_map(), + openfpga_ctx.module_name_map(), openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.arch().circuit_lib, + openfpga_ctx.arch().config_protocol, options); +} + +/******************************************************************** + * A wrapper function to call the testbench I/O connection generator of + *FPGA-Verilog + *******************************************************************/ +template +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(), openfpga_ctx.bitstream_manager(), + g_vpr_ctx.atom(), g_vpr_ctx.placement(), pin_constraints, bus_group, + openfpga_ctx.io_location_map(), openfpga_ctx.io_name_map(), + openfpga_ctx.module_name_map(), openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.arch().circuit_lib, + openfpga_ctx.arch().config_protocol, options); +} + /******************************************************************** * A wrapper function to call the mock fpga wrapper generator of *FPGA-Verilog diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index d7c266b793..c8282893ef 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -20,6 +20,7 @@ #include "verilog_grid.h" #include "verilog_mock_fpga_wrapper.h" #include "verilog_preconfig_top_module.h" +#include "verilog_template_testbench.h" #include "verilog_routing.h" #include "verilog_simulation_info_writer.h" #include "verilog_submodule.h" @@ -256,6 +257,49 @@ int fpga_verilog_preconfigured_fabric_wrapper( return status; } +/******************************************************************** + * A top-level function of FPGA-Verilog which focuses on template 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_template_testbench( + const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, const AtomContext &atom_ctx, + const PlacementContext &place_ctx, const PinConstraints &pin_constraints, + const BusGroup &bus_group, const IoLocationMap &io_location_map, + const IoNameMap &io_name_map, const ModuleNameMap &module_name_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 template testbench 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 testbench_file_path = + src_dir_path + options.top_module_name() + + std::string(VERILOG_NETLIST_FILE_POSTFIX); + status = print_verilog_template_testbench( + module_manager, bitstream_manager, config_protocol, circuit_lib, + fabric_global_port_info, atom_ctx, place_ctx, pin_constraints, bus_group, + io_location_map, io_name_map, module_name_map, netlist_annotation, + netlist_name, testbench_file_path, options); + + return status; +} + + /******************************************************************** * A top-level function of FPGA-Verilog which focuses on a wrapper module, * which encapsulate the application HDL into a mock FPGA module diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index 490697d95b..10a0c28779 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -18,6 +18,7 @@ #include "openfpga_port.h" #include "openfpga_reserved_words.h" #include "verilog_constants.h" +#include "verilog_preconfig_top_module_utils.h" #include "verilog_preconfig_top_module.h" #include "verilog_testbench_utils.h" #include "verilog_writer_utils.h" @@ -130,176 +131,6 @@ static void print_verilog_preconfig_top_module_ports( fp << std::endl; } -/******************************************************************** - * Print internal wires for the pre-configured FPGA top module - * The internal wires are tailored for the ports of FPGA top module - * which will be different in various configuration protocols - *******************************************************************/ -static void print_verilog_preconfig_top_module_internal_wires( - std::fstream &fp, const ModuleManager &module_manager, - const ModuleId &top_module) { - /* Validate the file stream */ - valid_file_stream(fp); - - /* Global ports of top-level module */ - print_verilog_comment(fp, - std::string("----- Local wires for FPGA fabric -----")); - for (const ModulePortId &module_port_id : - module_manager.module_ports(top_module)) { - BasicPort module_port = - module_manager.module_port(top_module, module_port_id); - /* Add a postfix to the internal wires to be different from other reserved - * ports */ - module_port.set_name( - module_port.get_name() + - std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)); - fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" - << std::endl; - } - /* Add an empty line as a splitter */ - fp << std::endl; -} - -/******************************************************************** - * Connect global ports of FPGA top module to constants except: - * 1. operating clock, which should be wired to the clock port of - * this pre-configured FPGA top module - *******************************************************************/ -static int print_verilog_preconfig_top_module_connect_global_ports( - std::fstream &fp, const ModuleManager &module_manager, - const ModuleId &top_module, const PinConstraints &pin_constraints, - const FabricGlobalPortInfo &fabric_global_ports, - const std::vector &benchmark_clock_port_names) { - /* Validate the file stream */ - valid_file_stream(fp); - - print_verilog_comment( - fp, - std::string("----- Begin Connect Global ports of FPGA top module -----")); - - for (const FabricGlobalPortId &global_port_id : - fabric_global_ports.global_ports()) { - ModulePortId module_global_port_id = - fabric_global_ports.global_module_port(global_port_id); - VTR_ASSERT(ModuleManager::MODULE_GLOBAL_PORT == - module_manager.port_type(top_module, module_global_port_id)); - BasicPort module_global_port = - module_manager.module_port(top_module, module_global_port_id); - /* Now, for operating clock port, we should wire it to the clock of - * benchmark! */ - if ((true == fabric_global_ports.global_port_is_clock(global_port_id)) && - (false == fabric_global_ports.global_port_is_prog(global_port_id))) { - /* Wiring to each pin of the global port: benchmark clock is always 1-bit - */ - for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); - ++pin_id) { - BasicPort module_clock_pin( - module_global_port.get_name() + - std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), - module_global_port.pins()[pin_id], module_global_port.pins()[pin_id]); - - /* If the clock port name is in the pin constraints, we should wire it - * to the constrained pin */ - std::string constrained_net_name = pin_constraints.pin_net(BasicPort( - module_global_port.get_name(), module_global_port.pins()[pin_id], - module_global_port.pins()[pin_id])); - - /* If constrained to an open net or there is no clock in the benchmark, - * we assign it to a default value */ - if ((true == pin_constraints.unmapped_net(constrained_net_name)) || - (true == benchmark_clock_port_names.empty())) { - std::vector default_values( - 1, fabric_global_ports.global_port_default_value(global_port_id)); - print_verilog_wire_constant_values(fp, module_clock_pin, - default_values); - continue; - } - - std::string clock_name_to_connect; - if (!pin_constraints.unconstrained_net(constrained_net_name)) { - clock_name_to_connect = constrained_net_name; - } else { - /* Otherwise, we must have a clear one-to-one clock net - * corresponding!!! */ - if (benchmark_clock_port_names.size() != - module_global_port.get_width()) { - VTR_LOG_ERROR( - "Unable to map %lu benchmark clocks to %lu clock pins of " - "FPGA!\nRequire clear pin constraints!\n", - benchmark_clock_port_names.size(), - module_global_port.get_width()); - return CMD_EXEC_FATAL_ERROR; - } - clock_name_to_connect = benchmark_clock_port_names[pin_id]; - } - - BasicPort benchmark_clock_pin(clock_name_to_connect, 1); - print_verilog_wire_connection(fp, module_clock_pin, benchmark_clock_pin, - false); - } - /* Finish, go to the next */ - continue; - } - - /* For other ports, give an default value */ - for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); - ++pin_id) { - BasicPort module_global_pin(module_global_port.get_name(), - module_global_port.pins()[pin_id], - module_global_port.pins()[pin_id]); - - /* If the global port name is in the pin constraints, we should wire it to - * the constrained pin */ - std::string constrained_net_name = - pin_constraints.pin_net(module_global_pin); - - module_global_pin.set_name( - module_global_port.get_name() + - std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)); - - /* - If constrained to a given net in the benchmark, we connect the global - * pin to the net - * - If constrained to an open net in the benchmark, we assign it to a - * default value - */ - if ((false == pin_constraints.unconstrained_net(constrained_net_name)) && - (false == pin_constraints.unmapped_net(constrained_net_name))) { - BasicPort benchmark_pin(constrained_net_name, 1); - print_verilog_wire_connection(fp, module_global_pin, benchmark_pin, - false); - } else { - VTR_ASSERT_SAFE(std::string(PIN_CONSTRAINT_OPEN_NET) == - constrained_net_name); - std::vector default_values( - module_global_pin.get_width(), - fabric_global_ports.global_port_default_value(global_port_id)); - /* For configuration done signals, we should enable them in - * preconfigured wrapper */ - if (fabric_global_ports.global_port_is_config_enable(global_port_id)) { - VTR_LOG( - "Config-enable port '%s' is detected with default value '%ld'", - module_global_pin.get_name().c_str(), - fabric_global_ports.global_port_default_value(global_port_id)); - default_values.clear(); - default_values.resize( - module_global_pin.get_width(), - 1 - fabric_global_ports.global_port_default_value(global_port_id)); - } - print_verilog_wire_constant_values(fp, module_global_pin, - default_values); - } - } - } - - print_verilog_comment( - fp, std::string("----- End Connect Global ports of FPGA top module -----")); - - /* Add an empty line as a splitter */ - fp << std::endl; - - return CMD_EXEC_SUCCESS; -} - /******************************************************************** * Impose the bitstream on the configuration memories * This function uses 'assign' syntax to impost the bitstream at mem port @@ -597,7 +428,7 @@ int print_verilog_preconfig_top_module( /* Print internal wires */ print_verilog_preconfig_top_module_internal_wires(fp, module_manager, - core_module); + core_module, std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)); /* Instanciate FPGA top-level module */ print_verilog_testbench_fpga_instance( @@ -614,7 +445,7 @@ int print_verilog_preconfig_top_module( * signals! */ status = print_verilog_preconfig_top_module_connect_global_ports( fp, module_manager, core_module, pin_constraints, global_ports, - benchmark_clock_port_names); + benchmark_clock_port_names, std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)); if (CMD_EXEC_FATAL_ERROR == status) { return status; } diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h index 0d7f3edac4..7cf187b294 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h @@ -28,7 +28,8 @@ /* begin namespace openfpga */ namespace openfpga { -int print_verilog_preconfig_top_module( + +int print_verilog_testbench_io_connection( const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib, @@ -40,6 +41,7 @@ int print_verilog_preconfig_top_module( const std::string& circuit_name, const std::string& verilog_fname, const VerilogTestbenchOption& options); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.cpp new file mode 100644 index 0000000000..f3081ed375 --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.cpp @@ -0,0 +1,194 @@ +/******************************************************************** + * This file includes functions that are used to generate + * a Verilog module of a pre-configured FPGA fabric + *******************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "command_exit_codes.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from openfpgautil library */ +#include "openfpga_atom_netlist_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "verilog_preconfig_top_module_utils.h" +#include "verilog_writer_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Print internal wires for the pre-configured FPGA top module + * The internal wires are tailored for the ports of FPGA top module + * which will be different in various configuration protocols + *******************************************************************/ +void print_verilog_preconfig_top_module_internal_wires( + std::fstream &fp, const ModuleManager &module_manager, + const ModuleId &top_module, const std::string& port_postfix) { + /* Validate the file stream */ + valid_file_stream(fp); + + /* Global ports of top-level module */ + print_verilog_comment(fp, + std::string("----- Local wires for FPGA fabric -----")); + for (const ModulePortId &module_port_id : + module_manager.module_ports(top_module)) { + BasicPort module_port = + module_manager.module_port(top_module, module_port_id); + /* Add a postfix to the internal wires to be different from other reserved + * ports */ + module_port.set_name( + module_port.get_name() + port_postfix); + fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" + << std::endl; + } + /* Add an empty line as a splitter */ + fp << std::endl; +} + +/******************************************************************** + * Connect global ports of FPGA top module to constants except: + * 1. operating clock, which should be wired to the clock port of + * this pre-configured FPGA top module + *******************************************************************/ +int print_verilog_preconfig_top_module_connect_global_ports( + std::fstream &fp, const ModuleManager &module_manager, + const ModuleId &top_module, const PinConstraints &pin_constraints, + const FabricGlobalPortInfo &fabric_global_ports, + const std::vector &benchmark_clock_port_names, + const std::string& port_postfix) { + /* Validate the file stream */ + valid_file_stream(fp); + + print_verilog_comment( + fp, + std::string("----- Begin Connect Global ports of FPGA top module -----")); + + for (const FabricGlobalPortId &global_port_id : + fabric_global_ports.global_ports()) { + ModulePortId module_global_port_id = + fabric_global_ports.global_module_port(global_port_id); + VTR_ASSERT(ModuleManager::MODULE_GLOBAL_PORT == + module_manager.port_type(top_module, module_global_port_id)); + BasicPort module_global_port = + module_manager.module_port(top_module, module_global_port_id); + /* Now, for operating clock port, we should wire it to the clock of + * benchmark! */ + if ((true == fabric_global_ports.global_port_is_clock(global_port_id)) && + (false == fabric_global_ports.global_port_is_prog(global_port_id))) { + /* Wiring to each pin of the global port: benchmark clock is always 1-bit + */ + for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); + ++pin_id) { + BasicPort module_clock_pin( + module_global_port.get_name() + + port_postfix, + module_global_port.pins()[pin_id], module_global_port.pins()[pin_id]); + + /* If the clock port name is in the pin constraints, we should wire it + * to the constrained pin */ + std::string constrained_net_name = pin_constraints.pin_net(BasicPort( + module_global_port.get_name(), module_global_port.pins()[pin_id], + module_global_port.pins()[pin_id])); + + /* If constrained to an open net or there is no clock in the benchmark, + * we assign it to a default value */ + if ((true == pin_constraints.unmapped_net(constrained_net_name)) || + (true == benchmark_clock_port_names.empty())) { + std::vector default_values( + 1, fabric_global_ports.global_port_default_value(global_port_id)); + print_verilog_wire_constant_values(fp, module_clock_pin, + default_values); + continue; + } + + std::string clock_name_to_connect; + if (!pin_constraints.unconstrained_net(constrained_net_name)) { + clock_name_to_connect = constrained_net_name; + } else { + /* Otherwise, we must have a clear one-to-one clock net + * corresponding!!! */ + if (benchmark_clock_port_names.size() != + module_global_port.get_width()) { + VTR_LOG_ERROR( + "Unable to map %lu benchmark clocks to %lu clock pins of " + "FPGA!\nRequire clear pin constraints!\n", + benchmark_clock_port_names.size(), + module_global_port.get_width()); + return CMD_EXEC_FATAL_ERROR; + } + clock_name_to_connect = benchmark_clock_port_names[pin_id]; + } + + BasicPort benchmark_clock_pin(clock_name_to_connect, 1); + print_verilog_wire_connection(fp, module_clock_pin, benchmark_clock_pin, + false); + } + /* Finish, go to the next */ + continue; + } + + /* For other ports, give an default value */ + for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); + ++pin_id) { + BasicPort module_global_pin(module_global_port.get_name(), + module_global_port.pins()[pin_id], + module_global_port.pins()[pin_id]); + + /* If the global port name is in the pin constraints, we should wire it to + * the constrained pin */ + std::string constrained_net_name = + pin_constraints.pin_net(module_global_pin); + + module_global_pin.set_name( + module_global_port.get_name() + + port_postfix); + + /* - If constrained to a given net in the benchmark, we connect the global + * pin to the net + * - If constrained to an open net in the benchmark, we assign it to a + * default value + */ + if ((false == pin_constraints.unconstrained_net(constrained_net_name)) && + (false == pin_constraints.unmapped_net(constrained_net_name))) { + BasicPort benchmark_pin(constrained_net_name, 1); + print_verilog_wire_connection(fp, module_global_pin, benchmark_pin, + false); + } else { + VTR_ASSERT_SAFE(std::string(PIN_CONSTRAINT_OPEN_NET) == + constrained_net_name); + std::vector default_values( + module_global_pin.get_width(), + fabric_global_ports.global_port_default_value(global_port_id)); + /* For configuration done signals, we should enable them in + * preconfigured wrapper */ + if (fabric_global_ports.global_port_is_config_enable(global_port_id)) { + VTR_LOG( + "Config-enable port '%s' is detected with default value '%ld'", + module_global_pin.get_name().c_str(), + fabric_global_ports.global_port_default_value(global_port_id)); + default_values.clear(); + default_values.resize( + module_global_pin.get_width(), + 1 - fabric_global_ports.global_port_default_value(global_port_id)); + } + print_verilog_wire_constant_values(fp, module_global_pin, + default_values); + } + } + } + + print_verilog_comment( + fp, std::string("----- End Connect Global ports of FPGA top module -----")); + + /* Add an empty line as a splitter */ + fp << std::endl; + + return CMD_EXEC_SUCCESS; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.h b/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.h new file mode 100644 index 0000000000..0a14663cae --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.h @@ -0,0 +1,44 @@ +#ifndef VERILOG_PRECONFIG_TOP_MODULE_UTILS_H +#define VERILOG_PRECONFIG_TOP_MODULE_UTILS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include + +#include "bitstream_manager.h" +#include "bus_group.h" +#include "circuit_library.h" +#include "config_protocol.h" +#include "fabric_global_port_info.h" +#include "io_location_map.h" +#include "io_name_map.h" +#include "module_manager.h" +#include "module_name_map.h" +#include "pin_constraints.h" +#include "verilog_testbench_options.h" +#include "vpr_context.h" +#include "vpr_netlist_annotation.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void print_verilog_preconfig_top_module_internal_wires( + std::fstream &fp, const ModuleManager &module_manager, + const ModuleId &top_module, const std::string& port_postfix); + +int print_verilog_preconfig_top_module_connect_global_ports( + std::fstream &fp, const ModuleManager &module_manager, + const ModuleId &top_module, const PinConstraints &pin_constraints, + const FabricGlobalPortInfo &fabric_global_ports, + const std::vector &benchmark_clock_port_names, const std::string& port_postfix); + + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fpga_verilog/verilog_template_testbench.cpp b/openfpga/src/fpga_verilog/verilog_template_testbench.cpp new file mode 100644 index 0000000000..3dbdadaab4 --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_template_testbench.cpp @@ -0,0 +1,138 @@ +/******************************************************************** + * This file includes functions that are used to generate + * a Verilog module of a pre-configured FPGA fabric + *******************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "command_exit_codes.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from openfpgautil library */ +#include "bitstream_manager_utils.h" +#include "openfpga_atom_netlist_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "openfpga_reserved_words.h" +#include "verilog_constants.h" +#include "verilog_template_testbench.h" +#include "verilog_preconfig_top_module_utils.h" +#include "verilog_testbench_utils.h" +#include "verilog_writer_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Top-level function to generate a template testbench for a FPGA fabric. + * + * Testbench + * +-------------------------------------------- + * | + * | FPGA fabric + * | +-------------------------------+ + * | | | + * | 0/1---->|FPGA global ports | + * | | | + * |--------->|FPGA_clock | + * | | | + * |--------->|FPGA mapped I/Os | + * | | | + * |<---------|FPGA mapped I/Os | + * | | | + * | 0/1---->|FPGA unmapped I/Os | + * | | | + * |--------->|Internal_configuration_ports | + * | +-------------------------------+ + * | + * +------------------------------------------- + *******************************************************************/ +int print_verilog_template_testbench( + const ModuleManager &module_manager, + const BitstreamManager &bitstream_manager, + const ConfigProtocol &config_protocol, const CircuitLibrary &circuit_lib, + const FabricGlobalPortInfo &global_ports, const AtomContext &atom_ctx, + const PlacementContext &place_ctx, const PinConstraints &pin_constraints, + const BusGroup &bus_group, const IoLocationMap &io_location_map, + const IoNameMap &io_name_map, const ModuleNameMap &module_name_map, + const VprNetlistAnnotation &netlist_annotation, + const std::string &circuit_name, const std::string &verilog_fname, + const VerilogTestbenchOption &options) { + std::string timer_message = + std::string( + "Write a template Verilog testbench for pre-configured FPGA top-level netlist"); + + int status = CMD_EXEC_SUCCESS; + + /* Start time count */ + vtr::ScopedStartFinishTimer timer(timer_message); + + /* 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); + + /* Generate a brief description on the Verilog file*/ + std::string title = + std::string("A template Verilog testbench for pre-configured FPGA fabric") + print_verilog_file_header(fp, title, options.time_stamp()); + + print_verilog_comment(fp, std::string("Require an adaption to your needs before used for design verification!!!")); + + print_verilog_default_net_type_declaration(fp, options.default_net_type()); + + /* Module declaration */ + fp << "module " << options.top_module(); + fp << ";" << std::endl; + + /* Spot the dut module */ + ModuleId top_module = + module_manager.find_module(module_name_map.name(options.dut_module())); + if (!module_manager.valid_module_id(top_module)) { + VTR_LOG_ERROR( + "Unable to find the DUT module '%s'. Please check if you create " + "dedicated module when building the fabric!\n", + options.dut_module().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + /* Note that we always need the core module as it contains the original port + * names before possible renaming at top-level module. If there is no core + * module, it means that the current top module is the core module */ + std::string core_module_name = generate_fpga_core_module_name(); + if (module_name_map.name_exist(core_module_name)) { + core_module_name = module_name_map.name(core_module_name); + } + ModuleId core_module = module_manager.find_module(core_module_name); + if (!module_manager.valid_module_id(core_module)) { + core_module = top_module; + } + + /* Print internal wires */ + print_verilog_preconfig_top_module_internal_wires(fp, module_manager, + core_module, std::string()); + + /* Instanciate FPGA top-level module */ + print_verilog_testbench_fpga_instance( + fp, module_manager, top_module, core_module, + std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME), + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), io_name_map, + options.explicit_port_mapping()); + + /* Testbench ends*/ + print_verilog_module_end( + fp, + options.top_module(), + options.default_net_type()); + + /* Close the file stream */ + fp.close(); + + return status; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_template_testbench.h b/openfpga/src/fpga_verilog/verilog_template_testbench.h new file mode 100644 index 0000000000..3bd4599756 --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_template_testbench.h @@ -0,0 +1,45 @@ +#ifndef VERILOG_TEMPLATE_TESTBENCH_H +#define VERILOG_TEMPLATE_TESTBENCH_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include + +#include "bitstream_manager.h" +#include "bus_group.h" +#include "circuit_library.h" +#include "config_protocol.h" +#include "fabric_global_port_info.h" +#include "io_location_map.h" +#include "io_name_map.h" +#include "module_manager.h" +#include "module_name_map.h" +#include "pin_constraints.h" +#include "verilog_testbench_options.h" +#include "vpr_context.h" +#include "vpr_netlist_annotation.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int print_verilog_template_testbench( + const ModuleManager& module_manager, + const BitstreamManager& bitstream_manager, + const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib, + const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx, + const PlacementContext& place_ctx, const PinConstraints& pin_constraints, + const BusGroup& bus_group, const IoLocationMap& io_location_map, + const IoNameMap& io_name_map, const ModuleNameMap& module_name_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& circuit_name, const std::string& verilog_fname, + const VerilogTestbenchOption& options); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fpga_verilog/verilog_testbench_options.cpp b/openfpga/src/fpga_verilog/verilog_testbench_options.cpp index 5e47094198..a6db0353b0 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_options.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_options.cpp @@ -15,6 +15,7 @@ namespace openfpga { *************************************************/ VerilogTestbenchOption::VerilogTestbenchOption() { output_directory_.clear(); + top_module_ = "top_tb"; dut_module_ = "fpga_top"; fabric_netlist_file_path_.clear(); reference_benchmark_file_path_.clear(); @@ -41,6 +42,8 @@ std::string VerilogTestbenchOption::output_directory() const { std::string VerilogTestbenchOption::dut_module() const { return dut_module_; } +std::string VerilogTestbenchOption::top_module() const { return top_module_; } + std::string VerilogTestbenchOption::fabric_netlist_file_path() const { return fabric_netlist_file_path_; } @@ -112,6 +115,19 @@ void VerilogTestbenchOption::set_output_directory( output_directory_ = output_dir; } +void VerilogTestbenchOption::set_top_module(const std::string& top_module) { + /* Precheck: avoid naming conflicts */ + if (top_module == generate_fpga_top_module_name() || + top_module == generate_fpga_core_module_name()) { + VTR_LOG_ERROR( + "Conflicted module name '%s' as top-levle module! Please avoid [%s|%s]\n", + top_module.c_str(), generate_fpga_top_module_name().c_str(), + generate_fpga_core_module_name().c_str()); + exit(1); + } + top_module_ = top_module; +} + void VerilogTestbenchOption::set_dut_module(const std::string& dut_module) { /* Precheck: only accept two legal names */ if (dut_module != generate_fpga_top_module_name() && diff --git a/openfpga/src/fpga_verilog/verilog_testbench_options.h b/openfpga/src/fpga_verilog/verilog_testbench_options.h index aafa15d717..97d2e27fd8 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_options.h +++ b/openfpga/src/fpga_verilog/verilog_testbench_options.h @@ -37,6 +37,7 @@ class VerilogTestbenchOption { public: /* Public accessors */ std::string output_directory() const; + std::string top_module() const; std::string dut_module() const; std::string fabric_netlist_file_path() const; std::string reference_benchmark_file_path() const; @@ -61,6 +62,7 @@ class VerilogTestbenchOption { public: /* Public mutators */ void set_output_directory(const std::string& output_dir); + void set_top_module(const std::string& top_module); void set_dut_module(const std::string& dut_module); /* The reference verilog file path is the key parameters that will have an * impact on other options: @@ -95,6 +97,7 @@ class VerilogTestbenchOption { private: /* Internal Data */ std::string output_directory_; + std::string top_module_; std::string dut_module_; std::string fabric_netlist_file_path_; std::string reference_benchmark_file_path_; From 36fa020c156317a84634eaf72526461d586c57da Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Nov 2023 16:33:19 -0700 Subject: [PATCH 2/7] [core] syntax --- openfpga/src/base/openfpga_verilog_template.h | 20 ++++----- openfpga/src/fpga_verilog/verilog_api.cpp | 45 ++++++++++++++----- openfpga/src/fpga_verilog/verilog_api.h | 16 +++++++ .../verilog_preconfig_top_module.h | 2 +- .../verilog_template_testbench.cpp | 10 +---- .../fpga_verilog/verilog_template_testbench.h | 23 ++-------- 6 files changed, 68 insertions(+), 48 deletions(-) diff --git a/openfpga/src/base/openfpga_verilog_template.h b/openfpga/src/base/openfpga_verilog_template.h index 0f59239485..93ee4be7a3 100644 --- a/openfpga/src/base/openfpga_verilog_template.h +++ b/openfpga/src/base/openfpga_verilog_template.h @@ -244,6 +244,11 @@ int write_testbench_template_template( 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)); } @@ -253,12 +258,8 @@ int write_testbench_template_template( } return fpga_verilog_template_testbench( - openfpga_ctx.module_graph(), openfpga_ctx.bitstream_manager(), - g_vpr_ctx.atom(), g_vpr_ctx.placement(), pin_constraints, bus_group, - openfpga_ctx.io_location_map(), openfpga_ctx.io_name_map(), - openfpga_ctx.module_name_map(), openfpga_ctx.fabric_global_port_info(), - openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.arch().circuit_lib, - openfpga_ctx.arch().config_protocol, options); + openfpga_ctx.module_graph(), openfpga_ctx.io_name_map(), + openfpga_ctx.module_name_map(), options); } /******************************************************************** @@ -303,12 +304,11 @@ int write_testbench_io_connection_template( } return fpga_verilog_testbench_io_connection( - openfpga_ctx.module_graph(), openfpga_ctx.bitstream_manager(), + openfpga_ctx.module_graph(), g_vpr_ctx.atom(), g_vpr_ctx.placement(), pin_constraints, bus_group, - openfpga_ctx.io_location_map(), openfpga_ctx.io_name_map(), + openfpga_ctx.io_location_map(), openfpga_ctx.module_name_map(), openfpga_ctx.fabric_global_port_info(), - openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.arch().circuit_lib, - openfpga_ctx.arch().config_protocol, options); + openfpga_ctx.vpr_netlist_annotation(), options); } /******************************************************************** diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index c8282893ef..c18220cbae 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -21,6 +21,7 @@ #include "verilog_mock_fpga_wrapper.h" #include "verilog_preconfig_top_module.h" #include "verilog_template_testbench.h" +#include "verilog_testbench_io_connection.h" #include "verilog_routing.h" #include "verilog_simulation_info_writer.h" #include "verilog_submodule.h" @@ -265,18 +266,45 @@ int fpga_verilog_preconfigured_fabric_wrapper( ********************************************************************/ int fpga_verilog_template_testbench( const ModuleManager &module_manager, - const BitstreamManager &bitstream_manager, const AtomContext &atom_ctx, + const IoNameMap &io_name_map, const ModuleNameMap &module_name_map, + const VerilogTestbenchOption &options) { + vtr::ScopedStartFinishTimer timer( + "Write a template testbench for a preconfigured FPGA fabric\n"); + + std::string src_dir_path = format_dir_path(find_path_dir_name(options.output_directory())); + std::string testbench_file_path = options.output_directory(); + + 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 */ + status = print_verilog_template_testbench( + module_manager, io_name_map, module_name_map, + testbench_file_path, options); + + return status; +} + +/******************************************************************** + * A top-level function of FPGA-Verilog which focuses on generating I/O connection part of testbenches + ********************************************************************/ +int fpga_verilog_testbench_io_connection( + const ModuleManager &module_manager, + const AtomContext &atom_ctx, const PlacementContext &place_ctx, const PinConstraints &pin_constraints, const BusGroup &bus_group, const IoLocationMap &io_location_map, - const IoNameMap &io_name_map, const ModuleNameMap &module_name_map, + const ModuleNameMap &module_name_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 template testbench for a preconfigured FPGA fabric\n"); - std::string src_dir_path = format_dir_path(options.output_directory()); + std::string src_dir_path = format_dir_path(find_path_dir_name(options.output_directory())); + std::string testbench_file_path = options.output_directory(); std::string netlist_name = atom_ctx.nlist.netlist_name(); @@ -287,13 +315,10 @@ int fpga_verilog_template_testbench( /* Generate wrapper module for FPGA fabric (mapped by the input benchmark and * pre-configured testbench for verification */ - std::string testbench_file_path = - src_dir_path + options.top_module_name() + - std::string(VERILOG_NETLIST_FILE_POSTFIX); - status = print_verilog_template_testbench( - module_manager, bitstream_manager, config_protocol, circuit_lib, + status = print_verilog_testbench_io_connection( + module_manager, fabric_global_port_info, atom_ctx, place_ctx, pin_constraints, bus_group, - io_location_map, io_name_map, module_name_map, netlist_annotation, + io_location_map, module_name_map, netlist_annotation, netlist_name, testbench_file_path, options); return status; diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index bef74daad2..be1c7f91ce 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -74,6 +74,22 @@ int fpga_verilog_preconfigured_fabric_wrapper( const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, const VerilogTestbenchOption& options); +int fpga_verilog_template_testbench( + const ModuleManager &module_manager, + const IoNameMap &io_name_map, const ModuleNameMap &module_name_map, + const VerilogTestbenchOption &options); + +int fpga_verilog_testbench_io_connection( + const ModuleManager &module_manager, + const AtomContext &atom_ctx, + const PlacementContext &place_ctx, const PinConstraints &pin_constraints, + const BusGroup &bus_group, const IoLocationMap &io_location_map, + const ModuleNameMap &module_name_map, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const VerilogTestbenchOption &options); + + int fpga_verilog_mock_fpga_wrapper( const ModuleManager& module_manager, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const PinConstraints& pin_constraints, diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h index 7cf187b294..bb5ec6138a 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h @@ -29,7 +29,7 @@ namespace openfpga { -int print_verilog_testbench_io_connection( +int print_verilog_preconfig_top_module( const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib, diff --git a/openfpga/src/fpga_verilog/verilog_template_testbench.cpp b/openfpga/src/fpga_verilog/verilog_template_testbench.cpp index 3dbdadaab4..5b10bfcac1 100644 --- a/openfpga/src/fpga_verilog/verilog_template_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_template_testbench.cpp @@ -52,14 +52,8 @@ namespace openfpga { *******************************************************************/ int print_verilog_template_testbench( const ModuleManager &module_manager, - const BitstreamManager &bitstream_manager, - const ConfigProtocol &config_protocol, const CircuitLibrary &circuit_lib, - const FabricGlobalPortInfo &global_ports, const AtomContext &atom_ctx, - const PlacementContext &place_ctx, const PinConstraints &pin_constraints, - const BusGroup &bus_group, const IoLocationMap &io_location_map, const IoNameMap &io_name_map, const ModuleNameMap &module_name_map, - const VprNetlistAnnotation &netlist_annotation, - const std::string &circuit_name, const std::string &verilog_fname, + const std::string &verilog_fname, const VerilogTestbenchOption &options) { std::string timer_message = std::string( @@ -79,7 +73,7 @@ int print_verilog_template_testbench( /* Generate a brief description on the Verilog file*/ std::string title = - std::string("A template Verilog testbench for pre-configured FPGA fabric") + std::string("A template Verilog testbench for pre-configured FPGA fabric"); print_verilog_file_header(fp, title, options.time_stamp()); print_verilog_comment(fp, std::string("Require an adaption to your needs before used for design verification!!!")); diff --git a/openfpga/src/fpga_verilog/verilog_template_testbench.h b/openfpga/src/fpga_verilog/verilog_template_testbench.h index 3bd4599756..6b4ea22839 100644 --- a/openfpga/src/fpga_verilog/verilog_template_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_template_testbench.h @@ -7,19 +7,10 @@ #include #include -#include "bitstream_manager.h" -#include "bus_group.h" -#include "circuit_library.h" -#include "config_protocol.h" -#include "fabric_global_port_info.h" -#include "io_location_map.h" #include "io_name_map.h" #include "module_manager.h" #include "module_name_map.h" -#include "pin_constraints.h" #include "verilog_testbench_options.h" -#include "vpr_context.h" -#include "vpr_netlist_annotation.h" /******************************************************************** * Function declaration @@ -29,16 +20,10 @@ namespace openfpga { int print_verilog_template_testbench( - const ModuleManager& module_manager, - const BitstreamManager& bitstream_manager, - const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib, - const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx, - const PlacementContext& place_ctx, const PinConstraints& pin_constraints, - const BusGroup& bus_group, const IoLocationMap& io_location_map, - const IoNameMap& io_name_map, const ModuleNameMap& module_name_map, - const VprNetlistAnnotation& netlist_annotation, - const std::string& circuit_name, const std::string& verilog_fname, - const VerilogTestbenchOption& options); + const ModuleManager &module_manager, + const IoNameMap &io_name_map, const ModuleNameMap &module_name_map, + const std::string &verilog_fname, + const VerilogTestbenchOption &options); } /* end namespace openfpga */ From 649d44b2d864223e09e4d471d49452735ea402c0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Nov 2023 16:33:55 -0700 Subject: [PATCH 3/7] [core] code format --- .../base/openfpga_verilog_command_template.h | 27 ++++++++------ openfpga/src/base/openfpga_verilog_template.h | 16 ++++----- openfpga/src/fpga_verilog/verilog_api.cpp | 35 +++++++++---------- openfpga/src/fpga_verilog/verilog_api.h | 24 ++++++------- .../verilog_preconfig_top_module.cpp | 10 +++--- .../verilog_preconfig_top_module.h | 2 -- .../verilog_preconfig_top_module_utils.cpp | 18 ++++------ .../verilog_preconfig_top_module_utils.h | 6 ++-- .../verilog_template_testbench.cpp | 30 ++++++++-------- .../fpga_verilog/verilog_template_testbench.h | 10 +++--- 10 files changed, 88 insertions(+), 90 deletions(-) diff --git a/openfpga/src/base/openfpga_verilog_command_template.h b/openfpga/src/base/openfpga_verilog_command_template.h index 160ce809f5..6b27dd5e16 100644 --- a/openfpga/src/base/openfpga_verilog_command_template.h +++ b/openfpga/src/base/openfpga_verilog_command_template.h @@ -283,9 +283,11 @@ ShellCommandId add_write_testbench_template_command_template( 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."); + 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'*/ @@ -315,10 +317,12 @@ ShellCommandId add_write_testbench_template_command_template( /* 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_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); + shell.set_command_execute_function(shell_cmd_id, + write_testbench_template_template); /* add command dependency to the shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); @@ -371,11 +375,14 @@ ShellCommandId add_write_testbench_io_connection_command_template( 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); + 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); + shell.set_command_execute_function(shell_cmd_id, + write_testbench_io_connection_template); /* add command dependency to the shell */ shell.set_command_dependency(shell_cmd_id, dependent_cmds); diff --git a/openfpga/src/base/openfpga_verilog_template.h b/openfpga/src/base/openfpga_verilog_template.h index 93ee4be7a3..66070a7771 100644 --- a/openfpga/src/base/openfpga_verilog_template.h +++ b/openfpga/src/base/openfpga_verilog_template.h @@ -222,9 +222,8 @@ int write_preconfigured_fabric_wrapper_template( *FPGA-Verilog *******************************************************************/ template -int write_testbench_template_template( - const T& openfpga_ctx, const Command& cmd, - const CommandContext& cmd_context) { +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"); @@ -267,9 +266,9 @@ int write_testbench_template_template( *FPGA-Verilog *******************************************************************/ template -int write_testbench_io_connection_template( - const T& openfpga_ctx, const Command& cmd, - const CommandContext& cmd_context) { +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"); @@ -304,9 +303,8 @@ int write_testbench_io_connection_template( } 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_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); } diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index c18220cbae..a8d2f78b24 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -20,11 +20,11 @@ #include "verilog_grid.h" #include "verilog_mock_fpga_wrapper.h" #include "verilog_preconfig_top_module.h" -#include "verilog_template_testbench.h" -#include "verilog_testbench_io_connection.h" #include "verilog_routing.h" #include "verilog_simulation_info_writer.h" #include "verilog_submodule.h" +#include "verilog_template_testbench.h" +#include "verilog_testbench_io_connection.h" #include "verilog_tile.h" #include "verilog_top_module.h" #include "verilog_top_testbench.h" @@ -264,14 +264,15 @@ int fpga_verilog_preconfigured_fabric_wrapper( * - A wrapper module, which encapsulate the FPGA module in a Verilog module *which have the same port as the input benchmark ********************************************************************/ -int fpga_verilog_template_testbench( - const ModuleManager &module_manager, - const IoNameMap &io_name_map, const ModuleNameMap &module_name_map, - const VerilogTestbenchOption &options) { +int fpga_verilog_template_testbench(const ModuleManager &module_manager, + const IoNameMap &io_name_map, + const ModuleNameMap &module_name_map, + const VerilogTestbenchOption &options) { vtr::ScopedStartFinishTimer timer( "Write a template testbench for a preconfigured FPGA fabric\n"); - std::string src_dir_path = format_dir_path(find_path_dir_name(options.output_directory())); + std::string src_dir_path = + format_dir_path(find_path_dir_name(options.output_directory())); std::string testbench_file_path = options.output_directory(); int status = CMD_EXEC_SUCCESS; @@ -282,18 +283,17 @@ int fpga_verilog_template_testbench( /* Generate wrapper module for FPGA fabric (mapped by the input benchmark and * pre-configured testbench for verification */ status = print_verilog_template_testbench( - module_manager, io_name_map, module_name_map, - testbench_file_path, options); + module_manager, io_name_map, module_name_map, testbench_file_path, options); return status; } /******************************************************************** - * A top-level function of FPGA-Verilog which focuses on generating I/O connection part of testbenches + * A top-level function of FPGA-Verilog which focuses on generating I/O + *connection part of testbenches ********************************************************************/ int fpga_verilog_testbench_io_connection( - const ModuleManager &module_manager, - const AtomContext &atom_ctx, + const ModuleManager &module_manager, const AtomContext &atom_ctx, const PlacementContext &place_ctx, const PinConstraints &pin_constraints, const BusGroup &bus_group, const IoLocationMap &io_location_map, const ModuleNameMap &module_name_map, @@ -303,7 +303,8 @@ int fpga_verilog_testbench_io_connection( vtr::ScopedStartFinishTimer timer( "Write a template testbench for a preconfigured FPGA fabric\n"); - std::string src_dir_path = format_dir_path(find_path_dir_name(options.output_directory())); + std::string src_dir_path = + format_dir_path(find_path_dir_name(options.output_directory())); std::string testbench_file_path = options.output_directory(); std::string netlist_name = atom_ctx.nlist.netlist_name(); @@ -316,15 +317,13 @@ int fpga_verilog_testbench_io_connection( /* Generate wrapper module for FPGA fabric (mapped by the input benchmark and * pre-configured testbench for verification */ status = print_verilog_testbench_io_connection( - module_manager, - fabric_global_port_info, atom_ctx, place_ctx, pin_constraints, bus_group, - io_location_map, module_name_map, netlist_annotation, - netlist_name, testbench_file_path, options); + module_manager, fabric_global_port_info, atom_ctx, place_ctx, + pin_constraints, bus_group, io_location_map, module_name_map, + netlist_annotation, netlist_name, testbench_file_path, options); return status; } - /******************************************************************** * A top-level function of FPGA-Verilog which focuses on a wrapper module, * which encapsulate the application HDL into a mock FPGA module diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index be1c7f91ce..5030288d06 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -74,21 +74,19 @@ int fpga_verilog_preconfigured_fabric_wrapper( const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, const VerilogTestbenchOption& options); -int fpga_verilog_template_testbench( - const ModuleManager &module_manager, - const IoNameMap &io_name_map, const ModuleNameMap &module_name_map, - const VerilogTestbenchOption &options); +int fpga_verilog_template_testbench(const ModuleManager& module_manager, + const IoNameMap& io_name_map, + const ModuleNameMap& module_name_map, + const VerilogTestbenchOption& options); int fpga_verilog_testbench_io_connection( - const ModuleManager &module_manager, - const AtomContext &atom_ctx, - const PlacementContext &place_ctx, const PinConstraints &pin_constraints, - const BusGroup &bus_group, const IoLocationMap &io_location_map, - const ModuleNameMap &module_name_map, - const FabricGlobalPortInfo &fabric_global_port_info, - const VprNetlistAnnotation &netlist_annotation, - const VerilogTestbenchOption &options); - + const ModuleManager& module_manager, const AtomContext& atom_ctx, + const PlacementContext& place_ctx, const PinConstraints& pin_constraints, + const BusGroup& bus_group, const IoLocationMap& io_location_map, + const ModuleNameMap& module_name_map, + const FabricGlobalPortInfo& fabric_global_port_info, + const VprNetlistAnnotation& netlist_annotation, + const VerilogTestbenchOption& options); int fpga_verilog_mock_fpga_wrapper( const ModuleManager& module_manager, const AtomContext& atom_ctx, diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index 10a0c28779..e278ff9fa7 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -18,8 +18,8 @@ #include "openfpga_port.h" #include "openfpga_reserved_words.h" #include "verilog_constants.h" -#include "verilog_preconfig_top_module_utils.h" #include "verilog_preconfig_top_module.h" +#include "verilog_preconfig_top_module_utils.h" #include "verilog_testbench_utils.h" #include "verilog_writer_utils.h" @@ -427,8 +427,9 @@ int print_verilog_preconfig_top_module( } /* Print internal wires */ - print_verilog_preconfig_top_module_internal_wires(fp, module_manager, - core_module, std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)); + print_verilog_preconfig_top_module_internal_wires( + fp, module_manager, core_module, + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)); /* Instanciate FPGA top-level module */ print_verilog_testbench_fpga_instance( @@ -445,7 +446,8 @@ int print_verilog_preconfig_top_module( * signals! */ status = print_verilog_preconfig_top_module_connect_global_ports( fp, module_manager, core_module, pin_constraints, global_ports, - benchmark_clock_port_names, std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)); + benchmark_clock_port_names, + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)); if (CMD_EXEC_FATAL_ERROR == status) { return status; } diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h index bb5ec6138a..0d7f3edac4 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h @@ -28,7 +28,6 @@ /* begin namespace openfpga */ namespace openfpga { - int print_verilog_preconfig_top_module( const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, @@ -41,7 +40,6 @@ int print_verilog_preconfig_top_module( const std::string& circuit_name, const std::string& verilog_fname, const VerilogTestbenchOption& options); - } /* end namespace openfpga */ #endif diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.cpp index f3081ed375..944506c89f 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.cpp @@ -28,7 +28,7 @@ namespace openfpga { *******************************************************************/ void print_verilog_preconfig_top_module_internal_wires( std::fstream &fp, const ModuleManager &module_manager, - const ModuleId &top_module, const std::string& port_postfix) { + const ModuleId &top_module, const std::string &port_postfix) { /* Validate the file stream */ valid_file_stream(fp); @@ -41,8 +41,7 @@ void print_verilog_preconfig_top_module_internal_wires( module_manager.module_port(top_module, module_port_id); /* Add a postfix to the internal wires to be different from other reserved * ports */ - module_port.set_name( - module_port.get_name() + port_postfix); + module_port.set_name(module_port.get_name() + port_postfix); fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" << std::endl; } @@ -60,7 +59,7 @@ int print_verilog_preconfig_top_module_connect_global_ports( const ModuleId &top_module, const PinConstraints &pin_constraints, const FabricGlobalPortInfo &fabric_global_ports, const std::vector &benchmark_clock_port_names, - const std::string& port_postfix) { + const std::string &port_postfix) { /* Validate the file stream */ valid_file_stream(fp); @@ -84,10 +83,9 @@ int print_verilog_preconfig_top_module_connect_global_ports( */ for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); ++pin_id) { - BasicPort module_clock_pin( - module_global_port.get_name() + - port_postfix, - module_global_port.pins()[pin_id], module_global_port.pins()[pin_id]); + BasicPort module_clock_pin(module_global_port.get_name() + port_postfix, + module_global_port.pins()[pin_id], + module_global_port.pins()[pin_id]); /* If the clock port name is in the pin constraints, we should wire it * to the constrained pin */ @@ -144,9 +142,7 @@ int print_verilog_preconfig_top_module_connect_global_ports( std::string constrained_net_name = pin_constraints.pin_net(module_global_pin); - module_global_pin.set_name( - module_global_port.get_name() + - port_postfix); + module_global_pin.set_name(module_global_port.get_name() + port_postfix); /* - If constrained to a given net in the benchmark, we connect the global * pin to the net diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.h b/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.h index 0a14663cae..55c85eadda 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.h +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module_utils.h @@ -30,14 +30,14 @@ namespace openfpga { void print_verilog_preconfig_top_module_internal_wires( std::fstream &fp, const ModuleManager &module_manager, - const ModuleId &top_module, const std::string& port_postfix); + const ModuleId &top_module, const std::string &port_postfix); int print_verilog_preconfig_top_module_connect_global_ports( std::fstream &fp, const ModuleManager &module_manager, const ModuleId &top_module, const PinConstraints &pin_constraints, const FabricGlobalPortInfo &fabric_global_ports, - const std::vector &benchmark_clock_port_names, const std::string& port_postfix); - + const std::vector &benchmark_clock_port_names, + const std::string &port_postfix); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_template_testbench.cpp b/openfpga/src/fpga_verilog/verilog_template_testbench.cpp index 5b10bfcac1..3f48d2a6c3 100644 --- a/openfpga/src/fpga_verilog/verilog_template_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_template_testbench.cpp @@ -18,8 +18,8 @@ #include "openfpga_port.h" #include "openfpga_reserved_words.h" #include "verilog_constants.h" -#include "verilog_template_testbench.h" #include "verilog_preconfig_top_module_utils.h" +#include "verilog_template_testbench.h" #include "verilog_testbench_utils.h" #include "verilog_writer_utils.h" @@ -29,7 +29,7 @@ namespace openfpga { /******************************************************************** * Top-level function to generate a template testbench for a FPGA fabric. * - * Testbench + * Testbench * +-------------------------------------------- * | * | FPGA fabric @@ -50,14 +50,14 @@ namespace openfpga { * | * +------------------------------------------- *******************************************************************/ -int print_verilog_template_testbench( - const ModuleManager &module_manager, - const IoNameMap &io_name_map, const ModuleNameMap &module_name_map, - const std::string &verilog_fname, - const VerilogTestbenchOption &options) { - std::string timer_message = - std::string( - "Write a template Verilog testbench for pre-configured FPGA top-level netlist"); +int print_verilog_template_testbench(const ModuleManager &module_manager, + const IoNameMap &io_name_map, + const ModuleNameMap &module_name_map, + const std::string &verilog_fname, + const VerilogTestbenchOption &options) { + std::string timer_message = std::string( + "Write a template Verilog testbench for pre-configured FPGA top-level " + "netlist"); int status = CMD_EXEC_SUCCESS; @@ -76,7 +76,9 @@ int print_verilog_template_testbench( std::string("A template Verilog testbench for pre-configured FPGA fabric"); print_verilog_file_header(fp, title, options.time_stamp()); - print_verilog_comment(fp, std::string("Require an adaption to your needs before used for design verification!!!")); + print_verilog_comment(fp, + std::string("Require an adaption to your needs before " + "used for design verification!!!")); print_verilog_default_net_type_declaration(fp, options.default_net_type()); @@ -118,10 +120,8 @@ int print_verilog_template_testbench( options.explicit_port_mapping()); /* Testbench ends*/ - print_verilog_module_end( - fp, - options.top_module(), - options.default_net_type()); + print_verilog_module_end(fp, options.top_module(), + options.default_net_type()); /* Close the file stream */ fp.close(); diff --git a/openfpga/src/fpga_verilog/verilog_template_testbench.h b/openfpga/src/fpga_verilog/verilog_template_testbench.h index 6b4ea22839..baa07cbc75 100644 --- a/openfpga/src/fpga_verilog/verilog_template_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_template_testbench.h @@ -19,11 +19,11 @@ /* begin namespace openfpga */ namespace openfpga { -int print_verilog_template_testbench( - const ModuleManager &module_manager, - const IoNameMap &io_name_map, const ModuleNameMap &module_name_map, - const std::string &verilog_fname, - const VerilogTestbenchOption &options); +int print_verilog_template_testbench(const ModuleManager &module_manager, + const IoNameMap &io_name_map, + const ModuleNameMap &module_name_map, + const std::string &verilog_fname, + const VerilogTestbenchOption &options); } /* end namespace openfpga */ From 8bee65853c9b14d1361a759327a4fb973ef2925f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Nov 2023 19:01:25 -0700 Subject: [PATCH 4/7] [core] add missing files --- .../verilog_testbench_io_connection.cpp | 111 ++++++++++++++++++ .../verilog_testbench_io_connection.h | 38 ++++++ 2 files changed, 149 insertions(+) create mode 100644 openfpga/src/fpga_verilog/verilog_testbench_io_connection.cpp create mode 100644 openfpga/src/fpga_verilog/verilog_testbench_io_connection.h diff --git a/openfpga/src/fpga_verilog/verilog_testbench_io_connection.cpp b/openfpga/src/fpga_verilog/verilog_testbench_io_connection.cpp new file mode 100644 index 0000000000..30018e4005 --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_testbench_io_connection.cpp @@ -0,0 +1,111 @@ +/******************************************************************** + * This file includes functions that are used to generate + * a Verilog module of a pre-configured FPGA fabric + *******************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "command_exit_codes.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from openfpgautil library */ +#include "openfpga_atom_netlist_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "openfpga_reserved_words.h" +#include "verilog_constants.h" +#include "verilog_preconfig_top_module_utils.h" +#include "verilog_testbench_io_connection.h" +#include "verilog_testbench_utils.h" +#include "verilog_writer_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Top-level function to generate the I/O connections for a pre-configured FPGA + *fabric. + *******************************************************************/ +int print_verilog_testbench_io_connection( + const ModuleManager &module_manager, const FabricGlobalPortInfo &global_ports, + const AtomContext &atom_ctx, const PlacementContext &place_ctx, + const PinConstraints &pin_constraints, const BusGroup &bus_group, + const IoLocationMap &io_location_map, const ModuleNameMap &module_name_map, + const VprNetlistAnnotation &netlist_annotation, + const std::string &circuit_name, const std::string &verilog_fname, + const VerilogTestbenchOption &options) { + std::string timer_message = std::string( + "Write I/O connections for pre-configured FPGA " + "fabric mapped to design '") + + circuit_name + std::string("'"); + + int status = CMD_EXEC_SUCCESS; + + /* Start time count */ + vtr::ScopedStartFinishTimer timer(timer_message); + + /* 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); + + /* Generate a brief description on the Verilog file*/ + std::string title = + std::string( + "I/O connections for a pre-configured FPGA fabric mapped to design: ") + + circuit_name; + print_verilog_file_header(fp, title, options.time_stamp()); + + /* Spot the dut module */ + ModuleId top_module = + module_manager.find_module(module_name_map.name(options.dut_module())); + if (!module_manager.valid_module_id(top_module)) { + VTR_LOG_ERROR( + "Unable to find the DUT module '%s'. Please check if you create " + "dedicated module when building the fabric!\n", + options.dut_module().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + /* Note that we always need the core module as it contains the original port + * names before possible renaming at top-level module. If there is no core + * module, it means that the current top module is the core module */ + std::string core_module_name = generate_fpga_core_module_name(); + if (module_name_map.name_exist(core_module_name)) { + core_module_name = module_name_map.name(core_module_name); + } + ModuleId core_module = module_manager.find_module(core_module_name); + if (!module_manager.valid_module_id(core_module)) { + core_module = top_module; + } + + /* Find clock ports in benchmark */ + std::vector benchmark_clock_port_names = + find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); + + /* Connect FPGA top module global ports to constant or benchmark global + * signals! */ + status = print_verilog_preconfig_top_module_connect_global_ports( + fp, module_manager, core_module, pin_constraints, global_ports, + benchmark_clock_port_names, std::string()); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + + /* Connect I/Os to benchmark I/Os or constant driver */ + print_verilog_testbench_connect_fpga_ios( + fp, module_manager, core_module, atom_ctx, place_ctx, io_location_map, + netlist_annotation, bus_group, std::string(), std::string(), std::string(), + std::vector(), (size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE); + + /* Close the file stream */ + fp.close(); + + return status; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_testbench_io_connection.h b/openfpga/src/fpga_verilog/verilog_testbench_io_connection.h new file mode 100644 index 0000000000..9875c4d61e --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_testbench_io_connection.h @@ -0,0 +1,38 @@ +#ifndef VERILOG_TESTBENCH_IO_CONNECTION_H +#define VERILOG_TESTBENCH_IO_CONNECTION_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include + +#include "bus_group.h" +#include "fabric_global_port_info.h" +#include "io_location_map.h" +#include "module_manager.h" +#include "module_name_map.h" +#include "pin_constraints.h" +#include "verilog_testbench_options.h" +#include "vpr_context.h" +#include "vpr_netlist_annotation.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int print_verilog_testbench_io_connection( + const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, + const AtomContext& atom_ctx, const PlacementContext& place_ctx, + const PinConstraints& pin_constraints, const BusGroup& bus_group, + const IoLocationMap& io_location_map, const ModuleNameMap& module_name_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& circuit_name, const std::string& verilog_fname, + const VerilogTestbenchOption& options); + +} /* end namespace openfpga */ + +#endif From 8e875f34533f94a78f437391e27077e30754f4f5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Nov 2023 21:08:36 -0700 Subject: [PATCH 5/7] [test] add a new test case to validate the new feature --- ...testbench_template_example_script.openfpga | 57 +++++++++++++++++++ .../regression_test_scripts/basic_reg_test.sh | 1 + .../config/counter8_bus_group.xml | 12 ++++ .../config/mac4_bus_group.xml | 26 +++++++++ .../config/pin_constraints_dummy.xml | 5 ++ .../config/pin_constraints_reset.xml | 7 +++ .../config/task.conf | 51 +++++++++++++++++ 7 files changed, 159 insertions(+) create mode 100644 openfpga_flow/openfpga_shell_scripts/write_testbench_template_example_script.openfpga create mode 100644 openfpga_flow/tasks/basic_tests/generate_template_testbench/config/counter8_bus_group.xml create mode 100644 openfpga_flow/tasks/basic_tests/generate_template_testbench/config/mac4_bus_group.xml create mode 100644 openfpga_flow/tasks/basic_tests/generate_template_testbench/config/pin_constraints_dummy.xml create mode 100644 openfpga_flow/tasks/basic_tests/generate_template_testbench/config/pin_constraints_reset.xml create mode 100644 openfpga_flow/tasks/basic_tests/generate_template_testbench/config/task.conf diff --git a/openfpga_flow/openfpga_shell_scripts/write_testbench_template_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/write_testbench_template_example_script.openfpga new file mode 100644 index 0000000000..7f0f8eeaf7 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/write_testbench_template_example_script.openfpga @@ -0,0 +1,57 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling ideal + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing #--verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --verbose + +# Write template testbenches +write_testbench_template --file ./TESTBENCH/template_testbench.v --top_module template_top_tb ${OPENFPGA_VERILOG_PORT_MAPPING} +write_testbench_io_connection --file ./TESTBENCH/io_connections.v --pin_constraints_file ${OPENFPGA_PIN_CONSTRAINTS_FILE} --bus_group_file ${OPENFPGA_BUS_GROUP_FILE} + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index dd945b4279..e240b64dd6 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -99,6 +99,7 @@ run-task basic_tests/generate_fabric $@ echo -e "Testing Verilog testbench generation only"; run-task basic_tests/generate_testbench $@ +run-task basic_tests/generate_template_testbench $@ echo -e "Testing separated Verilog fabric netlists and testbench locations"; run-task basic_tests/custom_fabric_netlist_location $@ diff --git a/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/counter8_bus_group.xml b/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/counter8_bus_group.xml new file mode 100644 index 0000000000..a0fd22f772 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/counter8_bus_group.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/mac4_bus_group.xml b/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/mac4_bus_group.xml new file mode 100644 index 0000000000..50a42a566a --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/mac4_bus_group.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/pin_constraints_dummy.xml b/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/pin_constraints_dummy.xml new file mode 100644 index 0000000000..9d692672b2 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/pin_constraints_dummy.xml @@ -0,0 +1,5 @@ + + + + diff --git a/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/pin_constraints_reset.xml b/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/pin_constraints_reset.xml new file mode 100644 index 0000000000..abcf209f6f --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/pin_constraints_reset.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/task.conf b/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/task.conf new file mode 100644 index 0000000000..e869ac5a13 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/generate_template_testbench/config/task.conf @@ -0,0 +1,51 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_testbench_template_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_verilog_port_mapping=--explicit_port_mapping + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counters/counter_8bit_async_reset/counter.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_4/mac_4.v + +[SYNTHESIS_PARAM] +# Yosys script parameters +bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v +bench_yosys_dff_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v +bench_yosys_bram_map_rules_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram.txt +bench_yosys_bram_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v +bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v +bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=36 -D DSP_B_MAXWIDTH=36 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_36x36 +bench_read_verilog_options_common = -nolatches +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys + +bench0_top = counter +bench0_openfpga_pin_constraints_file=${PATH:TASK_DIR}/config/pin_constraints_reset.xml +bench0_openfpga_bus_group_file=${PATH:TASK_DIR}/config/counter8_bus_group.xml + +bench1_top = mac_4 +bench1_openfpga_pin_constraints_file=${PATH:TASK_DIR}/config/pin_constraints_dummy.xml +bench1_openfpga_bus_group_file=${PATH:TASK_DIR}/config/mac4_bus_group.xml + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] From 16f4e2938f8fc2d8429043e1a4b5d2ca5e249ec4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Nov 2023 21:22:37 -0700 Subject: [PATCH 6/7] [doc] add new comand --- .../fpga_verilog_commands.rst | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst index d8337a9ce9..16db7cf8cb 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst @@ -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 or -f + + The file path to output the testbench file. For example, ``--file /temp/testbench_template.v`` + + .. option:: --top_module + + 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 + + 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 + + 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 or -f + + The file path to output the netlist file. For example, ``--file /temp/testbench_io_conkt.v`` + + .. option:: --dut_module + + 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 or -pcf + + 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 or -bgf + + 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 ~~~~~~~~~~~~~~~~~~~~~~~ From 442dc9ddec2e2441daf20ee48a5345cfdda4401f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Nov 2023 21:27:12 -0700 Subject: [PATCH 7/7] [doc] format --- .../openfpga_commands/fpga_verilog_commands.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst index 16db7cf8cb..d3497cd982 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst @@ -188,7 +188,7 @@ 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!!! + .. 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 or -f @@ -227,7 +227,7 @@ 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!!! + .. 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 or -f