1 from nmigen
import Module
, Signal
3 # NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
4 # Also, check out the cxxsim nmigen branch, and latest yosys from git
5 from nmutil
.sim_tmp_alternative
import Simulator
, Delay
7 from nmutil
.formaltest
import FHDLTestCase
9 from soc
.decoder
.power_decoder
import (create_pdecode
)
10 from soc
.decoder
.power_enums
import (Function
, MicrOp
,
11 In1Sel
, In2Sel
, In3Sel
,
12 OutSel
, RC
, LdstLen
, CryIn
,
13 single_bit_flags
, Form
, SPR
,
14 get_signal_name
, get_csv
)
15 from soc
.decoder
.power_decoder2
import (PowerDecode2
)
16 from soc
.simulator
.gas
import get_assembled_instruction
21 def __init__(self
, num
):
29 def get_imm(self
, in2_sel
):
30 if in2_sel
== In2Sel
.CONST_UI
.value
:
31 return self
.imm
& 0xffff
32 if in2_sel
== In2Sel
.CONST_UI_HI
.value
:
33 return (self
.imm
& 0xffff) << 16
34 if in2_sel
== In2Sel
.CONST_SI
.value
:
36 return (self
.imm
& (sign_bit
-1)) - (self
.imm
& sign_bit
)
37 if in2_sel
== In2Sel
.CONST_SI_HI
.value
:
40 return (imm
& (sign_bit
-1)) - (imm
& sign_bit
)
49 "add.": MicrOp
.OP_ADD
,
50 "lwzx": MicrOp
.OP_LOAD
,
51 "stwx": MicrOp
.OP_STORE
,
53 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
54 self
.opcode
= self
.ops
[self
.opcodestr
]
55 self
.r1
= Register(random
.randrange(32))
56 self
.r2
= Register(random
.randrange(32))
57 self
.r3
= Register(random
.randrange(32))
59 def generate_instruction(self
):
60 string
= "{} {}, {}, {}\n".format(self
.opcodestr
,
66 def check_results(self
, pdecode2
):
67 if self
.opcode
== MicrOp
.OP_STORE
:
68 r1sel
= yield pdecode2
.e
.read_reg3
.data
70 r1sel
= yield pdecode2
.e
.write_reg
.data
72 r3sel
= yield pdecode2
.e
.read_reg2
.data
74 # For some reason r2 gets decoded either in read_reg1
76 out_sel
= yield pdecode2
.dec
.op
.out_sel
77 if out_sel
== OutSel
.RA
.value
:
78 r2sel
= yield pdecode2
.e
.read_reg3
.data
80 r2sel
= yield pdecode2
.e
.read_reg1
.data
81 assert(r1sel
== self
.r1
.num
)
82 assert(r3sel
== self
.r3
.num
)
83 assert(r2sel
== self
.r2
.num
)
85 opc_out
= yield pdecode2
.dec
.op
.internal_op
86 assert(opc_out
== self
.opcode
.value
)
87 # check RC value (the dot in the instruction)
88 rc
= yield pdecode2
.e
.rc
.data
89 if '.' in self
.opcodestr
:
95 class RegImmOp(Checker
):
99 "addi": MicrOp
.OP_ADD
,
100 "addis": MicrOp
.OP_ADD
,
101 "andi.": MicrOp
.OP_AND
,
104 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
105 self
.opcode
= self
.ops
[self
.opcodestr
]
106 self
.r1
= Register(random
.randrange(32))
107 self
.r2
= Register(random
.randrange(32))
108 self
.imm
= random
.randrange(32767)
110 def generate_instruction(self
):
111 string
= "{} {}, {}, {}\n".format(self
.opcodestr
,
117 def check_results(self
, pdecode2
):
119 r1sel
= yield pdecode2
.e
.write_reg
.data
120 # For some reason r2 gets decoded either in read_reg1
122 out_sel
= yield pdecode2
.dec
.op
.out_sel
123 if out_sel
== OutSel
.RA
.value
:
124 r2sel
= yield pdecode2
.e
.read_reg3
.data
126 r2sel
= yield pdecode2
.e
.read_reg1
.data
127 assert(r1sel
== self
.r1
.num
)
128 assert(r2sel
== self
.r2
.num
)
130 imm
= yield pdecode2
.e
.imm_data
.data
131 in2_sel
= yield pdecode2
.dec
.op
.in2_sel
132 imm_expected
= self
.get_imm(in2_sel
)
133 msg
= "imm: got {:x}, expected {:x}".format(imm
, imm_expected
)
134 assert imm
== imm_expected
, msg
136 rc
= yield pdecode2
.e
.rc
.data
137 if '.' in self
.opcodestr
:
143 class LdStOp(Checker
):
147 "lwz": MicrOp
.OP_LOAD
,
148 "stw": MicrOp
.OP_STORE
,
149 "lwzu": MicrOp
.OP_LOAD
,
150 "stwu": MicrOp
.OP_STORE
,
151 "lbz": MicrOp
.OP_LOAD
,
152 "lhz": MicrOp
.OP_LOAD
,
153 "stb": MicrOp
.OP_STORE
,
154 "sth": MicrOp
.OP_STORE
,
156 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
157 self
.opcode
= self
.ops
[self
.opcodestr
]
158 self
.r1
= Register(random
.randrange(32))
159 self
.r2
= Register(random
.randrange(1, 32))
160 while self
.r2
.num
== self
.r1
.num
:
161 self
.r2
= Register(random
.randrange(1, 32))
162 self
.imm
= random
.randrange(32767)
164 def generate_instruction(self
):
165 string
= "{} {}, {}({})\n".format(self
.opcodestr
,
171 def check_results(self
, pdecode2
):
173 r2sel
= yield pdecode2
.e
.read_reg1
.data
174 if self
.opcode
== MicrOp
.OP_STORE
:
175 r1sel
= yield pdecode2
.e
.read_reg3
.data
177 r1sel
= yield pdecode2
.e
.write_reg
.data
178 assert(r1sel
== self
.r1
.num
)
179 assert(r2sel
== self
.r2
.num
)
181 imm
= yield pdecode2
.e
.imm_data
.data
182 in2_sel
= yield pdecode2
.dec
.op
.in2_sel
183 assert(imm
== self
.get_imm(in2_sel
))
185 update
= yield pdecode2
.e
.update
186 if "u" in self
.opcodestr
:
191 size
= yield pdecode2
.e
.data_len
192 if "w" in self
.opcodestr
:
194 elif "h" in self
.opcodestr
:
196 elif "b" in self
.opcodestr
:
205 "cmp": MicrOp
.OP_CMP
,
207 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
208 self
.opcode
= self
.ops
[self
.opcodestr
]
209 self
.r1
= Register(random
.randrange(32))
210 self
.r2
= Register(random
.randrange(32))
211 self
.cr
= Register(random
.randrange(8))
213 def generate_instruction(self
):
214 string
= "{} {}, 0, {}, {}\n".format(self
.opcodestr
,
220 def check_results(self
, pdecode2
):
221 r1sel
= yield pdecode2
.e
.read_reg1
.data
222 r2sel
= yield pdecode2
.e
.read_reg2
.data
223 crsel
= yield pdecode2
.dec
.BF
225 assert(r1sel
== self
.r1
.num
)
226 assert(r2sel
== self
.r2
.num
)
227 assert(crsel
== self
.cr
.num
)
233 "rlwinm": MicrOp
.OP_CMP
,
234 "rlwnm": MicrOp
.OP_CMP
,
235 "rlwimi": MicrOp
.OP_CMP
,
236 "rlwinm.": MicrOp
.OP_CMP
,
237 "rlwnm.": MicrOp
.OP_CMP
,
238 "rlwimi.": MicrOp
.OP_CMP
,
240 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
241 self
.opcode
= self
.ops
[self
.opcodestr
]
242 self
.r1
= Register(random
.randrange(32))
243 self
.r2
= Register(random
.randrange(32))
244 self
.shift
= random
.randrange(32)
245 self
.mb
= random
.randrange(32)
246 self
.me
= random
.randrange(32)
248 def generate_instruction(self
):
249 string
= "{} {},{},{},{},{}\n".format(self
.opcodestr
,
257 def check_results(self
, pdecode2
):
258 r1sel
= yield pdecode2
.e
.write_reg
.data
259 r2sel
= yield pdecode2
.e
.read_reg3
.data
262 if "i" in self
.opcodestr
:
265 shift
= yield pdecode2
.e
.read_reg2
.data
269 assert(r1sel
== self
.r1
.num
)
270 assert(r2sel
== self
.r2
.num
)
271 assert(shift
== self
.shift
)
272 assert(mb
== self
.mb
)
273 assert(me
== self
.me
)
275 rc
= yield pdecode2
.e
.rc
.data
276 if '.' in self
.opcodestr
:
290 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
291 self
.opcode
= self
.ops
[self
.opcodestr
]
292 self
.addr
= random
.randrange(2**23) * 4
294 def generate_instruction(self
):
295 string
= "{} {}\n".format(self
.opcodestr
,
299 def check_results(self
, pdecode2
):
300 imm
= yield pdecode2
.e
.imm_data
.data
302 assert(imm
== self
.addr
)
303 lk
= yield pdecode2
.e
.lk
304 if "l" in self
.opcodestr
:
308 aa
= yield pdecode2
.dec
.AA
309 if "a" in self
.opcodestr
:
323 # Given in Figure 40 "BO field encodings" in section 2.4, page
324 # 33 of the Power ISA v3.0B manual
325 self
.branchops
= [0b00000, 0b00010, 0b00100, 0b01000, 0b01010,
326 0b01100, 0b10000, 0b10100]
327 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
328 self
.opcode
= self
.ops
[self
.opcodestr
]
329 self
.addr
= random
.randrange(2**13) * 4
330 self
.bo
= random
.choice(self
.branchops
)
331 self
.bi
= random
.randrange(32)
333 def generate_instruction(self
):
334 string
= "{} {},{},{}\n".format(self
.opcodestr
,
340 def check_results(self
, pdecode2
):
341 imm
= yield pdecode2
.e
.imm_data
.data
342 bo
= yield pdecode2
.dec
.BO
343 bi
= yield pdecode2
.dec
.BI
345 assert(imm
== self
.addr
)
346 assert(bo
== self
.bo
)
347 assert(bi
== self
.bi
)
348 lk
= yield pdecode2
.e
.lk
349 if "l" in self
.opcodestr
:
353 aa
= yield pdecode2
.dec
.AA
354 if "a" in self
.opcodestr
:
359 cr_sel
= yield pdecode2
.e
.read_cr1
.data
360 assert cr_sel
== (self
.bi
//8), f
"{cr_sel} {self.bi}"
368 "bcctr": MicrOp
.OP_B
,
369 "bclrl": MicrOp
.OP_B
,
370 "bcctrl": MicrOp
.OP_B
,
372 # Given in Figure 40 "BO field encodings" in section 2.4, page
373 # 33 of the Power ISA v3.0B manual
374 self
.branchops
= [0b00100, 0b01100, 0b10100]
375 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
376 self
.opcode
= self
.ops
[self
.opcodestr
]
377 self
.bh
= random
.randrange(4)
378 self
.bo
= random
.choice(self
.branchops
)
379 self
.bi
= random
.randrange(32)
381 def generate_instruction(self
):
382 string
= "{} {},{},{}\n".format(self
.opcodestr
,
388 def check_results(self
, pdecode2
):
389 bo
= yield pdecode2
.dec
.BO
390 bi
= yield pdecode2
.dec
.BI
392 assert(bo
== self
.bo
)
393 assert(bi
== self
.bi
)
395 spr
= yield pdecode2
.e
.read_spr2
.data
396 if "lr" in self
.opcodestr
:
397 assert(spr
== SPR
.LR
.value
)
399 assert(spr
== SPR
.CTR
.value
)
401 lk
= yield pdecode2
.e
.lk
402 if self
.opcodestr
[-1] == 'l':
410 "crand": MicrOp
.OP_CROP
,
412 # Given in Figure 40 "BO field encodings" in section 2.4, page
413 # 33 of the Power ISA v3.0B manual
414 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
415 self
.opcode
= self
.ops
[self
.opcodestr
]
416 self
.ba
= random
.randrange(32)
417 self
.bb
= random
.randrange(32)
418 self
.bt
= random
.randrange(32)
420 def generate_instruction(self
):
421 string
= "{} {},{},{}\n".format(self
.opcodestr
,
427 def check_results(self
, pdecode2
):
428 cr1
= yield pdecode2
.e
.read_cr1
.data
429 assert cr1
== self
.ba
//4
431 cr2
= yield pdecode2
.e
.read_cr2
.data
432 assert cr2
== self
.bb
//4
434 cr_out
= yield pdecode2
.e
.write_cr
.data
435 cr3
= yield pdecode2
.e
.read_cr3
.data
436 assert cr_out
== self
.bt
//4
437 assert cr3
== self
.bt
//4
441 class DecoderTestCase(FHDLTestCase
):
443 def run_tst(self
, kls
, name
):
446 instruction
= Signal(32)
448 pdecode
= create_pdecode()
450 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
451 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
457 ins
= checker
.generate_instruction()
458 print("instr", ins
.strip())
461 # turn the instruction into binary data (endian'd)
462 ibin
= get_assembled_instruction(ins
, mode
)
463 print("code", mode
, hex(ibin
), bin(ibin
))
465 # ask the decoder to decode this binary data (endian'd)
466 yield pdecode2
.dec
.bigendian
.eq(mode
) # little / big?
467 yield instruction
.eq(ibin
) # raw binary instr.
470 yield from checker
.check_results(pdecode2
)
472 sim
.add_process(process
)
473 ports
= pdecode2
.ports()
475 with sim
.write_vcd("%s.vcd" % name
, "%s.gtkw" % name
,
479 def test_reg_reg(self
):
480 self
.run_tst(RegRegOp
, "reg_reg")
482 def test_reg_imm(self
):
483 self
.run_tst(RegImmOp
, "reg_imm")
485 def test_ldst_imm(self
):
486 self
.run_tst(LdStOp
, "ldst_imm")
488 def test_cmp_reg(self
):
489 self
.run_tst(CmpRegOp
, "cmp_reg")
492 self
.run_tst(RotateOp
, "rot")
494 def test_branch(self
):
495 self
.run_tst(Branch
, "branch")
497 def test_branch_cond(self
):
498 self
.run_tst(BranchCond
, "branch_cond")
500 def test_branch_rel(self
):
501 self
.run_tst(BranchRel
, "branch_rel")
503 def test_cr_op(self
):
504 self
.run_tst(CROp
, "cr_op")
507 if __name__
== "__main__":