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
):
24 def get_imm(self
, in2_sel
):
25 if in2_sel
== In2Sel
.CONST_UI
.value
:
26 return self
.imm
& 0xffff
27 if in2_sel
== In2Sel
.CONST_UI_HI
.value
:
28 return (self
.imm
& 0xffff) << 16
29 if in2_sel
== In2Sel
.CONST_SI
.value
:
31 return (self
.imm
& (sign_bit
-1)) - (self
.imm
& sign_bit
)
32 if in2_sel
== In2Sel
.CONST_SI_HI
.value
:
35 return (imm
& (sign_bit
-1)) - (imm
& sign_bit
)
41 "add": InternalOp
.OP_ADD
,
42 "and": InternalOp
.OP_AND
,
43 "or": InternalOp
.OP_OR
,
44 "add.": InternalOp
.OP_ADD
,
45 "lwzx": InternalOp
.OP_LOAD
,
46 "stwx": InternalOp
.OP_STORE
,
48 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
49 self
.opcode
= self
.ops
[self
.opcodestr
]
50 self
.r1
= Register(random
.randrange(32))
51 self
.r2
= Register(random
.randrange(32))
52 self
.r3
= Register(random
.randrange(32))
54 def generate_instruction(self
):
55 string
= "{} {}, {}, {}\n".format(self
.opcodestr
,
61 def check_results(self
, pdecode2
):
62 if self
.opcode
== InternalOp
.OP_STORE
:
63 r1sel
= yield pdecode2
.e
.read_reg3
.data
65 r1sel
= yield pdecode2
.e
.write_reg
.data
67 r3sel
= yield pdecode2
.e
.read_reg2
.data
69 # For some reason r2 gets decoded either in read_reg1
71 out_sel
= yield pdecode2
.dec
.op
.out_sel
72 if out_sel
== OutSel
.RA
.value
:
73 r2sel
= yield pdecode2
.e
.read_reg3
.data
75 r2sel
= yield pdecode2
.e
.read_reg1
.data
76 assert(r1sel
== self
.r1
.num
)
77 assert(r3sel
== self
.r3
.num
)
78 assert(r2sel
== self
.r2
.num
)
80 opc_out
= yield pdecode2
.dec
.op
.internal_op
81 assert(opc_out
== self
.opcode
.value
)
82 # check RC value (the dot in the instruction)
83 rc
= yield pdecode2
.e
.rc
.data
84 if '.' in self
.opcodestr
:
90 class RegImmOp(Checker
):
94 "addi": InternalOp
.OP_ADD
,
95 "addis": InternalOp
.OP_ADD
,
96 "andi.": InternalOp
.OP_AND
,
97 "ori": InternalOp
.OP_OR
,
99 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
100 self
.opcode
= self
.ops
[self
.opcodestr
]
101 self
.r1
= Register(random
.randrange(32))
102 self
.r2
= Register(random
.randrange(32))
103 self
.imm
= random
.randrange(32767)
105 def generate_instruction(self
):
106 string
= "{} {}, {}, {}\n".format(self
.opcodestr
,
112 def check_results(self
, pdecode2
):
114 r1sel
= yield pdecode2
.e
.write_reg
.data
115 # For some reason r2 gets decoded either in read_reg1
117 out_sel
= yield pdecode2
.dec
.op
.out_sel
118 if out_sel
== OutSel
.RA
.value
:
119 r2sel
= yield pdecode2
.e
.read_reg3
.data
121 r2sel
= yield pdecode2
.e
.read_reg1
.data
122 assert(r1sel
== self
.r1
.num
)
123 assert(r2sel
== self
.r2
.num
)
125 imm
= yield pdecode2
.e
.imm_data
.data
126 in2_sel
= yield pdecode2
.dec
.op
.in2_sel
127 imm_expected
= self
.get_imm(in2_sel
)
128 msg
= "imm: got {:x}, expected {:x}".format(imm
, imm_expected
)
129 assert imm
== imm_expected
, msg
131 rc
= yield pdecode2
.e
.rc
.data
132 if '.' in self
.opcodestr
:
138 class LdStOp(Checker
):
142 "lwz": InternalOp
.OP_LOAD
,
143 "stw": InternalOp
.OP_STORE
,
144 "lwzu": InternalOp
.OP_LOAD
,
145 "stwu": InternalOp
.OP_STORE
,
146 "lbz": InternalOp
.OP_LOAD
,
147 "lhz": InternalOp
.OP_LOAD
,
148 "stb": InternalOp
.OP_STORE
,
149 "sth": InternalOp
.OP_STORE
,
151 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
152 self
.opcode
= self
.ops
[self
.opcodestr
]
153 self
.r1
= Register(random
.randrange(32))
154 self
.r2
= Register(random
.randrange(1, 32))
155 while self
.r2
.num
== self
.r1
.num
:
156 self
.r2
= Register(random
.randrange(1, 32))
157 self
.imm
= random
.randrange(32767)
159 def generate_instruction(self
):
160 string
= "{} {}, {}({})\n".format(self
.opcodestr
,
166 def check_results(self
, pdecode2
):
168 r2sel
= yield pdecode2
.e
.read_reg1
.data
169 if self
.opcode
== InternalOp
.OP_STORE
:
170 r1sel
= yield pdecode2
.e
.read_reg3
.data
172 r1sel
= yield pdecode2
.e
.write_reg
.data
173 assert(r1sel
== self
.r1
.num
)
174 assert(r2sel
== self
.r2
.num
)
176 imm
= yield pdecode2
.e
.imm_data
.data
177 in2_sel
= yield pdecode2
.dec
.op
.in2_sel
178 assert(imm
== self
.get_imm(in2_sel
))
180 update
= yield pdecode2
.e
.update
181 if "u" in self
.opcodestr
:
186 size
= yield pdecode2
.e
.data_len
187 if "w" in self
.opcodestr
:
189 elif "h" in self
.opcodestr
:
191 elif "b" in self
.opcodestr
:
200 "cmp": InternalOp
.OP_CMP
,
202 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
203 self
.opcode
= self
.ops
[self
.opcodestr
]
204 self
.r1
= Register(random
.randrange(32))
205 self
.r2
= Register(random
.randrange(32))
206 self
.cr
= Register(random
.randrange(8))
208 def generate_instruction(self
):
209 string
= "{} {}, 0, {}, {}\n".format(self
.opcodestr
,
215 def check_results(self
, pdecode2
):
216 r1sel
= yield pdecode2
.e
.read_reg1
.data
217 r2sel
= yield pdecode2
.e
.read_reg2
.data
218 crsel
= yield pdecode2
.dec
.BF
220 assert(r1sel
== self
.r1
.num
)
221 assert(r2sel
== self
.r2
.num
)
222 assert(crsel
== self
.cr
.num
)
228 "rlwinm": InternalOp
.OP_CMP
,
229 "rlwnm": InternalOp
.OP_CMP
,
230 "rlwimi": InternalOp
.OP_CMP
,
231 "rlwinm.": InternalOp
.OP_CMP
,
232 "rlwnm.": InternalOp
.OP_CMP
,
233 "rlwimi.": InternalOp
.OP_CMP
,
235 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
236 self
.opcode
= self
.ops
[self
.opcodestr
]
237 self
.r1
= Register(random
.randrange(32))
238 self
.r2
= Register(random
.randrange(32))
239 self
.shift
= random
.randrange(32)
240 self
.mb
= random
.randrange(32)
241 self
.me
= random
.randrange(32)
243 def generate_instruction(self
):
244 string
= "{} {},{},{},{},{}\n".format(self
.opcodestr
,
252 def check_results(self
, pdecode2
):
253 r1sel
= yield pdecode2
.e
.write_reg
.data
254 r2sel
= yield pdecode2
.e
.read_reg3
.data
257 if "i" in self
.opcodestr
:
260 shift
= yield pdecode2
.e
.read_reg2
.data
264 assert(r1sel
== self
.r1
.num
)
265 assert(r2sel
== self
.r2
.num
)
266 assert(shift
== self
.shift
)
267 assert(mb
== self
.mb
)
268 assert(me
== self
.me
)
270 rc
= yield pdecode2
.e
.rc
.data
271 if '.' in self
.opcodestr
:
280 "b": InternalOp
.OP_B
,
281 "bl": InternalOp
.OP_B
,
282 "ba": InternalOp
.OP_B
,
283 "bla": InternalOp
.OP_B
,
285 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
286 self
.opcode
= self
.ops
[self
.opcodestr
]
287 self
.addr
= random
.randrange(2**23) * 4
289 def generate_instruction(self
):
290 string
= "{} {}\n".format(self
.opcodestr
,
294 def check_results(self
, pdecode2
):
295 imm
= yield pdecode2
.e
.imm_data
.data
297 assert(imm
== self
.addr
)
298 lk
= yield pdecode2
.e
.lk
299 if "l" in self
.opcodestr
:
303 aa
= yield pdecode2
.dec
.AA
304 if "a" in self
.opcodestr
:
313 "bc": InternalOp
.OP_B
,
314 "bcl": InternalOp
.OP_B
,
315 "bca": InternalOp
.OP_B
,
316 "bcla": InternalOp
.OP_B
,
318 # Given in Figure 40 "BO field encodings" in section 2.4, page
319 # 33 of the Power ISA v3.0B manual
320 self
.branchops
= [0b00000, 0b00010, 0b00100, 0b01000, 0b01010,
321 0b01100, 0b10000, 0b10100]
322 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
323 self
.opcode
= self
.ops
[self
.opcodestr
]
324 self
.addr
= random
.randrange(2**13) * 4
325 self
.bo
= random
.choice(self
.branchops
)
326 self
.bi
= random
.randrange(32)
328 def generate_instruction(self
):
329 string
= "{} {},{},{}\n".format(self
.opcodestr
,
335 def check_results(self
, pdecode2
):
336 imm
= yield pdecode2
.e
.imm_data
.data
337 bo
= yield pdecode2
.dec
.BO
338 bi
= yield pdecode2
.dec
.BI
340 assert(imm
== self
.addr
)
341 assert(bo
== self
.bo
)
342 assert(bi
== self
.bi
)
343 lk
= yield pdecode2
.e
.lk
344 if "l" in self
.opcodestr
:
348 aa
= yield pdecode2
.dec
.AA
349 if "a" in self
.opcodestr
:
358 "bclr": InternalOp
.OP_B
,
359 "bcctr": InternalOp
.OP_B
,
360 "bclrl": InternalOp
.OP_B
,
361 "bcctrl": InternalOp
.OP_B
,
363 # Given in Figure 40 "BO field encodings" in section 2.4, page
364 # 33 of the Power ISA v3.0B manual
365 self
.branchops
= [0b00100, 0b01100, 0b10100]
366 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
367 self
.opcode
= self
.ops
[self
.opcodestr
]
368 self
.bh
= random
.randrange(4)
369 self
.bo
= random
.choice(self
.branchops
)
370 self
.bi
= random
.randrange(32)
372 def generate_instruction(self
):
373 string
= "{} {},{},{}\n".format(self
.opcodestr
,
379 def check_results(self
, pdecode2
):
380 bo
= yield pdecode2
.dec
.BO
381 bi
= yield pdecode2
.dec
.BI
383 assert(bo
== self
.bo
)
384 assert(bi
== self
.bi
)
386 spr
= yield pdecode2
.e
.read_spr2
.data
387 if "lr" in self
.opcodestr
:
388 assert(spr
== SPR
.LR
.value
)
390 assert(spr
== SPR
.CTR
.value
)
392 lk
= yield pdecode2
.e
.lk
393 if self
.opcodestr
[-1] == 'l':
399 class DecoderTestCase(FHDLTestCase
):
401 def run_tst(self
, kls
, name
):
404 instruction
= Signal(32)
406 pdecode
= create_pdecode()
408 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
409 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
415 ins
= checker
.generate_instruction()
416 print("instr", ins
.strip())
419 # turn the instruction into binary data (endian'd)
420 ibin
= get_assembled_instruction(ins
, mode
)
421 print("code", mode
, hex(ibin
), bin(ibin
))
423 # ask the decoder to decode this binary data (endian'd)
424 yield pdecode2
.dec
.bigendian
.eq(mode
) # little / big?
425 yield instruction
.eq(ibin
) # raw binary instr.
428 yield from checker
.check_results(pdecode2
)
430 sim
.add_process(process
)
431 with sim
.write_vcd("%s.vcd" % name
, "%s.gtkw" % name
,
432 traces
=pdecode2
.ports()):
435 def test_reg_reg(self
):
436 self
.run_tst(RegRegOp
, "reg_reg")
438 def test_reg_imm(self
):
439 self
.run_tst(RegImmOp
, "reg_imm")
441 def test_ldst_imm(self
):
442 self
.run_tst(LdStOp
, "ldst_imm")
444 def test_cmp_reg(self
):
445 self
.run_tst(CmpRegOp
, "cmp_reg")
448 self
.run_tst(RotateOp
, "rot")
450 def test_branch(self
):
451 self
.run_tst(Branch
, "branch")
453 def test_branch_cond(self
):
454 self
.run_tst(BranchCond
, "branch_cond")
456 def test_branch_rel(self
):
457 self
.run_tst(BranchRel
, "branch_rel")
460 if __name__
== "__main__":