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
)
12 from soc
.simulator
.gas
import get_assembled_instruction
17 def __init__(self
, num
):
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
:
32 return (self
.imm
& (sign_bit
-1)) - (self
.imm
& sign_bit
)
33 if in2_sel
== In2Sel
.CONST_SI_HI
.value
:
36 return (imm
& (sign_bit
-1)) - (imm
& sign_bit
)
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
,
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))
55 def generate_instruction(self
):
56 string
= "{} {}, {}, {}\n".format(self
.opcodestr
,
62 def check_results(self
, pdecode2
):
63 if self
.opcode
== InternalOp
.OP_STORE
:
64 r1sel
= yield pdecode2
.e
.read_reg3
.data
66 r1sel
= yield pdecode2
.e
.write_reg
.data
68 r3sel
= yield pdecode2
.e
.read_reg2
.data
70 # For some reason r2 gets decoded either in read_reg1
72 out_sel
= yield pdecode2
.dec
.op
.out_sel
73 if out_sel
== OutSel
.RA
.value
:
74 r2sel
= yield pdecode2
.e
.read_reg3
.data
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
)
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
:
91 class RegImmOp(Checker
):
95 "addi": InternalOp
.OP_ADD
,
96 "addis": InternalOp
.OP_ADD
,
97 "andi.": InternalOp
.OP_AND
,
98 "ori": InternalOp
.OP_OR
,
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)
106 def generate_instruction(self
):
107 string
= "{} {}, {}, {}\n".format(self
.opcodestr
,
113 def check_results(self
, pdecode2
):
115 r1sel
= yield pdecode2
.e
.write_reg
.data
116 # For some reason r2 gets decoded either in read_reg1
118 out_sel
= yield pdecode2
.dec
.op
.out_sel
119 if out_sel
== OutSel
.RA
.value
:
120 r2sel
= yield pdecode2
.e
.read_reg3
.data
122 r2sel
= yield pdecode2
.e
.read_reg1
.data
123 assert(r1sel
== self
.r1
.num
)
124 assert(r2sel
== self
.r2
.num
)
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
132 rc
= yield pdecode2
.e
.rc
.data
133 if '.' in self
.opcodestr
:
139 class LdStOp(Checker
):
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
,
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)
160 def generate_instruction(self
):
161 string
= "{} {}, {}({})\n".format(self
.opcodestr
,
167 def check_results(self
, pdecode2
):
169 r2sel
= yield pdecode2
.e
.read_reg1
.data
170 if self
.opcode
== InternalOp
.OP_STORE
:
171 r1sel
= yield pdecode2
.e
.read_reg3
.data
173 r1sel
= yield pdecode2
.e
.write_reg
.data
174 assert(r1sel
== self
.r1
.num
)
175 assert(r2sel
== self
.r2
.num
)
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
))
181 update
= yield pdecode2
.e
.update
182 if "u" in self
.opcodestr
:
187 size
= yield pdecode2
.e
.data_len
188 if "w" in self
.opcodestr
:
190 elif "h" in self
.opcodestr
:
192 elif "b" in self
.opcodestr
:
201 "cmp": InternalOp
.OP_CMP
,
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))
209 def generate_instruction(self
):
210 string
= "{} {}, 0, {}, {}\n".format(self
.opcodestr
,
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
221 assert(r1sel
== self
.r1
.num
)
222 assert(r2sel
== self
.r2
.num
)
223 assert(crsel
== self
.cr
.num
)
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
,
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)
244 def generate_instruction(self
):
245 string
= "{} {},{},{},{},{}\n".format(self
.opcodestr
,
253 def check_results(self
, pdecode2
):
254 r1sel
= yield pdecode2
.e
.write_reg
.data
255 r2sel
= yield pdecode2
.e
.read_reg3
.data
258 if "i" in self
.opcodestr
:
261 shift
= yield pdecode2
.e
.read_reg2
.data
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
)
271 rc
= yield pdecode2
.e
.rc
.data
272 if '.' in self
.opcodestr
:
281 "b": InternalOp
.OP_B
,
282 "bl": InternalOp
.OP_B
,
283 "ba": InternalOp
.OP_B
,
284 "bla": InternalOp
.OP_B
,
286 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
287 self
.opcode
= self
.ops
[self
.opcodestr
]
288 self
.addr
= random
.randrange(2**23) * 4
290 def generate_instruction(self
):
291 string
= "{} {}\n".format(self
.opcodestr
,
295 def check_results(self
, pdecode2
):
296 imm
= yield pdecode2
.e
.imm_data
.data
298 assert(imm
== self
.addr
)
299 lk
= yield pdecode2
.e
.lk
300 if "l" in self
.opcodestr
:
304 aa
= yield pdecode2
.dec
.AA
305 if "a" in self
.opcodestr
:
314 "bc": InternalOp
.OP_B
,
315 "bcl": InternalOp
.OP_B
,
316 "bca": InternalOp
.OP_B
,
317 "bcla": InternalOp
.OP_B
,
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)
329 def generate_instruction(self
):
330 string
= "{} {},{},{}\n".format(self
.opcodestr
,
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
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
:
349 aa
= yield pdecode2
.dec
.AA
350 if "a" in self
.opcodestr
:
355 cr_sel
= yield pdecode2
.e
.read_cr1
.data
356 assert cr_sel
== (self
.bi
//8), f
"{cr_sel} {self.bi}"
363 "bclr": InternalOp
.OP_B
,
364 "bcctr": InternalOp
.OP_B
,
365 "bclrl": InternalOp
.OP_B
,
366 "bcctrl": InternalOp
.OP_B
,
368 # Given in Figure 40 "BO field encodings" in section 2.4, page
369 # 33 of the Power ISA v3.0B manual
370 self
.branchops
= [0b00100, 0b01100, 0b10100]
371 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
372 self
.opcode
= self
.ops
[self
.opcodestr
]
373 self
.bh
= random
.randrange(4)
374 self
.bo
= random
.choice(self
.branchops
)
375 self
.bi
= random
.randrange(32)
377 def generate_instruction(self
):
378 string
= "{} {},{},{}\n".format(self
.opcodestr
,
384 def check_results(self
, pdecode2
):
385 bo
= yield pdecode2
.dec
.BO
386 bi
= yield pdecode2
.dec
.BI
388 assert(bo
== self
.bo
)
389 assert(bi
== self
.bi
)
391 spr
= yield pdecode2
.e
.read_spr2
.data
392 if "lr" in self
.opcodestr
:
393 assert(spr
== SPR
.LR
.value
)
395 assert(spr
== SPR
.CTR
.value
)
397 lk
= yield pdecode2
.e
.lk
398 if self
.opcodestr
[-1] == 'l':
404 class DecoderTestCase(FHDLTestCase
):
406 def run_tst(self
, kls
, name
):
409 instruction
= Signal(32)
411 pdecode
= create_pdecode()
413 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
414 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
420 ins
= checker
.generate_instruction()
421 print("instr", ins
.strip())
424 # turn the instruction into binary data (endian'd)
425 ibin
= get_assembled_instruction(ins
, mode
)
426 print("code", mode
, hex(ibin
), bin(ibin
))
428 # ask the decoder to decode this binary data (endian'd)
429 yield pdecode2
.dec
.bigendian
.eq(mode
) # little / big?
430 yield instruction
.eq(ibin
) # raw binary instr.
433 yield from checker
.check_results(pdecode2
)
435 sim
.add_process(process
)
436 ports
= pdecode2
.ports()
438 with sim
.write_vcd("%s.vcd" % name
, "%s.gtkw" % name
,
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__":