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 self
.imm
= random
.randrange(32767)
157 def generate_instruction(self
):
158 string
= "{} {}, {}({})\n".format(self
.opcodestr
,
164 def check_results(self
, pdecode2
):
166 r2sel
= yield pdecode2
.e
.read_reg1
.data
167 if self
.opcode
== InternalOp
.OP_STORE
:
168 r1sel
= yield pdecode2
.e
.read_reg3
.data
170 r1sel
= yield pdecode2
.e
.write_reg
.data
171 assert(r1sel
== self
.r1
.num
)
172 assert(r2sel
== self
.r2
.num
)
174 imm
= yield pdecode2
.e
.imm_data
.data
175 in2_sel
= yield pdecode2
.dec
.op
.in2_sel
176 assert(imm
== self
.get_imm(in2_sel
))
178 update
= yield pdecode2
.e
.update
179 if "u" in self
.opcodestr
:
184 size
= yield pdecode2
.e
.data_len
185 if "w" in self
.opcodestr
:
187 elif "h" in self
.opcodestr
:
189 elif "b" in self
.opcodestr
:
198 "cmp": InternalOp
.OP_CMP
,
200 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
201 self
.opcode
= self
.ops
[self
.opcodestr
]
202 self
.r1
= Register(random
.randrange(32))
203 self
.r2
= Register(random
.randrange(32))
204 self
.cr
= Register(random
.randrange(8))
206 def generate_instruction(self
):
207 string
= "{} {}, 0, {}, {}\n".format(self
.opcodestr
,
213 def check_results(self
, pdecode2
):
214 r1sel
= yield pdecode2
.e
.read_reg1
.data
215 r2sel
= yield pdecode2
.e
.read_reg2
.data
216 crsel
= yield pdecode2
.dec
.BF
[0:-1]
218 assert(r1sel
== self
.r1
.num
)
219 assert(r2sel
== self
.r2
.num
)
220 assert(crsel
== self
.cr
.num
)
226 "rlwinm": InternalOp
.OP_CMP
,
227 "rlwnm": InternalOp
.OP_CMP
,
228 "rlwimi": InternalOp
.OP_CMP
,
229 "rlwinm.": InternalOp
.OP_CMP
,
230 "rlwnm.": InternalOp
.OP_CMP
,
231 "rlwimi.": InternalOp
.OP_CMP
,
233 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
234 self
.opcode
= self
.ops
[self
.opcodestr
]
235 self
.r1
= Register(random
.randrange(32))
236 self
.r2
= Register(random
.randrange(32))
237 self
.shift
= random
.randrange(32)
238 self
.mb
= random
.randrange(32)
239 self
.me
= random
.randrange(32)
241 def generate_instruction(self
):
242 string
= "{} {},{},{},{},{}\n".format(self
.opcodestr
,
250 def check_results(self
, pdecode2
):
251 r1sel
= yield pdecode2
.e
.write_reg
.data
252 r2sel
= yield pdecode2
.e
.read_reg3
.data
255 if "i" in self
.opcodestr
:
256 shift
= yield dec
.SH
[0:-1]
258 shift
= yield pdecode2
.e
.read_reg2
.data
259 mb
= yield dec
.MB
[0:-1]
260 me
= yield dec
.ME
[0:-1]
262 assert(r1sel
== self
.r1
.num
)
263 assert(r2sel
== self
.r2
.num
)
264 assert(shift
== self
.shift
)
265 assert(mb
== self
.mb
)
266 assert(me
== self
.me
)
268 rc
= yield pdecode2
.e
.rc
.data
269 if '.' in self
.opcodestr
:
278 "b": InternalOp
.OP_B
,
279 "bl": InternalOp
.OP_B
,
280 "ba": InternalOp
.OP_B
,
281 "bla": InternalOp
.OP_B
,
283 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
284 self
.opcode
= self
.ops
[self
.opcodestr
]
285 self
.addr
= random
.randrange(2**23) * 4
287 def generate_instruction(self
):
288 string
= "{} {}\n".format(self
.opcodestr
,
292 def check_results(self
, pdecode2
):
293 imm
= yield pdecode2
.e
.imm_data
.data
295 assert(imm
== self
.addr
)
296 lk
= yield pdecode2
.e
.lk
297 if "l" in self
.opcodestr
:
301 aa
= yield pdecode2
.dec
.AA
[0:-1]
302 if "a" in self
.opcodestr
:
311 "bc": InternalOp
.OP_B
,
312 "bcl": InternalOp
.OP_B
,
313 "bca": InternalOp
.OP_B
,
314 "bcla": InternalOp
.OP_B
,
316 # Given in Figure 40 "BO field encodings" in section 2.4, page
317 # 33 of the Power ISA v3.0B manual
318 self
.branchops
= [0b00000, 0b00010, 0b00100, 0b01000, 0b01010,
319 0b01100, 0b10000, 0b10100]
320 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
321 self
.opcode
= self
.ops
[self
.opcodestr
]
322 self
.addr
= random
.randrange(2**13) * 4
323 self
.bo
= random
.choice(self
.branchops
)
324 self
.bi
= random
.randrange(32)
326 def generate_instruction(self
):
327 string
= "{} {},{},{}\n".format(self
.opcodestr
,
333 def check_results(self
, pdecode2
):
334 imm
= yield pdecode2
.e
.imm_data
.data
335 bo
= yield pdecode2
.dec
.BO
[0:-1]
336 bi
= yield pdecode2
.dec
.BI
[0:-1]
338 assert(imm
== self
.addr
)
339 assert(bo
== self
.bo
)
340 assert(bi
== self
.bi
)
341 lk
= yield pdecode2
.e
.lk
342 if "l" in self
.opcodestr
:
346 aa
= yield pdecode2
.dec
.AA
[0:-1]
347 if "a" in self
.opcodestr
:
356 "bclr": InternalOp
.OP_B
,
357 "bcctr": InternalOp
.OP_B
,
358 "bclrl": InternalOp
.OP_B
,
359 "bcctrl": InternalOp
.OP_B
,
361 # Given in Figure 40 "BO field encodings" in section 2.4, page
362 # 33 of the Power ISA v3.0B manual
363 self
.branchops
= [0b00100, 0b01100, 0b10100]
364 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
365 self
.opcode
= self
.ops
[self
.opcodestr
]
366 self
.bh
= random
.randrange(4)
367 self
.bo
= random
.choice(self
.branchops
)
368 self
.bi
= random
.randrange(32)
370 def generate_instruction(self
):
371 string
= "{} {},{},{}\n".format(self
.opcodestr
,
377 def check_results(self
, pdecode2
):
378 bo
= yield pdecode2
.dec
.BO
[0:-1]
379 bi
= yield pdecode2
.dec
.BI
[0:-1]
381 assert(bo
== self
.bo
)
382 assert(bi
== self
.bi
)
384 spr
= yield pdecode2
.e
.read_spr2
.data
385 if "lr" in self
.opcodestr
:
386 assert(spr
== SPR
.LR
.value
)
388 assert(spr
== SPR
.CTR
.value
)
390 lk
= yield pdecode2
.e
.lk
391 if self
.opcodestr
[-1] == 'l':
397 class DecoderTestCase(FHDLTestCase
):
399 def run_tst(self
, kls
, name
):
402 instruction
= Signal(32)
404 pdecode
= create_pdecode()
406 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
407 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
413 ins
= checker
.generate_instruction()
414 print("instr", ins
.strip())
417 # turn the instruction into binary data (endian'd)
418 ibin
= get_assembled_instruction(ins
, mode
)
419 print("code", mode
, hex(ibin
), bin(ibin
))
421 # ask the decoder to decode this binary data (endian'd)
422 yield pdecode2
.dec
.bigendian
.eq(mode
) # little / big?
423 yield instruction
.eq(ibin
) # raw binary instr.
426 yield from checker
.check_results(pdecode2
)
428 sim
.add_process(process
)
429 with sim
.write_vcd("%s.vcd" % name
, "%s.gtkw" % name
,
430 traces
=[pdecode2
.ports()]):
433 def test_reg_reg(self
):
434 self
.run_tst(RegRegOp
, "reg_reg")
436 def test_reg_imm(self
):
437 self
.run_tst(RegImmOp
, "reg_imm")
439 def test_ldst_imm(self
):
440 self
.run_tst(LdStOp
, "ldst_imm")
442 def test_cmp_reg(self
):
443 self
.run_tst(CmpRegOp
, "cmp_reg")
446 self
.run_tst(RotateOp
, "rot")
448 def test_branch(self
):
449 self
.run_tst(Branch
, "branch")
451 def test_branch_cond(self
):
452 self
.run_tst(BranchCond
, "branch_cond")
454 def test_branch_rel(self
):
455 self
.run_tst(BranchRel
, "branch_rel")
458 if __name__
== "__main__":