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