fix tests
[soc.git] / src / soc / decoder / test / test_decoder_gas.py
1 from nmigen import Module, Signal
2 from nmigen.back.pysim import Simulator, Delay
3 from nmigen.test.utils import FHDLTestCase
4 import unittest
5 from soc.decoder.power_decoder import (create_pdecode)
6 from soc.decoder.power_enums import (Function, InternalOp,
7 In1Sel, In2Sel, In3Sel,
8 OutSel, RC, LdstLen, CryIn,
9 single_bit_flags, Form, SPR,
10 get_signal_name, get_csv)
11 from soc.decoder.power_decoder2 import (PowerDecode2)
12 from soc.simulator.gas import get_assembled_instruction
13 import random
14
15
16 class Register:
17 def __init__(self, num):
18 self.num = num
19
20
21 class Checker:
22 def __init__(self):
23 self.imm = 0
24
25 def get_imm(self, in2_sel):
26 if in2_sel == In2Sel.CONST_UI.value:
27 return self.imm & 0xffff
28 if in2_sel == In2Sel.CONST_UI_HI.value:
29 return (self.imm & 0xffff) << 16
30 if in2_sel == In2Sel.CONST_SI.value:
31 sign_bit = 1 << 15
32 return (self.imm & (sign_bit-1)) - (self.imm & sign_bit)
33 if in2_sel == In2Sel.CONST_SI_HI.value:
34 imm = self.imm << 16
35 sign_bit = 1 << 31
36 return (imm & (sign_bit-1)) - (imm & sign_bit)
37
38
39 class RegRegOp:
40 def __init__(self):
41 self.ops = {
42 "add": InternalOp.OP_ADD,
43 "and": InternalOp.OP_AND,
44 "or": InternalOp.OP_OR,
45 "add.": InternalOp.OP_ADD,
46 "lwzx": InternalOp.OP_LOAD,
47 "stwx": InternalOp.OP_STORE,
48 }
49 self.opcodestr = random.choice(list(self.ops.keys()))
50 self.opcode = self.ops[self.opcodestr]
51 self.r1 = Register(random.randrange(32))
52 self.r2 = Register(random.randrange(32))
53 self.r3 = Register(random.randrange(32))
54
55 def generate_instruction(self):
56 string = "{} {}, {}, {}\n".format(self.opcodestr,
57 self.r1.num,
58 self.r2.num,
59 self.r3.num)
60 return string
61
62 def check_results(self, pdecode2):
63 if self.opcode == InternalOp.OP_STORE:
64 r1sel = yield pdecode2.e.read_reg3.data
65 else:
66 r1sel = yield pdecode2.e.write_reg.data
67
68 r3sel = yield pdecode2.e.read_reg2.data
69
70 # For some reason r2 gets decoded either in read_reg1
71 # or read_reg3
72 out_sel = yield pdecode2.dec.op.out_sel
73 if out_sel == OutSel.RA.value:
74 r2sel = yield pdecode2.e.read_reg3.data
75 else:
76 r2sel = yield pdecode2.e.read_reg1.data
77 assert(r1sel == self.r1.num)
78 assert(r3sel == self.r3.num)
79 assert(r2sel == self.r2.num)
80
81 opc_out = yield pdecode2.dec.op.internal_op
82 assert(opc_out == self.opcode.value)
83 # check RC value (the dot in the instruction)
84 rc = yield pdecode2.e.rc.data
85 if '.' in self.opcodestr:
86 assert(rc == 1)
87 else:
88 assert(rc == 0)
89
90
91 class RegImmOp(Checker):
92 def __init__(self):
93 super().__init__()
94 self.ops = {
95 "addi": InternalOp.OP_ADD,
96 "addis": InternalOp.OP_ADD,
97 "andi.": InternalOp.OP_AND,
98 "ori": InternalOp.OP_OR,
99 }
100 self.opcodestr = random.choice(list(self.ops.keys()))
101 self.opcode = self.ops[self.opcodestr]
102 self.r1 = Register(random.randrange(32))
103 self.r2 = Register(random.randrange(32))
104 self.imm = random.randrange(32767)
105
106 def generate_instruction(self):
107 string = "{} {}, {}, {}\n".format(self.opcodestr,
108 self.r1.num,
109 self.r2.num,
110 self.imm)
111 return string
112
113 def check_results(self, pdecode2):
114 print("Check")
115 r1sel = yield pdecode2.e.write_reg.data
116 # For some reason r2 gets decoded either in read_reg1
117 # or read_reg3
118 out_sel = yield pdecode2.dec.op.out_sel
119 if out_sel == OutSel.RA.value:
120 r2sel = yield pdecode2.e.read_reg3.data
121 else:
122 r2sel = yield pdecode2.e.read_reg1.data
123 assert(r1sel == self.r1.num)
124 assert(r2sel == self.r2.num)
125
126 imm = yield pdecode2.e.imm_data.data
127 in2_sel = yield pdecode2.dec.op.in2_sel
128 imm_expected = self.get_imm(in2_sel)
129 msg = "imm: got {:x}, expected {:x}".format(imm, imm_expected)
130 assert imm == imm_expected, msg
131
132 rc = yield pdecode2.e.rc.data
133 if '.' in self.opcodestr:
134 assert(rc == 1)
135 else:
136 assert(rc == 0)
137
138
139 class LdStOp(Checker):
140 def __init__(self):
141 super().__init__()
142 self.ops = {
143 "lwz": InternalOp.OP_LOAD,
144 "stw": InternalOp.OP_STORE,
145 "lwzu": InternalOp.OP_LOAD,
146 "stwu": InternalOp.OP_STORE,
147 "lbz": InternalOp.OP_LOAD,
148 "lhz": InternalOp.OP_LOAD,
149 "stb": InternalOp.OP_STORE,
150 "sth": InternalOp.OP_STORE,
151 }
152 self.opcodestr = random.choice(list(self.ops.keys()))
153 self.opcode = self.ops[self.opcodestr]
154 self.r1 = Register(random.randrange(32))
155 self.r2 = Register(random.randrange(1, 32))
156 while self.r2.num == self.r1.num:
157 self.r2 = Register(random.randrange(1, 32))
158 self.imm = random.randrange(32767)
159
160 def generate_instruction(self):
161 string = "{} {}, {}({})\n".format(self.opcodestr,
162 self.r1.num,
163 self.imm,
164 self.r2.num)
165 return string
166
167 def check_results(self, pdecode2):
168 print("Check")
169 r2sel = yield pdecode2.e.read_reg1.data
170 if self.opcode == InternalOp.OP_STORE:
171 r1sel = yield pdecode2.e.read_reg3.data
172 else:
173 r1sel = yield pdecode2.e.write_reg.data
174 assert(r1sel == self.r1.num)
175 assert(r2sel == self.r2.num)
176
177 imm = yield pdecode2.e.imm_data.data
178 in2_sel = yield pdecode2.dec.op.in2_sel
179 assert(imm == self.get_imm(in2_sel))
180
181 update = yield pdecode2.e.update
182 if "u" in self.opcodestr:
183 assert(update == 1)
184 else:
185 assert(update == 0)
186
187 size = yield pdecode2.e.data_len
188 if "w" in self.opcodestr:
189 assert(size == 4)
190 elif "h" in self.opcodestr:
191 assert(size == 2)
192 elif "b" in self.opcodestr:
193 assert(size == 1)
194 else:
195 assert(False)
196
197
198 class CmpRegOp:
199 def __init__(self):
200 self.ops = {
201 "cmp": InternalOp.OP_CMP,
202 }
203 self.opcodestr = random.choice(list(self.ops.keys()))
204 self.opcode = self.ops[self.opcodestr]
205 self.r1 = Register(random.randrange(32))
206 self.r2 = Register(random.randrange(32))
207 self.cr = Register(random.randrange(8))
208
209 def generate_instruction(self):
210 string = "{} {}, 0, {}, {}\n".format(self.opcodestr,
211 self.cr.num,
212 self.r1.num,
213 self.r2.num)
214 return string
215
216 def check_results(self, pdecode2):
217 r1sel = yield pdecode2.e.read_reg1.data
218 r2sel = yield pdecode2.e.read_reg2.data
219 crsel = yield pdecode2.dec.BF
220
221 assert(r1sel == self.r1.num)
222 assert(r2sel == self.r2.num)
223 assert(crsel == self.cr.num)
224
225
226 class RotateOp:
227 def __init__(self):
228 self.ops = {
229 "rlwinm": InternalOp.OP_CMP,
230 "rlwnm": InternalOp.OP_CMP,
231 "rlwimi": InternalOp.OP_CMP,
232 "rlwinm.": InternalOp.OP_CMP,
233 "rlwnm.": InternalOp.OP_CMP,
234 "rlwimi.": InternalOp.OP_CMP,
235 }
236 self.opcodestr = random.choice(list(self.ops.keys()))
237 self.opcode = self.ops[self.opcodestr]
238 self.r1 = Register(random.randrange(32))
239 self.r2 = Register(random.randrange(32))
240 self.shift = random.randrange(32)
241 self.mb = random.randrange(32)
242 self.me = random.randrange(32)
243
244 def generate_instruction(self):
245 string = "{} {},{},{},{},{}\n".format(self.opcodestr,
246 self.r1.num,
247 self.r2.num,
248 self.shift,
249 self.mb,
250 self.me)
251 return string
252
253 def check_results(self, pdecode2):
254 r1sel = yield pdecode2.e.write_reg.data
255 r2sel = yield pdecode2.e.read_reg3.data
256 dec = pdecode2.dec
257
258 if "i" in self.opcodestr:
259 shift = yield dec.SH
260 else:
261 shift = yield pdecode2.e.read_reg2.data
262 mb = yield dec.MB
263 me = yield dec.ME
264
265 assert(r1sel == self.r1.num)
266 assert(r2sel == self.r2.num)
267 assert(shift == self.shift)
268 assert(mb == self.mb)
269 assert(me == self.me)
270
271 rc = yield pdecode2.e.rc.data
272 if '.' in self.opcodestr:
273 assert(rc == 1)
274 else:
275 assert(rc == 0)
276
277
278 class Branch:
279 def __init__(self):
280 self.ops = {
281 "b": InternalOp.OP_B,
282 "bl": InternalOp.OP_B,
283 "ba": InternalOp.OP_B,
284 "bla": InternalOp.OP_B,
285 }
286 self.opcodestr = random.choice(list(self.ops.keys()))
287 self.opcode = self.ops[self.opcodestr]
288 self.addr = random.randrange(2**23) * 4
289
290 def generate_instruction(self):
291 string = "{} {}\n".format(self.opcodestr,
292 self.addr)
293 return string
294
295 def check_results(self, pdecode2):
296 imm = yield pdecode2.e.imm_data.data
297
298 assert(imm == self.addr)
299 lk = yield pdecode2.e.lk
300 if "l" in self.opcodestr:
301 assert(lk == 1)
302 else:
303 assert(lk == 0)
304 aa = yield pdecode2.dec.AA
305 if "a" in self.opcodestr:
306 assert(aa == 1)
307 else:
308 assert(aa == 0)
309
310
311 class BranchCond:
312 def __init__(self):
313 self.ops = {
314 "bc": InternalOp.OP_B,
315 "bcl": InternalOp.OP_B,
316 "bca": InternalOp.OP_B,
317 "bcla": InternalOp.OP_B,
318 }
319 # Given in Figure 40 "BO field encodings" in section 2.4, page
320 # 33 of the Power ISA v3.0B manual
321 self.branchops = [0b00000, 0b00010, 0b00100, 0b01000, 0b01010,
322 0b01100, 0b10000, 0b10100]
323 self.opcodestr = random.choice(list(self.ops.keys()))
324 self.opcode = self.ops[self.opcodestr]
325 self.addr = random.randrange(2**13) * 4
326 self.bo = random.choice(self.branchops)
327 self.bi = random.randrange(32)
328
329 def generate_instruction(self):
330 string = "{} {},{},{}\n".format(self.opcodestr,
331 self.bo,
332 self.bi,
333 self.addr)
334 return string
335
336 def check_results(self, pdecode2):
337 imm = yield pdecode2.e.imm_data.data
338 bo = yield pdecode2.dec.BO
339 bi = yield pdecode2.dec.BI
340
341 assert(imm == self.addr)
342 assert(bo == self.bo)
343 assert(bi == self.bi)
344 lk = yield pdecode2.e.lk
345 if "l" in self.opcodestr:
346 assert(lk == 1)
347 else:
348 assert(lk == 0)
349 aa = yield pdecode2.dec.AA
350 if "a" in self.opcodestr:
351 assert(aa == 1)
352 else:
353 assert(aa == 0)
354
355
356 class BranchRel:
357 def __init__(self):
358 self.ops = {
359 "bclr": InternalOp.OP_B,
360 "bcctr": InternalOp.OP_B,
361 "bclrl": InternalOp.OP_B,
362 "bcctrl": InternalOp.OP_B,
363 }
364 # Given in Figure 40 "BO field encodings" in section 2.4, page
365 # 33 of the Power ISA v3.0B manual
366 self.branchops = [0b00100, 0b01100, 0b10100]
367 self.opcodestr = random.choice(list(self.ops.keys()))
368 self.opcode = self.ops[self.opcodestr]
369 self.bh = random.randrange(4)
370 self.bo = random.choice(self.branchops)
371 self.bi = random.randrange(32)
372
373 def generate_instruction(self):
374 string = "{} {},{},{}\n".format(self.opcodestr,
375 self.bo,
376 self.bi,
377 self.bh)
378 return string
379
380 def check_results(self, pdecode2):
381 bo = yield pdecode2.dec.BO
382 bi = yield pdecode2.dec.BI
383
384 assert(bo == self.bo)
385 assert(bi == self.bi)
386
387 spr = yield pdecode2.e.read_spr2.data
388 if "lr" in self.opcodestr:
389 assert(spr == SPR.LR.value)
390 else:
391 assert(spr == SPR.CTR.value)
392
393 lk = yield pdecode2.e.lk
394 if self.opcodestr[-1] == 'l':
395 assert(lk == 1)
396 else:
397 assert(lk == 0)
398
399
400 class DecoderTestCase(FHDLTestCase):
401
402 def run_tst(self, kls, name):
403 m = Module()
404 comb = m.d.comb
405 instruction = Signal(32)
406
407 pdecode = create_pdecode()
408
409 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
410 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
411 sim = Simulator(m)
412
413 def process():
414 for i in range(20):
415 checker = kls()
416 ins = checker.generate_instruction()
417 print("instr", ins.strip())
418 for mode in [0, 1]:
419
420 # turn the instruction into binary data (endian'd)
421 ibin = get_assembled_instruction(ins, mode)
422 print("code", mode, hex(ibin), bin(ibin))
423
424 # ask the decoder to decode this binary data (endian'd)
425 yield pdecode2.dec.bigendian.eq(mode) # little / big?
426 yield instruction.eq(ibin) # raw binary instr.
427 yield Delay(1e-6)
428
429 yield from checker.check_results(pdecode2)
430
431 sim.add_process(process)
432 ports = pdecode2.ports()
433 print(ports)
434 with sim.write_vcd("%s.vcd" % name, "%s.gtkw" % name,
435 traces=ports):
436 sim.run()
437
438 def test_reg_reg(self):
439 self.run_tst(RegRegOp, "reg_reg")
440
441 def test_reg_imm(self):
442 self.run_tst(RegImmOp, "reg_imm")
443
444 def test_ldst_imm(self):
445 self.run_tst(LdStOp, "ldst_imm")
446
447 def test_cmp_reg(self):
448 self.run_tst(CmpRegOp, "cmp_reg")
449
450 def test_rot(self):
451 self.run_tst(RotateOp, "rot")
452
453 def test_branch(self):
454 self.run_tst(Branch, "branch")
455
456 def test_branch_cond(self):
457 self.run_tst(BranchCond, "branch_cond")
458
459 def test_branch_rel(self):
460 self.run_tst(BranchRel, "branch_rel")
461
462
463 if __name__ == "__main__":
464 unittest.main()