add unit test for multi-in multi-out FPADDBasePipe
[ieee754fpu.git] / src / add / test_fpadd_pipe.py
1 """ key strategic example showing how to do multi-input fan-in into a
2 multi-stage pipeline, then multi-output fanout.
3
4 the multiplex ID from the fan-in is passed in to the pipeline, preserved,
5 and used as a routing ID on the fanout.
6 """
7
8 from random import randint
9 from math import log
10 from nmigen import Module, Signal, Cat, Value
11 from nmigen.compat.sim import run_simulation
12 from nmigen.cli import verilog, rtlil
13
14 from nmigen_add_experiment import (FPADDMuxInOut,)
15
16
17 class InputTest:
18 def __init__(self, dut):
19 self.dut = dut
20 self.di = {}
21 self.do = {}
22 self.tlen = 4
23 for mid in range(dut.num_rows):
24 self.di[mid] = {}
25 self.do[mid] = []
26 for i in range(self.tlen):
27 op1 = randint(0, 255)
28 op2 = randint(0, 255)
29 self.di[mid][i] = (op1, op2)
30 self.do[mid].append(op1 + op2)
31
32 def send(self, mid):
33 for i in range(self.tlen):
34 op1, op2 = self.di[mid][i]
35 rs = dut.p[mid]
36 yield rs.i_valid.eq(1)
37 yield rs.i_data.a.eq(op1)
38 yield rs.i_data.b.eq(op2)
39 yield rs.i_data.mid.eq(mid)
40 yield
41 o_p_ready = yield rs.o_ready
42 while not o_p_ready:
43 yield
44 o_p_ready = yield rs.o_ready
45
46 print ("send", mid, i, op1, op2, op1+op2)
47
48 yield rs.i_valid.eq(0)
49 # wait random period of time before queueing another value
50 for i in range(randint(0, 3)):
51 yield
52
53 yield rs.i_valid.eq(0)
54 yield
55
56 print ("send ended", mid)
57
58 ## wait random period of time before queueing another value
59 #for i in range(randint(0, 3)):
60 # yield
61
62 #send_range = randint(0, 3)
63 #if send_range == 0:
64 # send = True
65 #else:
66 # send = randint(0, send_range) != 0
67
68 def rcv(self, mid):
69 while True:
70 #stall_range = randint(0, 3)
71 #for j in range(randint(1,10)):
72 # stall = randint(0, stall_range) != 0
73 # yield self.dut.n[0].i_ready.eq(stall)
74 # yield
75 n = self.dut.n[mid]
76 yield n.i_ready.eq(1)
77 yield
78 o_n_valid = yield n.o_valid
79 i_n_ready = yield n.i_ready
80 if not o_n_valid or not i_n_ready:
81 continue
82
83 out_mid = yield n.o_data.mid
84 out_z = yield n.o_data.z
85
86 print ("recv", out_mid, out_z)
87
88 out_i = 0
89
90 # see if this output has occurred already, delete it if it has
91 assert mid == out_mid, "out_mid %d not correct %d" % (out_mid, mid)
92 assert self.do[mid][out_i] == out_z # pass-through data
93 del self.do[mid][out_i]
94
95 # check if there's any more outputs
96 if len(self.do[mid]) == 0:
97 break
98 print ("recv ended", mid)
99
100
101
102 if __name__ == '__main__':
103 dut = FPADDMuxInOut(16, 2, 4)
104 vl = rtlil.convert(dut, ports=dut.ports())
105 with open("test_fpadd_pipe.il", "w") as f:
106 f.write(vl)
107 #run_simulation(dut, testbench(dut), vcd_name="test_inputgroup.vcd")
108
109 test = InputTest(dut)
110 run_simulation(dut, [test.rcv(1), test.rcv(0),
111 test.rcv(3), test.rcv(2),
112 test.send(0), test.send(1),
113 test.send(3), test.send(2),
114 ],
115 vcd_name="test_inoutmux_pipe.vcd")
116