c34094eee29718c9134afedd8cc2da5c53938f22
[openpower-isa.git] / src / openpower / decoder / isa / test_caller_svp64_predication.py
1 from nmigen import Module, Signal
2 from nmigen.back.pysim import Simulator, Delay, Settle
3 from nmutil.formaltest import FHDLTestCase
4 import unittest
5 from openpower.decoder.isa.caller import ISACaller
6 from openpower.decoder.power_decoder import (create_pdecode)
7 from openpower.decoder.power_decoder2 import (PowerDecode2)
8 from openpower.simulator.program import Program
9 from openpower.decoder.isa.caller import ISACaller, SVP64State, CRFields
10 from openpower.decoder.selectable_int import SelectableInt
11 from openpower.decoder.orderedset import OrderedSet
12 from openpower.decoder.isa.all import ISA
13 from openpower.decoder.isa.test_caller import Register, run_tst
14 from openpower.sv.trans.svp64 import SVP64Asm
15 from openpower.consts import SVP64CROffs
16 from copy import deepcopy
17
18 class DecoderTestCase(FHDLTestCase):
19
20 def _check_regs(self, sim, expected):
21 for i in range(32):
22 self.assertEqual(sim.gpr(i), SelectableInt(expected[i], 64))
23
24 def tst_sv_load_store(self):
25 lst = SVP64Asm(["addi 1, 0, 0x0010",
26 "addi 2, 0, 0x0008",
27 "addi 5, 0, 0x1234",
28 "addi 6, 0, 0x1235",
29 "sv.stw 5.v, 0(1.v)",
30 "sv.lwz 9.v, 0(1.v)"])
31 lst = list(lst)
32
33 # SVSTATE (in this case, VL=2)
34 svstate = SVP64State()
35 svstate.vl = 2 # VL
36 svstate.maxvl = 2 # MAXVL
37 print ("SVSTATE", bin(svstate.asint()))
38
39 with Program(lst, bigendian=False) as program:
40 sim = self.run_tst_program(program, svstate=svstate)
41 print(sim.gpr(1))
42 self.assertEqual(sim.gpr(9), SelectableInt(0x1234, 64))
43 self.assertEqual(sim.gpr(10), SelectableInt(0x1235, 64))
44
45 def test_sv_extsw_intpred(self):
46 # extsb, integer twin-pred mask: source is ~r3 (0b01), dest r3 (0b10)
47 # works as follows, where any zeros indicate "skip element"
48 # - sources are 9 and 10
49 # - dests are 5 and 6
50 # - source mask says "pick first element from source (5)
51 # - dest mask says "pick *second* element from dest (10)
52 #
53 # therefore the operation that's carried out is:
54 # GPR(10) = extsb(GPR(5))
55 #
56 # this is a type of back-to-back VREDUCE and VEXPAND but it applies
57 # to *operations*, not just MVs like in traditional Vector ISAs
58 # ascii graphic:
59 #
60 # reg num 0 1 2 3 4 5 6 7 8 9 10
61 # src ~r3=0b01 Y N
62 # |
63 # +-----+
64 # |
65 # dest r3=0b10 N Y
66
67 isa = SVP64Asm(['sv.extsb/sm=~r3/dm=r3 5.v, 9.v'
68 ])
69 lst = list(isa)
70 print ("listing", lst)
71
72 # initial values in GPR regfile
73 initial_regs = [0] * 32
74 initial_regs[3] = 0b10 # predicate mask
75 initial_regs[9] = 0x91 # source ~r3 is 0b01 so this will be used
76 initial_regs[10] = 0x90 # this gets skipped
77 # SVSTATE (in this case, VL=2)
78 svstate = SVP64State()
79 svstate.vl = 2 # VL
80 svstate.maxvl = 2 # MAXVL
81 print ("SVSTATE", bin(svstate.asint()))
82 # copy before running
83 expected_regs = deepcopy(initial_regs)
84 expected_regs[5] = 0x0 # dest r3 is 0b10: skip
85 expected_regs[6] = 0xffff_ffff_ffff_ff91 # 2nd bit of r3 is 1
86
87 with Program(lst, bigendian=False) as program:
88 sim = self.run_tst_program(program, initial_regs, svstate)
89 self._check_regs(sim, expected_regs)
90
91 def test_sv_extsw_intpred_dz(self):
92 # extsb, integer twin-pred mask: dest is r3 (0b01), zeroing on dest
93 isa = SVP64Asm(['sv.extsb/dm=r3/dz 5.v, 9.v'
94 ])
95 lst = list(isa)
96 print ("listing", lst)
97
98 # initial values in GPR regfile
99 initial_regs = [0] * 32
100 initial_regs[3] = 0b01 # predicate mask (dest)
101 initial_regs[5] = 0xfeed # going to be overwritten
102 initial_regs[6] = 0xbeef # going to be overwritten (with zero)
103 initial_regs[9] = 0x91 # dest r3 is 0b01 so this will be used
104 initial_regs[10] = 0x90 # this gets read but the output gets zero'd
105 # SVSTATE (in this case, VL=2)
106 svstate = SVP64State()
107 svstate.vl = 2 # VL
108 svstate.maxvl = 2 # MAXVL
109 print ("SVSTATE", bin(svstate.asint()))
110 # copy before running
111 expected_regs = deepcopy(initial_regs)
112 expected_regs[5] = 0xffff_ffff_ffff_ff91 # dest r3 is 0b01: store
113 expected_regs[6] = 0 # 2nd bit of r3 is 1: zero
114
115 with Program(lst, bigendian=False) as program:
116 sim = self.run_tst_program(program, initial_regs, svstate)
117 self._check_regs(sim, expected_regs)
118
119 def test_sv_add_intpred(self):
120 # adds, integer predicated mask r3=0b10
121 # 1 = 5 + 9 => not to be touched (skipped)
122 # 2 = 6 + 10 => 0x3334 = 0x2223+0x1111
123 # reg num 0 1 2 3 4 5 6 7 8 9 10 11
124 # src r3=0b10 N Y N Y
125 # | | | |
126 # +-------+ | add + |
127 # | +-------+ add --+
128 # | |
129 # dest r3=0b10 N Y
130 isa = SVP64Asm(['sv.add/m=r3 1.v, 5.v, 9.v'
131 ])
132 lst = list(isa)
133 print ("listing", lst)
134
135 # initial values in GPR regfile
136 initial_regs = [0] * 32
137 initial_regs[1] = 0xbeef # not to be altered
138 initial_regs[3] = 0b10 # predicate mask
139 initial_regs[9] = 0x1234
140 initial_regs[10] = 0x1111
141 initial_regs[5] = 0x4321
142 initial_regs[6] = 0x2223
143 # SVSTATE (in this case, VL=2)
144 svstate = SVP64State()
145 svstate.vl = 2 # VL
146 svstate.maxvl = 2 # MAXVL
147 print ("SVSTATE", bin(svstate.asint()))
148 # copy before running
149 expected_regs = deepcopy(initial_regs)
150 expected_regs[1] = 0xbeef
151 expected_regs[2] = 0x3334
152
153 with Program(lst, bigendian=False) as program:
154 sim = self.run_tst_program(program, initial_regs, svstate)
155 self._check_regs(sim, expected_regs)
156
157 def test_sv_add_cr_pred(self):
158 # adds, CR predicated mask CR4.eq = 1, CR5.eq = 0, invert (ne)
159 # 1 = 5 + 9 => not to be touched (skipped)
160 # 2 = 6 + 10 => 0x3334 = 0x2223+0x1111
161 isa = SVP64Asm(['sv.add/m=ne 1.v, 5.v, 9.v'
162 ])
163 lst = list(isa)
164 print ("listing", lst)
165
166 # initial values in GPR regfile
167 initial_regs = [0] * 32
168 initial_regs[1] = 0xbeef # not to be altered
169 initial_regs[9] = 0x1234
170 initial_regs[10] = 0x1111
171 initial_regs[5] = 0x4321
172 initial_regs[6] = 0x2223
173 # SVSTATE (in this case, VL=2)
174 svstate = SVP64State()
175 svstate.vl = 2 # VL
176 svstate.maxvl = 2 # MAXVL
177 print ("SVSTATE", bin(svstate.asint()))
178 # copy before running
179 expected_regs = deepcopy(initial_regs)
180 expected_regs[1] = 0xbeef
181 expected_regs[2] = 0x3334
182
183 # set up CR predicate - CR4.eq=1 and CR5.eq=0
184 cr = (0b0010) << ((7-4)*4) # CR4.eq (we hope)
185
186 with Program(lst, bigendian=False) as program:
187 sim = self.run_tst_program(program, initial_regs, svstate,
188 initial_cr=cr)
189 self._check_regs(sim, expected_regs)
190
191 def test_intpred_vcompress(self):
192 # reg num 0 1 2 3 4 5 6 7 8 9 10 11
193 # src r3=0b101 Y N Y
194 # | |
195 # +-------+ |
196 # | +-----------+
197 # | |
198 # dest always Y Y Y
199
200 isa = SVP64Asm(['sv.extsb/sm=r3 5.v, 9.v'])
201 lst = list(isa)
202 print("listing", lst)
203
204 # initial values in GPR regfile
205 initial_regs = [0] * 32
206 initial_regs[3] = 0b101 # predicate mask
207 initial_regs[9] = 0x90 # source r3 is 0b101 so this will be used
208 initial_regs[10] = 0x91 # this gets skipped
209 initial_regs[11] = 0x92 # source r3 is 0b101 so this will be used
210 # SVSTATE (in this case, VL=3)
211 svstate = SVP64State()
212 svstate.vl = 3 # VL
213 svstate.maxvl = 3 # MAXVL
214 print("SVSTATE", bin(svstate.asint()))
215 # copy before running
216 expected_regs = deepcopy(initial_regs)
217 expected_regs[5] = 0xffff_ffff_ffff_ff90 # (from r9)
218 expected_regs[6] = 0xffff_ffff_ffff_ff92 # (from r11)
219 expected_regs[7] = 0x0 # (VL loop runs out before we can use it)
220
221 with Program(lst, bigendian=False) as program:
222 sim = self.run_tst_program(program, initial_regs, svstate)
223 self._check_regs(sim, expected_regs)
224
225 def test_intpred_vexpand(self):
226 # reg num 0 1 2 3 4 5 6 7 8 9 10 11
227 # src always Y Y Y
228 # | |
229 # +-------+ |
230 # | +------+
231 # | |
232 # dest r3=0b101 Y N Y
233
234 isa = SVP64Asm(['sv.extsb/dm=r3 5.v, 9.v'])
235 lst = list(isa)
236 print("listing", lst)
237
238 # initial values in GPR regfile
239 initial_regs = [0] * 32
240 initial_regs[3] = 0b101 # predicate mask
241 initial_regs[9] = 0x90 # source is "always", so this will be used
242 initial_regs[10] = 0x91 # likewise
243 initial_regs[11] = 0x92 # the VL loop runs out before we can use it
244 # SVSTATE (in this case, VL=3)
245 svstate = SVP64State()
246 svstate.vl = 3 # VL
247 svstate.maxvl = 3 # MAXVL
248 print("SVSTATE", bin(svstate.asint()))
249 # copy before running
250 expected_regs = deepcopy(initial_regs)
251 expected_regs[5] = 0xffff_ffff_ffff_ff90 # 1st bit of r3 is 1
252 expected_regs[6] = 0x0 # skip
253 expected_regs[7] = 0xffff_ffff_ffff_ff91 # 3nd bit of r3 is 1
254
255 with Program(lst, bigendian=False) as program:
256 sim = self.run_tst_program(program, initial_regs, svstate)
257 self._check_regs(sim, expected_regs)
258
259 def test_intpred_twinpred(self):
260 # reg num 0 1 2 3 4 5 6 7 8 9 10 11
261 # src r3=0b101 Y N Y
262 # |
263 # +-----+
264 # |
265 # dest ~r3=0b010 N Y N
266
267 isa = SVP64Asm(['sv.extsb/sm=r3/dm=~r3 5.v, 9.v'])
268 lst = list(isa)
269 print("listing", lst)
270
271 # initial values in GPR regfile
272 initial_regs = [0] * 32
273 initial_regs[3] = 0b101 # predicate mask
274 initial_regs[9] = 0x90 # source r3 is 0b101 so this will be used
275 initial_regs[10] = 0x91 # this gets skipped
276 initial_regs[11] = 0x92 # VL loop runs out before we can use it
277 # SVSTATE (in this case, VL=3)
278 svstate = SVP64State()
279 svstate.vl = 3 # VL
280 svstate.maxvl = 3 # MAXVL
281 print("SVSTATE", bin(svstate.asint()))
282 # copy before running
283 expected_regs = deepcopy(initial_regs)
284 expected_regs[5] = 0x0 # dest ~r3 is 0b010: skip
285 expected_regs[6] = 0xffff_ffff_ffff_ff90 # 2nd bit of ~r3 is 1
286 expected_regs[7] = 0x0 # dest ~r3 is 0b010: skip
287
288 with Program(lst, bigendian=False) as program:
289 sim = self.run_tst_program(program, initial_regs, svstate)
290 self._check_regs(sim, expected_regs)
291
292 # checks that we are able to resume in the middle of a VL loop,
293 # after an interrupt, or after the user has updated src/dst step
294 # let's assume the user has prepared src/dst step before running this
295 # vector instruction
296 def test_intpred_reentrant(self):
297 # reg num 0 1 2 3 4 5 6 7 8 9 10 11 12
298 # srcstep=1 v
299 # src r3=0b0101 Y N Y N
300 # : |
301 # + - - + |
302 # : +-------+
303 # : |
304 # dest ~r3=0b1010 N Y N Y
305 # dststep=2 ^
306
307 isa = SVP64Asm(['sv.extsb/sm=r3/dm=~r3 5.v, 9.v'])
308 lst = list(isa)
309 print("listing", lst)
310
311 # initial values in GPR regfile
312 initial_regs = [0] * 32
313 initial_regs[3] = 0b0101 # mask
314 initial_regs[9] = 0x90 # srcstep starts at 2, so this gets skipped
315 initial_regs[10] = 0x91 # skip
316 initial_regs[11] = 0x92 # this will be used
317 initial_regs[12] = 0x93 # skip
318
319 # SVSTATE (in this case, VL=4)
320 svstate = SVP64State()
321 svstate.vl = 4 # VL
322 svstate.maxvl = 4 # MAXVL
323 # set src/dest step on the middle of the loop
324 svstate.srcstep = 1
325 svstate.dststep = 2
326 print("SVSTATE", bin(svstate.asint()))
327 # copy before running
328 expected_regs = deepcopy(initial_regs)
329 expected_regs[5] = 0x0 # skip
330 expected_regs[6] = 0x0 # dststep starts at 3, so this gets skipped
331 expected_regs[7] = 0x0 # skip
332 expected_regs[8] = 0xffff_ffff_ffff_ff92 # this will be used
333
334 with Program(lst, bigendian=False) as program:
335 sim = self.run_tst_program(program, initial_regs, svstate)
336 self._check_regs(sim, expected_regs)
337
338 def test_shift_one_by_r3_dest(self):
339 # reg num 0 1 2 3 4 5 6 7 8 9 10 11
340 # src r30=0b100 N N Y
341 # |
342 # +-----------+
343 # |
344 # dest r3=1: 1<<r3=0b010 N Y N
345
346 isa = SVP64Asm(['sv.extsb/dm=1<<r3/sm=r30 5.v, 9.v'])
347 lst = list(isa)
348 print("listing", lst)
349
350 # initial values in GPR regfile
351 initial_regs = [0] * 32
352 initial_regs[3] = 1 # dest mask = 1<<r3 = 0b010
353 initial_regs[30] = 0b100 # source mask
354 initial_regs[9] = 0x90 # skipped
355 initial_regs[10] = 0x91 # skipped
356 initial_regs[11] = 0x92 # 3rd bit of r30 is 1
357 # SVSTATE (in this case, VL=3)
358 svstate = SVP64State()
359 svstate.vl = 3 # VL
360 svstate.maxvl = 3 # MAXVL
361 print("SVSTATE", bin(svstate.asint()))
362 # copy before running
363 expected_regs = deepcopy(initial_regs)
364 expected_regs[5] = 0x0 # skip
365 expected_regs[6] = 0xffff_ffff_ffff_ff92 # r3 is 1, so this is used
366 expected_regs[7] = 0x0 # skip
367
368 with Program(lst, bigendian=False) as program:
369 sim = self.run_tst_program(program, initial_regs, svstate)
370 self._check_regs(sim, expected_regs)
371
372 def test_shift_one_by_r3_source(self):
373 # reg num 0 1 2 3 4 5 6 7 8 9 10 11
374 # src r3=2: 1<<r3=0b100 N N Y
375 # |
376 # +-----------+
377 # |
378 # dest r30=0b010 N Y N
379
380 isa = SVP64Asm(['sv.extsb/sm=1<<r3/dm=r30 5.v, 9.v'])
381 lst = list(isa)
382 print("listing", lst)
383
384 # initial values in GPR regfile
385 initial_regs = [0] * 32
386 initial_regs[3] = 2 # source mask = 1<<r3 = 0b100
387 initial_regs[30] = 0b010 # dest mask
388 initial_regs[9] = 0x90 # skipped
389 initial_regs[10] = 0x91 # skipped
390 initial_regs[11] = 0x92 # r3 is 2, so this will be used
391 # SVSTATE (in this case, VL=3)
392 svstate = SVP64State()
393 svstate.vl = 3 # VL
394 svstate.maxvl = 3 # MAXVL
395 print("SVSTATE", bin(svstate.asint()))
396 # copy before running
397 expected_regs = deepcopy(initial_regs)
398 expected_regs[5] = 0x0 # skip
399 expected_regs[6] = 0xffff_ffff_ffff_ff92 # 2nd bit of r30 is 1
400 expected_regs[7] = 0x0 # skip
401
402 with Program(lst, bigendian=False) as program:
403 sim = self.run_tst_program(program, initial_regs, svstate)
404 self._check_regs(sim, expected_regs)
405
406 # checks reentrant CR predication
407 def test_crpred_reentrant(self):
408 # reg num 0 1 2 3 4 5 6 7 8 9 10 11 12
409 # srcstep=1 v
410 # src cr4.eq=1 Y N Y N
411 # cr6.eq=1 : |
412 # + - - + |
413 # : +-------+
414 # dest cr5.lt=1 : |
415 # cr7.lt=1 N Y N Y
416 # dststep=2 ^
417
418 isa = SVP64Asm(['sv.extsb/sm=eq/dm=lt 5.v, 9.v'])
419 lst = list(isa)
420 print("listing", lst)
421
422 # initial values in GPR regfile
423 initial_regs = [0] * 32
424 initial_regs[9] = 0x90 # srcstep starts at 2, so this gets skipped
425 initial_regs[10] = 0x91 # skip
426 initial_regs[11] = 0x92 # this will be used
427 initial_regs[12] = 0x93 # skip
428
429 cr = CRFields()
430 # set up CR predicate
431 # CR4.eq=1 and CR6.eq=1
432 cr.crl[4][CRFields.EQ] = 1
433 cr.crl[6][CRFields.EQ] = 1
434 # CR5.lt=1 and CR7.lt=1
435 cr.crl[5][CRFields.LT] = 1
436 cr.crl[7][CRFields.LT] = 1
437 # SVSTATE (in this case, VL=4)
438 svstate = SVP64State()
439 svstate.vl = 4 # VL
440 svstate.maxvl = 4 # MAXVL
441 # set src/dest step on the middle of the loop
442 svstate.srcstep = 1
443 svstate.dststep = 2
444 print("SVSTATE", bin(svstate.asint()))
445 # copy before running
446 expected_regs = deepcopy(initial_regs)
447 expected_regs[5] = 0x0 # skip
448 expected_regs[6] = 0x0 # dststep starts at 3, so this gets skipped
449 expected_regs[7] = 0x0 # skip
450 expected_regs[8] = 0xffff_ffff_ffff_ff92 # this will be used
451
452 with Program(lst, bigendian=False) as program:
453 sim = self.run_tst_program(program, initial_regs, svstate,
454 initial_cr=cr.cr.asint())
455 self._check_regs(sim, expected_regs)
456
457 def run_tst_program(self, prog, initial_regs=None,
458 svstate=None,
459 initial_cr=0):
460 if initial_regs is None:
461 initial_regs = [0] * 32
462 simulator = run_tst(prog, initial_regs, svstate=svstate,
463 initial_cr=initial_cr)
464 simulator.gpr.dump()
465 return simulator
466
467
468 if __name__ == "__main__":
469 unittest.main()