whoops, no ability to add comments in between functions in pseudocode
[openpower-isa.git] / src / openpower / decoder / isa / test_caller_svstate.py
1 """SVP64 unit test for doing strange things to SVSTATE, manually.
2 """
3 from nmigen import Module, Signal
4 from nmigen.back.pysim import Simulator, Delay, Settle
5 from nmutil.formaltest import FHDLTestCase
6 import unittest
7 from openpower.decoder.isa.caller import ISACaller
8 from openpower.decoder.power_decoder import (create_pdecode)
9 from openpower.decoder.power_decoder2 import (PowerDecode2)
10 from openpower.simulator.program import Program
11 from openpower.decoder.isa.caller import ISACaller, SVP64State, CRFields
12 from openpower.decoder.selectable_int import SelectableInt
13 from openpower.decoder.orderedset import OrderedSet
14 from openpower.decoder.isa.all import ISA
15 from openpower.decoder.isa.test_caller import Register, run_tst
16 from openpower.sv.trans.svp64 import SVP64Asm
17 from openpower.consts import SVP64CROffs
18 from copy import deepcopy
19
20
21 class SVSTATETestCase(FHDLTestCase):
22
23 def _check_regs(self, sim, expected):
24 print ("GPR")
25 sim.gpr.dump()
26 for i in range(32):
27 self.assertEqual(sim.gpr(i), SelectableInt(expected[i], 64))
28
29 def test_sv_add(self):
30 """sets VL=2 (via SVSTATE) with a manual srcstep/dststep,
31 then does a scalar-result add. the result should be:
32
33 add 1, 6, 10
34
35 because whilst the Vector instruction was moved on by srcstep,
36 the Scalar one is NOT moved on.
37 """
38 isa = SVP64Asm(['sv.add 1, 5.v, 9.v'
39 ])
40 lst = list(isa)
41 print ("listing", lst)
42
43 # initial values in GPR regfile
44 initial_regs = [0] * 32
45 initial_regs[9] = 0x1234
46 initial_regs[10] = 0x1111
47 initial_regs[5] = 0x4321
48 initial_regs[6] = 0x2223
49
50 # SVSTATE (in this case, VL=3, and src/dststep set ALREADY to 1)
51 svstate = SVP64State()
52 svstate.vl = 2 # VL
53 svstate.maxvl = 2 # MAXVL
54 svstate.srcstep = 1 # srcstep
55 svstate.dststep = 1 # srcstep
56 print ("SVSTATE", bin(svstate.asint()))
57
58 # copy before running
59 expected_regs = deepcopy(initial_regs)
60 expected_regs[1] = 0x3334
61
62 with Program(lst, bigendian=False) as program:
63 sim = self.run_tst_program(program, initial_regs, svstate=svstate)
64 self._check_regs(sim, expected_regs)
65
66 def test_svstep_add_1(self):
67 """tests svstep with an add, using scalar adds, when it reaches VL
68 lst = SVP64Asm(["setvl 3, 0, 2, 1, 1, 1",
69 'sv.add 1, 5.v, 9.v',
70 'sv.addi 12.v, 1, 1',
71 "setvl. 0, 0, 1, 1, 0, 0",
72 'sv.add 1, 5.v, 9.v',
73 'sv.addi 12.v, 1, 1',
74 "setvl. 0, 0, 1, 1, 0, 0"
75 ])
76
77 sequence is as follows:
78
79 * setvl sets VL=2 but also "Vertical First" mode.
80 this sets MSR[SVF].
81 * first add, which has srcstep/dststep = 0, does add 1,5,9
82 * first addi, which has srcstep/dststep = 0, does addi 12, 1, #1
83 * svstep EXPLICITLY walks srcstep/dststep to next element
84 * second add, which now has srcstep/dststep = 1, does add 1,6,10
85 (because RT is a *SCALAR*)
86 * second addi, which has srcstep/dststep = 1, does addi 13, 1, #1
87 * svstep EXPLICITLY walks srcstep/dststep to next element,
88 which now equals VL. srcstep and dststep are both set to
89 zero, and MSR[SVF] is cleared.
90
91 the first add will write 0x5555 into r1, then the vector-addi
92 will add 1 to that and store the result in r12 (0x5556)
93
94 the second add will write 0x3334 into the temp r1, this *stays* there
95 obviously, and the second vector-addi will add 1 to the *new* r1 and
96 store the result in r13 (0x3335).
97
98 """
99 lst = SVP64Asm(["setvl 3, 0, 2, 1, 1, 1",
100 'sv.add 1, 5.v, 9.v', # scalar dest (into r1)
101 'sv.addi 12.v, 1, 1', # scalar src (from r1)
102 "setvl. 0, 0, 1, 1, 0, 0", # svstep
103 'sv.add 1, 5.v, 9.v', # again, scalar dest
104 'sv.addi 12.v, 1, 1', # but vector dest
105 "setvl. 0, 0, 1, 1, 0, 0" # svstep
106 ])
107 lst = list(lst)
108
109 # SVSTATE (in this case, VL=2)
110 svstate = SVP64State()
111 svstate.vl = 2 # VL
112 svstate.maxvl = 2 # MAXVL
113 print ("SVSTATE", bin(svstate.asint()))
114
115 # initial values in GPR regfile
116 initial_regs = [0] * 32
117 initial_regs[9] = 0x1234
118 initial_regs[10] = 0x1111
119 initial_regs[5] = 0x4321
120 initial_regs[6] = 0x2223
121
122 # copy before running
123 expected_regs = deepcopy(initial_regs)
124 expected_regs[1] = 0x3334 # last temporary
125 expected_regs[12] = 0x5556
126 expected_regs[13] = 0x3335
127 expected_regs[3] = 2 # setvl places copy of VL here
128
129 with Program(lst, bigendian=False) as program:
130 sim = self.run_tst_program(program, initial_regs, svstate=svstate)
131 print ("SVSTATE after", bin(sim.svstate.asint()))
132 print (" vl", bin(sim.svstate.vl))
133 print (" mvl", bin(sim.svstate.maxvl))
134 print (" srcstep", bin(sim.svstate.srcstep))
135 print (" dststep", bin(sim.svstate.dststep))
136 self.assertEqual(sim.svstate.vl, 2)
137 self.assertEqual(sim.svstate.maxvl, 2)
138 self.assertEqual(sim.svstate.srcstep, 0)
139 self.assertEqual(sim.svstate.dststep, 0)
140 # when end reached, vertical mode is exited
141 print(" msr", bin(sim.msr.value)) # should be zero
142 self.assertEqual(sim.msr, SelectableInt(0<<(63-6), 64))
143 CR0 = sim.crl[0]
144 print(" CR0", bin(CR0.get_range().value))
145 self.assertEqual(CR0[CRFields.EQ], 1)
146 self.assertEqual(CR0[CRFields.LT], 0)
147 self.assertEqual(CR0[CRFields.GT], 0)
148 self.assertEqual(CR0[CRFields.SO], 0)
149
150 # check registers as expected
151 self._check_regs(sim, expected_regs)
152
153 def run_tst_program(self, prog, initial_regs=None,
154 svstate=None):
155 if initial_regs is None:
156 initial_regs = [0] * 32
157 simulator = run_tst(prog, initial_regs, svstate=svstate)
158 simulator.gpr.dump()
159 return simulator
160
161
162 if __name__ == "__main__":
163 unittest.main()
164