remove unneeded imports
[soc.git] / src / soc / fu / compunits / test / test_compunit.py
1 from nmigen import Module, Signal
2 from nmigen.back.pysim import Simulator, Delay, Settle
3 from nmutil.formaltest import FHDLTestCase
4 from nmigen.cli import rtlil
5 import unittest
6 from soc.decoder.power_decoder import (create_pdecode)
7 from soc.decoder.power_decoder2 import (PowerDecode2)
8 from soc.decoder.isa.all import ISA
9
10 from soc.experiment.compalu_multi import find_ok # hack
11
12
13 def set_cu_input(cu, idx, data):
14 rdop = cu.get_in_name(idx)
15 yield cu.src_i[idx].eq(data)
16 while True:
17 rd_rel_o = yield cu.rd.rel[idx]
18 print ("rd_rel %d wait HI" % idx, rd_rel_o, rdop, hex(data))
19 if rd_rel_o:
20 break
21 yield
22 yield cu.rd.go[idx].eq(1)
23 while True:
24 yield
25 rd_rel_o = yield cu.rd.rel[idx]
26 if rd_rel_o:
27 break
28 print ("rd_rel %d wait HI" % idx, rd_rel_o)
29 yield
30 yield cu.rd.go[idx].eq(0)
31 yield cu.src_i[idx].eq(0)
32
33
34 def get_cu_output(cu, idx, code):
35 wrmask = yield cu.wrmask
36 wrop = cu.get_out_name(idx)
37 wrok = cu.get_out(idx)
38 fname = find_ok(wrok.fields)
39 wrok = yield getattr(wrok, fname)
40 print ("wr_rel mask", repr(code), idx, wrop, bin(wrmask), fname, wrok)
41 assert wrmask & (1<<idx), \
42 "get_cu_output '%s': mask bit %d not set\n" \
43 "write-operand '%s' Data.ok likely not set (%s)" \
44 % (code, idx, wrop, hex(wrok))
45 while True:
46 wr_relall_o = yield cu.wr.rel
47 wr_rel_o = yield cu.wr.rel[idx]
48 print ("wr_rel %d wait" % idx, hex(wr_relall_o), wr_rel_o)
49 if wr_rel_o:
50 break
51 yield
52 yield cu.wr.go[idx].eq(1)
53 yield Settle()
54 result = yield cu.dest[idx]
55 yield
56 yield cu.wr.go[idx].eq(0)
57 print ("result", repr(code), idx, wrop, wrok, hex(result))
58 return result
59
60
61 def set_cu_inputs(cu, inp):
62 for idx, data in inp.items():
63 yield from set_cu_input(cu, idx, data)
64
65
66 def set_operand(cu, dec2, sim):
67 yield from cu.oper_i.eq_from_execute1(dec2.e)
68 yield cu.issue_i.eq(1)
69 yield
70 yield cu.issue_i.eq(0)
71 yield
72
73
74 def get_cu_outputs(cu, code):
75 res = {}
76 for i in range(cu.n_dst):
77 wr_rel_o = yield cu.wr.rel[i]
78 if wr_rel_o:
79 result = yield from get_cu_output(cu, i, code)
80 wrop = cu.get_out_name(i)
81 print ("output", i, wrop, hex(result))
82 res[wrop] = result
83 return res
84
85
86 def get_inp_indexed(cu, inp):
87 res = {}
88 for i in range(cu.n_src):
89 wrop = cu.get_in_name(i)
90 if wrop in inp:
91 res[i] = inp[wrop]
92 return res
93
94
95 class TestRunner(FHDLTestCase):
96 def __init__(self, test_data, fukls, iodef, funit):
97 super().__init__("run_all")
98 self.test_data = test_data
99 self.fukls = fukls
100 self.iodef = iodef
101 self.funit = funit
102
103 def run_all(self):
104 m = Module()
105 comb = m.d.comb
106 instruction = Signal(32)
107
108 pdecode = create_pdecode()
109
110 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
111 m.submodules.cu = cu = self.fukls()
112
113 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
114 sim = Simulator(m)
115
116 sim.add_clock(1e-6)
117
118 def process():
119 yield cu.issue_i.eq(0)
120 yield
121
122 for test in self.test_data:
123 print(test.name)
124 program = test.program
125 self.subTest(test.name)
126 sim = ISA(pdecode2, test.regs, test.sprs, 0)
127 gen = program.generate_instructions()
128 instructions = list(zip(gen, program.assembly.splitlines()))
129
130 index = sim.pc.CIA.value//4
131 while index < len(instructions):
132 ins, code = instructions[index]
133
134 print("0x{:X}".format(ins & 0xffffffff))
135 print(code)
136
137 # ask the decoder to decode this binary data (endian'd)
138 yield pdecode2.dec.bigendian.eq(0) # little / big?
139 yield instruction.eq(ins) # raw binary instr.
140 yield Settle()
141 fn_unit = yield pdecode2.e.fn_unit
142 fuval = self.funit.value
143 self.assertEqual(fn_unit & fuval, fuval)
144
145 # set operand and get inputs
146 yield from set_operand(cu, pdecode2, sim)
147 iname = yield from self.iodef.get_cu_inputs(pdecode2, sim)
148 inp = get_inp_indexed(cu, iname)
149
150 # reset read-operand mask
151 rdmask = pdecode2.rdflags(cu)
152 #print ("hardcoded rdmask", cu.rdflags(pdecode2.e))
153 #print ("decoder rdmask", rdmask)
154 yield cu.rdmaskn.eq(~rdmask)
155
156 # reset write-operand mask
157 for idx in range(cu.n_dst):
158 wrok = cu.get_out(idx)
159 fname = find_ok(wrok.fields)
160 yield getattr(wrok, fname).eq(0)
161
162 yield Settle()
163
164 # set inputs into CU
165 rd_rel_o = yield cu.rd.rel
166 wr_rel_o = yield cu.wr.rel
167 print ("before inputs, rd_rel, wr_rel: ",
168 bin(rd_rel_o), bin(wr_rel_o))
169 assert wr_rel_o == 0, "wr.rel %s must be zero. "\
170 "previous instr not written all regs\n"\
171 "respec %s" % \
172 (bin(wr_rel_o), cu.rwid[1])
173 yield from set_cu_inputs(cu, inp)
174 yield
175 rd_rel_o = yield cu.rd.rel
176 wr_rel_o = yield cu.wr.rel
177 wrmask = yield cu.wrmask
178 print ("after inputs, rd_rel, wr_rel, wrmask: ",
179 bin(rd_rel_o), bin(wr_rel_o), bin(wrmask))
180
181 # call simulated operation
182 opname = code.split(' ')[0]
183 yield from sim.call(opname)
184 index = sim.pc.CIA.value//4
185
186 yield Settle()
187 # get all outputs (one by one, just "because")
188 res = yield from get_cu_outputs(cu, code)
189
190 yield from self.iodef.check_cu_outputs(res, pdecode2,
191 sim, code)
192
193 sim.add_sync_process(process)
194 with sim.write_vcd("simulator.vcd", "simulator.gtkw",
195 traces=[]):
196 sim.run()
197
198