Skip to content

Commit

Permalink
Merge pull request #1607 from lnis-uofu/xt_preconfig_wrapper
Browse files Browse the repository at this point in the history
Support waveform output in preconfigured fabric wrapper generator
  • Loading branch information
tangxifan authored Mar 29, 2024
2 parents 2ab423e + 3824b00 commit 8796687
Show file tree
Hide file tree
Showing 102 changed files with 20,204 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ __ iverilog_website_

.. warning:: Signal initialization is only applied to the datapath inputs of routing multiplexers (considering the fact that they are indispensible cells of FPGAs)! If your FPGA does not contain any multiplexer cells, signal initialization is not applicable.

.. option:: --dump_waveform

Enable waveform output when runnign HDL simulation on the preconfigured wrapper. When enabled, waveform files can be outputted in two formats: ``fsdb`` and ``vcd`` through preprocessing flags ``DUMP_FSDB`` and ``DUMP_VCD`` respectively. For example, when using VCS,. the flag can be activiated by ``+define+DUMP_FSDB=1``.

.. option:: --no_time_stamp

Do not print time stamp in Verilog netlists
Expand Down
4 changes: 4 additions & 0 deletions openfpga/src/base/openfpga_verilog_command_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,10 @@ ShellCommandId add_write_preconfigured_fabric_wrapper_command_template(
shell_cmd.add_option("include_signal_init", false,
"initialize all the signals in verilog testbenches");

/* add an option '--dump_waveform' */
shell_cmd.add_option("dump_waveform", false,
"add waveform output commands to the output file");

/* Add an option '--no_time_stamp' */
shell_cmd.add_option("no_time_stamp", false,
"Do not print a time stamp in the output files");
Expand Down
2 changes: 2 additions & 0 deletions openfpga/src/base/openfpga_verilog_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ int write_preconfigured_fabric_wrapper_template(
CommandOptionId opt_include_signal_init = cmd.option("include_signal_init");
CommandOptionId opt_embed_bitstream = cmd.option("embed_bitstream");
CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp");
CommandOptionId opt_dump_waveform = cmd.option("dump_waveform");
CommandOptionId opt_verbose = cmd.option("verbose");

/* This is an intermediate data structure which is designed to modularize the
Expand All @@ -184,6 +185,7 @@ int write_preconfigured_fabric_wrapper_template(
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
options.set_include_signal_init(
cmd_context.option_enable(cmd, opt_include_signal_init));
options.set_dump_waveform(cmd_context.option_enable(cmd, opt_dump_waveform));
options.set_print_formal_verification_top_netlist(true);

if (true == cmd_context.option_enable(cmd, opt_dut_module)) {
Expand Down
5 changes: 5 additions & 0 deletions openfpga/src/fpga_verilog/verilog_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ constexpr const char* FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME =
constexpr const char* FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX =
"_top_formal_verification_random_tb";

constexpr const char* VERILOG_FSDB_PREPROC_FLAG =
"DUMP_FSDB"; // the flag to enable fsdb waveform output during compilation
constexpr const char* VERILOG_VCD_PREPROC_FLAG =
"DUMP_VCD"; // the flag to enable vcd waveform output during compilation

#define VERILOG_DEFAULT_SIGNAL_INIT_VALUE 0

#endif
6 changes: 6 additions & 0 deletions openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,12 @@ int print_verilog_preconfig_top_module(
module_manager, top_module, false);
}

/* Add waveform output command, support both fsdb and vcd */
if (true == options.dump_waveform()) {
print_verilog_testbench_dump_waveform(
fp, circuit_name, std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME));
}

/* Testbench ends*/
print_verilog_module_end(
fp,
Expand Down
7 changes: 7 additions & 0 deletions openfpga/src/fpga_verilog/verilog_testbench_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ VerilogTestbenchOption::VerilogTestbenchOption() {
time_stamp_ = true;
use_relative_path_ = false;
simulator_type_ = e_simulator_type::IVERILOG;
dump_waveform_ = false;
verbose_output_ = false;

SIMULATOR_TYPE_STRING_ = {{"iverilog", "vcs"}};
Expand Down Expand Up @@ -87,6 +88,8 @@ bool VerilogTestbenchOption::include_signal_init() const {
return include_signal_init_;
}

bool VerilogTestbenchOption::dump_waveform() const { return dump_waveform_; }

bool VerilogTestbenchOption::no_self_checking() const {
return reference_benchmark_file_path_.empty();
}
Expand Down Expand Up @@ -206,6 +209,10 @@ void VerilogTestbenchOption::set_include_signal_init(const bool& enabled) {
include_signal_init_ = enabled;
}

void VerilogTestbenchOption::set_dump_waveform(const bool& enabled) {
dump_waveform_ = enabled;
}

void VerilogTestbenchOption::set_default_net_type(
const std::string& default_net_type) {
/* Decode from net type string */;
Expand Down
3 changes: 3 additions & 0 deletions openfpga/src/fpga_verilog/verilog_testbench_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class VerilogTestbenchOption {
std::string simulation_ini_path() const;
bool explicit_port_mapping() const;
bool include_signal_init() const;
bool dump_waveform() const;
bool no_self_checking() const;
e_verilog_default_net_type default_net_type() const;
e_embedded_bitstream_hdl_type embedded_bitstream_hdl_type() const;
Expand Down Expand Up @@ -98,6 +99,7 @@ class VerilogTestbenchOption {
void set_print_simulation_ini(const std::string& simulation_ini_path);
void set_explicit_port_mapping(const bool& enabled);
void set_include_signal_init(const bool& enabled);
void set_dump_waveform(const bool& enabled);
void set_default_net_type(const std::string& default_net_type);
void set_time_unit(const float& time_unit);
void set_embedded_bitstream_hdl_type(
Expand Down Expand Up @@ -132,6 +134,7 @@ class VerilogTestbenchOption {
std::string simulation_ini_path_;
bool explicit_port_mapping_;
bool include_signal_init_;
bool dump_waveform_;
e_verilog_default_net_type default_net_type_;
e_embedded_bitstream_hdl_type embedded_bitstream_hdl_type_;
e_simulator_type simulator_type_;
Expand Down
30 changes: 30 additions & 0 deletions openfpga/src/fpga_verilog/verilog_testbench_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1344,4 +1344,34 @@ void print_verilog_testbench_signal_initialization(
}
}

/********************************************************************
* Print waveform output commands: support both VCD and FSDB
*******************************************************************/
void print_verilog_testbench_dump_waveform(std::fstream& fp,
const std::string& circuit_name,
const std::string& uut_name) {
/* Validate the file stream */
valid_file_stream(fp);

print_verilog_comment(
fp, std::string("------ Use " + std::string(VERILOG_FSDB_PREPROC_FLAG) +
" to enable FSDB waveform output -----"));
print_verilog_preprocessing_flag(fp, std::string(VERILOG_FSDB_PREPROC_FLAG));
fp << "initial begin\n";
fp << "\t$fsdbDumpfile(\"" << circuit_name << ".fsdb\");\n";
fp << "\t$fsdbDumpvars(0, \"" << uut_name << "\");\n";
fp << "end\n";
print_verilog_endif(fp);

print_verilog_comment(
fp, std::string("------ Use " + std::string(VERILOG_VCD_PREPROC_FLAG) +
" to enable VCD waveform output -----"));
print_verilog_preprocessing_flag(fp, std::string(VERILOG_VCD_PREPROC_FLAG));
fp << "initial begin\n";
fp << "\t$dumpfile(\"" << circuit_name << ".vcd\");\n";
fp << "\t$dumpvars(0, \"" << uut_name << "\");\n";
fp << "end\n";
print_verilog_endif(fp);
}

} /* end namespace openfpga */
4 changes: 4 additions & 0 deletions openfpga/src/fpga_verilog/verilog_testbench_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ void print_verilog_testbench_signal_initialization(
const CircuitLibrary& circuit_lib, const ModuleManager& module_manager,
const ModuleId& top_module, const bool& deposit_random_values);

void print_verilog_testbench_dump_waveform(std::fstream& fp,
const std::string& circuit_name,
const std::string& uut_name);

} /* end namespace openfpga */

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ write_fabric_verilog --file ${OPENFPGA_OUTPUT_DIR} --explicit_port_mapping --inc
# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA
# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase
# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts
write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ${OPENFPGA_OUTPUT_DIR} --explicit_port_mapping --no_time_stamp
write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ${OPENFPGA_OUTPUT_DIR} --explicit_port_mapping --no_time_stamp ${OPENFPGA_PRECONFIG_FABRIC_WRAPPER_DUMP_WAVEFORM}
write_preconfigured_testbench --file ${OPENFPGA_OUTPUT_DIR} --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --use_relative_path --explicit_port_mapping --no_time_stamp

# Write the SDC files for PnR backend
Expand Down
1 change: 1 addition & 0 deletions openfpga_flow/regression_test_scripts/basic_reg_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ echo -e "Testing output files without time stamp";
run-task basic_tests/no_time_stamp/device_1x1 $@
run-task basic_tests/no_time_stamp/device_4x4 $@
run-task basic_tests/no_time_stamp/no_cout_in_gsb $@
run-task basic_tests/no_time_stamp/dump_waveform $@
# Run git-diff to ensure no changes on the golden netlists
# Switch to root path in case users are running the tests in another location
cd ${OPENFPGA_PATH}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulatio
openfpga_vpr_device_layout = auto
openfpga_vpr_route_chan_width = 26
openfpga_output_dir=${PATH:TASK_DIR}/golden_outputs_no_time_stamp
openfpga_preconfig_fabric_wrapper_dump_waveform=

[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulatio
openfpga_vpr_device_layout = 4x4
openfpga_vpr_route_chan_width = 20
openfpga_output_dir=${PATH:TASK_DIR}/golden_outputs_no_time_stamp
openfpga_preconfig_fabric_wrapper_dump_waveform=

[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# Configuration file for running experiments
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
# Each job execute fpga_flow script on combination of architecture & benchmark
# timeout_each_job is timeout for each job
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

[GENERAL]
run_engine=openfpga_shell
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
power_analysis = true
spice_output=false
verilog_output=true
timeout_each_job = 20*60
fpga_flow=yosys_vpr

[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/no_time_stamp_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_abspath_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
openfpga_vpr_device_layout = auto
openfpga_vpr_route_chan_width = 26
openfpga_output_dir=${PATH:TASK_DIR}/golden_outputs_no_time_stamp
openfpga_preconfig_fabric_wrapper_dump_waveform=--dump_waveform

[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml

[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v

[SYNTHESIS_PARAM]
bench_read_verilog_options_common = -nolatches
bench0_top = and2

[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//-------------------------------------------
// FPGA Synthesizable Verilog Netlist
// Description: FPGA Verilog Testbench for Formal Top-level netlist of Design: and2
// Author: Xifan TANG
// Organization: University of Utah
//-------------------------------------------
//----- Default net type -----
`default_nettype none

module and2_top_formal_verification_random_tb;
// ----- Default clock port is added here since benchmark does not contain one -------
reg [0:0] clk;

// ----- Shared inputs -------
reg [0:0] a;
reg [0:0] b;

// ----- FPGA fabric outputs -------
wire [0:0] c_gfpga;

// ----- Benchmark outputs -------
wire [0:0] c_bench;

// ----- Output vectors checking flags -------
reg [0:0] c_flag;

// ----- Error counter -------
integer nb_error= 0;

// ----- FPGA fabric instanciation -------
and2_top_formal_verification FPGA_DUT(
.a(a),
.b(b),
.c(c_gfpga)
);
// ----- End FPGA Fabric Instanication -------

// ----- Reference Benchmark Instanication -------
and2 REF_DUT(
.a(a),
.b(b),
.c(c_bench)
);
// ----- End reference Benchmark Instanication -------

// ----- Clock 'clk' Initialization -------
initial begin
clk[0] <= 1'b0;
while(1) begin
#0.4628907144
clk[0] <= !clk[0];
end
end

// ----- Begin reset signal generation -----
// ----- End reset signal generation -----

// ----- Input Initialization -------
initial begin
a <= 1'b0;
b <= 1'b0;

c_flag[0] <= 1'b0;
end

// ----- Input Stimulus -------
always@(negedge clk[0]) begin
a <= $random;
b <= $random;
end

// ----- Begin checking output vectors -------
// ----- Skip the first falling edge of clock, it is for initialization -------
reg [0:0] sim_start;

always@(negedge clk[0]) begin
if (1'b1 == sim_start[0]) begin
sim_start[0] <= ~sim_start[0];
end else
begin
if(!(c_gfpga === c_bench) && !(c_bench === 1'bx)) begin
c_flag <= 1'b1;
end else begin
c_flag<= 1'b0;
end
end
end

always@(posedge c_flag) begin
if(c_flag) begin
nb_error = nb_error + 1;
$display("Mismatch on c_gfpga at time = %t", $realtime);
end
end


// ----- Begin output waveform to VCD file-------
initial begin
$dumpfile("and2_formal.vcd");
$dumpvars(1, and2_top_formal_verification_random_tb);
end
// ----- END output waveform to VCD file -------

initial begin
sim_start[0] <= 1'b1;
$timeformat(-9, 2, "ns", 20);
$display("Simulation start");
// ----- Can be changed by the user for his/her need -------
#6.480470181
if(nb_error == 0) begin
$display("Simulation Succeed");
end else begin
$display("Simulation Failed with %d error(s)", nb_error);
end
$finish;
end

endmodule
// ----- END Verilog module for and2_top_formal_verification_random_tb -----

Loading

0 comments on commit 8796687

Please sign in to comment.