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