refactoring auto-check top Verilog testbench
This commit is contained in:
parent
dc241e6c03
commit
0ec465d4e1
|
@ -22,11 +22,12 @@ arch1=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_til
|
||||||
[BENCHMARKS]
|
[BENCHMARKS]
|
||||||
# Pass
|
# Pass
|
||||||
#bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/alu4/alu4.blif
|
#bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/alu4/alu4.blif
|
||||||
# Fail, due to port does not match, i_15_ is dangling
|
# Pass, but port does not match, i_15_ is dangling
|
||||||
#bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.blif
|
#bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.blif
|
||||||
# To be tested
|
# Pass
|
||||||
#bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/apex4/apex4.blif
|
#bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/apex4/apex4.blif
|
||||||
#bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/bigkey/bigkey.blif
|
bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/bigkey/bigkey.blif
|
||||||
|
# To be tested
|
||||||
#bench4=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/clma/clma.blif
|
#bench4=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/clma/clma.blif
|
||||||
#bench5=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/des/des.blif
|
#bench5=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/des/des.blif
|
||||||
#bench6=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/diffeq/diffeq.blif
|
#bench6=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/diffeq/diffeq.blif
|
||||||
|
|
|
@ -152,14 +152,10 @@ void vpr_fpga_verilog(ModuleManager& module_manager,
|
||||||
char* fm_dir_path = NULL;
|
char* fm_dir_path = NULL;
|
||||||
char* top_netlist_file = NULL;
|
char* top_netlist_file = NULL;
|
||||||
char* top_netlist_path = NULL;
|
char* top_netlist_path = NULL;
|
||||||
char* top_testbench_file_name = NULL;
|
|
||||||
char* top_testbench_file_path = NULL;
|
|
||||||
char* blif_testbench_file_name = NULL;
|
char* blif_testbench_file_name = NULL;
|
||||||
char* blif_testbench_file_path = NULL;
|
char* blif_testbench_file_path = NULL;
|
||||||
char* bitstream_file_name = NULL;
|
char* bitstream_file_name = NULL;
|
||||||
char* bitstream_file_path = NULL;
|
char* bitstream_file_path = NULL;
|
||||||
char* autocheck_top_testbench_file_name = NULL;
|
|
||||||
char* autocheck_top_testbench_file_path = NULL;
|
|
||||||
|
|
||||||
char* chomped_parent_dir = NULL;
|
char* chomped_parent_dir = NULL;
|
||||||
char* chomped_circuit_name = NULL;
|
char* chomped_circuit_name = NULL;
|
||||||
|
@ -390,19 +386,31 @@ void vpr_fpga_verilog(ModuleManager& module_manager,
|
||||||
my_free(bitstream_file_path);
|
my_free(bitstream_file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dump verilog testbench only for top-level: ONLY valid when bitstream is generated! */
|
/* Collect global ports from the circuit library
|
||||||
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_testbench) {
|
* TODO: move outside this function
|
||||||
top_testbench_file_name = my_strcat(chomped_circuit_name, top_testbench_verilog_file_postfix);
|
*/
|
||||||
top_testbench_file_path = my_strcat(src_dir_path, top_testbench_file_name);
|
|
||||||
dump_verilog_top_testbench(sram_verilog_orgz_info, chomped_circuit_name, top_testbench_file_path,
|
|
||||||
src_dir_path, *(Arch.spice));
|
|
||||||
/* Free */
|
|
||||||
my_free(top_testbench_file_name);
|
|
||||||
my_free(top_testbench_file_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<CircuitPortId> global_ports = find_circuit_library_global_ports(Arch.spice->circuit_lib);
|
std::vector<CircuitPortId> global_ports = find_circuit_library_global_ports(Arch.spice->circuit_lib);
|
||||||
|
|
||||||
|
/* dump verilog testbench only for top-level: ONLY valid when bitstream is generated! */
|
||||||
|
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_testbench) {
|
||||||
|
std::string top_testbench_file_path = std::string(src_dir_path)
|
||||||
|
+ std::string(chomped_circuit_name)
|
||||||
|
+ std::string(top_testbench_verilog_file_postfix);
|
||||||
|
/* TODO: this is an old function, to be shadowed */
|
||||||
|
dump_verilog_top_testbench(sram_verilog_orgz_info, chomped_circuit_name, top_testbench_file_path.c_str(),
|
||||||
|
src_dir_path, *(Arch.spice));
|
||||||
|
/* TODO: new function: to be tested */
|
||||||
|
print_verilog_top_testbench(module_manager, bitstream_manager, fabric_bitstream,
|
||||||
|
sram_verilog_orgz_info->type,
|
||||||
|
Arch.spice->circuit_lib, global_ports,
|
||||||
|
L_logical_blocks, device_size, L_grids, L_blocks,
|
||||||
|
std::string(chomped_circuit_name),
|
||||||
|
std::string(top_testbench_file_path + std::string(".bak")),
|
||||||
|
std::string(src_dir_path),
|
||||||
|
std::string(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.reference_verilog_benchmark_file),
|
||||||
|
Arch.spice->spice_params);
|
||||||
|
}
|
||||||
|
|
||||||
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_formal_verification_top_netlist) {
|
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_formal_verification_top_netlist) {
|
||||||
std::string formal_verification_top_netlist_file_path = std::string(src_dir_path)
|
std::string formal_verification_top_netlist_file_path = std::string(src_dir_path)
|
||||||
+ std::string(chomped_circuit_name)
|
+ std::string(chomped_circuit_name)
|
||||||
|
@ -446,10 +454,12 @@ void vpr_fpga_verilog(ModuleManager& module_manager,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_autocheck_top_testbench) {
|
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_autocheck_top_testbench) {
|
||||||
autocheck_top_testbench_file_name = my_strcat(chomped_circuit_name, autocheck_top_testbench_verilog_file_postfix);
|
std::string autocheck_top_testbench_file_path = std::string(src_dir_path)
|
||||||
autocheck_top_testbench_file_path = my_strcat(src_dir_path, autocheck_top_testbench_file_name);
|
+ std::string(chomped_circuit_name)
|
||||||
|
+ std::string(autocheck_top_testbench_verilog_file_postfix);
|
||||||
|
/* TODO: this is an old function, to be shadowed */
|
||||||
dump_verilog_autocheck_top_testbench(sram_verilog_orgz_info, chomped_circuit_name,
|
dump_verilog_autocheck_top_testbench(sram_verilog_orgz_info, chomped_circuit_name,
|
||||||
autocheck_top_testbench_file_path, src_dir_path,
|
autocheck_top_testbench_file_path.c_str(), src_dir_path,
|
||||||
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, *(Arch.spice));
|
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, *(Arch.spice));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -348,7 +348,7 @@ void dump_verilog_top_auto_testbench_check(FILE* fp){
|
||||||
|
|
||||||
void dump_verilog_autocheck_top_testbench(t_sram_orgz_info* cur_sram_orgz_info,
|
void dump_verilog_autocheck_top_testbench(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
char* circuit_name,
|
char* circuit_name,
|
||||||
char* top_netlist_name,
|
const char* top_netlist_name,
|
||||||
char* verilog_dir_path,
|
char* verilog_dir_path,
|
||||||
t_syn_verilog_opts fpga_verilog_opts,
|
t_syn_verilog_opts fpga_verilog_opts,
|
||||||
t_spice verilog) {
|
t_spice verilog) {
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
/********************************************************************
|
|
||||||
* This file includes functions that are used to create
|
|
||||||
* an auto-check top-level testbench for a FPGA fabric
|
|
||||||
*******************************************************************/
|
|
||||||
#include <ctime>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include "vtr_assert.h"
|
|
||||||
|
|
||||||
#include "fpga_x2p_utils.h"
|
|
||||||
|
|
||||||
#include "verilog_writer_utils.h"
|
|
||||||
|
|
||||||
#include "verilog_autocheck_top_testbench.h"
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
* 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
|
|
||||||
*******************************************************************/
|
|
||||||
void print_verilog_autocheck_top_testbench(const ModuleManager& module_manager,
|
|
||||||
const BitstreamManager& bitstream_manager,
|
|
||||||
const CircuitLibrary& circuit_lib,
|
|
||||||
const std::vector<CircuitPortId>& global_ports,
|
|
||||||
const std::vector<t_logical_block>& L_logical_blocks,
|
|
||||||
const vtr::Point<size_t>& device_size,
|
|
||||||
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
|
||||||
const std::vector<t_block>& L_blocks,
|
|
||||||
const std::string& circuit_name,
|
|
||||||
const std::string& verilog_fname,
|
|
||||||
const std::string& verilog_dir,
|
|
||||||
const t_syn_verilog_opts& fpga_verilog_opts,
|
|
||||||
const t_spice_params& simulation_parameters) {
|
|
||||||
vpr_printf(TIO_MESSAGE_INFO,
|
|
||||||
"Writing Autocheck Testbench for FPGA Top-level Verilog netlist for %s...",
|
|
||||||
circuit_name.c_str());
|
|
||||||
|
|
||||||
/* Start time count */
|
|
||||||
clock_t t_start = clock();
|
|
||||||
|
|
||||||
/* Create the file stream */
|
|
||||||
std::fstream fp;
|
|
||||||
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
|
|
||||||
|
|
||||||
/* Validate the file stream */
|
|
||||||
check_file_handler(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);
|
|
||||||
|
|
||||||
/* Print preprocessing flags and external netlists */
|
|
||||||
print_verilog_include_defines_preproc_file(fp, verilog_dir);
|
|
||||||
|
|
||||||
/* Start of testbench */
|
|
||||||
//dump_verilog_top_auto_testbench_ports(fp, cur_sram_orgz_info, circuit_name, fpga_verilog_opts);
|
|
||||||
|
|
||||||
/* Call defined top-level module */
|
|
||||||
//dump_verilog_top_testbench_call_top_module(cur_sram_orgz_info, fp,
|
|
||||||
// circuit_name, is_explicit_mapping);
|
|
||||||
|
|
||||||
/* Call defined benchmark */
|
|
||||||
//dump_verilog_top_auto_testbench_call_benchmark(fp, circuit_name);
|
|
||||||
|
|
||||||
/* Add stimuli for reset, set, clock and iopad signals */
|
|
||||||
//dump_verilog_top_testbench_stimuli(cur_sram_orgz_info, fp, verilog);
|
|
||||||
|
|
||||||
/* Add output autocheck */
|
|
||||||
//dump_verilog_top_auto_testbench_check(fp);
|
|
||||||
|
|
||||||
/* Add Icarus requirement */
|
|
||||||
//dump_verilog_timeout_and_vcd(fp, circuit_name , verilog, cur_sram_orgz_info);
|
|
||||||
|
|
||||||
/* Testbench ends*/
|
|
||||||
//fprintf(fp, "endmodule\n");
|
|
||||||
|
|
||||||
/* Close the file stream */
|
|
||||||
fp.close();
|
|
||||||
|
|
||||||
/* End time count */
|
|
||||||
clock_t t_end = clock();
|
|
||||||
|
|
||||||
float run_time_sec = (float)(t_end - t_start) / CLOCKS_PER_SEC;
|
|
||||||
vpr_printf(TIO_MESSAGE_INFO,
|
|
||||||
"took %g seconds\n",
|
|
||||||
run_time_sec);
|
|
||||||
}
|
|
|
@ -1,33 +1,12 @@
|
||||||
#ifndef VERILOG_AUTOCHECK_TOP_TESTBENCH_H
|
#ifndef VERILOG_AUTOCHECK_TOP_TESTBENCH_H
|
||||||
#define VERILOG_AUTOCHECK_TOP_TESTBENCH_H
|
#define VERILOG_AUTOCHECK_TOP_TESTBENCH_H
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include "module_manager.h"
|
|
||||||
#include "bitstream_manager.h"
|
|
||||||
#include "circuit_library.h"
|
|
||||||
|
|
||||||
void dump_verilog_autocheck_top_testbench(t_sram_orgz_info* cur_sram_orgz_info,
|
void dump_verilog_autocheck_top_testbench(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
char* circuit_name,
|
char* circuit_name,
|
||||||
char* top_netlist_name,
|
const char* top_netlist_name,
|
||||||
char* verilog_dir_path,
|
char* verilog_dir_path,
|
||||||
t_syn_verilog_opts fpga_verilog_opts,
|
t_syn_verilog_opts fpga_verilog_opts,
|
||||||
t_spice verilog);
|
t_spice verilog);
|
||||||
|
|
||||||
/*
|
|
||||||
void print_verilog_autocheck_top_testbench(const ModuleManager& module_manager,
|
|
||||||
const BitstreamManager& bitstream_manager,
|
|
||||||
const CircuitLibrary& circuit_lib,
|
|
||||||
const std::vector<CircuitPortId>& global_ports,
|
|
||||||
const std::vector<t_logical_block>& L_logical_blocks,
|
|
||||||
const vtr::Point<size_t>& device_size,
|
|
||||||
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
|
||||||
const std::vector<t_block>& L_blocks,
|
|
||||||
const std::string& circuit_name,
|
|
||||||
const std::string& verilog_fname,
|
|
||||||
const std::string& verilog_dir,
|
|
||||||
const t_syn_verilog_opts& fpga_verilog_opts,
|
|
||||||
const t_spice_params& simulation_parameters);
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
/* Include FPGA Verilog headers*/
|
/* Include FPGA Verilog headers*/
|
||||||
#include "verilog_global.h"
|
#include "verilog_global.h"
|
||||||
#include "verilog_writer_utils.h"
|
#include "verilog_writer_utils.h"
|
||||||
|
#include "verilog_testbench_utils.h"
|
||||||
#include "verilog_formal_random_top_testbench.h"
|
#include "verilog_formal_random_top_testbench.h"
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
|
@ -175,61 +176,6 @@ void print_verilog_top_random_testbench_ports(std::fstream& fp,
|
||||||
fp << std::endl;
|
fp << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
* Instanciate the FPGA fabric module
|
|
||||||
*******************************************************************/
|
|
||||||
static
|
|
||||||
void print_verilog_random_testbench_instance(std::fstream& fp,
|
|
||||||
const std::string& module_name,
|
|
||||||
const std::string& instance_name,
|
|
||||||
const std::string& module_input_port_postfix,
|
|
||||||
const std::string& module_output_port_postfix,
|
|
||||||
const std::string& output_port_postfix,
|
|
||||||
const std::vector<t_logical_block>& L_logical_blocks,
|
|
||||||
const bool& use_explicit_port_map) {
|
|
||||||
|
|
||||||
/* Validate the file stream */
|
|
||||||
check_file_handler(fp);
|
|
||||||
|
|
||||||
fp << "\t" << module_name << " " << instance_name << "(" << std::endl;
|
|
||||||
|
|
||||||
size_t port_counter = 0;
|
|
||||||
for (const t_logical_block& lb : L_logical_blocks) {
|
|
||||||
/* Bypass non-I/O logical blocks ! */
|
|
||||||
if ( (VPACK_INPAD != lb.type) && (VPACK_OUTPAD != lb.type) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* The first port does not need a comma */
|
|
||||||
if(0 < port_counter){
|
|
||||||
fp << "," << std::endl;
|
|
||||||
}
|
|
||||||
/* Input port follows the logical block name while output port requires a special postfix */
|
|
||||||
if (VPACK_INPAD == lb.type){
|
|
||||||
fp << "\t\t";
|
|
||||||
if (true == use_explicit_port_map) {
|
|
||||||
fp << "." << std::string(lb.name) << module_input_port_postfix << "(";
|
|
||||||
}
|
|
||||||
fp << std::string(lb.name);
|
|
||||||
if (true == use_explicit_port_map) {
|
|
||||||
fp << ")";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
VTR_ASSERT_SAFE(VPACK_OUTPAD == lb.type);
|
|
||||||
fp << "\t\t";
|
|
||||||
if (true == use_explicit_port_map) {
|
|
||||||
fp << "." << std::string(lb.name) << module_output_port_postfix << "(";
|
|
||||||
}
|
|
||||||
fp << std::string(lb.name) << output_port_postfix;
|
|
||||||
if (true == use_explicit_port_map) {
|
|
||||||
fp << ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Update the counter */
|
|
||||||
port_counter++;
|
|
||||||
}
|
|
||||||
fp << "\t);" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Instanciate the input benchmark module
|
* Instanciate the input benchmark module
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
@ -248,12 +194,12 @@ void print_verilog_top_random_testbench_benchmark_instance(std::fstream& fp,
|
||||||
/* Do NOT use explicit port mapping here:
|
/* Do NOT use explicit port mapping here:
|
||||||
* VPR added a prefix of "out_" to the output ports of input benchmark
|
* VPR added a prefix of "out_" to the output ports of input benchmark
|
||||||
*/
|
*/
|
||||||
print_verilog_random_testbench_instance(fp, reference_verilog_top_name,
|
print_verilog_testbench_benchmark_instance(fp, reference_verilog_top_name,
|
||||||
std::string(BENCHMARK_INSTANCE_NAME),
|
std::string(BENCHMARK_INSTANCE_NAME),
|
||||||
std::string(),
|
std::string(),
|
||||||
std::string(),
|
std::string(),
|
||||||
std::string(BENCHMARK_PORT_POSTFIX), L_logical_blocks,
|
std::string(BENCHMARK_PORT_POSTFIX), L_logical_blocks,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- End reference Benchmark Instanication -------"));
|
print_verilog_comment(fp, std::string("----- End reference Benchmark Instanication -------"));
|
||||||
|
|
||||||
|
@ -411,12 +357,12 @@ void print_verilog_random_testbench_fpga_instance(std::fstream& fp,
|
||||||
print_verilog_comment(fp, std::string("----- FPGA fabric instanciation -------"));
|
print_verilog_comment(fp, std::string("----- FPGA fabric instanciation -------"));
|
||||||
|
|
||||||
/* Always use explicit port mapping */
|
/* Always use explicit port mapping */
|
||||||
print_verilog_random_testbench_instance(fp, std::string(circuit_name + std::string(formal_verification_top_postfix)),
|
print_verilog_testbench_benchmark_instance(fp, std::string(circuit_name + std::string(formal_verification_top_postfix)),
|
||||||
std::string(FPGA_INSTANCE_NAME),
|
std::string(FPGA_INSTANCE_NAME),
|
||||||
std::string(formal_verification_top_module_port_postfix),
|
std::string(formal_verification_top_module_port_postfix),
|
||||||
std::string(formal_verification_top_module_port_postfix),
|
std::string(formal_verification_top_module_port_postfix),
|
||||||
std::string(FPGA_PORT_POSTFIX), L_logical_blocks,
|
std::string(FPGA_PORT_POSTFIX), L_logical_blocks,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- End FPGA Fabric Instanication -------"));
|
print_verilog_comment(fp, std::string("----- End FPGA Fabric Instanication -------"));
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "verilog_global.h"
|
#include "verilog_global.h"
|
||||||
#include "verilog_writer_utils.h"
|
#include "verilog_writer_utils.h"
|
||||||
|
#include "verilog_testbench_utils.h"
|
||||||
#include "verilog_preconfig_top_module.h"
|
#include "verilog_preconfig_top_module.h"
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
|
@ -89,31 +90,6 @@ void print_verilog_preconfig_top_module_internal_wires(std::fstream& fp,
|
||||||
fp << std::endl;
|
fp << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
* Print an instance of the FPGA top-level module
|
|
||||||
*******************************************************************/
|
|
||||||
static
|
|
||||||
void print_verilog_preconfig_top_instance(std::fstream& fp,
|
|
||||||
const ModuleManager& module_manager,
|
|
||||||
const ModuleId& top_module) {
|
|
||||||
/* Validate the file stream */
|
|
||||||
check_file_handler(fp);
|
|
||||||
|
|
||||||
/* Include defined top-level module */
|
|
||||||
print_verilog_comment(fp, std::string("----- FPGA top-level module to be capsulated -----"));
|
|
||||||
|
|
||||||
/* Create an empty port-to-port name mapping, because we use default names */
|
|
||||||
std::map<std::string, BasicPort> port2port_name_map;
|
|
||||||
|
|
||||||
/* Use explicit port mapping for a clean instanciation */
|
|
||||||
print_verilog_module_instance(fp, module_manager, top_module,
|
|
||||||
std::string(formal_verification_top_module_uut_name),
|
|
||||||
port2port_name_map, true);
|
|
||||||
|
|
||||||
/* Add an empty line as a splitter */
|
|
||||||
fp << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Connect global ports of FPGA top module to constants except:
|
* Connect global ports of FPGA top module to constants except:
|
||||||
* 1. operating clock, which should be wired to the clock port of
|
* 1. operating clock, which should be wired to the clock port of
|
||||||
|
@ -180,90 +156,6 @@ void print_verilog_preconfig_top_module_connect_global_ports(std::fstream& fp,
|
||||||
fp << std::endl;
|
fp << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
* This function adds stimuli to I/Os of FPGA fabric
|
|
||||||
* 1. For mapped I/Os, this function will wire them to the input ports
|
|
||||||
* of the pre-configured FPGA top module
|
|
||||||
* 2. For unmapped I/Os, this function will assign a constant value
|
|
||||||
* by default
|
|
||||||
*******************************************************************/
|
|
||||||
static
|
|
||||||
void print_verilog_preconfig_top_module_connect_ios(std::fstream& fp,
|
|
||||||
const ModuleManager& module_manager,
|
|
||||||
const ModuleId& top_module,
|
|
||||||
const std::vector<t_logical_block>& L_logical_blocks,
|
|
||||||
const vtr::Point<size_t>& device_size,
|
|
||||||
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
|
||||||
const std::vector<t_block>& L_blocks) {
|
|
||||||
/* Validate the file stream */
|
|
||||||
check_file_handler(fp);
|
|
||||||
|
|
||||||
/* In this function, we support only 1 type of I/Os */
|
|
||||||
VTR_ASSERT(1 == module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPIO_PORT).size());
|
|
||||||
BasicPort module_io_port = module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPIO_PORT)[0];
|
|
||||||
|
|
||||||
/* Keep tracking which I/Os have been used */
|
|
||||||
std::vector<bool> io_used(module_io_port.get_width(), false);
|
|
||||||
|
|
||||||
/* See if this I/O should be wired to a benchmark input/output */
|
|
||||||
/* Add signals from blif benchmark and short-wire them to FPGA I/O PADs
|
|
||||||
* This brings convenience to checking functionality
|
|
||||||
*/
|
|
||||||
print_verilog_comment(fp, std::string("----- Link BLIF Benchmark I/Os to FPGA I/Os -----"));
|
|
||||||
for (const t_logical_block& io_lb : L_logical_blocks) {
|
|
||||||
/* We only care I/O logical blocks !*/
|
|
||||||
if ( (VPACK_INPAD != io_lb.type) && (VPACK_OUTPAD != io_lb.type) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the index of the mapped GPIO in top-level FPGA fabric */
|
|
||||||
size_t io_index = find_benchmark_io_index(io_lb, device_size, L_grids, L_blocks);
|
|
||||||
|
|
||||||
/* Ensure that IO index is in range */
|
|
||||||
BasicPort module_mapped_io_port = module_io_port;
|
|
||||||
/* Set the port pin index */
|
|
||||||
VTR_ASSERT(io_index < module_mapped_io_port.get_width());
|
|
||||||
module_mapped_io_port.set_width(io_index, io_index);
|
|
||||||
|
|
||||||
/* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always has a size of 1 */
|
|
||||||
BasicPort benchmark_io_port(std::string(std::string(io_lb.name)+ std::string(formal_verification_top_module_port_postfix)), 1);
|
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- Blif Benchmark inout " + std::string(io_lb.name) + " is mapped to FPGA IOPAD " + module_mapped_io_port.get_name() + "[" + std::to_string(io_index) + "] -----"));
|
|
||||||
if (VPACK_INPAD == io_lb.type) {
|
|
||||||
print_verilog_wire_connection(fp, module_mapped_io_port, benchmark_io_port, false);
|
|
||||||
} else {
|
|
||||||
VTR_ASSERT(VPACK_OUTPAD == io_lb.type);
|
|
||||||
print_verilog_wire_connection(fp, benchmark_io_port, module_mapped_io_port, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mark this I/O has been used/wired */
|
|
||||||
io_used[io_index] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add an empty line as a splitter */
|
|
||||||
fp << std::endl;
|
|
||||||
|
|
||||||
/* Wire the unused iopads to a constant */
|
|
||||||
print_verilog_comment(fp, std::string("----- Wire unused FPGA I/Os to constants -----"));
|
|
||||||
for (size_t io_index = 0; io_index < io_used.size(); ++io_index) {
|
|
||||||
/* Bypass used iopads */
|
|
||||||
if (true == io_used[io_index]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wire to a contant */
|
|
||||||
BasicPort module_unused_io_port = module_io_port;
|
|
||||||
/* Set the port pin index */
|
|
||||||
module_unused_io_port.set_width(io_index, io_index);
|
|
||||||
|
|
||||||
std::vector<size_t> default_values(module_unused_io_port.get_width(), verilog_default_signal_init_value);
|
|
||||||
print_verilog_wire_constant_values(fp, module_unused_io_port, default_values);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add an empty line as a splitter */
|
|
||||||
fp << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Impose the bitstream on the configuration memories
|
* Impose the bitstream on the configuration memories
|
||||||
* This function uses 'assign' syntax to impost the bitstream at mem port
|
* This function uses 'assign' syntax to impost the bitstream at mem port
|
||||||
|
@ -514,7 +406,8 @@ void print_verilog_preconfig_top_module(const ModuleManager& module_manager,
|
||||||
print_verilog_preconfig_top_module_internal_wires(fp, module_manager, top_module);
|
print_verilog_preconfig_top_module_internal_wires(fp, module_manager, top_module);
|
||||||
|
|
||||||
/* Instanciate FPGA top-level module */
|
/* Instanciate FPGA top-level module */
|
||||||
print_verilog_preconfig_top_instance(fp, module_manager, top_module);
|
print_verilog_testbench_fpga_instance(fp, module_manager, top_module,
|
||||||
|
std::string(formal_verification_top_module_uut_name));
|
||||||
|
|
||||||
/* Find clock ports in benchmark */
|
/* Find clock ports in benchmark */
|
||||||
std::vector<std::string> benchmark_clock_port_names = find_benchmark_clock_port_name(L_logical_blocks);
|
std::vector<std::string> benchmark_clock_port_names = find_benchmark_clock_port_name(L_logical_blocks);
|
||||||
|
@ -525,9 +418,11 @@ void print_verilog_preconfig_top_module(const ModuleManager& module_manager,
|
||||||
benchmark_clock_port_names);
|
benchmark_clock_port_names);
|
||||||
|
|
||||||
/* Connect I/Os to benchmark I/Os or constant driver */
|
/* Connect I/Os to benchmark I/Os or constant driver */
|
||||||
print_verilog_preconfig_top_module_connect_ios(fp, module_manager, top_module,
|
print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module,
|
||||||
L_logical_blocks, device_size, L_grids,
|
L_logical_blocks, device_size, L_grids,
|
||||||
L_blocks);
|
L_blocks,
|
||||||
|
std::string(formal_verification_top_module_port_postfix),
|
||||||
|
(size_t)verilog_default_signal_init_value);
|
||||||
|
|
||||||
/* Assign FPGA internal SRAM/Memory ports to bitstream values */
|
/* Assign FPGA internal SRAM/Memory ports to bitstream values */
|
||||||
print_verilog_preconfig_top_module_load_bitstream(fp, module_manager, top_module,
|
print_verilog_preconfig_top_module_load_bitstream(fp, module_manager, top_module,
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
/********************************************************************
|
||||||
|
* This file includes most utilized functions that are used to create
|
||||||
|
* Verilog testbenches
|
||||||
|
*
|
||||||
|
* Note: please do NOT use global variables in this file
|
||||||
|
* so that we can make it free to use anywhere
|
||||||
|
*******************************************************************/
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
#include "device_port.h"
|
||||||
|
|
||||||
|
#include "fpga_x2p_utils.h"
|
||||||
|
#include "fpga_x2p_benchmark_utils.h"
|
||||||
|
|
||||||
|
#include "verilog_writer_utils.h"
|
||||||
|
#include "verilog_testbench_utils.h"
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Print an instance of the FPGA top-level module
|
||||||
|
*******************************************************************/
|
||||||
|
void print_verilog_testbench_fpga_instance(std::fstream& fp,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module,
|
||||||
|
const std::string& top_instance_name) {
|
||||||
|
/* Validate the file stream */
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
/* Include defined top-level module */
|
||||||
|
print_verilog_comment(fp, std::string("----- FPGA top-level module to be capsulated -----"));
|
||||||
|
|
||||||
|
/* Create an empty port-to-port name mapping, because we use default names */
|
||||||
|
std::map<std::string, BasicPort> port2port_name_map;
|
||||||
|
|
||||||
|
/* Use explicit port mapping for a clean instanciation */
|
||||||
|
print_verilog_module_instance(fp, module_manager, top_module,
|
||||||
|
top_instance_name,
|
||||||
|
port2port_name_map, true);
|
||||||
|
|
||||||
|
/* Add an empty line as a splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Instanciate the input benchmark module
|
||||||
|
*******************************************************************/
|
||||||
|
void print_verilog_testbench_benchmark_instance(std::fstream& fp,
|
||||||
|
const std::string& module_name,
|
||||||
|
const std::string& instance_name,
|
||||||
|
const std::string& module_input_port_postfix,
|
||||||
|
const std::string& module_output_port_postfix,
|
||||||
|
const std::string& output_port_postfix,
|
||||||
|
const std::vector<t_logical_block>& L_logical_blocks,
|
||||||
|
const bool& use_explicit_port_map) {
|
||||||
|
/* Validate the file stream */
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
fp << "\t" << module_name << " " << instance_name << "(" << std::endl;
|
||||||
|
|
||||||
|
size_t port_counter = 0;
|
||||||
|
for (const t_logical_block& lb : L_logical_blocks) {
|
||||||
|
/* Bypass non-I/O logical blocks ! */
|
||||||
|
if ( (VPACK_INPAD != lb.type) && (VPACK_OUTPAD != lb.type) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* The first port does not need a comma */
|
||||||
|
if(0 < port_counter){
|
||||||
|
fp << "," << std::endl;
|
||||||
|
}
|
||||||
|
/* Input port follows the logical block name while output port requires a special postfix */
|
||||||
|
if (VPACK_INPAD == lb.type){
|
||||||
|
fp << "\t\t";
|
||||||
|
if (true == use_explicit_port_map) {
|
||||||
|
fp << "." << std::string(lb.name) << module_input_port_postfix << "(";
|
||||||
|
}
|
||||||
|
fp << std::string(lb.name);
|
||||||
|
if (true == use_explicit_port_map) {
|
||||||
|
fp << ")";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VTR_ASSERT_SAFE(VPACK_OUTPAD == lb.type);
|
||||||
|
fp << "\t\t";
|
||||||
|
if (true == use_explicit_port_map) {
|
||||||
|
fp << "." << std::string(lb.name) << module_output_port_postfix << "(";
|
||||||
|
}
|
||||||
|
fp << std::string(lb.name) << output_port_postfix;
|
||||||
|
if (true == use_explicit_port_map) {
|
||||||
|
fp << ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Update the counter */
|
||||||
|
port_counter++;
|
||||||
|
}
|
||||||
|
fp << "\t);" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* This function adds stimuli to I/Os of FPGA fabric
|
||||||
|
* 1. For mapped I/Os, this function will wire them to the input ports
|
||||||
|
* of the pre-configured FPGA top module
|
||||||
|
* 2. For unmapped I/Os, this function will assign a constant value
|
||||||
|
* by default
|
||||||
|
*******************************************************************/
|
||||||
|
void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module,
|
||||||
|
const std::vector<t_logical_block>& L_logical_blocks,
|
||||||
|
const vtr::Point<size_t>& device_size,
|
||||||
|
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
||||||
|
const std::vector<t_block>& L_blocks,
|
||||||
|
const std::string& io_port_name_postfix,
|
||||||
|
const size_t& unused_io_value) {
|
||||||
|
/* Validate the file stream */
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
/* In this function, we support only 1 type of I/Os */
|
||||||
|
VTR_ASSERT(1 == module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPIO_PORT).size());
|
||||||
|
BasicPort module_io_port = module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPIO_PORT)[0];
|
||||||
|
|
||||||
|
/* Keep tracking which I/Os have been used */
|
||||||
|
std::vector<bool> io_used(module_io_port.get_width(), false);
|
||||||
|
|
||||||
|
/* See if this I/O should be wired to a benchmark input/output */
|
||||||
|
/* Add signals from blif benchmark and short-wire them to FPGA I/O PADs
|
||||||
|
* This brings convenience to checking functionality
|
||||||
|
*/
|
||||||
|
print_verilog_comment(fp, std::string("----- Link BLIF Benchmark I/Os to FPGA I/Os -----"));
|
||||||
|
for (const t_logical_block& io_lb : L_logical_blocks) {
|
||||||
|
/* We only care I/O logical blocks !*/
|
||||||
|
if ( (VPACK_INPAD != io_lb.type) && (VPACK_OUTPAD != io_lb.type) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the index of the mapped GPIO in top-level FPGA fabric */
|
||||||
|
size_t io_index = find_benchmark_io_index(io_lb, device_size, L_grids, L_blocks);
|
||||||
|
|
||||||
|
/* Ensure that IO index is in range */
|
||||||
|
BasicPort module_mapped_io_port = module_io_port;
|
||||||
|
/* Set the port pin index */
|
||||||
|
VTR_ASSERT(io_index < module_mapped_io_port.get_width());
|
||||||
|
module_mapped_io_port.set_width(io_index, io_index);
|
||||||
|
|
||||||
|
/* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always has a size of 1 */
|
||||||
|
BasicPort benchmark_io_port(std::string(std::string(io_lb.name)+ io_port_name_postfix), 1);
|
||||||
|
|
||||||
|
print_verilog_comment(fp, std::string("----- Blif Benchmark inout " + std::string(io_lb.name) + " is mapped to FPGA IOPAD " + module_mapped_io_port.get_name() + "[" + std::to_string(io_index) + "] -----"));
|
||||||
|
if (VPACK_INPAD == io_lb.type) {
|
||||||
|
print_verilog_wire_connection(fp, module_mapped_io_port, benchmark_io_port, false);
|
||||||
|
} else {
|
||||||
|
VTR_ASSERT(VPACK_OUTPAD == io_lb.type);
|
||||||
|
print_verilog_wire_connection(fp, benchmark_io_port, module_mapped_io_port, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mark this I/O has been used/wired */
|
||||||
|
io_used[io_index] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add an empty line as a splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
/* Wire the unused iopads to a constant */
|
||||||
|
print_verilog_comment(fp, std::string("----- Wire unused FPGA I/Os to constants -----"));
|
||||||
|
for (size_t io_index = 0; io_index < io_used.size(); ++io_index) {
|
||||||
|
/* Bypass used iopads */
|
||||||
|
if (true == io_used[io_index]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wire to a contant */
|
||||||
|
BasicPort module_unused_io_port = module_io_port;
|
||||||
|
/* Set the port pin index */
|
||||||
|
module_unused_io_port.set_width(io_index, io_index);
|
||||||
|
|
||||||
|
std::vector<size_t> default_values(module_unused_io_port.get_width(), unused_io_value);
|
||||||
|
print_verilog_wire_constant_values(fp, module_unused_io_port, default_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add an empty line as a splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef VERILOG_TESTBENCH_UTILS_H
|
||||||
|
#define VERILOG_TESTBENCH_UTILS_H
|
||||||
|
|
||||||
|
/* Include header files which are used in the function declaration */
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "module_manager.h"
|
||||||
|
#include "vpr_types.h"
|
||||||
|
|
||||||
|
void print_verilog_testbench_fpga_instance(std::fstream& fp,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module,
|
||||||
|
const std::string& top_instance_name);
|
||||||
|
|
||||||
|
void print_verilog_testbench_benchmark_instance(std::fstream& fp,
|
||||||
|
const std::string& module_name,
|
||||||
|
const std::string& instance_name,
|
||||||
|
const std::string& module_input_port_postfix,
|
||||||
|
const std::string& module_output_port_postfix,
|
||||||
|
const std::string& output_port_postfix,
|
||||||
|
const std::vector<t_logical_block>& L_logical_blocks,
|
||||||
|
const bool& use_explicit_port_map);
|
||||||
|
|
||||||
|
void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module,
|
||||||
|
const std::vector<t_logical_block>& L_logical_blocks,
|
||||||
|
const vtr::Point<size_t>& device_size,
|
||||||
|
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
||||||
|
const std::vector<t_block>& L_blocks,
|
||||||
|
const std::string& io_port_name_postfix,
|
||||||
|
const size_t& unused_io_value);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1329,7 +1329,7 @@ void dump_verilog_input_blif_testbench_stimuli(FILE* fp,
|
||||||
*/
|
*/
|
||||||
void dump_verilog_top_testbench(t_sram_orgz_info* cur_sram_orgz_info,
|
void dump_verilog_top_testbench(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
char* circuit_name,
|
char* circuit_name,
|
||||||
char* top_netlist_name,
|
const char* top_netlist_name,
|
||||||
char* verilog_dir_path,
|
char* verilog_dir_path,
|
||||||
t_spice verilog) {
|
t_spice verilog) {
|
||||||
FILE* fp = NULL;
|
FILE* fp = NULL;
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
#ifndef VERILOG_TOP_TESTBENCH
|
||||||
|
#define VERILOG_TOP_TESTBENCH
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "module_manager.h"
|
||||||
|
#include "bitstream_manager.h"
|
||||||
|
#include "circuit_library.h"
|
||||||
|
|
||||||
|
void print_verilog_top_testbench(const ModuleManager& module_manager,
|
||||||
|
const BitstreamManager& bitstream_manager,
|
||||||
|
const std::vector<ConfigBitId>& fabric_bitstream,
|
||||||
|
const e_sram_orgz& sram_orgz_type,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const std::vector<CircuitPortId>& global_ports,
|
||||||
|
const std::vector<t_logical_block>& L_logical_blocks,
|
||||||
|
const vtr::Point<size_t>& device_size,
|
||||||
|
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
||||||
|
const std::vector<t_block>& L_blocks,
|
||||||
|
const std::string& circuit_name,
|
||||||
|
const std::string& verilog_fname,
|
||||||
|
const std::string& verilog_dir,
|
||||||
|
const std::string& reference_benchmark_file,
|
||||||
|
const t_spice_params& simulation_parameters);
|
||||||
|
|
||||||
void dump_verilog_top_testbench_global_ports(FILE* fp, t_llist* head,
|
void dump_verilog_top_testbench_global_ports(FILE* fp, t_llist* head,
|
||||||
enum e_dump_verilog_port_type dump_port_type);
|
enum e_dump_verilog_port_type dump_port_type);
|
||||||
|
@ -15,7 +39,7 @@ void dump_verilog_top_testbench_stimuli(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
|
|
||||||
void dump_verilog_top_testbench(t_sram_orgz_info* cur_sram_orgz_info,
|
void dump_verilog_top_testbench(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
char* circuit_name,
|
char* circuit_name,
|
||||||
char* top_netlist_name,
|
const char* top_netlist_name,
|
||||||
char* verilog_dir_path,
|
char* verilog_dir_path,
|
||||||
t_spice verilog);
|
t_spice verilog);
|
||||||
|
|
||||||
|
@ -23,3 +47,5 @@ void dump_verilog_input_blif_testbench(char* circuit_name,
|
||||||
char* top_netlist_name,
|
char* top_netlist_name,
|
||||||
char* verilog_dir_path,
|
char* verilog_dir_path,
|
||||||
t_spice verilog);
|
t_spice verilog);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#include "vtr_assert.h"
|
#include "vtr_assert.h"
|
||||||
|
|
||||||
/* Device-level header files */
|
/* Device-level header files */
|
||||||
|
@ -1210,3 +1212,131 @@ void print_verilog_formal_verification_mux_sram_ports_wiring(std::fstream& fp,
|
||||||
print_verilog_wire_connection(fp, mux_sram_output, formal_verification_port, false);
|
print_verilog_wire_connection(fp, mux_sram_output, formal_verification_port, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Print stimuli for a pulse generation
|
||||||
|
*
|
||||||
|
* |<--- pulse width --->|
|
||||||
|
* +------ flip_value
|
||||||
|
* |
|
||||||
|
* initial_value ----------------------+
|
||||||
|
*
|
||||||
|
*******************************************************************/
|
||||||
|
void print_verilog_pulse_stimuli(std::fstream& fp,
|
||||||
|
const BasicPort& port,
|
||||||
|
const size_t& initial_value,
|
||||||
|
const float& pulse_width,
|
||||||
|
const size_t& flip_value) {
|
||||||
|
/* Validate the file stream */
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
/* Config_done signal: indicate when configuration is finished */
|
||||||
|
fp << "initial" << std::endl;
|
||||||
|
fp << "\tbegin" << std::endl;
|
||||||
|
fp << "\t";
|
||||||
|
std::vector<size_t> initial_values(port.get_width(), initial_value);
|
||||||
|
print_verilog_wire_constant_values(fp, port, initial_values);
|
||||||
|
|
||||||
|
/* if flip_value is the same as initial value, we do not need to flip the signal ! */
|
||||||
|
if (flip_value != initial_value) {
|
||||||
|
fp << "\t" << "#" << std::setprecision(2) << pulse_width;
|
||||||
|
std::vector<size_t> port_flip_values(port.get_width(), flip_value);
|
||||||
|
print_verilog_wire_constant_values(fp, port, port_flip_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << "\tend" << std::endl;
|
||||||
|
|
||||||
|
/* Print an empty line as splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Print stimuli for a pulse generation
|
||||||
|
* This function supports multiple signal switching under different pulse width
|
||||||
|
*
|
||||||
|
* |<-- wait condition -->|
|
||||||
|
* |<--- pulse width --->|
|
||||||
|
* +------ flip_values
|
||||||
|
* |
|
||||||
|
* initial_value ------- ... --------------------------------+
|
||||||
|
*
|
||||||
|
*******************************************************************/
|
||||||
|
void print_verilog_pulse_stimuli(std::fstream& fp,
|
||||||
|
const BasicPort& port,
|
||||||
|
const size_t& initial_value,
|
||||||
|
const std::vector<float>& pulse_widths,
|
||||||
|
const std::vector<size_t>& flip_values,
|
||||||
|
const std::string& wait_condition) {
|
||||||
|
/* Validate the file stream */
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
/* Config_done signal: indicate when configuration is finished */
|
||||||
|
fp << "initial" << std::endl;
|
||||||
|
fp << "\tbegin" << std::endl;
|
||||||
|
fp << "\t";
|
||||||
|
std::vector<size_t> initial_values(port.get_width(), initial_value);
|
||||||
|
print_verilog_wire_constant_values(fp, port, initial_values);
|
||||||
|
|
||||||
|
/* Set a wait condition if specified */
|
||||||
|
if (false == wait_condition.empty()) {
|
||||||
|
fp << "\twait(" << wait_condition << ")" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Number of flip conditions and values should match */
|
||||||
|
VTR_ASSERT(flip_values.size() == pulse_widths.size());
|
||||||
|
for (size_t ipulse = 0; ipulse < pulse_widths.size(); ++ipulse) {
|
||||||
|
fp << "\t" << "#" << std::setprecision(2) << pulse_widths[ipulse];
|
||||||
|
std::vector<size_t> port_flip_value(port.get_width(), flip_values[ipulse]);
|
||||||
|
print_verilog_wire_constant_values(fp, port, port_flip_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << "\tend" << std::endl;
|
||||||
|
|
||||||
|
/* Print an empty line as splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Print stimuli for a clock signal
|
||||||
|
* This function can support if the clock signal should wait for a period
|
||||||
|
* of time and then start
|
||||||
|
* pulse width
|
||||||
|
* |<----->|
|
||||||
|
* +-------+ +-------+
|
||||||
|
* | | | |
|
||||||
|
* initial_value --- ... ---+ +-------+ +------ ...
|
||||||
|
* |<--wait_condition-->|
|
||||||
|
*
|
||||||
|
*******************************************************************/
|
||||||
|
void print_verilog_clock_stimuli(std::fstream& fp,
|
||||||
|
const BasicPort& port,
|
||||||
|
const size_t& initial_value,
|
||||||
|
const float& pulse_width,
|
||||||
|
const std::string& wait_condition) {
|
||||||
|
/* Validate the file stream */
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
/* Config_done signal: indicate when configuration is finished */
|
||||||
|
fp << "initial" << std::endl;
|
||||||
|
fp << "\tbegin" << std::endl;
|
||||||
|
fp << "\t";
|
||||||
|
std::vector<size_t> initial_values(port.get_width(), initial_value);
|
||||||
|
print_verilog_wire_constant_values(fp, port, initial_values);
|
||||||
|
fp << "\tend" << std::endl;
|
||||||
|
fp << "always";
|
||||||
|
|
||||||
|
/* Set a wait condition if specified */
|
||||||
|
if (true == wait_condition.empty()) {
|
||||||
|
fp << std::endl;
|
||||||
|
} else {
|
||||||
|
fp << " wait(" << wait_condition << ")" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << "\tbegin" << std::endl;
|
||||||
|
fp << "\t\t" << "#" << std::setprecision(2) << pulse_width;
|
||||||
|
print_verilog_wire_connection(fp, port, port, true);
|
||||||
|
fp << "\tend" << std::endl;
|
||||||
|
|
||||||
|
/* Print an empty line as splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#ifndef VERILOG_WRITER_UTILS_H
|
#ifndef VERILOG_WRITER_UTILS_H
|
||||||
#define VERILOG_WRITER_UTILS_H
|
#define VERILOG_WRITER_UTILS_H
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "verilog_global.h"
|
#include "verilog_global.h"
|
||||||
#include "device_port.h"
|
#include "device_port.h"
|
||||||
|
@ -143,4 +145,23 @@ void print_verilog_formal_verification_mux_sram_ports_wiring(std::fstream& fp,
|
||||||
const size_t& num_conf_bits,
|
const size_t& num_conf_bits,
|
||||||
const BasicPort& fm_config_bus);
|
const BasicPort& fm_config_bus);
|
||||||
|
|
||||||
|
void print_verilog_pulse_stimuli(std::fstream& fp,
|
||||||
|
const BasicPort& port,
|
||||||
|
const size_t& initial_value,
|
||||||
|
const float& pulse_width,
|
||||||
|
const size_t& flip_value);
|
||||||
|
|
||||||
|
void print_verilog_pulse_stimuli(std::fstream& fp,
|
||||||
|
const BasicPort& port,
|
||||||
|
const size_t& initial_value,
|
||||||
|
const std::vector<float>& pulse_widths,
|
||||||
|
const std::vector<size_t>& flip_values,
|
||||||
|
const std::string& wait_condition);
|
||||||
|
|
||||||
|
void print_verilog_clock_stimuli(std::fstream& fp,
|
||||||
|
const BasicPort& port,
|
||||||
|
const size_t& initial_value,
|
||||||
|
const float& pulse_width,
|
||||||
|
const std::string& wait_condition);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue