tests.py (11828:36b064696175) tests.py (12068:0097c445aa64)
1#!/usr/bin/env python2
2#
1#!/usr/bin/env python2
2#
3# Copyright (c) 2016 ARM Limited
3# Copyright (c) 2016-2017 ARM Limited
4# All rights reserved
5#
6# The license below extends only to copyright in the software and shall
7# not be construed as granting a license to any other intellectual
8# property including but not limited to intellectual property relating
9# to a hardware implementation of the functionality of the software
10# licensed hereunder. You may use the software subject to the license
11# terms below provided that you ensure that this notice is replicated
12# unmodified and in its entirety in all distributions of the software,
13# modified or unmodified, in source code or in binary form.
14#
15# Redistribution and use in source and binary forms, with or without
16# modification, are permitted provided that the following conditions are
17# met: redistributions of source code must retain the above copyright
18# notice, this list of conditions and the following disclaimer;
19# redistributions in binary form must reproduce the above copyright
20# notice, this list of conditions and the following disclaimer in the
21# documentation and/or other materials provided with the distribution;
22# neither the name of the copyright holders nor the names of its
23# contributors may be used to endorse or promote products derived from
24# this software without specific prior written permission.
25#
26# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37#
38# Authors: Andreas Sandberg
39
40from abc import ABCMeta, abstractmethod
41import os
42from collections import namedtuple
43from units import *
44from results import TestResult
45import shutil
46
47_test_base = os.path.join(os.path.dirname(__file__), "..")
48
49ClassicConfig = namedtuple("ClassicConfig", (
50 "category",
51 "mode",
52 "workload",
53 "isa",
54 "os",
55 "config",
56))
57
58# There are currently two "classes" of test
59# configurations. Architecture-specific ones and generic ones
60# (typically SE mode tests). In both cases, the configuration name
61# matches a file in tests/configs/ that will be picked up by the test
62# runner (run.py).
63#
64# Architecture specific configurations are listed in the arch_configs
65# dictionary. This is indexed by a (cpu architecture, gpu
66# architecture) tuple. GPU architecture is optional and may be None.
67#
68# Generic configurations are listed in the generic_configs tuple.
69#
70# When discovering available test cases, this script look uses the
71# test list as a list of /candidate/ configurations. A configuration
72# is only used if a test has a reference output for that
73# configuration. In addition to the base configurations from
74# arch_configs and generic_configs, a Ruby configuration may be
75# appended to the base name (this is probed /in addition/ to the
76# original name. See get_tests() for details.
77#
78arch_configs = {
79 ("alpha", None) : (
80 'tsunami-simple-atomic',
81 'tsunami-simple-timing',
82 'tsunami-simple-atomic-dual',
83 'tsunami-simple-timing-dual',
84 'twosys-tsunami-simple-atomic',
85 'tsunami-o3', 'tsunami-o3-dual',
86 'tsunami-minor', 'tsunami-minor-dual',
87 'tsunami-switcheroo-full',
88 ),
89
90 ("arm", None) : (
91 'simple-atomic-dummychecker',
92 'o3-timing-checker',
93 'realview-simple-atomic',
94 'realview-simple-atomic-dual',
95 'realview-simple-atomic-checkpoint',
96 'realview-simple-timing',
97 'realview-simple-timing-dual',
98 'realview-o3',
99 'realview-o3-checker',
100 'realview-o3-dual',
101 'realview-minor',
102 'realview-minor-dual',
103 'realview-switcheroo-atomic',
104 'realview-switcheroo-timing',
105 'realview-switcheroo-o3',
106 'realview-switcheroo-full',
107 'realview64-simple-atomic',
108 'realview64-simple-atomic-checkpoint',
109 'realview64-simple-atomic-dual',
110 'realview64-simple-timing',
111 'realview64-simple-timing-dual',
112 'realview64-o3',
113 'realview64-o3-checker',
114 'realview64-o3-dual',
115 'realview64-minor',
116 'realview64-minor-dual',
117 'realview64-switcheroo-atomic',
118 'realview64-switcheroo-timing',
119 'realview64-switcheroo-o3',
120 'realview64-switcheroo-full',
121 ),
122
123 ("sparc", None) : (
124 't1000-simple-atomic',
125 't1000-simple-x86',
126 ),
127
128 ("timing", None) : (
129 'pc-simple-atomic',
130 'pc-simple-timing',
131 'pc-o3-timing',
132 'pc-switcheroo-full',
133 ),
134
135 ("x86", "hsail") : (
136 'gpu',
137 ),
138}
139
140generic_configs = (
141 'simple-atomic',
142 'simple-atomic-mp',
143 'simple-timing',
144 'simple-timing-mp',
145
146 'minor-timing',
147 'minor-timing-mp',
148
149 'o3-timing',
150 'o3-timing-mt',
151 'o3-timing-mp',
152
153 'rubytest',
154 'memcheck',
155 'memtest',
156 'memtest-filter',
157 'tgen-simple-mem',
158 'tgen-dram-ctrl',
159
160 'learning-gem5-p1-simple',
161 'learning-gem5-p1-two-level',
162)
163
4# All rights reserved
5#
6# The license below extends only to copyright in the software and shall
7# not be construed as granting a license to any other intellectual
8# property including but not limited to intellectual property relating
9# to a hardware implementation of the functionality of the software
10# licensed hereunder. You may use the software subject to the license
11# terms below provided that you ensure that this notice is replicated
12# unmodified and in its entirety in all distributions of the software,
13# modified or unmodified, in source code or in binary form.
14#
15# Redistribution and use in source and binary forms, with or without
16# modification, are permitted provided that the following conditions are
17# met: redistributions of source code must retain the above copyright
18# notice, this list of conditions and the following disclaimer;
19# redistributions in binary form must reproduce the above copyright
20# notice, this list of conditions and the following disclaimer in the
21# documentation and/or other materials provided with the distribution;
22# neither the name of the copyright holders nor the names of its
23# contributors may be used to endorse or promote products derived from
24# this software without specific prior written permission.
25#
26# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37#
38# Authors: Andreas Sandberg
39
40from abc import ABCMeta, abstractmethod
41import os
42from collections import namedtuple
43from units import *
44from results import TestResult
45import shutil
46
47_test_base = os.path.join(os.path.dirname(__file__), "..")
48
49ClassicConfig = namedtuple("ClassicConfig", (
50 "category",
51 "mode",
52 "workload",
53 "isa",
54 "os",
55 "config",
56))
57
58# There are currently two "classes" of test
59# configurations. Architecture-specific ones and generic ones
60# (typically SE mode tests). In both cases, the configuration name
61# matches a file in tests/configs/ that will be picked up by the test
62# runner (run.py).
63#
64# Architecture specific configurations are listed in the arch_configs
65# dictionary. This is indexed by a (cpu architecture, gpu
66# architecture) tuple. GPU architecture is optional and may be None.
67#
68# Generic configurations are listed in the generic_configs tuple.
69#
70# When discovering available test cases, this script look uses the
71# test list as a list of /candidate/ configurations. A configuration
72# is only used if a test has a reference output for that
73# configuration. In addition to the base configurations from
74# arch_configs and generic_configs, a Ruby configuration may be
75# appended to the base name (this is probed /in addition/ to the
76# original name. See get_tests() for details.
77#
78arch_configs = {
79 ("alpha", None) : (
80 'tsunami-simple-atomic',
81 'tsunami-simple-timing',
82 'tsunami-simple-atomic-dual',
83 'tsunami-simple-timing-dual',
84 'twosys-tsunami-simple-atomic',
85 'tsunami-o3', 'tsunami-o3-dual',
86 'tsunami-minor', 'tsunami-minor-dual',
87 'tsunami-switcheroo-full',
88 ),
89
90 ("arm", None) : (
91 'simple-atomic-dummychecker',
92 'o3-timing-checker',
93 'realview-simple-atomic',
94 'realview-simple-atomic-dual',
95 'realview-simple-atomic-checkpoint',
96 'realview-simple-timing',
97 'realview-simple-timing-dual',
98 'realview-o3',
99 'realview-o3-checker',
100 'realview-o3-dual',
101 'realview-minor',
102 'realview-minor-dual',
103 'realview-switcheroo-atomic',
104 'realview-switcheroo-timing',
105 'realview-switcheroo-o3',
106 'realview-switcheroo-full',
107 'realview64-simple-atomic',
108 'realview64-simple-atomic-checkpoint',
109 'realview64-simple-atomic-dual',
110 'realview64-simple-timing',
111 'realview64-simple-timing-dual',
112 'realview64-o3',
113 'realview64-o3-checker',
114 'realview64-o3-dual',
115 'realview64-minor',
116 'realview64-minor-dual',
117 'realview64-switcheroo-atomic',
118 'realview64-switcheroo-timing',
119 'realview64-switcheroo-o3',
120 'realview64-switcheroo-full',
121 ),
122
123 ("sparc", None) : (
124 't1000-simple-atomic',
125 't1000-simple-x86',
126 ),
127
128 ("timing", None) : (
129 'pc-simple-atomic',
130 'pc-simple-timing',
131 'pc-o3-timing',
132 'pc-switcheroo-full',
133 ),
134
135 ("x86", "hsail") : (
136 'gpu',
137 ),
138}
139
140generic_configs = (
141 'simple-atomic',
142 'simple-atomic-mp',
143 'simple-timing',
144 'simple-timing-mp',
145
146 'minor-timing',
147 'minor-timing-mp',
148
149 'o3-timing',
150 'o3-timing-mt',
151 'o3-timing-mp',
152
153 'rubytest',
154 'memcheck',
155 'memtest',
156 'memtest-filter',
157 'tgen-simple-mem',
158 'tgen-dram-ctrl',
159
160 'learning-gem5-p1-simple',
161 'learning-gem5-p1-two-level',
162)
163
164default_ruby_protocol = {
165 "arm" : "MOESI_CMP_directory",
166}
167
168def get_default_protocol(arch):
169 try:
170 return default_ruby_protocol[arch]
171 except KeyError:
172 return 'MI-example'
173
164all_categories = ("quick", "long")
165all_modes = ("fs", "se")
166
167class Test(object):
168 """Test case base class.
169
170 Test cases consists of one or more test units that are run in two
171 phases. A run phase (units produced by run_units() and a verify
172 phase (units from verify_units()). The verify phase is skipped if
173 the run phase fails.
174
175 """
176
177 __metaclass__ = ABCMeta
178
179 def __init__(self, name):
180 self.test_name = name
181
182 @abstractmethod
183 def ref_files(self):
184 """Get a list of reference files used by this test case"""
185 pass
186
187 @abstractmethod
188 def run_units(self):
189 """Units (typically RunGem5 instances) that describe the run phase of
190 this test.
191
192 """
193 pass
194
195 @abstractmethod
196 def verify_units(self):
197 """Verify the output from the run phase (see run_units())."""
198 pass
199
200 @abstractmethod
201 def update_ref(self):
202 """Update reference files with files from a test run"""
203 pass
204
205 def run(self):
206 """Run this test case and return a list of results"""
207
208 run_results = [ u.run() for u in self.run_units() ]
209 run_ok = all([not r.skipped() and r for r in run_results ])
210
211 verify_results = [
212 u.run() if run_ok else u.skip()
213 for u in self.verify_units()
214 ]
215
216 return TestResult(self.test_name,
217 run_results=run_results,
218 verify_results=verify_results)
219
220 def __str__(self):
221 return self.test_name
222
223class ClassicTest(Test):
224 # The diff ignore list contains all files that shouldn't be diffed
225 # using DiffOutFile. These files typically use special-purpose
226 # diff tools (e.g., DiffStatFile).
227 diff_ignore_files = FileIgnoreList(
228 names=(
229 # Stat files use a special stat differ
230 "stats.txt",
231 ), rex=(
232 ))
233
234 # These files should never be included in the list of
235 # reference files. This list should include temporary files
236 # and other files that we don't care about.
237 ref_ignore_files = FileIgnoreList(
238 names=(
239 "EMPTY",
240 ), rex=(
241 # Mercurial sometimes leaves backups when applying MQ patches
242 r"\.orig$",
243 r"\.rej$",
244 ))
245
246 def __init__(self, gem5, output_dir, config_tuple,
247 timeout=None,
248 skip=False, skip_diff_out=False, skip_diff_stat=False):
249
250 super(ClassicTest, self).__init__("/".join(config_tuple))
251
252 ct = config_tuple
253
254 self.gem5 = os.path.abspath(gem5)
255 self.script = os.path.join(_test_base, "run.py")
256 self.config_tuple = ct
257 self.timeout = timeout
258
259 self.output_dir = output_dir
260 self.ref_dir = os.path.join(_test_base,
261 ct.category, ct.mode, ct.workload,
262 "ref", ct.isa, ct.os, ct.config)
263 self.skip_run = skip
264 self.skip_diff_out = skip or skip_diff_out
265 self.skip_diff_stat = skip or skip_diff_stat
266
267 def ref_files(self):
268 ref_dir = os.path.abspath(self.ref_dir)
269 for root, dirs, files in os.walk(ref_dir, topdown=False):
270 for f in files:
271 fpath = os.path.join(root[len(ref_dir) + 1:], f)
272 if fpath not in ClassicTest.ref_ignore_files:
273 yield fpath
274
275 def run_units(self):
276 args = [
277 self.script,
278 "/".join(self.config_tuple),
279 ]
280
281 return [
282 RunGem5(self.gem5, args,
283 ref_dir=self.ref_dir, test_dir=self.output_dir,
284 skip=self.skip_run),
285 ]
286
287 def verify_units(self):
288 ref_files = set(self.ref_files())
289 units = []
290 if "stats.txt" in ref_files:
291 units.append(
292 DiffStatFile(ref_dir=self.ref_dir, test_dir=self.output_dir,
293 skip=self.skip_diff_stat))
294 units += [
295 DiffOutFile(f,
296 ref_dir=self.ref_dir, test_dir=self.output_dir,
297 skip=self.skip_diff_out)
298 for f in ref_files if f not in ClassicTest.diff_ignore_files
299 ]
300
301 return units
302
303 def update_ref(self):
304 for fname in self.ref_files():
305 shutil.copy(
306 os.path.join(self.output_dir, fname),
307 os.path.join(self.ref_dir, fname))
308
309def parse_test_filter(test_filter):
310 wildcards = ("", "*")
311
312 _filter = list(test_filter.split("/"))
313 if len(_filter) > 3:
314 raise RuntimeError("Illegal test filter string")
315 _filter += [ "", ] * (3 - len(_filter))
316
317 isa, cat, mode = _filter
318
319 if isa in wildcards:
320 raise RuntimeError("No ISA specified")
321
322 cat = all_categories if cat in wildcards else (cat, )
323 mode = all_modes if mode in wildcards else (mode, )
324
325 return isa, cat, mode
326
327def get_tests(isa,
328 categories=all_categories, modes=all_modes,
329 ruby_protocol=None, gpu_isa=None):
330
331 # Generate a list of candidate configs
332 configs = list(arch_configs.get((isa, gpu_isa), []))
333
334 if (isa, gpu_isa) == ("x86", "hsail"):
335 if ruby_protocol == "GPU_RfO":
336 configs += ['gpu-randomtest']
337 else:
338 configs += generic_configs
339
174all_categories = ("quick", "long")
175all_modes = ("fs", "se")
176
177class Test(object):
178 """Test case base class.
179
180 Test cases consists of one or more test units that are run in two
181 phases. A run phase (units produced by run_units() and a verify
182 phase (units from verify_units()). The verify phase is skipped if
183 the run phase fails.
184
185 """
186
187 __metaclass__ = ABCMeta
188
189 def __init__(self, name):
190 self.test_name = name
191
192 @abstractmethod
193 def ref_files(self):
194 """Get a list of reference files used by this test case"""
195 pass
196
197 @abstractmethod
198 def run_units(self):
199 """Units (typically RunGem5 instances) that describe the run phase of
200 this test.
201
202 """
203 pass
204
205 @abstractmethod
206 def verify_units(self):
207 """Verify the output from the run phase (see run_units())."""
208 pass
209
210 @abstractmethod
211 def update_ref(self):
212 """Update reference files with files from a test run"""
213 pass
214
215 def run(self):
216 """Run this test case and return a list of results"""
217
218 run_results = [ u.run() for u in self.run_units() ]
219 run_ok = all([not r.skipped() and r for r in run_results ])
220
221 verify_results = [
222 u.run() if run_ok else u.skip()
223 for u in self.verify_units()
224 ]
225
226 return TestResult(self.test_name,
227 run_results=run_results,
228 verify_results=verify_results)
229
230 def __str__(self):
231 return self.test_name
232
233class ClassicTest(Test):
234 # The diff ignore list contains all files that shouldn't be diffed
235 # using DiffOutFile. These files typically use special-purpose
236 # diff tools (e.g., DiffStatFile).
237 diff_ignore_files = FileIgnoreList(
238 names=(
239 # Stat files use a special stat differ
240 "stats.txt",
241 ), rex=(
242 ))
243
244 # These files should never be included in the list of
245 # reference files. This list should include temporary files
246 # and other files that we don't care about.
247 ref_ignore_files = FileIgnoreList(
248 names=(
249 "EMPTY",
250 ), rex=(
251 # Mercurial sometimes leaves backups when applying MQ patches
252 r"\.orig$",
253 r"\.rej$",
254 ))
255
256 def __init__(self, gem5, output_dir, config_tuple,
257 timeout=None,
258 skip=False, skip_diff_out=False, skip_diff_stat=False):
259
260 super(ClassicTest, self).__init__("/".join(config_tuple))
261
262 ct = config_tuple
263
264 self.gem5 = os.path.abspath(gem5)
265 self.script = os.path.join(_test_base, "run.py")
266 self.config_tuple = ct
267 self.timeout = timeout
268
269 self.output_dir = output_dir
270 self.ref_dir = os.path.join(_test_base,
271 ct.category, ct.mode, ct.workload,
272 "ref", ct.isa, ct.os, ct.config)
273 self.skip_run = skip
274 self.skip_diff_out = skip or skip_diff_out
275 self.skip_diff_stat = skip or skip_diff_stat
276
277 def ref_files(self):
278 ref_dir = os.path.abspath(self.ref_dir)
279 for root, dirs, files in os.walk(ref_dir, topdown=False):
280 for f in files:
281 fpath = os.path.join(root[len(ref_dir) + 1:], f)
282 if fpath not in ClassicTest.ref_ignore_files:
283 yield fpath
284
285 def run_units(self):
286 args = [
287 self.script,
288 "/".join(self.config_tuple),
289 ]
290
291 return [
292 RunGem5(self.gem5, args,
293 ref_dir=self.ref_dir, test_dir=self.output_dir,
294 skip=self.skip_run),
295 ]
296
297 def verify_units(self):
298 ref_files = set(self.ref_files())
299 units = []
300 if "stats.txt" in ref_files:
301 units.append(
302 DiffStatFile(ref_dir=self.ref_dir, test_dir=self.output_dir,
303 skip=self.skip_diff_stat))
304 units += [
305 DiffOutFile(f,
306 ref_dir=self.ref_dir, test_dir=self.output_dir,
307 skip=self.skip_diff_out)
308 for f in ref_files if f not in ClassicTest.diff_ignore_files
309 ]
310
311 return units
312
313 def update_ref(self):
314 for fname in self.ref_files():
315 shutil.copy(
316 os.path.join(self.output_dir, fname),
317 os.path.join(self.ref_dir, fname))
318
319def parse_test_filter(test_filter):
320 wildcards = ("", "*")
321
322 _filter = list(test_filter.split("/"))
323 if len(_filter) > 3:
324 raise RuntimeError("Illegal test filter string")
325 _filter += [ "", ] * (3 - len(_filter))
326
327 isa, cat, mode = _filter
328
329 if isa in wildcards:
330 raise RuntimeError("No ISA specified")
331
332 cat = all_categories if cat in wildcards else (cat, )
333 mode = all_modes if mode in wildcards else (mode, )
334
335 return isa, cat, mode
336
337def get_tests(isa,
338 categories=all_categories, modes=all_modes,
339 ruby_protocol=None, gpu_isa=None):
340
341 # Generate a list of candidate configs
342 configs = list(arch_configs.get((isa, gpu_isa), []))
343
344 if (isa, gpu_isa) == ("x86", "hsail"):
345 if ruby_protocol == "GPU_RfO":
346 configs += ['gpu-randomtest']
347 else:
348 configs += generic_configs
349
340 if ruby_protocol == 'MI_example':
341 configs += [ "%s-ruby" % (c, ) for c in configs ]
350 if ruby_protocol == get_default_protocol(isa):
351 if ruby_protocol == 'MI_example':
352 configs += [ "%s-ruby" % (c, ) for c in configs ]
353 else:
354 configs += [ "%s-ruby-%s" % (c, ruby_protocol) for c in configs ]
342 elif ruby_protocol is not None:
343 # Override generic ISA configs when using Ruby (excluding
344 # MI_example which is included in all ISAs by default). This
345 # reduces the number of generic tests we re-run for when
346 # compiling Ruby targets.
347 configs = [ "%s-ruby-%s" % (c, ruby_protocol) for c in configs ]
348
349 # /(quick|long)/(fs|se)/workload/ref/arch/guest/config/
350 for conf_script in configs:
351 for cat in categories:
352 for mode in modes:
353 mode_dir = os.path.join(_test_base, cat, mode)
354 if not os.path.exists(mode_dir):
355 continue
356
357 for workload in os.listdir(mode_dir):
358 isa_dir = os.path.join(mode_dir, workload, "ref", isa)
359 if not os.path.isdir(isa_dir):
360 continue
361
362 for _os in os.listdir(isa_dir):
363 test_dir = os.path.join(isa_dir, _os, conf_script)
364 if not os.path.exists(test_dir) or \
365 os.path.exists(os.path.join(test_dir, "skip")):
366 continue
367
368 yield ClassicConfig(cat, mode, workload, isa, _os,
369 conf_script)
355 elif ruby_protocol is not None:
356 # Override generic ISA configs when using Ruby (excluding
357 # MI_example which is included in all ISAs by default). This
358 # reduces the number of generic tests we re-run for when
359 # compiling Ruby targets.
360 configs = [ "%s-ruby-%s" % (c, ruby_protocol) for c in configs ]
361
362 # /(quick|long)/(fs|se)/workload/ref/arch/guest/config/
363 for conf_script in configs:
364 for cat in categories:
365 for mode in modes:
366 mode_dir = os.path.join(_test_base, cat, mode)
367 if not os.path.exists(mode_dir):
368 continue
369
370 for workload in os.listdir(mode_dir):
371 isa_dir = os.path.join(mode_dir, workload, "ref", isa)
372 if not os.path.isdir(isa_dir):
373 continue
374
375 for _os in os.listdir(isa_dir):
376 test_dir = os.path.join(isa_dir, _os, conf_script)
377 if not os.path.exists(test_dir) or \
378 os.path.exists(os.path.join(test_dir, "skip")):
379 continue
380
381 yield ClassicConfig(cat, mode, workload, isa, _os,
382 conf_script)