fix form and pseudo-code for fmvis, tests in 64-bit mode
[openpower-isa.git] / src / openpower / test / state.py
1 """ Power ISA test API
2
3 This module implements the creation, inspection and comparison
4 of test states from different sources.
5
6 The basic premise is to create a test state using the TestState method.
7 The TestState method returns a test state object initialized with a
8 basic set of registers pulled from the 'to_test' object. The
9 state created can then be tested against other test states using the
10 'compare' method.
11
12 The SimState class provides an example of needed registers and naming.
13
14 The TestState method relies on the 'state_factory' dictionary for lookup
15 of associated test class creation. The dictionary can be added to using
16 the state_add method.
17
18 Also note when creating and accessing test state classes and object
19 methods, the use of yield from/yield is required.
20
21
22 """
23
24
25 from openpower.decoder.power_enums import XER_bits
26 from openpower.decoder.isa.radixmmu import RADIX
27 from openpower.util import log
28 import os
29 import sys
30 from copy import deepcopy
31
32 global staterunner_factory
33 staterunner_factory = {}
34
35
36 def staterunner_add(name, kls):
37 log("staterunner_add", name, kls)
38 staterunner_factory[name] = kls
39
40
41 # TBD an Abstract Base Class
42 class StateRunner:
43 """StateRunner: an Abstract Base Class for preparing and running "State".
44 near-identical in concept to python unittest.TestCase
45 """
46 def __init__(self, name, kls):
47 staterunner_add(name, kls)
48 self.name = name
49
50 def setup_for_test(self):
51 if False: yield
52 def setup_during_test(self):
53 if False: yield
54 def prepare_for_test(self, test):
55 if False: yield
56 def run_test(self):
57 if False: yield
58 def end_test(self):
59 if False: yield
60 def cleanup(self):
61 if False: yield
62
63
64 class State:
65 """State: Base class for the "state" of the Power ISA object to be tested
66 including methods to compare various registers and memory between
67 them.
68
69 All methods implemented must be generators.
70
71 GPRs and CRs - stored as lists
72 XERs/PC - simple members
73 memory - stored as a dictionary {location: data}
74 """
75 def get_state(self):
76 yield from self.get_intregs()
77 yield from self.get_crregs()
78 yield from self.get_xregs()
79 yield from self.get_pc()
80 yield from self.get_mem()
81
82 def compare(self, s2):
83 # Compare int registers
84 for i, (intreg, intreg2) in enumerate(
85 zip(self.intregs, s2.intregs)):
86 log("asserting...reg", i, intreg, intreg2)
87 log("code, frepr(code)", self.code, repr(self.code))
88 self.dut.assertEqual(intreg, intreg2,
89 "int reg %d (%s) not equal (%s) %s. "
90 " got %x expected %x at pc %x %x\n" %
91 (i, self.state_type, s2.state_type, repr(self.code),
92 intreg, intreg2, self.pc, s2.pc))
93
94 # CR registers
95 for i, (crreg, crreg2) in enumerate(
96 zip(self.crregs, s2.crregs)):
97 log("asserting...cr", i, crreg, crreg2)
98
99 for i, (crreg, crreg2) in enumerate(
100 zip(self.crregs, s2.crregs)):
101 self.dut.assertEqual(crreg, crreg2,
102 "cr reg %d (%s) not equal (%s) %s. got %x expected %x" %
103 (i, self.state_type, s2.state_type, repr(self.code),
104 crreg, crreg2))
105
106 # XER
107 self.dut.assertEqual(self.so, s2.so, "so mismatch (%s != %s) %s" %
108 (self.state_type, s2.state_type, repr(self.code)))
109 self.dut.assertEqual(self.ov, s2.ov, "ov mismatch (%s != %s) %s" %
110 (self.state_type, s2.state_type, repr(self.code)))
111 self.dut.assertEqual(self.ca, s2.ca, "ca mismatch (%s != %s) %s" %
112 (self.state_type, s2.state_type, repr(self.code)))
113
114 # pc
115 self.dut.assertEqual(self.pc, s2.pc, "pc mismatch (%s != %s) %s" %
116 (self.state_type, s2.state_type, repr(self.code)))
117
118 def compare_mem(self, s2):
119 # copy dics to preserve state mem then pad empty locs since
120 # different Power ISA objects may differ how theystore memory
121 s1mem, s2mem = self.mem.copy(), s2.mem.copy()
122 for i in set(self.mem).difference(set(s2.mem)):
123 s2mem[i] = 0
124 for i in set(s2.mem).difference(set(self.mem)):
125 s1mem[i] = 0
126 for i in s1mem:
127 self.dut.assertEqual(s1mem[i], s2mem[i],
128 "mem mismatch location %d %s" % (i, self.code))
129
130 def dump_state_tofile(self, testname=None, testfile=None):
131 """dump_state_tofile: Takes a passed in teststate object along
132 with a test name and generates a code file located at
133 /tmp/testfile/testname to set an expected state object
134 """
135 lindent = ' '*8 # indent for code
136 # create the path
137 if testname is not None:
138 path = "/tmp/expected/"
139 if testfile is not None:
140 path += testfile + '/'
141 os.makedirs(path, exist_ok=True)
142 sout = open("%s%s.py" % (path, testname), "a+")
143 else:
144 sout = sys.stdout
145
146 # pc and intregs
147 sout.write("%se = ExpectedState(pc=%d)\n" % (lindent, self.pc))
148 for i, reg in enumerate(self.intregs):
149 if(reg != 0):
150 msg = "%se.intregs[%d] = 0x%x\n"
151 sout.write( msg % (lindent, i, reg))
152 # CR fields
153 for i in range(8):
154 cri = self.crregs[i]
155 if(cri != 0):
156 msg = "%se.crregs[%d] = 0x%x\n"
157 sout.write( msg % (lindent, i, cri))
158 # XER
159 if(self.so != 0):
160 sout.write("%se.so = 0x%x\n" % (lindent, self.so))
161 if(self.ov != 0):
162 sout.write("%se.ov = 0x%x\n" % (lindent, self.ov))
163 if(self.ca != 0):
164 sout.write("%se.ca = 0x%x\n" % (lindent, self.ca))
165
166 if sout != sys.stdout:
167 sout.close()
168
169
170 class SimState(State):
171 """SimState: Obtains registers and memory from an ISACaller object.
172 Note that yields are "faked" to maintain consistency and compatability
173 within the API.
174 """
175 def __init__(self, sim):
176 self.sim = sim
177
178 def get_intregs(self):
179 if False:
180 yield
181 self.intregs = []
182 for i in range(32):
183 simregval = self.sim.gpr[i].asint()
184 self.intregs.append(simregval)
185 log("class sim int regs", list(map(hex, self.intregs)))
186
187 def get_crregs(self):
188 if False:
189 yield
190 self.crregs = []
191 for i in range(8):
192 cri = self.sim.crl[i].get_range().value
193 self.crregs.append(cri)
194 log("class sim cr regs", list(map(hex, self.crregs)))
195
196 def get_xregs(self):
197 if False:
198 yield
199 self.xregs = []
200 self.so = self.sim.spr['XER'][XER_bits['SO']].value
201 self.ov = self.sim.spr['XER'][XER_bits['OV']].value
202 self.ov32 = self.sim.spr['XER'][XER_bits['OV32']].value
203 self.ca = self.sim.spr['XER'][XER_bits['CA']].value
204 self.ca32 = self.sim.spr['XER'][XER_bits['CA32']].value
205 self.ov = self.ov | (self.ov32 << 1)
206 self.ca = self.ca | (self.ca32 << 1)
207 self.xregs.extend((self.so, self.ov, self.ca))
208 log("class sim xregs", list(map(hex, self.xregs)))
209
210 def get_pc(self):
211 if False:
212 yield
213 self.pcl = []
214 self.pc = self.sim.pc.CIA.value
215 self.pcl.append(self.pc)
216 log("class sim pc", hex(self.pc))
217
218 def get_mem(self):
219 if False:
220 yield
221 mem = self.sim.mem
222 if isinstance(mem, RADIX):
223 mem = mem.mem
224 keys = list(mem.mem.keys())
225 self.mem = {}
226 # from each address in the underlying mem-simulated dictionary
227 # issue a 64-bit LD (with no byte-swapping)
228 for k in keys:
229 data = mem.ld(k*8, 8, False)
230 self.mem[k*8] = data
231
232
233 class ExpectedState(State):
234 """ExpectedState: A user defined state set manually.
235 No methods, just pass into what expected values you want to test
236 with against other states.
237
238 see openpower/test/shift_rot/shift_rot_cases2.py for examples
239 """
240 def __init__(self, int_regs=None, pc=0, crregs=None,
241 so=0, ov=0, ca=0):
242 if int_regs is None:
243 int_regs = 32
244 if isinstance(int_regs, int):
245 int_regs = [0] * int_regs
246 self.intregs = deepcopy(int_regs)
247 self.pc = pc
248 if crregs is None:
249 crregs = 8
250 if isinstance(crregs, int):
251 crregs = [0] * crregs
252 self.crregs = deepcopy(crregs)
253 self.so = so
254 self.ov = ov
255 self.ca = ca
256
257 def get_intregs(self):
258 if False: yield
259 def get_crregs(self):
260 if False: yield
261 def get_xregs(self):
262 if False: yield
263 def get_pc(self):
264 if False: yield
265 def get_mem(self):
266 if False: yield
267
268
269 global state_factory
270 state_factory = {'sim': SimState, 'expected': ExpectedState}
271
272
273 def state_add(name, kls):
274 log("state_add", name, kls)
275 state_factory[name] = kls
276
277
278 def TestState(state_type, to_test, dut, code=0):
279 """TestState: Factory that returns a TestState object loaded with
280 registers and memory that can then be compared.
281
282 state_type: Type of state to create from global state_factory dictionary
283 to_test: The Power ISA object to test
284 dut: The unittest object
285 code: Actual machine code of what is being tested
286
287 The state_type can be added to the factory types using the state_add
288 function in this module.
289 """
290 state_class = state_factory[state_type]
291 state = state_class(to_test)
292 state.to_test = to_test
293 state.dut = dut
294 state.state_type = state_type
295 state.code = code
296 yield from state.get_state()
297 return state
298
299
300 def teststate_check_regs(dut, states, test, code):
301 """teststate_check_regs: compares a set of Power ISA objects
302 to check if they have the same "state" (registers only, at the moment)
303 """
304 slist = []
305 # create one TestState per "thing"
306 for stype, totest in states.items():
307 state = yield from TestState(stype, totest, dut, code)
308 slist.append(state)
309 # compare each "thing" against the next "thing" in the list.
310 # (no need to do an O(N^2) comparison here, they *all* have to be the same
311 for i in range(len(slist)-1):
312 state, against = slist[i], slist[i+1]
313 state.compare(against)
314
315
316 def teststate_check_mem(dut, states, test, code):
317 """teststate_check_mem: compares a set of Power ISA objects
318 to check if they have the same "state" (memory)
319 """
320 slist = []
321 # create one TestState per "thing"
322 for stype, totest in states.items():
323 state = yield from TestState(stype, totest, dut, code)
324 slist.append(state)
325 # compare each "thing" against the next "thing" in the list.
326 # (no need to do an O(N^2) comparison here, they *all* have to be the same
327 for i in range(len(slist)-1):
328 state, against = slist[i], slist[i+1]
329 state.compare_mem(against)