074e628fb89c1710038db74d65493c7bd9a5e9f2
[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,
10 get_signal_name, get_csv)
11 from soc.decoder.power_decoder2 import (PowerDecode2)
12 import tempfile
13 import subprocess
14 import struct
15 import random
16 import pdb
17
18
19
20 class Register:
21 def __init__(self, num):
22 self.num = num
23
24 class RegRegOp:
25 def __init__(self):
26 self.ops = {
27 "add": InternalOp.OP_ADD,
28 "and": InternalOp.OP_AND,
29 "or": InternalOp.OP_OR,
30 "add.": InternalOp.OP_ADD,
31 }
32 self.opcodestr = random.choice(list(self.ops.keys()))
33 self.opcode = self.ops[self.opcodestr]
34 self.r1 = Register(random.randrange(32))
35 self.r2 = Register(random.randrange(32))
36 self.r3 = Register(random.randrange(32))
37
38 def generate_instruction(self):
39 string = "{} {}, {}, {}\n".format(self.opcodestr,
40 self.r1.num,
41 self.r2.num,
42 self.r3.num)
43 return string
44
45 def check_results(self, pdecode2):
46 r1sel = yield pdecode2.e.write_reg.data
47 r3sel = yield pdecode2.e.read_reg2.data
48
49 # For some reason r2 gets decoded either in read_reg1
50 # or read_reg3
51 out_sel = yield pdecode2.dec.op.out_sel
52 if out_sel == OutSel.RA.value:
53 r2sel = yield pdecode2.e.read_reg3.data
54 else:
55 r2sel = yield pdecode2.e.read_reg1.data
56 assert(r1sel == self.r1.num)
57 assert(r3sel == self.r3.num)
58 assert(r2sel == self.r2.num)
59
60 opc_out = yield pdecode2.dec.op.internal_op
61 assert(opc_out == self.opcode.value)
62 # check RC value (the dot in the instruction)
63 rc = yield pdecode2.e.rc.data
64 if '.' in self.opcodestr:
65 assert(rc == 1)
66 else:
67 assert(rc == 0)
68
69
70
71 class RegImmOp:
72 def __init__(self):
73 self.ops = {
74 "addi": InternalOp.OP_ADD,
75 "addis": InternalOp.OP_ADD,
76 "andi.": InternalOp.OP_AND,
77 "ori": InternalOp.OP_OR,
78 }
79 self.opcodestr = random.choice(list(self.ops.keys()))
80 self.opcode = self.ops[self.opcodestr]
81 self.r1 = Register(random.randrange(32))
82 self.r2 = Register(random.randrange(32))
83 self.imm = random.randrange(32767)
84
85 def generate_instruction(self):
86 string = "{} {}, {}, {}\n".format(self.opcodestr,
87 self.r1.num,
88 self.r2.num,
89 self.imm)
90 return string
91
92 def check_results(self, pdecode2):
93 print("Check")
94 r1sel = yield pdecode2.e.write_reg.data
95 # For some reason r2 gets decoded either in read_reg1
96 # or read_reg3
97 out_sel = yield pdecode2.dec.op.out_sel
98 if out_sel == OutSel.RA.value:
99 r2sel = yield pdecode2.e.read_reg3.data
100 else:
101 r2sel = yield pdecode2.e.read_reg1.data
102 assert(r1sel == self.r1.num)
103 assert(r2sel == self.r2.num)
104
105 imm = yield pdecode2.e.imm_data.data
106 in2_sel = yield pdecode2.dec.op.in2_sel
107 if in2_sel in [In2Sel.CONST_SI_HI.value, In2Sel.CONST_UI_HI.value]:
108 assert(imm == (self.imm << 16))
109 else:
110 assert(imm == self.imm)
111
112 rc = yield pdecode2.e.rc.data
113 if '.' in self.opcodestr:
114 assert(rc == 1)
115 else:
116 assert(rc == 0)
117
118 class DecoderTestCase(FHDLTestCase):
119
120 def get_assembled_instruction(self, instruction):
121 with tempfile.NamedTemporaryFile(suffix=".o") as outfile:
122 args = ["powerpc64-linux-gnu-as",
123 "-o",
124 outfile.name]
125 p = subprocess.Popen(args, stdin=subprocess.PIPE)
126 p.communicate(instruction.encode('utf-8'))
127 assert(p.wait() == 0)
128
129 with tempfile.NamedTemporaryFile(suffix=".bin") as binfile:
130 args = ["powerpc64-linux-gnu-objcopy",
131 "-O", "binary",
132 outfile.name,
133 binfile.name]
134 subprocess.check_output(args)
135 binary = struct.unpack('>i', binfile.read(4))[0]
136 return binary
137
138 def run_tst(self, kls, name):
139 m = Module()
140 comb = m.d.comb
141 instruction = Signal(32)
142
143 pdecode = create_pdecode()
144
145 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
146 comb += pdecode2.dec.opcode_in.eq(instruction)
147
148 sim = Simulator(m)
149
150 def process():
151 for i in range(20):
152 checker = kls()
153
154 instruction_str = checker.generate_instruction()
155 print("instr", instruction_str.strip())
156 instruction_bin = self.get_assembled_instruction(
157 instruction_str)
158 print("code", hex(instruction_bin), bin(instruction_bin))
159
160 yield instruction.eq(instruction_bin)
161 yield Delay(1e-6)
162
163 yield from checker.check_results(pdecode2)
164
165
166 sim.add_process(process)
167 with sim.write_vcd("%s.vcd" % name, "%s.gtkw" % name,
168 traces=[pdecode2.ports()]):
169 sim.run()
170 def test_reg_reg(self):
171 self.run_tst(RegRegOp, "reg_reg")
172
173 def test_reg_imm(self):
174 self.run_tst(RegImmOp, "reg_imm")
175
176
177 if __name__ == "__main__":
178 unittest.main()