01832ec47b65f113d342bb9b7729e5d892436b2d
[ieee754fpu.git] / src / ieee754 / fpcommon / test / fpmux.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 nmigen.compat.sim import run_simulation
10 from nmigen.cli import verilog, rtlil
11
12
13 class InputTest:
14 def __init__(self, dut, width, fpkls, fpop):
15 self.dut = dut
16 self.fpkls = fpkls
17 self.fpop = fpop
18 self.di = {}
19 self.do = {}
20 self.tlen = 10
21 self.width = width
22 for mid in range(dut.num_rows):
23 self.di[mid] = {}
24 self.do[mid] = []
25 for i in range(self.tlen):
26 op1 = randint(0, (1<<self.width)-1)
27 op2 = randint(0, (1<<self.width)-1)
28 #op1 = 0x513ba448
29 #op2 = 0xfff5c7fe
30 #op1 = 0xffcaeefa
31 #op2 = 0x3f803262
32 #op1 = 0xae430313
33 #op2 = 0x901c3214
34 #op1 = 0xa4504d7
35 #op2 = 0xb4658540 # expect 0x8016147c
36 #op1 = 0x40900000
37 #op2 = 0x40200000
38 res = self.fpop(self.fpkls(op1), self.fpkls(op2))
39 self.di[mid][i] = (op1, op2)
40 self.do[mid].append(res.bits)
41
42 def send(self, mid):
43 for i in range(self.tlen):
44 op1, op2 = self.di[mid][i]
45 rs = self.dut.p[mid]
46 yield rs.valid_i.eq(1)
47 yield rs.data_i.a.eq(op1)
48 yield rs.data_i.b.eq(op2)
49 yield rs.data_i.mid.eq(mid)
50 yield
51 o_p_ready = yield rs.ready_o
52 while not o_p_ready:
53 yield
54 o_p_ready = yield rs.ready_o
55
56 fop1 = self.fpkls(op1)
57 fop2 = self.fpkls(op2)
58 res = self.fpop(fop1, fop2)
59 print ("send", mid, i, hex(op1), hex(op2), hex(res.bits),
60 fop1, fop2, res)
61
62 yield rs.valid_i.eq(0)
63 # wait random period of time before queueing another value
64 for i in range(randint(0, 3)):
65 yield
66
67 yield rs.valid_i.eq(0)
68 yield
69
70 print ("send ended", mid)
71
72 ## wait random period of time before queueing another value
73 #for i in range(randint(0, 3)):
74 # yield
75
76 #send_range = randint(0, 3)
77 #if send_range == 0:
78 # send = True
79 #else:
80 # send = randint(0, send_range) != 0
81
82 def rcv(self, mid):
83 while True:
84 #stall_range = randint(0, 3)
85 #for j in range(randint(1,10)):
86 # stall = randint(0, stall_range) != 0
87 # yield self.dut.n[0].ready_i.eq(stall)
88 # yield
89 n = self.dut.n[mid]
90 yield n.ready_i.eq(1)
91 yield
92 o_n_valid = yield n.valid_o
93 i_n_ready = yield n.ready_i
94 if not o_n_valid or not i_n_ready:
95 continue
96
97 out_mid = yield n.data_o.mid
98 out_z = yield n.data_o.z
99
100 out_i = 0
101
102 print ("recv", out_mid, hex(out_z), "expected",
103 hex(self.do[mid][out_i] ))
104
105 # see if this output has occurred already, delete it if it has
106 assert mid == out_mid, "out_mid %d not correct %d" % (out_mid, mid)
107 assert self.do[mid][out_i] == out_z
108 del self.do[mid][out_i]
109
110 # check if there's any more outputs
111 if len(self.do[mid]) == 0:
112 break
113 print ("recv ended", mid)
114
115
116 def runfp(dut, width, name, fpkls, fpop):
117 vl = rtlil.convert(dut, ports=dut.ports())
118 with open("%s.il" % name, "w") as f:
119 f.write(vl)
120
121 test = InputTest(dut, width, fpkls, fpop)
122 run_simulation(dut, [test.rcv(1), test.rcv(0),
123 test.rcv(3), test.rcv(2),
124 test.send(0), test.send(1),
125 test.send(3), test.send(2),
126 ],
127 vcd_name="%s.vcd" % name)
128