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
,
10 get_signal_name
, get_csv
)
11 from soc
.decoder
.power_decoder2
import (PowerDecode2
)
21 def __init__(self
, num
):
27 "add": InternalOp
.OP_ADD
,
28 "and": InternalOp
.OP_AND
,
29 "or": InternalOp
.OP_OR
,
30 "add.": InternalOp
.OP_ADD
,
31 "lwzx": InternalOp
.OP_LOAD
,
32 "stwx": InternalOp
.OP_STORE
,
34 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
35 self
.opcode
= self
.ops
[self
.opcodestr
]
36 self
.r1
= Register(random
.randrange(32))
37 self
.r2
= Register(random
.randrange(32))
38 self
.r3
= Register(random
.randrange(32))
40 def generate_instruction(self
):
41 string
= "{} {}, {}, {}\n".format(self
.opcodestr
,
47 def check_results(self
, pdecode2
):
48 if self
.opcode
== InternalOp
.OP_STORE
:
49 r1sel
= yield pdecode2
.e
.read_reg3
.data
51 r1sel
= yield pdecode2
.e
.write_reg
.data
53 r3sel
= yield pdecode2
.e
.read_reg2
.data
55 # For some reason r2 gets decoded either in read_reg1
57 out_sel
= yield pdecode2
.dec
.op
.out_sel
58 if out_sel
== OutSel
.RA
.value
:
59 r2sel
= yield pdecode2
.e
.read_reg3
.data
61 r2sel
= yield pdecode2
.e
.read_reg1
.data
62 assert(r1sel
== self
.r1
.num
)
63 assert(r3sel
== self
.r3
.num
)
64 assert(r2sel
== self
.r2
.num
)
66 opc_out
= yield pdecode2
.dec
.op
.internal_op
67 assert(opc_out
== self
.opcode
.value
)
68 # check RC value (the dot in the instruction)
69 rc
= yield pdecode2
.e
.rc
.data
70 if '.' in self
.opcodestr
:
80 "addi": InternalOp
.OP_ADD
,
81 "addis": InternalOp
.OP_ADD
,
82 "andi.": InternalOp
.OP_AND
,
83 "ori": InternalOp
.OP_OR
,
85 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
86 self
.opcode
= self
.ops
[self
.opcodestr
]
87 self
.r1
= Register(random
.randrange(32))
88 self
.r2
= Register(random
.randrange(32))
89 self
.imm
= random
.randrange(32767)
91 def generate_instruction(self
):
92 string
= "{} {}, {}, {}\n".format(self
.opcodestr
,
98 def check_results(self
, pdecode2
):
100 r1sel
= yield pdecode2
.e
.write_reg
.data
101 # For some reason r2 gets decoded either in read_reg1
103 out_sel
= yield pdecode2
.dec
.op
.out_sel
104 if out_sel
== OutSel
.RA
.value
:
105 r2sel
= yield pdecode2
.e
.read_reg3
.data
107 r2sel
= yield pdecode2
.e
.read_reg1
.data
108 assert(r1sel
== self
.r1
.num
)
109 assert(r2sel
== self
.r2
.num
)
111 imm
= yield pdecode2
.e
.imm_data
.data
112 in2_sel
= yield pdecode2
.dec
.op
.in2_sel
113 if in2_sel
in [In2Sel
.CONST_SI_HI
.value
, In2Sel
.CONST_UI_HI
.value
]:
114 assert(imm
== (self
.imm
<< 16))
116 assert(imm
== self
.imm
)
118 rc
= yield pdecode2
.e
.rc
.data
119 if '.' in self
.opcodestr
:
127 "lwz": InternalOp
.OP_LOAD
,
128 "stw": InternalOp
.OP_STORE
,
129 "lwzu": InternalOp
.OP_LOAD
,
130 "stwu": InternalOp
.OP_STORE
,
131 "lbz": InternalOp
.OP_LOAD
,
132 "lhz": InternalOp
.OP_LOAD
,
133 "stb": InternalOp
.OP_STORE
,
134 "sth": InternalOp
.OP_STORE
,
136 self
.opcodestr
= random
.choice(list(self
.ops
.keys()))
137 self
.opcode
= self
.ops
[self
.opcodestr
]
138 self
.r1
= Register(random
.randrange(32))
139 self
.r2
= Register(random
.randrange(1,32))
140 self
.imm
= random
.randrange(32767)
142 def generate_instruction(self
):
143 string
= "{} {}, {}({})\n".format(self
.opcodestr
,
149 def check_results(self
, pdecode2
):
151 r2sel
= yield pdecode2
.e
.read_reg1
.data
152 if self
.opcode
== InternalOp
.OP_STORE
:
153 r1sel
= yield pdecode2
.e
.read_reg3
.data
155 r1sel
= yield pdecode2
.e
.write_reg
.data
156 assert(r1sel
== self
.r1
.num
)
157 assert(r2sel
== self
.r2
.num
)
159 imm
= yield pdecode2
.e
.imm_data
.data
160 in2_sel
= yield pdecode2
.dec
.op
.in2_sel
161 assert(imm
== self
.imm
)
163 update
= yield pdecode2
.e
.update
164 if "u" in self
.opcodestr
:
169 size
= yield pdecode2
.e
.data_len
170 if "w" in self
.opcodestr
:
172 elif "h" in self
.opcodestr
:
174 elif "b" in self
.opcodestr
:
179 class DecoderTestCase(FHDLTestCase
):
181 def get_assembled_instruction(self
, instruction
):
182 with tempfile
.NamedTemporaryFile(suffix
=".o") as outfile
:
183 args
= ["powerpc64-linux-gnu-as",
186 p
= subprocess
.Popen(args
, stdin
=subprocess
.PIPE
)
187 p
.communicate(instruction
.encode('utf-8'))
188 assert(p
.wait() == 0)
190 with tempfile
.NamedTemporaryFile(suffix
=".bin") as binfile
:
191 args
= ["powerpc64-linux-gnu-objcopy",
195 subprocess
.check_output(args
)
196 binary
= struct
.unpack('>i', binfile
.read(4))[0]
199 def run_tst(self
, kls
, name
):
202 instruction
= Signal(32)
204 pdecode
= create_pdecode()
206 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
207 comb
+= pdecode2
.dec
.opcode_in
.eq(instruction
)
215 instruction_str
= checker
.generate_instruction()
216 print("instr", instruction_str
.strip())
217 instruction_bin
= self
.get_assembled_instruction(
219 print("code", hex(instruction_bin
), bin(instruction_bin
))
221 yield instruction
.eq(instruction_bin
)
224 yield from checker
.check_results(pdecode2
)
227 sim
.add_process(process
)
228 with sim
.write_vcd("%s.vcd" % name
, "%s.gtkw" % name
,
229 traces
=[pdecode2
.ports()]):
231 def test_reg_reg(self
):
232 self
.run_tst(RegRegOp
, "reg_reg")
234 def test_reg_imm(self
):
235 self
.run_tst(RegImmOp
, "reg_imm")
237 def test_ldst_imm(self
):
238 self
.run_tst(LdStOp
, "ldst_imm")
241 if __name__
== "__main__":