[Tool] Add signal initialization to Verilog testbench generator and remove it from fabric netlists
This commit is contained in:
parent
655da9f3d0
commit
3b2a4c5387
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue