Add assertions for input registers
[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 from nmigen.cli import rtlil
5 import os
6 import unittest
7 from soc.decoder.power_decoder import (create_pdecode)
8 from soc.decoder.power_enums import (Function, InternalOp,
9 In1Sel, In2Sel,In3Sel,
10 OutSel, RC, LdstLen, CryIn,
11 single_bit_flags, Form,
12 get_signal_name, get_csv)
13 from soc.decoder.power_decoder2 import (PowerDecode2)
14 import tempfile
15 import subprocess
16 import struct
17 import random
18
19 ops = {
20 InternalOp.OP_ADD: "add",
21 InternalOp.OP_AND: "and",
22 InternalOp.OP_OR: "or"}
23
24 class Register:
25 def __init__(self, num):
26 self.num = num
27
28
29 class DecoderTestCase(FHDLTestCase):
30 def generate_opcode_string(self, internalop, r1, r2, op3):
31 opcodestr = ops[internalop]
32 if isinstance(op3, Register):
33 immstring = ""
34 op3str = op3.num
35 else:
36 immstring = "i"
37 op3str = str(op3)
38 string = "{}{} {}, {}, {}\n".format(opcodestr,
39 immstring,
40 r1.num,
41 r2.num,
42 op3str)
43 return string
44
45 def get_assembled_instruction(self, instruction):
46 with tempfile.NamedTemporaryFile(suffix=".o") as outfile:
47 args = ["powerpc64-linux-gnu-as",
48 "-o",
49 outfile.name]
50 p = subprocess.Popen(args, stdin = subprocess.PIPE)
51 p.communicate(instruction.encode('utf-8'))
52 assert(p.wait() == 0)
53
54 with tempfile.NamedTemporaryFile(suffix=".bin") as binfile:
55 args = ["powerpc64-linux-gnu-objcopy",
56 "-O", "binary",
57 outfile.name,
58 binfile.name]
59 subprocess.check_output(args)
60 binary = struct.unpack('>i', binfile.read(4))[0]
61 return binary
62
63 def test_decoder(self):
64 m = Module()
65 comb = m.d.comb
66 instruction = Signal(32)
67
68 pdecode = create_pdecode()
69
70 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
71 dec1 = pdecode2.dec
72 comb += pdecode2.dec.opcode_in.eq(instruction)
73
74 sim = Simulator(m)
75
76 def process():
77 for i in range(10):
78 opcode = random.choice(list(ops.keys()))
79 r1 = Register(random.randrange(32))
80 r2 = Register(random.randrange(32))
81 r3 = Register(random.randrange(32))
82
83 instruction_str = self.generate_opcode_string(opcode, r1, r2, r3)
84 print("instr", instruction_str.strip())
85 instruction_bin = self.get_assembled_instruction(instruction_str)
86 print("code", hex(instruction_bin), bin(instruction_bin))
87
88 yield instruction.eq(instruction_bin)
89 yield Delay(1e-6)
90
91 r1sel = yield pdecode2.e.write_reg.data
92 r3sel = yield pdecode2.e.read_reg2.data
93
94 # For some reason r2 gets decoded either in read_reg1
95 # or read_reg3
96 form = yield pdecode2.dec.op.form
97 if form == Form.X.value:
98 r2sel = yield pdecode2.e.read_reg3.data
99 else:
100 r2sel = yield pdecode2.e.read_reg1.data
101 assert(r1sel == r1.num)
102 assert(r3sel == r3.num)
103 assert(r2sel == r2.num)
104
105 sim.add_process(process)
106 with sim.write_vcd("gas.vcd", "gas.gtkw", traces=[pdecode2.ports()]):
107 sim.run()
108
109
110
111 if __name__ == "__main__":
112 unittest.main()