add name parameter to StateRunner
[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
38 # TBD an Abstract Base Class
39 class StateRunner:
40 """StateRunner: an Abstract Base Class for preparing and running "State".
41 near-identical in concept to python unittest.TestCase
42 """
43 def __init__(self, name, kls):
44 staterunner_add(name, kls)
45 self.name = name
46
47 def setup_for_test(self):
48 if False: yield
49 def setup_during_test(self):
50 if False: yield
51 def prepare_for_test(self, test):
52 if False: yield
53 def run_test(self):
54 if False: yield
55 def end_test(self):
56 if False: yield
57 def cleanup(self):
58 if False: yield
59
60
61 class SimRunner(StateRunner):
62 def __init__(self, dut, **kwargs):
63 super().__init__("sim", SimRunner)
64 self.pspec = kwargs['pspec']
65 self.m = kwargs['m']
66
67
68 class State:
69 def get_state(self):
70 yield from self.get_intregs()
71 yield from self.get_crregs()
72 yield from self.get_xregs()
73 yield from self.get_pc()
74 yield from self.get_mem()
75
76 def compare(self, s2):
77 # Compare int registers
78 for i, (self.intregs, s2.intregs) in enumerate(
79 zip(self.intregs, s2.intregs)):
80 log("asserting...reg", i, self.intregs, s2.intregs)
81 log("code, frepr(code)", self.code, repr(self.code))
82 self.dut.assertEqual(self.intregs, s2.intregs,
83 "int reg %d (%s) not equal (%s) %s. got %x expected %x" %
84 (i, self.state_type, s2.state_type, repr(self.code),
85 self.intregs, s2.intregs))
86
87 # CR registers
88 for i, (self.crregs, s2.crregs) in enumerate(
89 zip(self.crregs, s2.crregs)):
90 log("asserting...cr", i, self.crregs, s2.crregs)
91 self.dut.assertEqual(self.crregs, s2.crregs,
92 "cr reg %d (%s) not equal (%s) %s. got %x expected %x" %
93 (i, self.state_type, s2.state_type, repr(self.code),
94 self.crregs, s2.crregs))
95
96 # XER
97 self.dut.assertEqual(self.so, s2.so, "so mismatch (%s != %s) %s" %
98 (self.state_type, s2.state_type, repr(self.code)))
99 self.dut.assertEqual(self.ov, s2.ov, "ov mismatch (%s != %s) %s" %
100 (self.state_type, s2.state_type, repr(self.code)))
101 self.dut.assertEqual(self.ca, s2.ca, "ca mismatch (%s != %s) %s" %
102 (self.state_type, s2.state_type, repr(self.code)))
103
104 # pc
105 self.dut.assertEqual(self.pc, s2.pc, "pc mismatch (%s != %s) %s" %
106 (self.state_type, s2.state_type, repr(self.code)))
107
108 def compare_mem(self, s2):
109 # copy dics to preserve state mem then pad empty locs
110 s1mem, s2mem = self.mem.copy(), s2.mem.copy()
111 for i in set(self.mem).difference(set(s2.mem)):
112 s2mem[i] = 0
113 for i in set(s2.mem).difference(set(self.mem)):
114 s1mem[i] = 0
115 for i in s1mem:
116 self.dut.assertEqual(s1mem[i], s2mem[i],
117 "mem mismatch location %d %s" % (i, self.code))
118
119
120 class SimState(State):
121 def __init__(self, sim):
122 self.sim = sim
123
124 def get_intregs(self):
125 if False:
126 yield
127 self.intregs = []
128 for i in range(32):
129 simregval = self.sim.gpr[i].asint()
130 self.intregs.append(simregval)
131 log("class sim int regs", list(map(hex, self.intregs)))
132
133 def get_crregs(self):
134 if False:
135 yield
136 self.crregs = []
137 for i in range(8):
138 cri = self.sim.crl[7 - i].get_range().value
139 self.crregs.append(cri)
140 log("class sim cr regs", list(map(hex, self.crregs)))
141
142 def get_xregs(self):
143 if False:
144 yield
145 self.xregs = []
146 self.so = self.sim.spr['XER'][XER_bits['SO']].value
147 self.ov = self.sim.spr['XER'][XER_bits['OV']].value
148 self.ov32 = self.sim.spr['XER'][XER_bits['OV32']].value
149 self.ca = self.sim.spr['XER'][XER_bits['CA']].value
150 self.ca32 = self.sim.spr['XER'][XER_bits['CA32']].value
151 self.ov = self.ov | (self.ov32 << 1)
152 self.ca = self.ca | (self.ca32 << 1)
153 self.xregs.extend((self.so, self.ov, self.ca))
154 log("class sim xregs", list(map(hex, self.xregs)))
155
156 def get_pc(self):
157 if False:
158 yield
159 self.pcl = []
160 self.pc = self.sim.pc.CIA.value
161 self.pcl.append(self.pc)
162 log("class sim pc", hex(self.pc))
163
164 def get_mem(self):
165 if False:
166 yield
167 keys = list(self.sim.mem.mem.keys())
168 self.mem = {}
169 # from each address in the underlying mem-simulated dictionary
170 # issue a 64-bit LD (with no byte-swapping)
171 for k in keys:
172 data = self.sim.mem.ld(k*8, 8, False)
173 self.mem[k*8] = data
174
175
176 class ExpectedState(State):
177 def __init__(self, int_regs=None, pc=0, crregs=None,
178 so=0, ov=0, ca=0):
179 if int_regs is None:
180 int_regs = 32
181 if isinstance(int_regs, int):
182 int_regs = [0] * int_regs
183 self.intregs = int_regs
184 self.pc = pc
185 if crregs is None:
186 crregs = 8
187 if isinstance(crregs, int):
188 crregs = [0] * crregs
189 self.crregs = crregs
190 self.so = so
191 self.ov = ov
192 self.ca = ca
193
194 def get_intregs(self):
195 if False: yield
196 def get_crregs(self):
197 if False: yield
198 def get_xregs(self):
199 if False: yield
200 def get_pc(self):
201 if False: yield
202 def get_mem(self):
203 if False: yield
204
205
206 global state_factory
207 state_factory = {'sim': SimState, 'expected': ExpectedState}
208
209
210 def state_add(name, kls):
211 log("state_add", name, kls)
212 state_factory[name] = kls
213
214
215 def TestState(state_type, to_test, dut, code=0):
216 state_class = state_factory[state_type]
217 state = state_class(to_test)
218 state.to_test = to_test
219 state.dut = dut
220 state.state_type = state_type
221 state.code = code
222 yield from state.get_state()
223 return state
224
225
226 def teststate_check_regs(dut, states, test, code):
227 """teststate_check_regs: compares a set of Power ISA objects
228 to check if they have the same "state" (registers only, at the moment)
229 """
230 slist = []
231 # create one TestState per "thing"
232 for stype, totest in states.items():
233 state = yield from TestState(stype, totest, dut, code)
234 slist.append(state)
235 # compare each "thing" against the next "thing" in the list.
236 # (no need to do an O(N^2) comparison here, they *all* have to be the same
237 for i in range(len(slist)-1):
238 state, against = slist[i], slist[i+1]
239 state.compare(against)
240
241
242 def teststate_check_mem(dut, states, test, code):
243 """teststate_check_mem: compares a set of Power ISA objects
244 to check if they have the same "state" (memory)
245 """
246 slist = []
247 # create one TestState per "thing"
248 for stype, totest in states.items():
249 state = yield from TestState(stype, totest, dut, code)
250 slist.append(state)
251 # compare each "thing" against the next "thing" in the list.
252 # (no need to do an O(N^2) comparison here, they *all* have to be the same
253 for i in range(len(slist)-1):
254 state, against = slist[i], slist[i+1]
255 state.compare_mem(against)