From 7ade48343cec8fa51c0f2b40f912c9043c950485 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 9 Jun 2021 17:06:01 -0600 Subject: [PATCH] [Tool] Deprecate command 'write_verilog_testbench' --- openfpga/src/base/openfpga_verilog.cpp | 58 -- openfpga/src/base/openfpga_verilog.h | 3 - .../src/base/openfpga_verilog_command.cpp | 78 -- openfpga/src/fpga_verilog/verilog_api.cpp | 113 --- openfpga/src/fpga_verilog/verilog_api.h | 14 - .../fpga_verilog/verilog_top_testbench.cpp | 951 ------------------ .../src/fpga_verilog/verilog_top_testbench.h | 16 - 7 files changed, 1233 deletions(-) diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index cc737554b..e279f1200 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -61,64 +61,6 @@ int write_fabric_verilog(OpenfpgaContext& openfpga_ctx, return CMD_EXEC_SUCCESS; } -/******************************************************************** - * A wrapper function to call the Verilog testbench generator of FPGA-Verilog - *******************************************************************/ -int write_verilog_testbench(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context) { - - CommandOptionId opt_output_dir = cmd.option("file"); - CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); - CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); - CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path"); - CommandOptionId opt_print_top_testbench = cmd.option("print_top_testbench"); - CommandOptionId opt_fast_configuration = cmd.option("fast_configuration"); - CommandOptionId opt_print_formal_verification_top_netlist = cmd.option("print_formal_verification_top_netlist"); - CommandOptionId opt_print_preconfig_top_testbench = cmd.option("print_preconfig_top_testbench"); - CommandOptionId opt_print_simulation_ini = cmd.option("print_simulation_ini"); - CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping"); - CommandOptionId opt_include_signal_init = cmd.option("include_signal_init"); - CommandOptionId opt_support_icarus_simulator = cmd.option("support_icarus_simulator"); - CommandOptionId opt_verbose = cmd.option("verbose"); - - /* This is an intermediate data structure which is designed to modularize the FPGA-Verilog - * Keep it independent from any other outside data structures - */ - VerilogTestbenchOption options; - options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); - options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist)); - options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark)); - options.set_print_formal_verification_top_netlist(cmd_context.option_enable(cmd, opt_print_formal_verification_top_netlist)); - options.set_print_preconfig_top_testbench(cmd_context.option_enable(cmd, opt_print_preconfig_top_testbench)); - options.set_fast_configuration(cmd_context.option_enable(cmd, opt_fast_configuration)); - options.set_print_top_testbench(cmd_context.option_enable(cmd, opt_print_top_testbench)); - options.set_print_simulation_ini(cmd_context.option_value(cmd, opt_print_simulation_ini)); - options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping)); - options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init)); - options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator)); - options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); - - /* If pin constraints are enabled by command options, read the file */ - PinConstraints pin_constraints; - if (true == cmd_context.option_enable(cmd, opt_pcf)) { - pin_constraints = read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); - } - - return fpga_verilog_testbench(openfpga_ctx.module_graph(), - openfpga_ctx.bitstream_manager(), - openfpga_ctx.fabric_bitstream(), - g_vpr_ctx.atom(), - g_vpr_ctx.placement(), - pin_constraints, - openfpga_ctx.io_location_map(), - openfpga_ctx.fabric_global_port_info(), - openfpga_ctx.vpr_netlist_annotation(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.simulation_setting(), - openfpga_ctx.arch().config_protocol, - options); -} - /******************************************************************** * A wrapper function to call the full testbench generator of FPGA-Verilog *******************************************************************/ diff --git a/openfpga/src/base/openfpga_verilog.h b/openfpga/src/base/openfpga_verilog.h index 7789335a8..3bbd7fab3 100644 --- a/openfpga/src/base/openfpga_verilog.h +++ b/openfpga/src/base/openfpga_verilog.h @@ -18,9 +18,6 @@ namespace openfpga { int write_fabric_verilog(OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); -int write_verilog_testbench(OpenfpgaContext& openfpga_ctx, - const Command& cmd, const CommandContext& cmd_context); - int write_full_testbench(const OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context); diff --git a/openfpga/src/base/openfpga_verilog_command.cpp b/openfpga/src/base/openfpga_verilog_command.cpp index 79388c4b9..174b8a4d7 100644 --- a/openfpga/src/base/openfpga_verilog_command.cpp +++ b/openfpga/src/base/openfpga_verilog_command.cpp @@ -54,74 +54,6 @@ ShellCommandId add_openfpga_write_fabric_verilog_command(openfpga::Shell& shell, - const ShellCommandClassId& cmd_class_id, - const std::vector& dependent_cmds) { - Command shell_cmd("write_verilog_testbench"); - - /* Add an option '--file' in short '-f'*/ - CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for Verilog netlists"); - shell_cmd.set_option_short_name(output_opt, "f"); - shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); - - /* Add an option '--fabric_netlist_file_path'*/ - CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "Specify the file path to the fabric Verilog netlist"); - shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING); - - /* Add an option '--pin_constraints_file in short '-pcf' */ - CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, "Specify the file path to the pin constraints"); - shell_cmd.set_option_short_name(pcf_opt, "pcf"); - shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING); - - /* Add an option '--reference_benchmark_file_path'*/ - CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "Specify the file path to the reference Verilog netlist"); - shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING); - - /* Add an option '--print_top_testbench' */ - shell_cmd.add_option("print_top_testbench", false, "Generate a full testbench for top-level fabric module with autocheck capability"); - - /* Add an option '--fast_configuration' */ - shell_cmd.add_option("fast_configuration", false, "Reduce the period of configuration by skip zero data points"); - - /* Add an option '--print_formal_verification_top_netlist' */ - shell_cmd.add_option("print_formal_verification_top_netlist", false, "Generate a top-level module which can be used in formal verification"); - - /* Add an option '--print_preconfig_top_testbench' */ - shell_cmd.add_option("print_preconfig_top_testbench", false, "Generate a pre-configured testbench for top-level fabric module with autocheck capability"); - - /* Add an option '--print_simulation_ini' */ - CommandOptionId sim_ini_opt = shell_cmd.add_option("print_simulation_ini", false, "Generate a .ini file as an exchangeable file to enable HDL simulations"); - shell_cmd.set_option_require_value(sim_ini_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 '--include_signal_init' */ - shell_cmd.add_option("include_signal_init", false, "Initialize all the signals in Verilog testbenches"); - - /* Add an option '--support_icarus_simulator' */ - shell_cmd.add_option("support_icarus_simulator", false, "Fine-tune Verilog testbenches to support icarus simulator"); - - /* Add an option '--verbose' */ - shell_cmd.add_option("verbose", false, "Enable verbose output"); - - /* Add command to the Shell */ - ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate Verilog testbenches for full FPGA fabric"); - shell.set_command_class(shell_cmd_id, cmd_class_id); - shell.set_command_execute_function(shell_cmd_id, write_verilog_testbench); - - /* 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 full testbench * - add associated options @@ -327,16 +259,6 @@ void add_openfpga_verilog_commands(openfpga::Shell& shell) { openfpga_verilog_cmd_class, fabric_verilog_dependent_cmds); - /******************************** - * Command 'write_verilog_testbench' - */ - /* The command 'write_verilog_testbench' should NOT be executed before 'build_fabric' */ - std::vector verilog_testbench_dependent_cmds; - verilog_testbench_dependent_cmds.push_back(build_fabric_cmd_id); - add_openfpga_write_verilog_testbench_command(shell, - openfpga_verilog_cmd_class, - verilog_testbench_dependent_cmds); - /******************************** * Command 'write_full_testbench' */ diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index d7ed62f64..f114f6d36 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -139,119 +139,6 @@ void fpga_fabric_verilog(ModuleManager &module_manager, module_manager.num_modules()); } -/******************************************************************** - * A top-level function of FPGA-Verilog which focuses on fabric Verilog 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 - * - Testbench, where a FPGA module is configured with a bitstream and then driven by input vectors - * - Pre-configured testbench, which can skip the configuration phase and pre-configure the FPGA module. - * This testbench is created for quick verification and formal verification purpose. - * - Verilog netlist including preprocessing flags and all the Verilog netlists that have been generated - ********************************************************************/ -int fpga_verilog_testbench(const ModuleManager &module_manager, - const BitstreamManager &bitstream_manager, - const FabricBitstream &fabric_bitstream, - const AtomContext &atom_ctx, - const PlacementContext &place_ctx, - const PinConstraints& pin_constraints, - const IoLocationMap &io_location_map, - const FabricGlobalPortInfo &fabric_global_port_info, - const VprNetlistAnnotation &netlist_annotation, - const CircuitLibrary &circuit_lib, - const SimulationSetting &simulation_setting, - const ConfigProtocol &config_protocol, - const VerilogTestbenchOption &options) { - - vtr::ScopedStartFinishTimer timer("Write Verilog testbenches for FPGA fabric\n"); - - std::string src_dir_path = format_dir_path(options.output_directory()); - - std::string netlist_name = atom_ctx.nlist.netlist_name(); - - int status = CMD_EXEC_SUCCESS; - - /* Create directories */ - create_directory(src_dir_path); - - /* Output preprocessing flags for HDL simulations */ - print_verilog_simulation_preprocessing_flags(std::string(src_dir_path), - options); - - /* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */ - if (true == options.print_formal_verification_top_netlist()) { - std::string formal_verification_top_netlist_file_path = src_dir_path + netlist_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX); - status = print_verilog_preconfig_top_module(module_manager, bitstream_manager, - config_protocol, - circuit_lib, fabric_global_port_info, - atom_ctx, place_ctx, - pin_constraints, - io_location_map, - netlist_annotation, - netlist_name, - formal_verification_top_netlist_file_path, - options.explicit_port_mapping()); - if (status == CMD_EXEC_FATAL_ERROR) { - return status; - } - } - - if (true == options.print_preconfig_top_testbench()) { - /* Generate top-level testbench using random vectors */ - std::string random_top_testbench_file_path = src_dir_path + netlist_name + std::string(RANDOM_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); - print_verilog_random_top_testbench(netlist_name, - random_top_testbench_file_path, - atom_ctx, - netlist_annotation, - module_manager, - fabric_global_port_info, - pin_constraints, - simulation_setting, - options.explicit_port_mapping()); - } - - /* Generate full testbench for verification, including configuration phase and operating phase */ - if (true == options.print_top_testbench()) { - std::string top_testbench_file_path = src_dir_path + netlist_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); - print_verilog_top_testbench(module_manager, - bitstream_manager, fabric_bitstream, - circuit_lib, - config_protocol, - fabric_global_port_info, - atom_ctx, place_ctx, - pin_constraints, - io_location_map, - netlist_annotation, - netlist_name, - top_testbench_file_path, - simulation_setting, - options); - } - - /* Generate exchangeable files which contains simulation settings */ - if (true == options.print_simulation_ini()) { - std::string simulation_ini_file_name = options.simulation_ini_path(); - VTR_ASSERT(true != options.simulation_ini_path().empty()); - print_verilog_simulation_info(simulation_ini_file_name, - netlist_name, - src_dir_path, - atom_ctx, place_ctx, io_location_map, - module_manager, - config_protocol.type(), - bitstream_manager.num_bits(), - simulation_setting.num_clock_cycles(), - simulation_setting.programming_clock_frequency(), - simulation_setting.default_operating_clock_frequency()); - } - - /* Generate a Verilog file including all the netlists that have been generated */ - print_verilog_testbench_include_netlists(src_dir_path, - netlist_name, - options.fabric_netlist_file_path(), - options.reference_benchmark_file_path()); - - return status; -} - /******************************************************************** * A top-level function of FPGA-Verilog which focuses on full testbench generation * This function will generate diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index 0bfb397f8..934dc08f7 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -43,20 +43,6 @@ void fpga_fabric_verilog(ModuleManager& module_manager, const DeviceRRGSB& device_rr_gsb, const FabricVerilogOption& options); -int fpga_verilog_testbench(const ModuleManager& module_manager, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const PinConstraints& pin_constraints, - const IoLocationMap& io_location_map, - const FabricGlobalPortInfo &fabric_global_port_info, - const VprNetlistAnnotation& netlist_annotation, - const CircuitLibrary& circuit_lib, - const SimulationSetting& simulation_parameters, - const ConfigProtocol& config_protocol, - const VerilogTestbenchOption& options); - int fpga_verilog_full_testbench(const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 0eb5f39f0..779b6ceaa 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -945,229 +945,6 @@ void print_verilog_top_testbench_benchmark_instance(std::fstream& fp, fp << std::endl; } -/******************************************************************** - * Print tasks (processes) in Verilog format, - * which is very useful in generating stimuli for each clock cycle - * This function is tuned for configuration-chain manipulation: - * During each programming cycle, we feed the input of scan chain with a memory bit - *******************************************************************/ -static -void print_verilog_top_testbench_load_bitstream_task_configuration_chain(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module) { - - /* Validate the file stream */ - valid_file_stream(fp); - - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - ModulePortId cc_head_port_id = module_manager.find_module_port(top_module, generate_configuration_chain_head_name()); - BasicPort cc_head_port = module_manager.module_port(top_module, cc_head_port_id); - BasicPort cc_head_value(generate_configuration_chain_head_name() + std::string("_val"), cc_head_port.get_width()); - - /* Add an empty line as splitter */ - fp << std::endl; - - /* Feed the scan-chain input at each falling edge of programming clock - * It aims at avoid racing the programming clock (scan-chain data changes at the rising edge). - */ - print_verilog_comment(fp, std::string("----- Task: input values during a programming clock cycle -----")); - fp << "task " << std::string(TOP_TESTBENCH_PROG_TASK_NAME) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_INPUT, cc_head_value) << ";" << std::endl; - fp << "\tbegin" << std::endl; - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, cc_head_port); - fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, cc_head_value); - fp << ";" << std::endl; - - fp << "\tend" << std::endl; - fp << "endtask" << std::endl; - - /* Add an empty line as splitter */ - fp << std::endl; -} - -/******************************************************************** - * Print tasks (processes) in Verilog format, - * which is very useful in generating stimuli for each clock cycle - * This function is tuned for memory bank manipulation: - * During each programming cycle, we feed - * - an address to the BL address port of top module - * - an address to the WL address port of top module - * - a data input to the din port of top module - *******************************************************************/ -static -void print_verilog_top_testbench_load_bitstream_task_memory_bank(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module) { - - /* Validate the file stream */ - valid_file_stream(fp); - - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - - ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_BL_ADDRESS_PORT_NAME)); - BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); - BasicPort bl_addr_value = bl_addr_port; - bl_addr_value.set_name(std::string(MEMORY_BL_PORT_NAME) + std::string("_val")); - - ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); - BasicPort wl_addr_value = wl_addr_port; - wl_addr_value.set_name(std::string(MEMORY_WL_PORT_NAME) + std::string("_val")); - - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort din_port = module_manager.module_port(top_module, din_port_id); - BasicPort din_value = din_port; - din_value.set_name(std::string(DECODER_DATA_IN_PORT_NAME) + std::string("_val")); - - /* Add an empty line as splitter */ - fp << std::endl; - - /* Feed the address and data input at each falling edge of programming clock - * As the enable signal is wired to the programming clock, we should synchronize - * address and data with the enable signal - */ - print_verilog_comment(fp, std::string("----- Task: assign BL and WL address, and data values at rising edge of enable signal -----")); - fp << "task " << std::string(TOP_TESTBENCH_PROG_TASK_NAME) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_INPUT, bl_addr_value) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_INPUT, wl_addr_value) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_INPUT, din_value) << ";" << std::endl; - fp << "\tbegin" << std::endl; - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, bl_addr_port); - fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, bl_addr_value); - fp << ";" << std::endl; - fp << std::endl; - - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_addr_port); - fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_addr_value); - fp << ";" << std::endl; - fp << std::endl; - - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); - fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, din_value); - fp << ";" << std::endl; - fp << std::endl; - - fp << "\tend" << std::endl; - fp << "endtask" << std::endl; - - /* Add an empty line as splitter */ - fp << std::endl; -} - - -/******************************************************************** - * Print tasks (processes) in Verilog format, - * which is very useful in generating stimuli for each clock cycle - * This function is tuned for frame-based memory manipulation: - * During each programming cycle, we feed - * - an address to the address port of top module - * - a data input to the din port of top module - *******************************************************************/ -static -void print_verilog_top_testbench_load_bitstream_task_frame_decoder(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module) { - - /* Validate the file stream */ - valid_file_stream(fp); - - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - - ModulePortId addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort addr_port = module_manager.module_port(top_module, addr_port_id); - BasicPort addr_value = addr_port; - addr_value.set_name(std::string(DECODER_ADDRESS_PORT_NAME) + std::string("_val")); - - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort din_port = module_manager.module_port(top_module, din_port_id); - BasicPort din_value = din_port; - din_value.set_name(std::string(DECODER_DATA_IN_PORT_NAME) + std::string("_val")); - - /* Add an empty line as splitter */ - fp << std::endl; - - /* Feed the address and data input at each falling edge of programming clock - * As the enable signal is wired to the programming clock, we should synchronize - * address and data with the enable signal - */ - print_verilog_comment(fp, std::string("----- Task: assign address and data values at rising edge of enable signal -----")); - fp << "task " << std::string(TOP_TESTBENCH_PROG_TASK_NAME) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_INPUT, addr_value) << ";" << std::endl; - fp << generate_verilog_port(VERILOG_PORT_INPUT, din_value) << ";" << std::endl; - fp << "\tbegin" << std::endl; - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); - fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_value); - fp << ";" << std::endl; - fp << std::endl; - - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); - fp << " = "; - fp << generate_verilog_port(VERILOG_PORT_CONKT, din_value); - fp << ";" << std::endl; - fp << std::endl; - - fp << "\tend" << std::endl; - fp << "endtask" << std::endl; - - /* Add an empty line as splitter */ - fp << std::endl; -} - -/******************************************************************** - * Print tasks, which is very useful in generating stimuli for each clock cycle - *******************************************************************/ -static -void print_verilog_top_testbench_load_bitstream_task(std::fstream& fp, - const e_config_protocol_type& sram_orgz_type, - const ModuleManager& module_manager, - const ModuleId& top_module) { - switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: - /* No need to have a specific task. Loading is done in 1 clock cycle */ - break; - case CONFIG_MEM_SCAN_CHAIN: - print_verilog_top_testbench_load_bitstream_task_configuration_chain(fp, - module_manager, - top_module); - break; - case CONFIG_MEM_MEMORY_BANK: - print_verilog_top_testbench_load_bitstream_task_memory_bank(fp, - module_manager, - top_module); - break; - case CONFIG_MEM_FRAME_BASED: - print_verilog_top_testbench_load_bitstream_task_frame_decoder(fp, - module_manager, - top_module); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid type of SRAM organization!\n"); - exit(1); - } -} - /******************************************************************** * Print generatic input stimuli for the top testbench * include: @@ -1370,477 +1147,6 @@ void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& f } } -/******************************************************************** - * Print stimulus for a FPGA fabric with a flatten memory (standalone) configuration protocol - * We will load the bitstream in the second clock cycle, right after the first reset cycle - *******************************************************************/ -static -void print_verilog_top_testbench_vanilla_bitstream(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { - /* Validate the file stream */ - valid_file_stream(fp); - - /* Find Bit-Line and Word-Line port */ - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - - /* Find Bit-Line and Word-Line port */ - ModulePortId bl_port_id = module_manager.find_module_port(top_module, std::string(MEMORY_BL_PORT_NAME)); - BasicPort bl_port = module_manager.module_port(top_module, bl_port_id); - - ModulePortId wl_port_id = module_manager.find_module_port(top_module, std::string(MEMORY_WL_PORT_NAME)); - BasicPort wl_port = module_manager.module_port(top_module, wl_port_id); - - /* Initial value should be the first configuration bits - * In the rest of programming cycles, - * configuration bits are fed at the falling edge of programming clock. - * We do not care the value of scan_chain head during the first programming cycle - * It is reset anyway - */ - std::vector initial_bl_values(bl_port.get_width(), 0); - std::vector initial_wl_values(wl_port.get_width(), 0); - - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); - fp << "initial" << std::endl; - fp << "\tbegin" << std::endl; - print_verilog_comment(fp, "----- Configuration chain default input -----"); - fp << "\t\t"; - fp << generate_verilog_port_constant_values(bl_port, initial_bl_values); - fp << ";" << std::endl; - fp << "\t\t"; - fp << generate_verilog_port_constant_values(wl_port, initial_wl_values); - fp << ";" << std::endl; - - fp << std::endl; - - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ") begin" << std::endl; - - /* Enable all the WLs */ - std::vector enabled_wl_values(wl_port.get_width(), 1); - fp << "\t\t\t"; - fp << generate_verilog_port_constant_values(wl_port, enabled_wl_values); - fp << ";" << std::endl; - - size_t ibit = 0; - for (const FabricBitId& bit_id : fabric_bitstream.bits()) { - BasicPort cur_bl_port(bl_port); - cur_bl_port.set_width(ibit, ibit); - - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, cur_bl_port); - fp << " = "; - fp << "1'b" << (size_t)bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id)); - fp << ";" << std::endl; - - ibit++; - } - - fp << "\t\tend" << std::endl; - - /* Disable all the WLs */ - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - fp << "\t\t\t"; - fp << generate_verilog_port_constant_values(wl_port, initial_wl_values); - fp << ";" << std::endl; - - /* Raise the flag of configuration done when bitstream loading is complete */ - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); - fp << " <= "; - std::vector config_done_enable_values(config_done_port.get_width(), 1); - fp << generate_verilog_constant_values(config_done_enable_values); - fp << ";" << std::endl; - - fp << "\tend" << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); -} - -/******************************************************************** - * Print stimulus for a FPGA fabric with a configuration chain protocol - * where configuration bits are programming in serial (one by one) - * Task list: - * 1. For clock signal, we should create voltage waveforms for two types of clock signals: - * a. operation clock - * b. programming clock - * 2. For Set/Reset, we reset the chip after programming phase ends - * and before operation phase starts - * 3. For input/output clb nets (mapped to I/O grids), - * we should create voltage waveforms only after programming phase - *******************************************************************/ -static -void print_verilog_top_testbench_configuration_chain_bitstream(std::fstream& fp, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { - /* Validate the file stream */ - valid_file_stream(fp); - - /* Initial value should be the first configuration bits - * In the rest of programming cycles, - * configuration bits are fed at the falling edge of programming clock. - * We do not care the value of scan_chain head during the first programming cycle - * It is reset anyway - */ - ModulePortId cc_head_port_id = module_manager.find_module_port(top_module, generate_configuration_chain_head_name()); - BasicPort config_chain_head_port = module_manager.module_port(top_module, cc_head_port_id); - std::vector initial_values(config_chain_head_port.get_width(), 0); - - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); - fp << "initial" << std::endl; - fp << "\tbegin" << std::endl; - print_verilog_comment(fp, "----- Configuration chain default input -----"); - fp << "\t\t"; - fp << generate_verilog_port_constant_values(config_chain_head_port, initial_values); - fp << ";"; - - fp << std::endl; - - /* Find the longest bitstream */ - size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream); - - /* For fast configuration, the bitstream size counts from the first bit '1' */ - size_t num_bits_to_skip = 0; - if (true == fast_configuration) { - num_bits_to_skip = find_configuration_chain_fabric_bitstream_size_to_be_skipped(fabric_bitstream, bitstream_manager, bit_value_to_skip); - } - VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size); - - /* Reorganize the regional bitstreams to be the same size */ - ConfigChainFabricBitstream regional_bitstreams = build_config_chain_fabric_bitstream_by_region(bitstream_manager, fabric_bitstream); - - /* Attention: when the fast configuration is enabled, we will start from the first bit '1' - * This requires a reset signal (as we forced in the first clock cycle) - * - * Note that bitstream may come from different regions - * The bitstream value to be loaded should be organized as follows - * - * cycleA - * | - * Region 0: 0|00000001111101010 - * Region 1: | 00000011010101 - * Region 2: | 0010101111000110 - * - * Zero bits will be added to the head of those bitstreams are shorter - * than the longest bitstream - */ - for (size_t ibit = num_bits_to_skip; ibit < regional_bitstream_max_size; ++ibit) { - std::vector curr_cc_head_val; - curr_cc_head_val.reserve(fabric_bitstream.regions().size()); - for (const auto& region_bitstream : regional_bitstreams) { - curr_cc_head_val.push_back((size_t)region_bitstream[ibit]); - } - - fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME); - fp << "(" << generate_verilog_constant_values(curr_cc_head_val) << ");" << std::endl; - } - - /* Raise the flag of configuration done when bitstream loading is complete */ - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); - fp << " <= "; - std::vector config_done_enable_values(config_done_port.get_width(), 1); - fp << generate_verilog_constant_values(config_done_enable_values); - fp << ";" << std::endl; - - fp << "\tend" << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); -} - -/******************************************************************** - * Print stimulus for a FPGA fabric with a memory bank configuration protocol - * where configuration bits are programming in serial (one by one) - * - * We will use the programming task function created before - *******************************************************************/ -static -void print_verilog_top_testbench_memory_bank_bitstream(std::fstream& fp, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream) { - /* Validate the file stream */ - valid_file_stream(fp); - - /* Feed addresss and data input pair one by one - * Note: the first cycle is reserved for programming reset - * We should give dummy values - */ - ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_BL_ADDRESS_PORT_NAME)); - BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); - std::vector initial_bl_addr_values(bl_addr_port.get_width(), 0); - - ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); - std::vector initial_wl_addr_values(wl_addr_port.get_width(), 0); - - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort din_port = module_manager.module_port(top_module, din_port_id); - std::vector initial_din_values(din_port.get_width(), 0); - - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); - fp << "initial" << std::endl; - fp << "\tbegin" << std::endl; - print_verilog_comment(fp, "----- Address port default input -----"); - fp << "\t\t"; - fp << generate_verilog_port_constant_values(bl_addr_port, initial_bl_addr_values); - fp << ";"; - fp << std::endl; - - fp << "\t\t"; - fp << generate_verilog_port_constant_values(wl_addr_port, initial_wl_addr_values); - fp << ";"; - fp << std::endl; - - print_verilog_comment(fp, "----- Data-input port default input -----"); - fp << "\t\t"; - fp << generate_verilog_port_constant_values(din_port, initial_din_values); - fp << ";"; - - fp << std::endl; - - /* Reorganize the fabric bitstream by the same address across regions */ - MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); - - for (const auto& addr_din_pair : fabric_bits_by_addr) { - /* When fast configuration is enabled, - * the rule to skip any configuration bit should consider the whole data input values. - * Only all the bits in the din port match the value to be skipped, - * the programming cycle can be skipped! - */ - if (true == fast_configuration) { - bool skip_curr_bits = true; - for (const bool& bit : addr_din_pair.second) { - if (bit_value_to_skip != bit) { - skip_curr_bits = false; - break; - } - } - - if (true == skip_curr_bits) { - continue; - } - } - - fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME); - fp << "(" << bl_addr_port.get_width() << "'b"; - VTR_ASSERT(bl_addr_port.get_width() == addr_din_pair.first.first.length()); - fp << addr_din_pair.first.first; - - fp << ", "; - fp << wl_addr_port.get_width() << "'b"; - VTR_ASSERT(wl_addr_port.get_width() == addr_din_pair.first.second.length()); - fp << addr_din_pair.first.second; - - fp << ", "; - fp << din_port.get_width() << "'b"; - VTR_ASSERT(din_port.get_width() == addr_din_pair.second.size()); - for (const bool& din_value : addr_din_pair.second) { - if (true == din_value) { - fp << "1"; - } else { - VTR_ASSERT(false == din_value); - fp << "0"; - } - } - fp << ");" << std::endl; - } - - /* Raise the flag of configuration done when bitstream loading is complete */ - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); - fp << " <= "; - std::vector config_done_enable_values(config_done_port.get_width(), 1); - fp << generate_verilog_constant_values(config_done_enable_values); - fp << ";" << std::endl; - - fp << "\tend" << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); -} - -/******************************************************************** - * Print stimulus for a FPGA fabric with a frame-based configuration protocol - * where configuration bits are programming in serial (one by one) - * - * We will use the programming task function created before - *******************************************************************/ -static -void print_verilog_top_testbench_frame_decoder_bitstream(std::fstream& fp, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream) { - /* Validate the file stream */ - valid_file_stream(fp); - - /* Feed addresss and data input pair one by one - * Note: the first cycle is reserved for programming reset - * We should give dummy values - */ - ModulePortId addr_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort addr_port = module_manager.module_port(top_module, addr_port_id); - std::vector initial_addr_values(addr_port.get_width(), 0); - - ModulePortId din_port_id = module_manager.find_module_port(top_module, - std::string(DECODER_DATA_IN_PORT_NAME)); - BasicPort din_port = module_manager.module_port(top_module, din_port_id); - std::vector initial_din_values(din_port.get_width(), 0); - - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); - fp << "initial" << std::endl; - fp << "\tbegin" << std::endl; - print_verilog_comment(fp, "----- Address port default input -----"); - fp << "\t\t"; - fp << generate_verilog_port_constant_values(addr_port, initial_addr_values); - fp << ";"; - fp << std::endl; - - print_verilog_comment(fp, "----- Data-input port default input -----"); - fp << "\t\t"; - fp << generate_verilog_port_constant_values(din_port, initial_din_values); - fp << ";"; - - fp << std::endl; - - /* Reorganize the fabric bitstream by the same address across regions */ - FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream); - - for (const auto& addr_din_pair : fabric_bits_by_addr) { - /* When fast configuration is enabled, - * the rule to skip any configuration bit should consider the whole data input values. - * Only all the bits in the din port match the value to be skipped, - * the programming cycle can be skipped! - */ - if (true == fast_configuration) { - bool skip_curr_bits = true; - for (const bool& bit : addr_din_pair.second) { - if (bit_value_to_skip != bit) { - skip_curr_bits = false; - break; - } - } - - if (true == skip_curr_bits) { - continue; - } - } - - fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME); - fp << "(" << addr_port.get_width() << "'b"; - VTR_ASSERT(addr_port.get_width() == addr_din_pair.first.size()); - fp << addr_din_pair.first; - fp << ", "; - fp << din_port.get_width() << "'b"; - VTR_ASSERT(din_port.get_width() == addr_din_pair.second.size()); - for (const bool& din_value : addr_din_pair.second) { - if (true == din_value) { - fp << "1"; - } else { - VTR_ASSERT(false == din_value); - fp << "0"; - } - } - fp << ");" << std::endl; - } - - /* Disable the address and din - fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME); - fp << "(" << addr_port.get_width() << "'b"; - std::vector all_zero_addr(addr_port.get_width(), 0); - for (const size_t& addr_bit : all_zero_addr) { - fp << addr_bit; - } - fp << ", "; - fp << generate_verilog_constant_values(initial_din_values); - fp << ");" << std::endl; - */ - - /* Raise the flag of configuration done when bitstream loading is complete */ - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1); - fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; - - BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); - fp << "\t\t\t"; - fp << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); - fp << " <= "; - std::vector config_done_enable_values(config_done_port.get_width(), 1); - fp << generate_verilog_constant_values(config_done_enable_values); - fp << ";" << std::endl; - - fp << "\tend" << std::endl; - print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); -} - -/******************************************************************** - * Generate the stimuli for the top-level testbench - * The simulation consists of two phases: configuration phase and operation phase - * Configuration bits are loaded serially. - * This is actually what we do for a physical FPGA - *******************************************************************/ -static -void print_verilog_top_testbench_bitstream(std::fstream& fp, - const e_config_protocol_type& config_protocol_type, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { - - /* Branch on the type of configuration protocol */ - switch (config_protocol_type) { - case CONFIG_MEM_STANDALONE: - print_verilog_top_testbench_vanilla_bitstream(fp, - module_manager, top_module, - bitstream_manager, fabric_bitstream); - break; - case CONFIG_MEM_SCAN_CHAIN: - print_verilog_top_testbench_configuration_chain_bitstream(fp, fast_configuration, - bit_value_to_skip, - module_manager, top_module, - bitstream_manager, fabric_bitstream); - break; - case CONFIG_MEM_MEMORY_BANK: - print_verilog_top_testbench_memory_bank_bitstream(fp, fast_configuration, - bit_value_to_skip, - module_manager, top_module, - fabric_bitstream); - break; - case CONFIG_MEM_FRAME_BASED: - print_verilog_top_testbench_frame_decoder_bitstream(fp, fast_configuration, - bit_value_to_skip, - module_manager, top_module, - fabric_bitstream); - break; - default: - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Invalid SRAM organization type!\n"); - exit(1); - } -} - /******************************************************************** * Print stimulus for a FPGA fabric with a flatten memory (standalone) configuration protocol * We will load the bitstream in the second clock cycle, right after the first reset cycle @@ -2534,263 +1840,6 @@ void print_verilog_top_testbench_check(std::fstream& fp, fp << std::endl; } -/******************************************************************** - * TODO: This top function will be deprecated!!! The only top function is - * print_verilog_full_testbench() - * The top-level function to generate a testbench, in order to verify: - * 1. Configuration phase of the FPGA fabric, where the bitstream is - * loaded to the configuration protocol of the FPGA fabric - * 2. Operating phase of the FPGA fabric, where input stimuli are - * fed to the I/Os of the FPGA fabric - * +----------+ - * | FPGA | +------------+ - * +----->| Fabric |------>| | - * | | | | | - * | +----------+ | | - * | | Output | - * random_input_vectors -----+ | Vector |---->Functional correct? - * | | Comparator | - * | +-----------+ | | - * | | Input | | | - * +----->| Benchmark |----->| | - * +-----------+ +------------+ - * - *******************************************************************/ -void print_verilog_top_testbench(const ModuleManager& module_manager, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const FabricGlobalPortInfo& global_ports, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const PinConstraints& pin_constraints, - const IoLocationMap& io_location_map, - const VprNetlistAnnotation& netlist_annotation, - const std::string& circuit_name, - const std::string& verilog_fname, - const SimulationSetting& simulation_parameters, - const VerilogTestbenchOption& options) { - - bool fast_configuration = options.fast_configuration(); - bool explicit_port_mapping = options.explicit_port_mapping(); - - std::string timer_message = std::string("Write autocheck testbench for FPGA top-level Verilog netlist for '") + circuit_name + std::string("'"); - - /* 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("FPGA Verilog Testbench for Top-level netlist of Design: ") + circuit_name; - print_verilog_file_header(fp, title); - - /* Find the top_module */ - ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); - VTR_ASSERT(true == module_manager.valid_module_id(top_module)); - - /* Preparation: find all the clock ports */ - std::vector clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); - - /* Preparation: find all the reset/set ports for programming usage */ - std::vector global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports); - std::vector global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports); - - /* Identify if we can apply fast configuration */ - bool apply_fast_configuration = fast_configuration && is_fast_configuration_applicable(global_ports); - bool bit_value_to_skip = false; - if (true == apply_fast_configuration) { - bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(), - global_ports, - bitstream_manager, - fabric_bitstream); - } - - /* Start of testbench */ - print_verilog_top_testbench_ports(fp, module_manager, top_module, - atom_ctx, netlist_annotation, - clock_port_names, - pin_constraints, - simulation_parameters, config_protocol, - circuit_name); - - /* Find the clock period */ - float prog_clock_period = (1./simulation_parameters.programming_clock_frequency()); - float default_op_clock_period = (1./simulation_parameters.default_operating_clock_frequency()); - float max_op_clock_period = 0.; - for (const SimulationClockId& clock_id : simulation_parameters.clocks()) { - max_op_clock_period = std::max(max_op_clock_period, (float)(1./simulation_parameters.clock_frequency(clock_id))); - } - - /* Estimate the number of configuration clock cycles */ - size_t num_config_clock_cycles = calculate_num_config_clock_cycles(config_protocol.type(), - apply_fast_configuration, - bit_value_to_skip, - bitstream_manager, - fabric_bitstream); - - /* Generate stimuli for general control signals */ - print_verilog_top_testbench_generic_stimulus(fp, - simulation_parameters, - num_config_clock_cycles, - prog_clock_period, - default_op_clock_period, - VERILOG_SIM_TIMESCALE); - - /* Generate stimuli for programming interface */ - print_verilog_top_testbench_configuration_protocol_stimulus(fp, - config_protocol.type(), - module_manager, top_module, - prog_clock_period, - VERILOG_SIM_TIMESCALE); - - /* Identify the stimulus for global reset/set for programming purpose: - * - If only reset port is seen we turn on Reset - * - If only set port is seen we turn on Reset - * - If both reset and set port is defined, - * we pick the one which is consistent with the bit value to be skipped - */ - bool active_global_prog_reset = false; - bool active_global_prog_set = false; - - if (!global_prog_reset_ports.empty()) { - active_global_prog_reset = true; - } - - if (!global_prog_set_ports.empty()) { - active_global_prog_set = true; - } - - /* Ensure that at most only one of the two switches is activated */ - if ( (true == active_global_prog_reset) - && (true == active_global_prog_set) ) { - /* If we will skip logic '0', we will activate programming reset */ - active_global_prog_reset = !bit_value_to_skip; - /* If we will skip logic '1', we will activate programming set */ - active_global_prog_set = bit_value_to_skip; - } - - /* Generate stimuli for global ports or connect them to existed signals */ - print_verilog_top_testbench_global_ports_stimuli(fp, - module_manager, top_module, - pin_constraints, - global_ports, - simulation_parameters, - active_global_prog_reset, - active_global_prog_set); - - /* Instanciate FPGA top-level module */ - print_verilog_testbench_fpga_instance(fp, module_manager, top_module, - std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), - explicit_port_mapping); - - /* Connect I/Os to benchmark I/Os or constant driver */ - print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module, - atom_ctx, place_ctx, io_location_map, - netlist_annotation, - std::string(), - std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), - (size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE); - - /* Instanciate input benchmark */ - print_verilog_top_testbench_benchmark_instance(fp, - circuit_name, - atom_ctx, - netlist_annotation, - explicit_port_mapping); - - /* Print tasks used for loading bitstreams */ - print_verilog_top_testbench_load_bitstream_task(fp, - config_protocol.type(), - module_manager, top_module); - - /* load bitstream to FPGA fabric in a configuration phase */ - print_verilog_top_testbench_bitstream(fp, config_protocol.type(), - apply_fast_configuration, - bit_value_to_skip, - module_manager, top_module, - bitstream_manager, fabric_bitstream); - - /* Add signal initialization: - * Bypass writing codes to files due to the autogenerated codes are very large. - */ - if (true == options.include_signal_init()) { - print_verilog_testbench_signal_initialization(fp, - std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), - circuit_lib, - module_manager, - top_module); - } - - - /* Add stimuli for reset, set, clock and iopad signals */ - print_verilog_top_testbench_reset_stimuli(fp, - atom_ctx, - netlist_annotation, - module_manager, - global_ports, - pin_constraints, - clock_port_names); - print_verilog_testbench_random_stimuli(fp, atom_ctx, - netlist_annotation, - module_manager, - global_ports, - pin_constraints, - clock_port_names, - std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), - std::vector(1, BasicPort(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1))); - - /* Add output autocheck */ - print_verilog_testbench_check(fp, - std::string(AUTOCHECKED_SIMULATION_FLAG), - std::string(TOP_TESTBENCH_SIM_START_PORT_NAME), - std::string(TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX), - std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), - std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), - std::string(TOP_TESTBENCH_ERROR_COUNTER), - atom_ctx, - netlist_annotation, - clock_port_names, - std::string(TOP_TB_OP_CLOCK_PORT_NAME)); - - /* Add autocheck for configuration phase */ - print_verilog_top_testbench_check(fp, - std::string(AUTOCHECKED_SIMULATION_FLAG), - std::string(TOP_TB_CONFIG_DONE_PORT_NAME), - std::string(TOP_TESTBENCH_ERROR_COUNTER)); - - /* Find simulation time */ - float simulation_time = find_simulation_time_period(VERILOG_SIM_TIMESCALE, - num_config_clock_cycles, - 1./simulation_parameters.programming_clock_frequency(), - simulation_parameters.num_clock_cycles(), - 1./simulation_parameters.default_operating_clock_frequency()); - - - /* Add Icarus requirement: - * Always ceil the simulation time so that we test a sufficient length of period!!! - */ - print_verilog_timeout_and_vcd(fp, - std::string(circuit_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX)), - std::string(circuit_name + std::string("_formal.vcd")), - std::string(TOP_TESTBENCH_SIM_START_PORT_NAME), - std::string(TOP_TESTBENCH_ERROR_COUNTER), - std::ceil(simulation_time)); - - - /* Testbench ends*/ - print_verilog_module_end(fp, std::string(circuit_name) + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX)); - - /* Close the file stream */ - fp.close(); -} - /******************************************************************** * The top-level function to generate a full testbench, in order to verify: * 1. Configuration phase of the FPGA fabric, where the bitstream is diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.h b/openfpga/src/fpga_verilog/verilog_top_testbench.h index 1704d0dd5..aff108d72 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.h @@ -26,22 +26,6 @@ /* begin namespace openfpga */ namespace openfpga { -void print_verilog_top_testbench(const ModuleManager& module_manager, - const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol, - const FabricGlobalPortInfo& global_ports, - const AtomContext& atom_ctx, - const PlacementContext& place_ctx, - const PinConstraints& pin_constraints, - const IoLocationMap& io_location_map, - const VprNetlistAnnotation& netlist_annotation, - const std::string& circuit_name, - const std::string& verilog_fname, - const SimulationSetting& simulation_parameters, - const VerilogTestbenchOption& options); - int print_verilog_full_testbench(const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream,