3 This module implements the creation, inspection and comparison
4 of test states from different sources.
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
12 The SimState class provides an example of needed registers and naming.
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
18 Also note when creating and accessing test state classes and object
19 methods, the use of yield from/yield is required.
25 from openpower
.decoder
.power_enums
import XER_bits
26 from openpower
.decoder
.isa
.radixmmu
import RADIX
27 from openpower
.util
import log
30 from copy
import deepcopy
32 global staterunner_factory
33 staterunner_factory
= {}
36 def staterunner_add(name
, kls
):
37 log("staterunner_add", name
, kls
)
38 staterunner_factory
[name
] = kls
41 # TBD an Abstract Base Class
43 """StateRunner: an Abstract Base Class for preparing and running "State".
44 near-identical in concept to python unittest.TestCase
46 def __init__(self
, name
, kls
):
47 staterunner_add(name
, kls
)
50 def setup_for_test(self
):
52 def setup_during_test(self
):
54 def prepare_for_test(self
, test
):
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
69 All methods implemented must be generators.
71 GPRs and CRs - stored as lists
72 XERs/PC - simple members
73 memory - stored as a dictionary {location: data}
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()
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
))
95 for i
, (crreg
, crreg2
) in enumerate(
96 zip(self
.crregs
, s2
.crregs
)):
97 log("asserting...cr", i
, crreg
, crreg2
)
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
),
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
)))
115 self
.dut
.assertEqual(self
.pc
, s2
.pc
, "pc mismatch (%s != %s) %s" %
116 (self
.state_type
, s2
.state_type
, repr(self
.code
)))
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
)):
124 for i
in set(s2
.mem
).difference(set(self
.mem
)):
127 self
.dut
.assertEqual(s1mem
[i
], s2mem
[i
],
128 "mem mismatch location %d %s" % (i
, self
.code
))
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
135 lindent
= ' '*8 # indent for code
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+")
147 sout
.write("%se = ExpectedState(pc=%d)\n" % (lindent
, self
.pc
))
148 for i
, reg
in enumerate(self
.intregs
):
150 msg
= "%se.intregs[%d] = 0x%x\n"
151 sout
.write( msg
% (lindent
, i
, reg
))
156 msg
= "%se.crregs[%d] = 0x%x\n"
157 sout
.write( msg
% (lindent
, i
, cri
))
160 sout
.write("%se.so = 0x%x\n" % (lindent
, self
.so
))
162 sout
.write("%se.ov = 0x%x\n" % (lindent
, self
.ov
))
164 sout
.write("%se.ca = 0x%x\n" % (lindent
, self
.ca
))
166 if sout
!= sys
.stdout
:
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
175 def __init__(self
, sim
):
178 def get_intregs(self
):
183 simregval
= self
.sim
.gpr
[i
].asint()
184 self
.intregs
.append(simregval
)
185 log("class sim int regs", list(map(hex, self
.intregs
)))
187 def get_crregs(self
):
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
)))
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
)))
214 self
.pc
= self
.sim
.pc
.CIA
.value
215 self
.pcl
.append(self
.pc
)
216 log("class sim pc", hex(self
.pc
))
222 if isinstance(mem
, RADIX
):
224 keys
= list(mem
.mem
.keys())
226 # from each address in the underlying mem-simulated dictionary
227 # issue a 64-bit LD (with no byte-swapping)
229 data
= mem
.ld(k
*8, 8, False)
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.
238 see openpower/test/shift_rot/shift_rot_cases2.py for examples
240 def __init__(self
, int_regs
=None, pc
=0, crregs
=None,
244 if isinstance(int_regs
, int):
245 int_regs
= [0] * int_regs
246 self
.intregs
= deepcopy(int_regs
)
250 if isinstance(crregs
, int):
251 crregs
= [0] * crregs
252 self
.crregs
= deepcopy(crregs
)
257 def get_intregs(self
):
259 def get_crregs(self
):
270 state_factory
= {'sim': SimState
, 'expected': ExpectedState
}
273 def state_add(name
, kls
):
274 log("state_add", name
, kls
)
275 state_factory
[name
] = kls
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.
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
287 The state_type can be added to the factory types using the state_add
288 function in this module.
290 state_class
= state_factory
[state_type
]
291 state
= state_class(to_test
)
292 state
.to_test
= to_test
294 state
.state_type
= state_type
296 yield from state
.get_state()
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)
305 # create one TestState per "thing"
306 for stype
, totest
in states
.items():
307 state
= yield from TestState(stype
, totest
, dut
, code
)
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
)
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)
321 # create one TestState per "thing"
322 for stype
, totest
in states
.items():
323 state
= yield from TestState(stype
, totest
, dut
, code
)
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
)