create actual FPADD Pipeline from stages
[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 from sfpy import Float32
17
18 class InputTest:
19 def __init__(self, dut):
20 self.dut = dut
21 self.di = {}
22 self.do = {}
23 self.tlen = 4
24 self.width = 32
25 for mid in range(dut.num_rows):
26 self.di[mid] = {}
27 self.do[mid] = []
28 for i in range(self.tlen):
29 op1 = randint(0, (1<<self.width)-1)
30 op2 = randint(0, (1<<self.width)-1)
31 res = Float32(op1) + Float32(op2)
32 self.di[mid][i] = (op1, op2)
33 self.do[mid].append(res.bits)
34
35 def send(self, mid):
36 for i in range(self.tlen):
37 op1, op2 = self.di[mid][i]
38 rs = dut.p[mid]
39 yield rs.i_valid.eq(1)
40 yield rs.i_data.a.eq(op1)
41 yield rs.i_data.b.eq(op2)
42 yield rs.i_data.mid.eq(mid)
43 yield
44 o_p_ready = yield rs.o_ready
45 while not o_p_ready:
46 yield
47 o_p_ready = yield rs.o_ready
48
49 fop1 = Float32(op1)
50 fop2 = Float32(op2)
51 res = fop1 + fop2
52 print ("send", mid, i, hex(op1), hex(op2), hex(res.bits),
53 fop1, fop2, res)
54
55 yield rs.i_valid.eq(0)
56 # wait random period of time before queueing another value
57 for i in range(randint(0, 3)):
58 yield
59
60 yield rs.i_valid.eq(0)
61 yield
62
63 print ("send ended", mid)
64
65 ## wait random period of time before queueing another value
66 #for i in range(randint(0, 3)):
67 # yield
68
69 #send_range = randint(0, 3)
70 #if send_range == 0:
71 # send = True
72 #else:
73 # send = randint(0, send_range) != 0
74
75 def rcv(self, mid):
76 while True:
77 #stall_range = randint(0, 3)
78 #for j in range(randint(1,10)):
79 # stall = randint(0, stall_range) != 0
80 # yield self.dut.n[0].i_ready.eq(stall)
81 # yield
82 n = self.dut.n[mid]
83 yield n.i_ready.eq(1)
84 yield
85 o_n_valid = yield n.o_valid
86 i_n_ready = yield n.i_ready
87 if not o_n_valid or not i_n_ready:
88 continue
89
90 out_mid = yield n.o_data.mid
91 out_z = yield n.o_data.z
92
93 out_i = 0
94
95 print ("recv", out_mid, hex(out_z), "expected",
96 hex(self.do[mid][out_i] ))
97
98 # see if this output has occurred already, delete it if it has
99 assert mid == out_mid, "out_mid %d not correct %d" % (out_mid, mid)
100 assert self.do[mid][out_i] == out_z
101 del self.do[mid][out_i]
102
103 # check if there's any more outputs
104 if len(self.do[mid]) == 0:
105 break
106 print ("recv ended", mid)
107
108
109
110 if __name__ == '__main__':
111 dut = FPADDMuxInOut(32, 2, 4)
112 vl = rtlil.convert(dut, ports=dut.ports())
113 with open("test_fpadd_pipe.il", "w") as f:
114 f.write(vl)
115 #run_simulation(dut, testbench(dut), vcd_name="test_inputgroup.vcd")
116
117 test = InputTest(dut)
118 run_simulation(dut, [test.rcv(1), test.rcv(0),
119 test.rcv(3), test.rcv(2),
120 test.send(0), test.send(1),
121 test.send(3), test.send(2),
122 ],
123 vcd_name="test_inoutmux_pipe.vcd")
124