11import random
2+ import string
23from decimal import Decimal
34
4- import siliconcompiler
5-
65import cocotb
76from cocotb .clock import Clock
87from cocotb .triggers import ClockCycles , Timer , Combine
9- from cocotb .regression import TestFactory
10- from cocotb import utils
118
12- from lambdalib import ramlib
139from lambdalib .utils ._tb_common import (
1410 run_cocotb ,
15- drive_reset ,
11+ do_reset ,
1612 random_bool_generator
1713)
18- from lambdalib . ramlib . la_asyncfifo . testbench .la_asyncfifo import (
14+ from .la_asyncfifo import (
1915 LaAsyncFifoWrBus ,
2016 LaAsyncFifoRdBus ,
2117 LaAsyncFifoSource ,
@@ -30,7 +26,13 @@ def bursty_en_gen(burst_len=20):
3026 yield en_state
3127
3228
33- @cocotb .test ()
29+ def random_decimal (max : int , min : int , decimal_places = 2 ) -> Decimal :
30+ prefix = str (random .randint (min , max ))
31+ suffix = '' .join (random .choice (string .digits ) for _ in range (decimal_places ))
32+ return Decimal (prefix + "." + suffix )
33+
34+
35+ @cocotb .test (timeout_time = 100 , timeout_unit = "ms" )
3436async def test_almost_full (dut ):
3537
3638 wr_clk_period_ns = 10.0
@@ -51,14 +53,14 @@ async def test_almost_full(dut):
5153
5254 # Reset DUT
5355 await Combine (
54- cocotb .start_soon (drive_reset (dut .wr_nreset )),
55- cocotb .start_soon (drive_reset (dut .rd_nreset ))
56+ cocotb .start_soon (do_reset (dut .wr_nreset , time_ns = wr_clk_period_ns * 4 )),
57+ cocotb .start_soon (do_reset (dut .rd_nreset , time_ns = rd_clk_period_ns * 4 ))
5658 )
5759
58- await cocotb . start ( Clock (dut .wr_clk , wr_clk_period_ns , units = "ns" ).start () )
60+ Clock (dut .wr_clk , wr_clk_period_ns , units = "ns" ).start ()
5961 # Randomize phase shift between clocks
6062 await Timer (wr_clk_period_ns * random .random (), "ns" , round_mode = "round" )
61- await cocotb . start ( Clock (dut .rd_clk , rd_clk_period_ns , units = "ns" ).start () )
63+ Clock (dut .rd_clk , rd_clk_period_ns , units = "ns" ).start ()
6264
6365 almost_full_level = int (dut .AFULLFINAL .value )
6466
@@ -85,6 +87,22 @@ async def test_almost_full(dut):
8587 assert dut .wr_almost_full .value == 0
8688
8789
90+ # Generate sets of tests based on the different permutations of the possible arguments to fifo_test
91+ MAX_PERIOD_NS = 10
92+ MIN_PERIOD_NS = 1
93+ # Generate random clk period to test between min and max
94+ RAND_WR_CLK_PERIOD_NS , RAND_RD_CLK_PERIOD_NS = [
95+ random_decimal (MAX_PERIOD_NS , MIN_PERIOD_NS ) for _ in range (2 )
96+ ]
97+
98+
99+ @cocotb .test (timeout_time = 100 , timeout_unit = "ms" )
100+ @cocotb .parametrize (
101+ wr_clk_period_ns = [MIN_PERIOD_NS , RAND_WR_CLK_PERIOD_NS , MAX_PERIOD_NS ],
102+ rd_clk_period_ns = [MIN_PERIOD_NS , RAND_RD_CLK_PERIOD_NS , MAX_PERIOD_NS ],
103+ wr_en_generator = [None , random_bool_generator , bursty_en_gen ],
104+ rd_en_generator = [None , random_bool_generator , bursty_en_gen ]
105+ )
88106async def fifo_rd_wr_test (
89107 dut ,
90108 wr_clk_period_ns = 10.0 ,
@@ -98,25 +116,27 @@ async def fifo_rd_wr_test(
98116 clock = dut .wr_clk ,
99117 reset = dut .wr_nreset
100118 )
101- fifo_source .set_wr_en_generator (random_bool_generator ())
119+ if wr_en_generator :
120+ fifo_source .set_wr_en_generator (wr_en_generator ())
102121
103122 fifo_sink = LaAsyncFifoSink (
104123 bus = LaAsyncFifoRdBus .from_prefix (dut , "" ),
105124 clock = dut .rd_clk ,
106125 reset = dut .rd_nreset
107126 )
108- fifo_sink .set_rd_en_generator (random_bool_generator ())
127+ if rd_en_generator :
128+ fifo_sink .set_rd_en_generator (rd_en_generator ())
109129
110130 # Reset DUT
111131 await Combine (
112- cocotb .start_soon (drive_reset (dut .wr_nreset )),
113- cocotb .start_soon (drive_reset (dut .rd_nreset ))
132+ cocotb .start_soon (do_reset (dut .wr_nreset , time_ns = wr_clk_period_ns * 4 )),
133+ cocotb .start_soon (do_reset (dut .rd_nreset , time_ns = rd_clk_period_ns * 4 ))
114134 )
115135
116- await cocotb . start ( Clock (dut .wr_clk , wr_clk_period_ns , units = "ns" ).start () )
136+ Clock (dut .wr_clk , wr_clk_period_ns , units = "ns" ).start ()
117137 # Randomize phase shift between clocks
118- await Timer (wr_clk_period_ns * random .random (), "ns" , round_mode = "round" )
119- await cocotb . start ( Clock (dut .rd_clk , rd_clk_period_ns , units = "ns" ).start () )
138+ await Timer (wr_clk_period_ns * Decimal ( random .random () ), "ns" , round_mode = "round" )
139+ Clock (dut .rd_clk , rd_clk_period_ns , units = "ns" ).start ()
120140
121141 await ClockCycles (dut .wr_clk , 3 )
122142
@@ -133,55 +153,25 @@ async def fifo_rd_wr_test(
133153 await ClockCycles (dut .wr_clk , 10 )
134154
135155
136- # Generate sets of tests based on the different permutations of the possible arguments to fifo_test
137- MAX_PERIOD_NS = 10.0
138- MIN_PERIOD_NS = 1.0
139- # Generate random clk period to test between min and max
140- RAND_WR_CLK_PERIOD_NS , RAND_RD_CLK_PERIOD_NS = [utils .get_time_from_sim_steps (
141- # Time step must be even for cocotb clock driver
142- steps = utils .get_sim_steps (
143- time = Decimal (MIN_PERIOD_NS ) + (
144- Decimal (MAX_PERIOD_NS - MIN_PERIOD_NS )
145- * Decimal (random .random ()).quantize (Decimal ("0.00" ))
146- ),
147- units = "ns" ,
148- round_mode = "round"
149- ) & ~ 1 ,
150- units = "ns"
151- ) for _ in range (0 , 2 )]
152-
153- # Factory to automatically generate a set of tests based on the different permutations
154- # of the provided test arguments
155- tf = TestFactory (fifo_rd_wr_test )
156- tf .add_option ('wr_clk_period_ns' , [MIN_PERIOD_NS , RAND_WR_CLK_PERIOD_NS , MAX_PERIOD_NS ])
157- tf .add_option ('rd_clk_period_ns' , [MIN_PERIOD_NS , RAND_RD_CLK_PERIOD_NS , MAX_PERIOD_NS ])
158- tf .add_option ('wr_en_generator' , [None , random_bool_generator , bursty_en_gen ])
159- tf .add_option ('rd_en_generator' , [None , random_bool_generator , bursty_en_gen ])
160- tf .generate_tests ()
161-
162-
163- def test_la_asyncfifo ():
164- chip = siliconcompiler .Chip ("la_asyncfifo" )
165-
166- # TODO: should not be needed?
167- chip .input ("ramlib/la_asyncfifo/rtl/la_asyncfifo.v" , package = 'lambdalib' )
168- chip .use (ramlib )
156+ def load_cocotb_test ():
157+ from siliconcompiler import Sim
158+ from lambdalib .ramlib import Asyncfifo
159+
160+ project = Sim (Asyncfifo ())
161+ project .add_fileset ("rtl" )
169162
170163 for depth in [2 , 4 , 8 ]:
171- test_module_name = "lambdalib.ramlib.tests.tb_la_asyncfifo"
164+ test_module_name = __name__
172165 test_name = f"{ test_module_name } _depth_{ depth } "
173166 tests_failed = run_cocotb (
174- chip = chip ,
167+ project = project ,
175168 test_module_name = test_module_name ,
176169 timescale = ("1ns" , "1ps" ),
177170 parameters = {
178171 "DW" : 32 ,
179172 "DEPTH" : depth
180173 },
181- output_dir_name = test_name
174+ output_dir_name = test_name ,
175+ waves = False
182176 )
183177 assert (tests_failed == 0 ), f"Error test { test_name } failed!"
184-
185-
186- if __name__ == "__main__" :
187- test_la_asyncfifo ()
0 commit comments