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
, SPR
,
10 get_signal_name
, get_csv
)
11 from soc
.decoder
.power_decoder2
import (PowerDecode2
)
19 def __init__(self
, num
):
26 "add": InternalOp
.OP_ADD
,
27 "and": InternalOp
.OP_AND
,
28 "or": InternalOp
.OP_OR
,
29 "add.": InternalOp
.OP_ADD
,
30 "lwzx": InternalOp
.OP_LOAD
,
31 "stwx": InternalOp
.OP_STORE
,
33 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
34 self
.opcode
= self
.ops
[self
.opcodestr
]
35 self
.r1
= Register(random
.randrange(32))
36 self
.r2
= Register(random
.randrange(32))
37 self
.r3
= Register(random
.randrange(32))
39 def generate_instruction(self
):
40 string
= "{} {}, {}, {}\n".format(self
.opcodestr
,
46 def check_results(self
, pdecode2
):
47 if self
.opcode
== InternalOp
.OP_STORE
:
48 r1sel
= yield pdecode2
.e
.read_reg3
.data
50 r1sel
= yield pdecode2
.e
.write_reg
.data
52 r3sel
= yield pdecode2
.e
.read_reg2
.data
54 # For some reason r2 gets decoded either in read_reg1
56 out_sel
= yield pdecode2
.dec
.op
.out_sel
57 if out_sel
== OutSel
.RA
.value
:
58 r2sel
= yield pdecode2
.e
.read_reg3
.data
60 r2sel
= yield pdecode2
.e
.read_reg1
.data
61 assert(r1sel
== self
.r1
.num
)
62 assert(r3sel
== self
.r3
.num
)
63 assert(r2sel
== self
.r2
.num
)
65 opc_out
= yield pdecode2
.dec
.op
.internal_op
66 assert(opc_out
== self
.opcode
.value
)
67 # check RC value (the dot in the instruction)
68 rc
= yield pdecode2
.e
.rc
.data
69 if '.' in self
.opcodestr
:
78 "addi": InternalOp
.OP_ADD
,
79 "addis": InternalOp
.OP_ADD
,
80 "andi.": InternalOp
.OP_AND
,
81 "ori": InternalOp
.OP_OR
,
83 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
84 self
.opcode
= self
.ops
[self
.opcodestr
]
85 self
.r1
= Register(random
.randrange(32))
86 self
.r2
= Register(random
.randrange(32))
87 self
.imm
= random
.randrange(32767)
89 def generate_instruction(self
):
90 string
= "{} {}, {}, {}\n".format(self
.opcodestr
,
96 def check_results(self
, pdecode2
):
98 r1sel
= yield pdecode2
.e
.write_reg
.data
99 # For some reason r2 gets decoded either in read_reg1
101 out_sel
= yield pdecode2
.dec
.op
.out_sel
102 if out_sel
== OutSel
.RA
.value
:
103 r2sel
= yield pdecode2
.e
.read_reg3
.data
105 r2sel
= yield pdecode2
.e
.read_reg1
.data
106 assert(r1sel
== self
.r1
.num
)
107 assert(r2sel
== self
.r2
.num
)
109 imm
= yield pdecode2
.e
.imm_data
.data
110 in2_sel
= yield pdecode2
.dec
.op
.in2_sel
111 if in2_sel
in [In2Sel
.CONST_SI_HI
.value
, In2Sel
.CONST_UI_HI
.value
]:
112 assert(imm
== (self
.imm
<< 16))
114 assert(imm
== self
.imm
)
116 rc
= yield pdecode2
.e
.rc
.data
117 if '.' in self
.opcodestr
:
126 "lwz": InternalOp
.OP_LOAD
,
127 "stw": InternalOp
.OP_STORE
,
128 "lwzu": InternalOp
.OP_LOAD
,
129 "stwu": InternalOp
.OP_STORE
,
130 "lbz": InternalOp
.OP_LOAD
,
131 "lhz": InternalOp
.OP_LOAD
,
132 "stb": InternalOp
.OP_STORE
,
133 "sth": InternalOp
.OP_STORE
,
135 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
136 self
.opcode
= self
.ops
[self
.opcodestr
]
137 self
.r1
= Register(random
.randrange(32))
138 self
.r2
= Register(random
.randrange(1, 32))
139 self
.imm
= random
.randrange(32767)
141 def generate_instruction(self
):
142 string
= "{} {}, {}({})\n".format(self
.opcodestr
,
148 def check_results(self
, pdecode2
):
150 r2sel
= yield pdecode2
.e
.read_reg1
.data
151 if self
.opcode
== InternalOp
.OP_STORE
:
152 r1sel
= yield pdecode2
.e
.read_reg3
.data
154 r1sel
= yield pdecode2
.e
.write_reg
.data
155 assert(r1sel
== self
.r1
.num
)
156 assert(r2sel
== self
.r2
.num
)
158 imm
= yield pdecode2
.e
.imm_data
.data
159 assert(imm
== self
.imm
)
161 update
= yield pdecode2
.e
.update
162 if "u" in self
.opcodestr
:
167 size
= yield pdecode2
.e
.data_len
168 if "w" in self
.opcodestr
:
170 elif "h" in self
.opcodestr
:
172 elif "b" in self
.opcodestr
:
181 "cmp": InternalOp
.OP_CMP
,
183 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
184 self
.opcode
= self
.ops
[self
.opcodestr
]
185 self
.r1
= Register(random
.randrange(32))
186 self
.r2
= Register(random
.randrange(32))
187 self
.cr
= Register(random
.randrange(8))
189 def generate_instruction(self
):
190 string
= "{} {}, 0, {}, {}\n".format(self
.opcodestr
,
196 def check_results(self
, pdecode2
):
197 r1sel
= yield pdecode2
.e
.read_reg1
.data
198 r2sel
= yield pdecode2
.e
.read_reg2
.data
199 crsel
= yield pdecode2
.dec
.BF
[0:-1]
201 assert(r1sel
== self
.r1
.num
)
202 assert(r2sel
== self
.r2
.num
)
203 assert(crsel
== self
.cr
.num
)
209 "rlwinm": InternalOp
.OP_CMP
,
210 "rlwnm": InternalOp
.OP_CMP
,
211 "rlwimi": InternalOp
.OP_CMP
,
212 "rlwinm.": InternalOp
.OP_CMP
,
213 "rlwnm.": InternalOp
.OP_CMP
,
214 "rlwimi.": InternalOp
.OP_CMP
,
216 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
217 self
.opcode
= self
.ops
[self
.opcodestr
]
218 self
.r1
= Register(random
.randrange(32))
219 self
.r2
= Register(random
.randrange(32))
220 self
.shift
= random
.randrange(32)
221 self
.mb
= random
.randrange(32)
222 self
.me
= random
.randrange(32)
224 def generate_instruction(self
):
225 string
= "{} {},{},{},{},{}\n".format(self
.opcodestr
,
233 def check_results(self
, pdecode2
):
234 r1sel
= yield pdecode2
.e
.write_reg
.data
235 r2sel
= yield pdecode2
.e
.read_reg3
.data
238 if "i" in self
.opcodestr
:
239 shift
= yield dec
.SH
[0:-1]
241 shift
= yield pdecode2
.e
.read_reg2
.data
242 mb
= yield dec
.MB
[0:-1]
243 me
= yield dec
.ME
[0:-1]
245 assert(r1sel
== self
.r1
.num
)
246 assert(r2sel
== self
.r2
.num
)
247 assert(shift
== self
.shift
)
248 assert(mb
== self
.mb
)
249 assert(me
== self
.me
)
251 rc
= yield pdecode2
.e
.rc
.data
252 if '.' in self
.opcodestr
:
261 "b": InternalOp
.OP_B
,
262 "bl": InternalOp
.OP_B
,
263 "ba": InternalOp
.OP_B
,
264 "bla": InternalOp
.OP_B
,
266 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
267 self
.opcode
= self
.ops
[self
.opcodestr
]
268 self
.addr
= random
.randrange(2**23) * 4
270 def generate_instruction(self
):
271 string
= "{} {}\n".format(self
.opcodestr
,
275 def check_results(self
, pdecode2
):
276 imm
= yield pdecode2
.e
.imm_data
.data
278 assert(imm
== self
.addr
)
279 lk
= yield pdecode2
.e
.lk
280 if "l" in self
.opcodestr
:
284 aa
= yield pdecode2
.dec
.AA
[0:-1]
285 if "a" in self
.opcodestr
:
294 "bc": InternalOp
.OP_B
,
295 "bcl": InternalOp
.OP_B
,
296 "bca": InternalOp
.OP_B
,
297 "bcla": InternalOp
.OP_B
,
299 # Given in Figure 40 "BO field encodings" in section 2.4, page
300 # 33 of the Power ISA v3.0B manual
301 self
.branchops
= [0b00000, 0b00010, 0b00100, 0b01000, 0b01010,
302 0b01100, 0b10000, 0b10100]
303 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
304 self
.opcode
= self
.ops
[self
.opcodestr
]
305 self
.addr
= random
.randrange(2**13) * 4
306 self
.bo
= random
.choice(self
.branchops
)
307 self
.bi
= random
.randrange(32)
309 def generate_instruction(self
):
310 string
= "{} {},{},{}\n".format(self
.opcodestr
,
316 def check_results(self
, pdecode2
):
317 imm
= yield pdecode2
.e
.imm_data
.data
318 bo
= yield pdecode2
.dec
.BO
[0:-1]
319 bi
= yield pdecode2
.dec
.BI
[0:-1]
321 assert(imm
== self
.addr
)
322 assert(bo
== self
.bo
)
323 assert(bi
== self
.bi
)
324 lk
= yield pdecode2
.e
.lk
325 if "l" in self
.opcodestr
:
329 aa
= yield pdecode2
.dec
.AA
[0:-1]
330 if "a" in self
.opcodestr
:
339 "bclr": InternalOp
.OP_B
,
340 "bcctr": InternalOp
.OP_B
,
341 "bclrl": InternalOp
.OP_B
,
342 "bcctrl": InternalOp
.OP_B
,
344 # Given in Figure 40 "BO field encodings" in section 2.4, page
345 # 33 of the Power ISA v3.0B manual
346 self
.branchops
= [0b00100, 0b01100, 0b10100]
347 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
348 self
.opcode
= self
.ops
[self
.opcodestr
]
349 self
.bh
= random
.randrange(4)
350 self
.bo
= random
.choice(self
.branchops
)
351 self
.bi
= random
.randrange(32)
353 def generate_instruction(self
):
354 string
= "{} {},{},{}\n".format(self
.opcodestr
,
360 def check_results(self
, pdecode2
):
361 bo
= yield pdecode2
.dec
.BO
[0:-1]
362 bi
= yield pdecode2
.dec
.BI
[0:-1]
364 assert(bo
== self
.bo
)
365 assert(bi
== self
.bi
)
367 spr
= yield pdecode2
.e
.read_spr2
.data
368 if "lr" in self
.opcodestr
:
369 assert(spr
== SPR
.LR
.value
)
371 assert(spr
== SPR
.CTR
.value
)
373 lk
= yield pdecode2
.e
.lk
374 if self
.opcodestr
[-1] == 'l':
380 class DecoderTestCase(FHDLTestCase
):
382 def get_assembled_instruction(self
, instruction
, bigendian
=False):
384 endian_fmt
= "elf64-big"
387 endian_fmt
= "elf64-little"
389 with tempfile
.NamedTemporaryFile(suffix
=".o") as outfile
:
390 args
= ["powerpc64-linux-gnu-as",
394 p
= subprocess
.Popen(args
, stdin
=subprocess
.PIPE
)
395 p
.communicate(instruction
.encode('utf-8'))
396 assert(p
.wait() == 0)
398 with tempfile
.NamedTemporaryFile(suffix
=".bin") as binfile
:
399 args
= ["powerpc64-linux-gnu-objcopy",
404 subprocess
.check_output(args
)
405 binary
= struct
.unpack('>i', binfile
.read(4))[0]
408 def run_tst(self
, kls
, name
):
411 instruction
= Signal(32)
413 pdecode
= create_pdecode()
415 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
416 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
422 ins
= checker
.generate_instruction()
423 print("instr", ins
.strip())
426 # turn the instruction into binary data (endian'd)
427 ibin
= self
.get_assembled_instruction(ins
, mode
)
428 print("code", mode
, hex(ibin
), bin(ibin
))
430 # ask the decoder to decode this binary data (endian'd)
431 yield pdecode2
.dec
.bigendian
.eq(endian
) # little / big?
432 yield instruction
.eq(ibin
) # raw binary instr.
435 yield from checker
.check_results(pdecode2
)
437 sim
.add_process(process
)
438 with sim
.write_vcd("%s.vcd" % name
, "%s.gtkw" % name
,
439 traces
=[pdecode2
.ports()]):
442 def test_reg_reg(self
):
443 self
.run_tst(RegRegOp
, "reg_reg")
445 def test_reg_imm(self
):
446 self
.run_tst(RegImmOp
, "reg_imm")
448 def test_ldst_imm(self
):
449 self
.run_tst(LdStOp
, "ldst_imm")
451 def test_cmp_reg(self
):
452 self
.run_tst(CmpRegOp
, "cmp_reg")
455 self
.run_tst(RotateOp
, "rot")
457 def test_branch(self
):
458 self
.run_tst(Branch
, "branch")
460 def test_branch_cond(self
):
461 self
.run_tst(BranchCond
, "branch_cond")
463 def test_branch_rel(self
):
464 self
.run_tst(BranchRel
, "branch_rel")
467 if __name__
== "__main__":