add random-busy, random-send single and dual buffered pipeline tests
[ieee754fpu.git] / src / add / test_buf_pipe.py
index 32c7aa1a0daeefb34406ec48ba5451a04c105f5d..860f25cb114e2f5920edd69a9c468d3b506c00cc 100644 (file)
@@ -1,6 +1,8 @@
 from nmigen import Module, Signal
 from nmigen.compat.sim import run_simulation
 from example_buf_pipe import BufPipe
+from random import randint
+
 
 def check_o_n_stb(dut, val):
     o_n_stb = yield dut.o_n_stb
@@ -15,24 +17,24 @@ def testbench(dut):
     yield
     #yield dut.i_p_rst.eq(0)
     yield dut.i_n_busy.eq(0)
-    yield dut.i_data.eq(5)
+    yield dut.stage.i_data.eq(5)
     yield dut.i_p_stb.eq(1)
     yield
 
-    yield dut.i_data.eq(7)
+    yield dut.stage.i_data.eq(7)
     yield from check_o_n_stb(dut, 0) # effects of i_p_stb delayed
     yield
     yield from check_o_n_stb(dut, 1) # ok *now* i_p_stb effect is felt
 
-    yield dut.i_data.eq(2)
+    yield dut.stage.i_data.eq(2)
     yield
     yield dut.i_n_busy.eq(1) # begin going into "stall" (next stage says busy)
-    yield dut.i_data.eq(9)
+    yield dut.stage.i_data.eq(9)
     yield
     yield dut.i_p_stb.eq(0)
-    yield dut.i_data.eq(12)
+    yield dut.stage.i_data.eq(12)
     yield
-    yield dut.i_data.eq(32)
+    yield dut.stage.i_data.eq(32)
     yield dut.i_n_busy.eq(0)
     yield
     yield from check_o_n_stb(dut, 1) # buffer still needs to output
@@ -84,13 +86,75 @@ def testbench2(dut):
     yield
 
 
+def testbench3(dut):
+    data = []
+    for i in range(1000):
+        #data.append(randint(0, 1<<16-1))
+        data.append(i+1)
+    i = 0
+    o = 0
+    while True:
+        stall = randint(0, 3) == 0
+        send = randint(0, 5) != 0
+        yield dut.i_n_busy.eq(stall)
+        o_p_busy = yield dut.o_p_busy
+        if not o_p_busy:
+            if send and i != len(data):
+                yield dut.i_p_stb.eq(1)
+                yield dut.stage.i_data.eq(data[i])
+                i += 1
+            else:
+                yield dut.i_p_stb.eq(0)
+        yield
+        o_n_stb = yield dut.o_n_stb
+        i_n_busy = yield dut.i_n_busy
+        if o_n_stb and not i_n_busy:
+            o_data = yield dut.stage.o_data
+            assert o_data == data[o] + 1, "%d-%d data %x not match %x\n" \
+                                        % (i, o, o_data, data[o])
+            o += 1
+            if o == len(data):
+                break
+
+
+def testbench4(dut):
+    data = []
+    for i in range(1000):
+        #data.append(randint(0, 1<<16-1))
+        data.append(i+1)
+    i = 0
+    o = 0
+    while True:
+        stall = randint(0, 3) == 0
+        send = randint(0, 5) != 0
+        yield dut.i_n_busy.eq(stall)
+        o_p_busy = yield dut.o_p_busy
+        if not o_p_busy:
+            if send and i != len(data):
+                yield dut.i_p_stb.eq(1)
+                yield dut.i_data.eq(data[i])
+                i += 1
+            else:
+                yield dut.i_p_stb.eq(0)
+        yield
+        o_n_stb = yield dut.o_n_stb
+        i_n_busy = yield dut.i_n_busy
+        if o_n_stb and not i_n_busy:
+            o_data = yield dut.o_data
+            assert o_data == data[o] + 2, "%d-%d data %x not match %x\n" \
+                                        % (i, o, o_data, data[o])
+            o += 1
+            if o == len(data):
+                break
+
+
 class BufPipe2:
     """
         connect these:  ------|---------------|
                               v               v
         i_p_stb  >>in  pipe1 o_n_stb  out>> i_p_stb  >>in  pipe2
         o_p_busy <<out pipe1 i_n_busy <<in  o_p_busy <<out pipe2
-        i_data   >>in  pipe1 o_data   out>> i_data   >>in  pipe2
+        stage.i_data   >>in  pipe1 o_data   out>> stage.i_data   >>in  pipe2
     """
     def __init__(self):
         self.pipe1 = BufPipe()
@@ -114,17 +178,17 @@ class BufPipe2:
         # connect inter-pipe input/output stb/busy/data
         m.d.comb += self.pipe2.i_p_stb.eq(self.pipe1.o_n_stb)
         m.d.comb += self.pipe1.i_n_busy.eq(self.pipe2.o_p_busy)
-        m.d.comb += self.pipe2.i_data.eq(self.pipe1.o_data)
+        m.d.comb += self.pipe2.stage.i_data.eq(self.pipe1.stage.o_data)
 
         # inputs/outputs to the module: pipe1 connections here (LHS)
         m.d.comb += self.pipe1.i_p_stb.eq(self.i_p_stb)
         m.d.comb += self.o_p_busy.eq(self.pipe1.o_p_busy)
-        m.d.comb += self.pipe1.i_data.eq(self.i_data)
+        m.d.comb += self.pipe1.stage.i_data.eq(self.i_data)
 
         # now pipe2 connections (RHS)
         m.d.comb += self.o_n_stb.eq(self.pipe2.o_n_stb)
         m.d.comb += self.pipe2.i_n_busy.eq(self.i_n_busy)
-        m.d.comb += self.o_data.eq(self.pipe2.o_data)
+        m.d.comb += self.o_data.eq(self.pipe2.stage.o_data)
 
         return m
 
@@ -134,3 +198,9 @@ if __name__ == '__main__':
 
     dut = BufPipe2()
     run_simulation(dut, testbench2(dut), vcd_name="test_bufpipe2.vcd")
+
+    dut = BufPipe()
+    run_simulation(dut, testbench3(dut), vcd_name="test_bufpipe3.vcd")
+
+    dut = BufPipe2()
+    run_simulation(dut, testbench4(dut), vcd_name="test_bufpipe4.vcd")