From 3b2a4c5387a57c8a2f919e3a9a0867a627f8fe97 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 22 Nov 2020 20:25:03 -0700 Subject: [PATCH] [Tool] Add signal initialization to Verilog testbench generator and remove it from fabric netlists --- openfpga/src/fpga_verilog/verilog_api.cpp | 1 + .../fpga_verilog/verilog_essential_gates.cpp | 6 - .../verilog_preconfig_top_module.cpp | 7 + .../fpga_verilog/verilog_submodule_utils.cpp | 37 ----- .../fpga_verilog/verilog_submodule_utils.h | 4 - .../fpga_verilog/verilog_testbench_utils.cpp | 136 ++++++++++++++++++ .../fpga_verilog/verilog_testbench_utils.h | 7 + .../fpga_verilog/verilog_top_testbench.cpp | 8 ++ .../src/fpga_verilog/verilog_top_testbench.h | 2 + 9 files changed, 161 insertions(+), 47 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index e012c32e6..623f141f1 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -202,6 +202,7 @@ void fpga_verilog_testbench(const ModuleManager &module_manager, 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, io_location_map, diff --git a/openfpga/src/fpga_verilog/verilog_essential_gates.cpp b/openfpga/src/fpga_verilog/verilog_essential_gates.cpp index 3fbcb5d45..9b4a356f4 100644 --- a/openfpga/src/fpga_verilog/verilog_essential_gates.cpp +++ b/openfpga/src/fpga_verilog/verilog_essential_gates.cpp @@ -195,9 +195,6 @@ void print_verilog_invbuf_module(const ModuleManager& module_manager, /* Print timing info */ print_verilog_submodule_timing(fp, circuit_lib, circuit_model); - /* Print signal initialization */ - print_verilog_submodule_signal_init(fp, circuit_lib, circuit_model); - /* Put an end to the Verilog module */ print_verilog_module_end(fp, circuit_lib.model_name(circuit_model)); } @@ -271,9 +268,6 @@ void print_verilog_passgate_module(const ModuleManager& module_manager, /* Print timing info */ print_verilog_submodule_timing(fp, circuit_lib, circuit_model); - /* Print signal initialization */ - print_verilog_submodule_signal_init(fp, circuit_lib, circuit_model); - /* Put an end to the Verilog module */ print_verilog_module_end(fp, circuit_lib.model_name(circuit_model)); } diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index 033fcc346..667463d53 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -470,6 +470,13 @@ namespace openfpga circuit_lib, sram_model, bitstream_manager); + /* Add signal initialization */ + print_verilog_testbench_signal_initialization(fp, + std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME), + circuit_lib, + module_manager, + top_module); + /* Testbench ends*/ print_verilog_module_end(fp, std::string(circuit_name) + std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX)); diff --git a/openfpga/src/fpga_verilog/verilog_submodule_utils.cpp b/openfpga/src/fpga_verilog/verilog_submodule_utils.cpp index faf965068..37009c930 100644 --- a/openfpga/src/fpga_verilog/verilog_submodule_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_submodule_utils.cpp @@ -88,43 +88,6 @@ void print_verilog_submodule_timing(std::fstream& fp, } -void print_verilog_submodule_signal_init(std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model) { - /* Ensure a valid file handler*/ - VTR_ASSERT(true == valid_file_stream(fp)); - - fp << std::endl; - fp << "`ifdef " << VERILOG_SIGNAL_INIT_PREPROC_FLAG << std::endl; - print_verilog_comment(fp, std::string("------ BEGIN driver initialization -----")); - fp << "\tinitial begin" << std::endl; - fp << "\t`ifdef " << VERILOG_FORMAL_VERIFICATION_PREPROC_FLAG << std::endl; - - /* Only for formal verification: deposite a zero signal values */ - /* Initialize each input port */ - for (const auto& input_port : circuit_lib.model_input_ports(circuit_model)) { - BasicPort input_port_info(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port)); - fp << "\t\t$deposit("; - fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info); - fp << ", " << circuit_lib.port_size(input_port) << "'b" << std::string(circuit_lib.port_size(input_port), '0'); - fp << ");" << std::endl; - } - fp << "\t`else" << std::endl; - - /* Regular case: deposite initial signal values: a random value */ - for (const auto& input_port : circuit_lib.model_input_ports(circuit_model)) { - BasicPort input_port_info(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port)); - fp << "\t\t$deposit("; - fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info); - fp << ", $random);" << std::endl; - } - - fp << "\t`endif\n" << std::endl; - fp << "\tend" << std::endl; - print_verilog_comment(fp, std::string("------ END driver initialization -----")); - fp << "`endif" << std::endl; -} - /********************************************************************* * Register all the user-defined modules in the module manager * Walk through the circuit library and add user-defined circuit models diff --git a/openfpga/src/fpga_verilog/verilog_submodule_utils.h b/openfpga/src/fpga_verilog/verilog_submodule_utils.h index 3f0e1dadd..51347de35 100644 --- a/openfpga/src/fpga_verilog/verilog_submodule_utils.h +++ b/openfpga/src/fpga_verilog/verilog_submodule_utils.h @@ -20,10 +20,6 @@ void print_verilog_submodule_timing(std::fstream& fp, const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); -void print_verilog_submodule_signal_init(std::fstream& fp, - const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model); - void add_user_defined_verilog_modules(ModuleManager& module_manager, const CircuitLibrary& circuit_lib); diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp index 6f08a1c85..d8d09bb38 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp @@ -16,6 +16,8 @@ #include "openfpga_port.h" #include "openfpga_digest.h" +#include "openfpga_naming.h" + #include "verilog_port_types.h" #include "module_manager_utils.h" @@ -732,4 +734,138 @@ void print_verilog_testbench_shared_ports(std::fstream& fp, fp << std::endl; } +/******************************************************************** + * Print signal initialization which + * deposit initial values for the input ports of primitive circuit models + * This function recusively walk through from the parent_module + * until reaching a primitive module that matches the circuit_model name + * The hierarchy walkthrough collects the full paths for the primitive modules + * in the graph of modules + *******************************************************************/ +static +void rec_print_verilog_testbench_primitive_module_signal_initialization(std::fstream& fp, + const std::string& hie_path, + const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model, + const ModuleManager& module_manager, + const ModuleId& parent_module, + const ModuleId& primitive_module) { + /* Validate the file stream */ + valid_file_stream(fp); + + /* Return if the current module has no children */ + if (0 == module_manager.child_modules(parent_module).size()) { + return; + } + + /* Go through child modules */ + for (const ModuleId& child_module : module_manager.child_modules(parent_module)) { + /* If the child module is not the primitive module, + * we recursively visit the child module + */ + for (const size_t& child_instance : module_manager.child_module_instances(parent_module, child_module)) { + std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); + /* Use default instanec name if not assigned */ + if (true == instance_name.empty()) { + instance_name = generate_instance_name(module_manager.module_name(child_module), child_instance); + } + + std::string child_hie_path = hie_path + "." + instance_name; + + if (child_module != primitive_module) { + rec_print_verilog_testbench_primitive_module_signal_initialization(fp, + child_hie_path, + circuit_lib, circuit_model, + module_manager, child_module, + primitive_module); + } else { + /* If the child module is the primitive module, + * we output the signal initialization codes for the input ports + */ + VTR_ASSERT_SAFE(child_module == primitive_module); + + print_verilog_comment(fp, std::string("------ BEGIN driver initialization -----")); + fp << "\tinitial begin" << std::endl; + fp << "\t`ifdef " << VERILOG_FORMAL_VERIFICATION_PREPROC_FLAG << std::endl; + + for (const auto& input_port : circuit_lib.model_input_ports(circuit_model)) { + /* Only for formal verification: deposite a zero signal values */ + /* Initialize each input port */ + BasicPort input_port_info(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port)); + fp << "\t\t$deposit("; + fp << child_hie_path << "."; + fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info); + fp << ", " << circuit_lib.port_size(input_port) << "'b" << std::string(circuit_lib.port_size(input_port), '0'); + fp << ");" << std::endl; + } + fp << "\t`else" << std::endl; + + /* Regular case: deposite initial signal values: a random value */ + for (const auto& input_port : circuit_lib.model_input_ports(circuit_model)) { + BasicPort input_port_info(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port)); + fp << "\t\t$deposit("; + fp << child_hie_path << "."; + fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info); + fp << ", $random);" << std::endl; + } + + fp << "\t`endif\n" << std::endl; + fp << "\tend" << std::endl; + print_verilog_comment(fp, std::string("------ END driver initialization -----")); + } + } + } +} + +/******************************************************************** + * Print signal initialization for Verilog testbenches + * which aim to deposit initial values for the input ports of primitive circuit models: + * - Passgate + * - Logic gates (ONLY for MUX2) + *******************************************************************/ +void print_verilog_testbench_signal_initialization(std::fstream& fp, + const std::string& top_instance_name, + const CircuitLibrary& circuit_lib, + const ModuleManager& module_manager, + const ModuleId& top_module) { + /* Validate the file stream */ + valid_file_stream(fp); + + /* Collect circuit models that need signal initialization */ + std::vector signal_init_circuit_models; + + for (const CircuitModelId& model : circuit_lib.models_by_type(CIRCUIT_MODEL_PASSGATE)) { + signal_init_circuit_models.push_back(model); + } + + for (const CircuitModelId& model : circuit_lib.models_by_type(CIRCUIT_MODEL_GATE)) { + if (CIRCUIT_MODEL_GATE_MUX2 == circuit_lib.gate_type(model)) { + signal_init_circuit_models.push_back(model); + } + } + + /* If there is no circuit model in the list, return directly */ + if (signal_init_circuit_models.empty()) { + return; + } + + /* Add signal initialization Verilog codes */ + fp << std::endl; + fp << "`ifdef " << VERILOG_SIGNAL_INIT_PREPROC_FLAG << std::endl; + for (const CircuitModelId& signal_init_circuit_model : signal_init_circuit_models) { + /* Find the module id corresponding to the circuit model from module graph */ + ModuleId primitive_module = module_manager.find_module(circuit_lib.model_name(signal_init_circuit_model)); + VTR_ASSERT(true == module_manager.valid_module_id(primitive_module)); + + /* Find all the instances created by the circuit model across the fabric*/ + rec_print_verilog_testbench_primitive_module_signal_initialization(fp, + top_instance_name, + circuit_lib, signal_init_circuit_model, + module_manager, top_module, + primitive_module); + } + + fp << "`endif" << std::endl; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.h b/openfpga/src/fpga_verilog/verilog_testbench_utils.h index 9ba67f298..9a6fbeb17 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.h +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.h @@ -8,6 +8,7 @@ #include #include #include "module_manager.h" +#include "circuit_library.h" #include "vpr_context.h" #include "io_location_map.h" #include "vpr_netlist_annotation.h" @@ -94,6 +95,12 @@ void print_verilog_testbench_shared_ports(std::fstream& fp, const std::string& check_flag_port_postfix, const std::string& autocheck_preprocessing_flag); +void print_verilog_testbench_signal_initialization(std::fstream& fp, + const std::string& top_instance_name, + const CircuitLibrary& circuit_lib, + const ModuleManager& module_manager, + const ModuleId& top_module); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index dbcb737e0..21e8de9d6 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1769,6 +1769,7 @@ void print_verilog_top_testbench_check(std::fstream& fp, 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, @@ -1916,6 +1917,13 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, module_manager, top_module, bitstream_manager, fabric_bitstream); + /* Add signal initialization */ + 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_testbench_random_stimuli(fp, atom_ctx, netlist_annotation, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.h b/openfpga/src/fpga_verilog/verilog_top_testbench.h index 6aeb5578b..1a657c526 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.h @@ -9,6 +9,7 @@ #include "module_manager.h" #include "bitstream_manager.h" #include "fabric_bitstream.h" +#include "circuit_library.h" #include "config_protocol.h" #include "vpr_context.h" #include "io_location_map.h" @@ -26,6 +27,7 @@ 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,