-
Notifications
You must be signed in to change notification settings - Fork 113
Random Coverage Testing of bsg_fifo_1rw_large #683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Asiadav
wants to merge
5
commits into
bespoke-silicon-group:master
Choose a base branch
from
Asiadav:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 3 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| # This file is public domain, it can be freely copied without restrictions. | ||
| # SPDX-License-Identifier: CC0-1.0 | ||
|
|
||
| # Cadenv Include | ||
| include /home/projects/ee478.2024spr/cadenv/cadenv_ee.mk | ||
|
|
||
| # CAD Tool Paths | ||
| VCS_BIN = $(VCS_HOME)/bin | ||
| VERDI_BIN = $(VERDI_HOME)/bin | ||
| VCS_BIN_DIR = $(VCS_BIN) | ||
| export PATH:=$(PATH):$(VCS_BIN):$(VERDI_BIN) | ||
|
|
||
| # VCS Arguments | ||
| EXTRA_ARGS += +v2k -l vcs.log | ||
| EXTRA_ARGS += -debug_pp +vcs+vcdpluson | ||
| EXTRA_ARGS += +lint=all,noSVA-UA,noSVA-NSVU,noVCDE,noNS -assert svaext | ||
| EXTRA_ARGS += -cm line+fsm+branch+cond+tgl | ||
| EXTRA_ARGS += -kdb -debug_access+all | ||
|
|
||
| # defaults | ||
| SIM ?= vcs | ||
| TOPLEVEL_LANG ?= verilog | ||
|
|
||
| # basejump_stl path | ||
| export BASEJUMP_STL_DIR = $(shell git rev-parse --show-toplevel)/../basejump_stl | ||
|
|
||
| # basejump_stl verilog header include path | ||
| EXTRA_ARGS += +incdir+$(BASEJUMP_STL_DIR)/bsg_misc | ||
|
|
||
| # basejump_stl verilog filelist | ||
| VERILOG_SOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_clock_gen.sv | ||
| VERILOG_SOURCES += $(BASEJUMP_STL_DIR)/bsg_test/bsg_nonsynth_reset_gen.sv | ||
| VERILOG_SOURCES += $(BASEJUMP_STL_DIR)/bsg_dataflow/bsg_fifo_1r1w_small_hardened.sv | ||
| VERILOG_SOURCES += $(BASEJUMP_STL_DIR)/bsg_dataflow/bsg_fifo_tracker.sv | ||
| VERILOG_SOURCES += $(BASEJUMP_STL_DIR)/bsg_misc/bsg_dff_en.sv | ||
| VERILOG_SOURCES += $(BASEJUMP_STL_DIR)/bsg_misc/bsg_circular_ptr.sv | ||
| VERILOG_SOURCES += $(BASEJUMP_STL_DIR)/bsg_mem/bsg_mem_1rw_sync.sv | ||
| VERILOG_SOURCES += $(BASEJUMP_STL_DIR)/bsg_mem/bsg_mem_1rw_sync_synth.sv | ||
| VERILOG_SOURCES += $(BASEJUMP_STL_DIR)/bsg_dataflow/bsg_fifo_1rw_large.sv | ||
|
|
||
| # testbench verilog filelist | ||
| VERILOG_SOURCES += $(PWD)/bsg_fifo_1rw_large_wrapper.sv | ||
| VERILOG_SOURCES += $(PWD)/bsg_fifo_1rw_large_cov.sv | ||
|
|
||
| # TOPLEVEL is the name of the toplevel module in your Verilog or VHDL file | ||
| TOPLEVEL = bsg_fifo_1rw_large_wrapper | ||
|
|
||
| # MODULE is the basename of the Python test file | ||
| MODULE = bsg_fifo_1rw_large_testbench | ||
|
|
||
| # include cocotb's make rules to take care of the simulator setup | ||
| include $(shell cocotb-config --makefiles)/Makefile.sim | ||
|
|
||
|
|
||
| # VERDI open waveform | ||
| ee-verdi: | ||
| verdi -ssf novas.fsdb & | ||
|
|
||
| # VERDI open coverages | ||
| ee-verdi-cov: | ||
| verdi -cov -covdir sim_build/simv.vdb & | ||
|
|
||
| # **DEPRECATED** DVE open waveform | ||
| ee-dve: | ||
| dve -full64 -vpd vcdplus.vpd & | ||
|
|
||
| # **DEPRECATED** DVE open coverages | ||
| ee-dve-cov: | ||
| dve -full64 -cov -covdir sim_build/simv.vdb & | ||
|
|
||
| # Clean simulation files | ||
| ee-clean: | ||
| make clean | ||
| rm -rf __pycache__ DVEfiles vcs.log vcdplus.vpd results.xml | ||
| rm -rf verdiLog vdCovLog novas.conf novas.fsdb novas.rc novas_dump.log |
110 changes: 110 additions & 0 deletions
110
testing/bsg_dataflow/bsg_fifo_1rw_large_random/bsg_fifo_1rw_large_cov.sv
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| // | ||
| // Davis Sauer 05/2024 | ||
| // | ||
| // This module defines functional coverages of module bsg_fifo_1rw_large | ||
| // | ||
| // | ||
|
|
||
| `include "bsg_defines.sv" | ||
| module bsg_fifo_1rw_large_cov | ||
|
|
||
| #(parameter els_p = "inv" | ||
| ,localparam ptr_width_lp = `BSG_SAFE_CLOG2(els_p) | ||
| ) | ||
|
|
||
| (input clk_i | ||
| ,input reset_i | ||
|
|
||
| // interface signals | ||
| ,input v_i | ||
| ,input enq_not_deq_i | ||
|
|
||
| // internal registers | ||
| ,input [ptr_width_lp-1:0] rd_ptr // registered in sub-module bsg_circular_ptr | ||
| ,input [ptr_width_lp-1:0] wr_ptr // registered in sub-module bsg_circular_ptr | ||
| ,input full_o // not a register | ||
| ,input empty_o // not a register | ||
| ,input last_op_is_read_r | ||
| ); | ||
|
|
||
| // reset | ||
| covergroup cg_reset @(negedge clk_i); | ||
| coverpoint reset_i; | ||
| endgroup | ||
|
|
||
| // Partitioning covergroup into smaller ones | ||
| // empty | ||
| covergroup cg_empty @ (negedge clk_i iff ~reset_i & empty_o & ~full_o); | ||
|
|
||
| cp_v: coverpoint v_i; | ||
| cp_rptr: coverpoint rd_ptr; | ||
| cp_wptr: coverpoint wr_ptr; | ||
| cp_loir: coverpoint last_op_is_read_r {illegal_bins ig = {0};} // resets to 1, and then only possible to read from cp_normal to get to cp_empty | ||
Asiadav marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| cp_end: coverpoint enq_not_deq_i;// {illegal_bins ig = {0};} // cannot deque when empty | ||
Asiadav marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| cross_all: cross cp_v, cp_rptr, cp_wptr, cp_loir, cp_end { | ||
| // by definition, fifo empty means r/w pointers are the same | ||
| illegal_bins ig0 = cross_all with (cp_rptr != cp_wptr); | ||
| illegal_bins ig1 = cross_all with (cp_v && !cp_end); // cannot read from empty fifo | ||
gaozihou marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| endgroup | ||
|
|
||
| // full | ||
| covergroup cg_full @ (negedge clk_i iff ~reset_i & ~empty_o & full_o); | ||
|
|
||
| cp_v: coverpoint v_i; | ||
| cp_rptr: coverpoint rd_ptr; | ||
| cp_wptr: coverpoint wr_ptr; | ||
| cp_loir: coverpoint last_op_is_read_r {illegal_bins ig = {1};} // cannot fill fifo by reading | ||
| cp_end: coverpoint enq_not_deq_i;// {illegal_bins ig = {1};} // cannot write to full fifo | ||
Asiadav marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| cross_all: cross cp_v, cp_rptr, cp_wptr, cp_loir, cp_end { | ||
| // by definition, fifo full means r/w pointers are the same | ||
| illegal_bins ig0 = cross_all with (cp_rptr != cp_wptr); | ||
|
|
||
| illegal_bins ig1 = cross_all with (cp_v && cp_end); // cannot write to full fifo | ||
| } | ||
|
|
||
| endgroup | ||
|
|
||
| // fifo normal | ||
| covergroup cg_normal @ (negedge clk_i iff ~reset_i & ~empty_o & ~full_o); | ||
|
|
||
| cp_v: coverpoint v_i; | ||
| cp_rptr: coverpoint rd_ptr; | ||
| cp_wptr: coverpoint wr_ptr; | ||
| cp_loir: coverpoint last_op_is_read_r; | ||
| cp_end: coverpoint enq_not_deq_i; | ||
|
|
||
| cross_all: cross cp_v, cp_rptr, cp_wptr, cp_loir, cp_end { | ||
| // by definition, r/w pointers are different when fifo is non-empty & non-full | ||
| illegal_bins ig0 = cross_all with (cp_rptr == cp_wptr); | ||
| } | ||
|
|
||
| endgroup | ||
|
|
||
| // fifo impossible (fifo cannot be both empty and full at the same time) | ||
| // covergroup cg_impossible @ (negedge clk_i iff ~reset_i & empty & full); | ||
Asiadav marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| // create cover groups | ||
| cg_reset cov_reset = new; | ||
| cg_empty cov_empty = new; | ||
| cg_full cov_full = new; | ||
| cg_normal cov_normal = new; | ||
|
|
||
| // print coverages when simulation is done | ||
| final | ||
| begin | ||
| $display(""); | ||
| $display("Instance: %m"); | ||
| $display("---------------------- Functional Coverage Results ----------------------"); | ||
| $display("Reset functional coverage is %f%%", cov_reset.get_coverage()); | ||
| $display("Fifo empty functional coverage is %f%%", cov_empty.cross_all.get_coverage()); | ||
| $display("Fifo full functional coverage is %f%%", cov_full.cross_all.get_coverage()); | ||
| $display("Fifo normal functional coverage is %f%%", cov_normal.cross_all.get_coverage()); | ||
| $display("-------------------------------------------------------------------------"); | ||
| $display(""); | ||
| end | ||
|
|
||
| endmodule | ||
134 changes: 134 additions & 0 deletions
134
testing/bsg_dataflow/bsg_fifo_1rw_large_random/bsg_fifo_1rw_large_testbench.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| # Davis Sauer | ||
| # 05/2024 | ||
|
|
||
| # Import python libraries | ||
| import math | ||
| import time | ||
| import random | ||
|
|
||
| # Import cocotb libraries | ||
| import cocotb | ||
| from cocotb.clock import Clock, Timer | ||
| from cocotb.triggers import RisingEdge, FallingEdge, Timer | ||
|
|
||
|
|
||
| # Data width, matching width_p parameter in DUT | ||
| WIDTH_P = 16 | ||
|
|
||
| # Testbench iterations | ||
| ITERATION = 1000 | ||
|
|
||
| # Flow control random seed | ||
| # Use different seeds on input and output sides for more randomness | ||
| CTRL_INPUT_SEED = 1 | ||
| CTRL_OUTPUT_SEED = 2 | ||
|
|
||
| # Testbench clock period | ||
| CLK_PERIOD = 10 | ||
|
|
||
|
|
||
| async def input_side_testbench(dut, seed): | ||
| """Handle input traffic""" | ||
|
|
||
| # Create local random generator for data generation | ||
| data_random = random.Random() | ||
| data_random.seed(seed) | ||
|
|
||
| # Create control random generator for flow control | ||
| control_random = random.Random() | ||
| control_random.seed(CTRL_INPUT_SEED) | ||
|
|
||
| # Initialize DUT interface values | ||
| dut.v_i.value = 0 | ||
| dut.data_i.value = 0 | ||
| dut.enq_not_deq_i.value = 1 | ||
|
|
||
| # Wait for reset deassertion | ||
| while 1: | ||
| await RisingEdge(dut.clk_i); await Timer(1, units="ps") | ||
| if dut.reset_i == 0: break | ||
|
|
||
| # Main iterations | ||
| i = 0 | ||
| data = [] | ||
| data_idx = 0 | ||
| while 1: | ||
| await RisingEdge(dut.clk_i); await Timer(1, units="ps") | ||
| rng = control_random.random() | ||
| if dut.full_o.value == 0 and rng >= 0.5: # write | ||
| # Assert DUT valid signal | ||
| dut.v_i.setimmediatevalue(1) | ||
| dut.enq_not_deq_i.setimmediatevalue(1) | ||
| # Generate send data | ||
| value = math.floor(data_random.random()*pow(2, WIDTH_P)) | ||
| data.append(value) | ||
| dut.data_i.setimmediatevalue(value) | ||
| await RisingEdge(dut.clk_i); await Timer(1, units="ps") | ||
| # Deassert DUT signals | ||
| dut.v_i.setimmediatevalue(0) | ||
| dut.enq_not_deq_i.setimmediatevalue(value > pow(2, WIDTH_P)/2) | ||
| # iteration increment | ||
| i += 1 | ||
| # Check iteration | ||
| if i == ITERATION: | ||
| # Test finished | ||
| break | ||
| elif dut.empty_o.value == 0: # read | ||
| # Assert DUT signals | ||
| dut.v_i.setimmediatevalue(1) | ||
| dut.enq_not_deq_i.setimmediatevalue(0) | ||
| await RisingEdge(dut.clk_i); await Timer(1, units="ps") | ||
| assert dut.data_o.value == data[data_idx], "data mismatch!" | ||
| # Deassert DUT signals | ||
| dut.v_i.setimmediatevalue(0) | ||
| dut.enq_not_deq_i.setimmediatevalue(data[data_idx] > pow(2, WIDTH_P)/2) | ||
| data_idx += 1 | ||
| else: # do nothing | ||
| await RisingEdge(dut.clk_i); await Timer(1, units="ps") | ||
|
|
||
| await RisingEdge(dut.clk_i); await Timer(1, units="ps") | ||
|
|
||
| # Deassert DUT valid signal | ||
| dut.v_i.value = 0 | ||
|
|
||
| @cocotb.test() | ||
| async def testbench(dut): | ||
| """Try accessing the design.""" | ||
|
|
||
| # Random seed assignment | ||
| seed = "fifo" | ||
|
|
||
| # Create a 10ps period clock on DUT port clk_i | ||
| clock = Clock(dut.clk_i, CLK_PERIOD, units="ps") | ||
|
|
||
| # Start the clock. Start it low to avoid issues on the first RisingEdge | ||
| clock_thread = cocotb.start_soon(clock.start(start_high=False)) | ||
|
|
||
| # Launch input and output testbench threads | ||
| input_thread = cocotb.start_soon(input_side_testbench(dut, seed)) | ||
|
|
||
| # Reset initialization | ||
| dut.reset_i.value = 1 | ||
|
|
||
| # Wait for 5 clock cycles | ||
| await Timer(CLK_PERIOD*5, units="ps") | ||
| await RisingEdge(dut.clk_i); await Timer(1, units="ps") | ||
|
|
||
| # Deassert reset | ||
| dut.reset_i.value = 0 | ||
|
|
||
| # Wait for threads to finish | ||
| await input_thread | ||
|
|
||
| # Wait for 5 clock cycles | ||
| await Timer(CLK_PERIOD*5, units="ps") | ||
| await RisingEdge(dut.clk_i); await Timer(1, units="ps") | ||
|
|
||
| # Assert reset | ||
| dut.reset_i.value = 1 | ||
|
|
||
| # Wait for 5 clock cycles | ||
| await Timer(CLK_PERIOD*5, units="ps") | ||
|
|
||
| # Test finished! | ||
| dut._log.info("Test finished! Current reset_i value = %s", dut.reset_i.value) |
35 changes: 35 additions & 0 deletions
35
testing/bsg_dataflow/bsg_fifo_1rw_large_random/bsg_fifo_1rw_large_wrapper.sv
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
|
|
||
| module bsg_fifo_1rw_large_wrapper #(parameter width_p = 16 | ||
| , parameter els_p = 8 | ||
| ) | ||
| ( input clk_i | ||
| , input reset_i | ||
|
|
||
| , input v_i | ||
| , input [width_p-1:0] data_i | ||
| , input enq_not_deq_i | ||
|
|
||
| , output full_o | ||
| , output empty_o | ||
| , output [width_p-1:0] data_o | ||
| ); | ||
|
|
||
| // Instantiate DUT | ||
| bsg_fifo_1rw_large #(.width_p(width_p) | ||
| ,.els_p(els_p) | ||
| ) fifo | ||
| (.*); | ||
|
|
||
| // Bind Covergroups | ||
| bind bsg_fifo_1rw_large bsg_fifo_1rw_large_cov | ||
| #(.els_p(els_p) | ||
| ) pc_cov | ||
| (.* | ||
| ); | ||
|
|
||
| // Dump Waveforms | ||
| initial begin | ||
| $fsdbDumpvars; | ||
| end | ||
|
|
||
| endmodule |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.