pysvp64db: fix traversal
[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.util import log
27
28 global staterunner_factory
29 staterunner_factory = {}
30
31
32 def staterunner_add(name, kls):
33 log("staterunner_add", name, kls)
34 staterunner_factory[name] = kls
35
36
37 # TBD an Abstract Base Class
38 class StateRunner:
39 """StateRunner: an Abstract Base Class for preparing and running "State".
40 near-identical in concept to python unittest.TestCase
41 """
42 def __init__(self, name, kls):
43 staterunner_add(name, kls)
44 self.name = name
45
46 def setup_for_test(self):
47 if False: yield
48 def setup_during_test(self):
49 if False: yield
50 def prepare_for_test(self, test):
51 if False: yield
52 def run_test(self):
53 if False: yield
54 def end_test(self):
55 if False: yield
56 def cleanup(self):
57 if False: yield
58
59
60 class State:
61 """State: Base class for the "state" of the Power ISA object to be tested
62 including methods to compare various registers and memory between
63 them.
64
65 All methods implemented must be generators.
66
67 GPRs and CRs - stored as lists
68 XERs/PC - simple members
69 memory - stored as a dictionary {location: data}
70 """
71 def get_state(self):
72 yield from self.get_intregs()
73 yield from self.get_crregs()
74 yield from self.get_xregs()
75 yield from self.get_pc()
76 yield from self.get_mem()
77
78 def compare(self, s2):
79 # Compare int registers
80 for i, (self.intregs, s2.intregs) in enumerate(
81 zip(self.intregs, s2.intregs)):
82 log("asserting...reg", i, self.intregs, s2.intregs)
83 log("code, frepr(code)", self.code, repr(self.code))
84 self.dut.assertEqual(self.intregs, s2.intregs,
85 "int reg %d (%s) not equal (%s) %s. got %x expected %x" %
86 (i, self.state_type, s2.state_type, repr(self.code),
87 self.intregs, s2.intregs))
88
89 # CR registers
90 for i, (self.crregs, s2.crregs) in enumerate(
91 zip(self.crregs, s2.crregs)):
92 log("asserting...cr", i, self.crregs, s2.crregs)
93 self.dut.assertEqual(self.crregs, s2.crregs,
94 "cr reg %d (%s) not equal (%s) %s. got %x expected %x" %
95 (i, self.state_type, s2.state_type, repr(self.code),
96 self.crregs, s2.crregs))
97
98 # XER
99 self.dut.assertEqual(self.so, s2.so, "so mismatch (%s != %s) %s" %
100 (self.state_type, s2.state_type, repr(self.code)))
101 self.dut.assertEqual(self.ov, s2.ov, "ov mismatch (%s != %s) %s" %
102 (self.state_type, s2.state_type, repr(self.code)))
103 self.dut.assertEqual(self.ca, s2.ca, "ca mismatch (%s != %s) %s" %
104 (self.state_type, s2.state_type, repr(self.code)))
105
106 # pc
107 self.dut.assertEqual(self.pc, s2.pc, "pc mismatch (%s != %s) %s" %
108 (self.state_type, s2.state_type, repr(self.code)))
109
110 def compare_mem(self, s2):
111 # copy dics to preserve state mem then pad empty locs since
112 # different Power ISA objects may differ how theystore memory
113 s1mem, s2mem = self.mem.copy(), s2.mem.copy()
114 for i in set(self.mem).difference(set(s2.mem)):
115 s2mem[i] = 0
116 for i in set(s2.mem).difference(set(self.mem)):
117 s1mem[i] = 0
118 for i in s1mem:
119 self.dut.assertEqual(s1mem[i], s2mem[i],
120 "mem mismatch location %d %s" % (i, self.code))
121
122
123 class SimState(State):
124 """SimState: Obtains registers and memory from an ISACaller object.
125 Note that yields are "faked" to maintain consistency and compatability
126 within the API.
127 """
128 def __init__(self, sim):
129 self.sim = sim
130
131 def get_intregs(self):
132 if False:
133 yield
134 self.intregs = []
135 for i in range(32):
136 simregval = self.sim.gpr[i].asint()
137 self.intregs.append(simregval)
138 log("class sim int regs", list(map(hex, self.intregs)))
139
140 def get_crregs(self):
141 if False:
142 yield
143 self.crregs = []
144 for i in range(8):
145 cri = self.sim.crl[7 - i].get_range().value
146 self.crregs.append(cri)
147 log("class sim cr regs", list(map(hex, self.crregs)))
148
149 def get_xregs(self):
150 if False:
151 yield
152 self.xregs = []
153 self.so = self.sim.spr['XER'][XER_bits['SO']].value
154 self.ov = self.sim.spr['XER'][XER_bits['OV']].value
155 self.ov32 = self.sim.spr['XER'][XER_bits['OV32']].value
156 self.ca = self.sim.spr['XER'][XER_bits['CA']].value
157 self.ca32 = self.sim.spr['XER'][XER_bits['CA32']].value
158 self.ov = self.ov | (self.ov32 << 1)
159 self.ca = self.ca | (self.ca32 << 1)
160 self.xregs.extend((self.so, self.ov, self.ca))
161 log("class sim xregs", list(map(hex, self.xregs)))
162
163 def get_pc(self):
164 if False:
165 yield
166 self.pcl = []
167 self.pc = self.sim.pc.CIA.value
168 self.pcl.append(self.pc)
169 log("class sim pc", hex(self.pc))
170
171 def get_mem(self):
172 if False:
173 yield
174 keys = list(self.sim.mem.mem.keys())
175 self.mem = {}
176 # from each address in the underlying mem-simulated dictionary
177 # issue a 64-bit LD (with no byte-swapping)
178 for k in keys:
179 data = self.sim.mem.ld(k*8, 8, False)
180 self.mem[k*8] = data
181
182
183 class ExpectedState(State):
184 """ExpectedState: A user defined state set manually.
185 No methods, just pass into what expected values you want to test
186 with against other states.
187
188 see openpower/test/shift_rot/shift_rot_cases2.py for examples
189 """
190 def __init__(self, int_regs=None, pc=0, crregs=None,
191 so=0, ov=0, ca=0):
192 if int_regs is None:
193 int_regs = 32
194 if isinstance(int_regs, int):
195 int_regs = [0] * int_regs
196 self.intregs = int_regs
197 self.pc = pc
198 if crregs is None:
199 crregs = 8
200 if isinstance(crregs, int):
201 crregs = [0] * crregs
202 self.crregs = crregs
203 self.so = so
204 self.ov = ov
205 self.ca = ca
206
207 def get_intregs(self):
208 if False: yield
209 def get_crregs(self):
210 if False: yield
211 def get_xregs(self):
212 if False: yield
213 def get_pc(self):
214 if False: yield
215 def get_mem(self):
216 if False: yield
217
218
219 global state_factory
220 state_factory = {'sim': SimState, 'expected': ExpectedState}
221
222
223 def state_add(name, kls):
224 log("state_add", name, kls)
225 state_factory[name] = kls
226
227
228 def TestState(state_type, to_test, dut, code=0):
229 """TestState: Factory that returns a TestState object loaded with
230 registers and memory that can then be compared.
231
232 state_type: Type of state to create from global state_factory dictionary
233 to_test: The Power ISA object to test
234 dut: The unittest object
235 code: Actual machine code of what is being tested
236
237 The state_type can be added to the factory types using the state_add
238 function in this module.
239 """
240 state_class = state_factory[state_type]
241 state = state_class(to_test)
242 state.to_test = to_test
243 state.dut = dut
244 state.state_type = state_type
245 state.code = code
246 yield from state.get_state()
247 return state
248
249
250 def teststate_check_regs(dut, states, test, code):
251 """teststate_check_regs: compares a set of Power ISA objects
252 to check if they have the same "state" (registers only, at the moment)
253 """
254 slist = []
255 # create one TestState per "thing"
256 for stype, totest in states.items():
257 state = yield from TestState(stype, totest, dut, code)
258 slist.append(state)
259 # compare each "thing" against the next "thing" in the list.
260 # (no need to do an O(N^2) comparison here, they *all* have to be the same
261 for i in range(len(slist)-1):
262 state, against = slist[i], slist[i+1]
263 state.compare(against)
264
265
266 def teststate_check_mem(dut, states, test, code):
267 """teststate_check_mem: compares a set of Power ISA objects
268 to check if they have the same "state" (memory)
269 """
270 slist = []
271 # create one TestState per "thing"
272 for stype, totest in states.items():
273 state = yield from TestState(stype, totest, dut, code)
274 slist.append(state)
275 # compare each "thing" against the next "thing" in the list.
276 # (no need to do an O(N^2) comparison here, they *all* have to be the same
277 for i in range(len(slist)-1):
278 state, against = slist[i], slist[i+1]
279 state.compare_mem(against)