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
31 global staterunner_factory
32 staterunner_factory
= {}
35 def staterunner_add(name
, kls
):
36 log("staterunner_add", name
, kls
)
37 staterunner_factory
[name
] = kls
40 # TBD an Abstract Base Class
42 """StateRunner: an Abstract Base Class for preparing and running "State".
43 near-identical in concept to python unittest.TestCase
45 def __init__(self
, name
, kls
):
46 staterunner_add(name
, kls
)
49 def setup_for_test(self
):
51 def setup_during_test(self
):
53 def prepare_for_test(self
, test
):
64 """State: Base class for the "state" of the Power ISA object to be tested
65 including methods to compare various registers and memory between
68 All methods implemented must be generators.
70 GPRs and CRs - stored as lists
71 XERs/PC - simple members
72 memory - stored as a dictionary {location: data}
75 yield from self
.get_intregs()
76 yield from self
.get_crregs()
77 yield from self
.get_xregs()
78 yield from self
.get_pc()
79 yield from self
.get_mem()
81 def compare(self
, s2
):
82 # Compare int registers
83 for i
, (intreg
, intreg2
) in enumerate(
84 zip(self
.intregs
, s2
.intregs
)):
85 log("asserting...reg", i
, intreg
, intreg2
)
86 log("code, frepr(code)", self
.code
, repr(self
.code
))
87 self
.dut
.assertEqual(intreg
, intreg2
,
88 "int reg %d (%s) not equal (%s) %s. "
89 " got %x expected %x at pc %x %x\n" %
90 (i
, self
.state_type
, s2
.state_type
, repr(self
.code
),
91 intreg
, intreg2
, self
.pc
, s2
.pc
))
94 for i
, (crreg
, crreg2
) in enumerate(
95 zip(self
.crregs
, s2
.crregs
)):
96 log("asserting...cr", i
, crreg
, crreg2
)
98 for i
, (crreg
, crreg2
) in enumerate(
99 zip(self
.crregs
, s2
.crregs
)):
100 self
.dut
.assertEqual(crreg
, crreg2
,
101 "cr reg %d (%s) not equal (%s) %s. got %x expected %x" %
102 (i
, self
.state_type
, s2
.state_type
, repr(self
.code
),
106 self
.dut
.assertEqual(self
.so
, s2
.so
, "so mismatch (%s != %s) %s" %
107 (self
.state_type
, s2
.state_type
, repr(self
.code
)))
108 self
.dut
.assertEqual(self
.ov
, s2
.ov
, "ov mismatch (%s != %s) %s" %
109 (self
.state_type
, s2
.state_type
, repr(self
.code
)))
110 self
.dut
.assertEqual(self
.ca
, s2
.ca
, "ca mismatch (%s != %s) %s" %
111 (self
.state_type
, s2
.state_type
, repr(self
.code
)))
114 self
.dut
.assertEqual(self
.pc
, s2
.pc
, "pc mismatch (%s != %s) %s" %
115 (self
.state_type
, s2
.state_type
, repr(self
.code
)))
117 def compare_mem(self
, s2
):
118 # copy dics to preserve state mem then pad empty locs since
119 # different Power ISA objects may differ how theystore memory
120 s1mem
, s2mem
= self
.mem
.copy(), s2
.mem
.copy()
121 for i
in set(self
.mem
).difference(set(s2
.mem
)):
123 for i
in set(s2
.mem
).difference(set(self
.mem
)):
126 self
.dut
.assertEqual(s1mem
[i
], s2mem
[i
],
127 "mem mismatch location %d %s" % (i
, self
.code
))
129 def dump_state_tofile(self
, testname
=None, testfile
=None):
130 """dump_state_tofile: Takes a passed in teststate object along
131 with a test name and generates a code file located at
132 /tmp/testfile/testname to set an expected state object
134 lindent
= ' '*8 # indent for code
136 if testname
is not None:
137 path
= "/tmp/expected/"
138 if testfile
is not None:
139 path
+= testfile
+ '/'
140 os
.makedirs(path
, exist_ok
=True)
141 sout
= open("%s%s.py" % (path
, testname
), "a+")
146 sout
.write("%se = ExpectedState(pc=%d)\n" % (lindent
, self
.pc
))
147 for i
, reg
in enumerate(self
.intregs
):
149 msg
= "%se.intregs[%d] = 0x%x\n"
150 sout
.write( msg
% (lindent
, i
, reg
))
155 msg
= "%se.crregs[%d] = 0x%x\n"
156 sout
.write( msg
% (lindent
, i
, cri
))
159 sout
.write("%se.so = 0x%x\n" % (lindent
, self
.so
))
161 sout
.write("%se.ov = 0x%x\n" % (lindent
, self
.ov
))
163 sout
.write("%se.ca = 0x%x\n" % (lindent
, self
.ca
))
165 if sout
!= sys
.stdout
:
169 class SimState(State
):
170 """SimState: Obtains registers and memory from an ISACaller object.
171 Note that yields are "faked" to maintain consistency and compatability
174 def __init__(self
, sim
):
177 def get_intregs(self
):
182 simregval
= self
.sim
.gpr
[i
].asint()
183 self
.intregs
.append(simregval
)
184 log("class sim int regs", list(map(hex, self
.intregs
)))
186 def get_crregs(self
):
191 cri
= self
.sim
.crl
[i
].get_range().value
192 self
.crregs
.append(cri
)
193 log("class sim cr regs", list(map(hex, self
.crregs
)))
199 self
.so
= self
.sim
.spr
['XER'][XER_bits
['SO']].value
200 self
.ov
= self
.sim
.spr
['XER'][XER_bits
['OV']].value
201 self
.ov32
= self
.sim
.spr
['XER'][XER_bits
['OV32']].value
202 self
.ca
= self
.sim
.spr
['XER'][XER_bits
['CA']].value
203 self
.ca32
= self
.sim
.spr
['XER'][XER_bits
['CA32']].value
204 self
.ov
= self
.ov |
(self
.ov32
<< 1)
205 self
.ca
= self
.ca |
(self
.ca32
<< 1)
206 self
.xregs
.extend((self
.so
, self
.ov
, self
.ca
))
207 log("class sim xregs", list(map(hex, self
.xregs
)))
213 self
.pc
= self
.sim
.pc
.CIA
.value
214 self
.pcl
.append(self
.pc
)
215 log("class sim pc", hex(self
.pc
))
221 if isinstance(mem
, RADIX
):
223 keys
= list(mem
.mem
.keys())
225 # from each address in the underlying mem-simulated dictionary
226 # issue a 64-bit LD (with no byte-swapping)
228 data
= mem
.ld(k
*8, 8, False)
232 class ExpectedState(State
):
233 """ExpectedState: A user defined state set manually.
234 No methods, just pass into what expected values you want to test
235 with against other states.
237 see openpower/test/shift_rot/shift_rot_cases2.py for examples
239 def __init__(self
, int_regs
=None, pc
=0, crregs
=None,
243 if isinstance(int_regs
, int):
244 int_regs
= [0] * int_regs
245 self
.intregs
= int_regs
249 if isinstance(crregs
, int):
250 crregs
= [0] * crregs
256 def get_intregs(self
):
258 def get_crregs(self
):
269 state_factory
= {'sim': SimState
, 'expected': ExpectedState
}
272 def state_add(name
, kls
):
273 log("state_add", name
, kls
)
274 state_factory
[name
] = kls
277 def TestState(state_type
, to_test
, dut
, code
=0):
278 """TestState: Factory that returns a TestState object loaded with
279 registers and memory that can then be compared.
281 state_type: Type of state to create from global state_factory dictionary
282 to_test: The Power ISA object to test
283 dut: The unittest object
284 code: Actual machine code of what is being tested
286 The state_type can be added to the factory types using the state_add
287 function in this module.
289 state_class
= state_factory
[state_type
]
290 state
= state_class(to_test
)
291 state
.to_test
= to_test
293 state
.state_type
= state_type
295 yield from state
.get_state()
299 def teststate_check_regs(dut
, states
, test
, code
):
300 """teststate_check_regs: compares a set of Power ISA objects
301 to check if they have the same "state" (registers only, at the moment)
304 # create one TestState per "thing"
305 for stype
, totest
in states
.items():
306 state
= yield from TestState(stype
, totest
, dut
, code
)
308 # compare each "thing" against the next "thing" in the list.
309 # (no need to do an O(N^2) comparison here, they *all* have to be the same
310 for i
in range(len(slist
)-1):
311 state
, against
= slist
[i
], slist
[i
+1]
312 state
.compare(against
)
315 def teststate_check_mem(dut
, states
, test
, code
):
316 """teststate_check_mem: compares a set of Power ISA objects
317 to check if they have the same "state" (memory)
320 # create one TestState per "thing"
321 for stype
, totest
in states
.items():
322 state
= yield from TestState(stype
, totest
, dut
, code
)
324 # compare each "thing" against the next "thing" in the list.
325 # (no need to do an O(N^2) comparison here, they *all* have to be the same
326 for i
in range(len(slist
)-1):
327 state
, against
= slist
[i
], slist
[i
+1]
328 state
.compare_mem(against
)