1 from nmigen
import Module
, Signal
2 from nmigen
.back
.pysim
import Simulator
, Delay
3 from nmigen
.test
.utils
import FHDLTestCase
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
)
21 def __init__(self
, num
):
27 "add": InternalOp
.OP_ADD
,
28 "and": InternalOp
.OP_AND
,
29 "or": InternalOp
.OP_OR
,
30 "add.": InternalOp
.OP_ADD
,
31 "lwzx": InternalOp
.OP_LOAD
,
32 "stwx": InternalOp
.OP_STORE
,
34 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
35 self
.opcode
= self
.ops
[self
.opcodestr
]
36 self
.r1
= Register(random
.randrange(32))
37 self
.r2
= Register(random
.randrange(32))
38 self
.r3
= Register(random
.randrange(32))
40 def generate_instruction(self
):
41 string
= "{} {}, {}, {}\n".format(self
.opcodestr
,
47 def check_results(self
, pdecode2
):
48 if self
.opcode
== InternalOp
.OP_STORE
:
49 r1sel
= yield pdecode2
.e
.read_reg3
.data
51 r1sel
= yield pdecode2
.e
.write_reg
.data
53 r3sel
= yield pdecode2
.e
.read_reg2
.data
55 # For some reason r2 gets decoded either in read_reg1
57 out_sel
= yield pdecode2
.dec
.op
.out_sel
58 if out_sel
== OutSel
.RA
.value
:
59 r2sel
= yield pdecode2
.e
.read_reg3
.data
61 r2sel
= yield pdecode2
.e
.read_reg1
.data
62 assert(r1sel
== self
.r1
.num
)
63 assert(r3sel
== self
.r3
.num
)
64 assert(r2sel
== self
.r2
.num
)
66 opc_out
= yield pdecode2
.dec
.op
.internal_op
67 assert(opc_out
== self
.opcode
.value
)
68 # check RC value (the dot in the instruction)
69 rc
= yield pdecode2
.e
.rc
.data
70 if '.' in self
.opcodestr
:
80 "addi": InternalOp
.OP_ADD
,
81 "addis": InternalOp
.OP_ADD
,
82 "andi.": InternalOp
.OP_AND
,
83 "ori": InternalOp
.OP_OR
,
85 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
86 self
.opcode
= self
.ops
[self
.opcodestr
]
87 self
.r1
= Register(random
.randrange(32))
88 self
.r2
= Register(random
.randrange(32))
89 self
.imm
= random
.randrange(32767)
91 def generate_instruction(self
):
92 string
= "{} {}, {}, {}\n".format(self
.opcodestr
,
98 def check_results(self
, pdecode2
):
100 r1sel
= yield pdecode2
.e
.write_reg
.data
101 # For some reason r2 gets decoded either in read_reg1
103 out_sel
= yield pdecode2
.dec
.op
.out_sel
104 if out_sel
== OutSel
.RA
.value
:
105 r2sel
= yield pdecode2
.e
.read_reg3
.data
107 r2sel
= yield pdecode2
.e
.read_reg1
.data
108 assert(r1sel
== self
.r1
.num
)
109 assert(r2sel
== self
.r2
.num
)
111 imm
= yield pdecode2
.e
.imm_data
.data
112 in2_sel
= yield pdecode2
.dec
.op
.in2_sel
113 if in2_sel
in [In2Sel
.CONST_SI_HI
.value
, In2Sel
.CONST_UI_HI
.value
]:
114 assert(imm
== (self
.imm
<< 16))
116 assert(imm
== self
.imm
)
118 rc
= yield pdecode2
.e
.rc
.data
119 if '.' in self
.opcodestr
:
127 "lwz": InternalOp
.OP_LOAD
,
128 "stw": InternalOp
.OP_STORE
,
129 "lwzu": InternalOp
.OP_LOAD
,
130 "stwu": InternalOp
.OP_STORE
,
131 "lbz": InternalOp
.OP_LOAD
,
132 "lhz": InternalOp
.OP_LOAD
,
133 "stb": InternalOp
.OP_STORE
,
134 "sth": InternalOp
.OP_STORE
,
136 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
137 self
.opcode
= self
.ops
[self
.opcodestr
]
138 self
.r1
= Register(random
.randrange(32))
139 self
.r2
= Register(random
.randrange(1,32))
140 self
.imm
= random
.randrange(32767)
142 def generate_instruction(self
):
143 string
= "{} {}, {}({})\n".format(self
.opcodestr
,
149 def check_results(self
, pdecode2
):
151 r2sel
= yield pdecode2
.e
.read_reg1
.data
152 if self
.opcode
== InternalOp
.OP_STORE
:
153 r1sel
= yield pdecode2
.e
.read_reg3
.data
155 r1sel
= yield pdecode2
.e
.write_reg
.data
156 assert(r1sel
== self
.r1
.num
)
157 assert(r2sel
== self
.r2
.num
)
159 imm
= yield pdecode2
.e
.imm_data
.data
160 in2_sel
= yield pdecode2
.dec
.op
.in2_sel
161 assert(imm
== self
.imm
)
163 update
= yield pdecode2
.e
.update
164 if "u" in self
.opcodestr
:
169 size
= yield pdecode2
.e
.data_len
170 if "w" in self
.opcodestr
:
172 elif "h" in self
.opcodestr
:
174 elif "b" in self
.opcodestr
:
183 "cmp": InternalOp
.OP_CMP
,
185 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
186 self
.opcode
= self
.ops
[self
.opcodestr
]
187 self
.r1
= Register(random
.randrange(32))
188 self
.r2
= Register(random
.randrange(32))
189 self
.cr
= Register(random
.randrange(8))
191 def generate_instruction(self
):
192 string
= "{} {}, 0, {}, {}\n".format(self
.opcodestr
,
198 def check_results(self
, pdecode2
):
199 r1sel
= yield pdecode2
.e
.read_reg1
.data
200 r2sel
= yield pdecode2
.e
.read_reg2
.data
201 crsel
= yield pdecode2
.e
.cr_sel
.data
203 assert(r1sel
== self
.r1
.num
)
204 assert(r2sel
== self
.r2
.num
)
205 assert(crsel
== self
.cr
.num
)
209 class DecoderTestCase(FHDLTestCase
):
211 def get_assembled_instruction(self
, instruction
):
212 with tempfile
.NamedTemporaryFile(suffix
=".o") as outfile
:
213 args
= ["powerpc64-linux-gnu-as",
216 p
= subprocess
.Popen(args
, stdin
=subprocess
.PIPE
)
217 p
.communicate(instruction
.encode('utf-8'))
218 assert(p
.wait() == 0)
220 with tempfile
.NamedTemporaryFile(suffix
=".bin") as binfile
:
221 args
= ["powerpc64-linux-gnu-objcopy",
225 subprocess
.check_output(args
)
226 binary
= struct
.unpack('>i', binfile
.read(4))[0]
229 def run_tst(self
, kls
, name
):
232 instruction
= Signal(32)
234 pdecode
= create_pdecode()
236 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
237 comb
+= pdecode2
.dec
.opcode_in
.eq(instruction
)
245 instruction_str
= checker
.generate_instruction()
246 print("instr", instruction_str
.strip())
247 instruction_bin
= self
.get_assembled_instruction(
249 print("code", hex(instruction_bin
), bin(instruction_bin
))
251 yield instruction
.eq(instruction_bin
)
254 yield from checker
.check_results(pdecode2
)
257 sim
.add_process(process
)
258 with sim
.write_vcd("%s.vcd" % name
, "%s.gtkw" % name
,
259 traces
=[pdecode2
.ports()]):
261 def test_reg_reg(self
):
262 self
.run_tst(RegRegOp
, "reg_reg")
264 def test_reg_imm(self
):
265 self
.run_tst(RegImmOp
, "reg_imm")
267 def test_ldst_imm(self
):
268 self
.run_tst(LdStOp
, "ldst_imm")
270 def test_cmp_reg(self
):
271 self
.run_tst(CmpRegOp
, "cmp_reg")
274 if __name__
== "__main__":