[Tool] Add signal initialization to Verilog testbench generator and remove it from fabric netlists

This commit is contained in:
tangxifan 2020-11-22 20:25:03 -07:00
parent 655da9f3d0
commit 3b2a4c5387
9 changed files with 161 additions and 47 deletions

View File

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

View File

@ -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));
}

View File

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

View File

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

View File

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

View File

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

View File

@ -8,6 +8,7 @@
#include <string>
#include <vector>
#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

View File

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

View File

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