3 # Copyright 2018 Google, Inc.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met: redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer;
9 # redistributions in binary form must reproduce the above copyright
10 # notice, this list of conditions and the following disclaimer in the
11 # documentation and/or other materials provided with the distribution;
12 # neither the name of the copyright holders nor the names of its
13 # contributors may be used to endorse or promote products derived from
14 # this software without specific prior written permission.
16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 from __future__
import print_function
42 script_path
= os
.path
.abspath(inspect
.getfile(inspect
.currentframe()))
43 script_dir
= os
.path
.dirname(script_path
)
44 config_path
= os
.path
.join(script_dir
, 'config.py')
46 systemc_rel_path
= 'systemc'
47 tests_rel_path
= os
.path
.join(systemc_rel_path
, 'tests')
48 json_rel_path
= os
.path
.join(tests_rel_path
, 'tests.json')
52 logging
.basicConfig(level
=logging
.INFO
)
55 args
= ['scons'] + list(args
)
56 subprocess
.check_call(args
)
61 def __init__(self
, target
, suffix
, build_dir
, props
):
64 self
.build_dir
= build_dir
66 for key
, val
in props
.iteritems():
67 setattr(self
, key
, val
)
70 return os
.path
.join(self
.build_dir
, tests_rel_path
, self
.path
)
73 return os
.path
.join(script_dir
, self
.path
)
76 return os
.path
.join(self
.src_dir(), 'golden')
79 return '.'.join([self
.name
, self
.suffix
])
82 return os
.path
.join(self
.dir(), self
.bin())
85 return os
.path
.join(self
.dir(), 'm5out.' + self
.suffix
)
89 test_phase_classes
= {}
91 class TestPhaseMeta(type):
92 def __init__(cls
, name
, bases
, d
):
93 if not d
.pop('abstract', False):
94 test_phase_classes
[d
['name']] = cls
96 super(TestPhaseMeta
, cls
).__init
__(name
, bases
, d
)
98 class TestPhaseBase(object):
99 __metaclass__
= TestPhaseMeta
102 def __init__(self
, main_args
, *args
):
103 self
.main_args
= main_args
106 def __lt__(self
, other
):
107 return self
.number
< other
.number
109 class CompilePhase(TestPhaseBase
):
113 def run(self
, tests
):
114 targets
= list([test
.full_path() for test
in tests
])
115 scons_args
= list(self
.args
) + targets
118 class RunPhase(TestPhaseBase
):
122 def run(self
, tests
):
124 if test
.compile_only
:
128 '-red', test
.m5out_dir(),
129 '--listener-mode=off',
132 subprocess
.check_call(args
)
134 class VerifyPhase(TestPhaseBase
):
138 def run(self
, tests
):
140 if test
.compile_only
:
142 logging
.info("Would verify %s", test
.m5out_dir())
146 parser
= argparse
.ArgumentParser(description
='SystemC test utility')
148 parser
.add_argument('build_dir', metavar
='BUILD_DIR',
149 help='The build directory (ie. build/ARM).')
151 parser
.add_argument('--update-json', action
='store_true',
152 help='Update the json manifest of tests.')
154 parser
.add_argument('--flavor', choices
=['debug', 'opt', 'fast'],
156 help='Flavor of binary to test.')
158 parser
.add_argument('--list', action
='store_true',
159 help='List the available tests')
161 filter_opts
= parser
.add_mutually_exclusive_group()
162 filter_opts
.add_argument('--filter', default
='True',
163 help='Python expression which filters tests based '
164 'on their properties')
165 filter_opts
.add_argument('--filter-file', default
=None,
166 type=argparse
.FileType('r'),
167 help='Same as --filter, but read from a file')
169 def collect_phases(args
):
170 phase_groups
= [list(g
) for k
, g
in
171 itertools
.groupby(args
, lambda x
: x
!= '--phase') if k
]
172 main_args
= parser
.parse_args(phase_groups
[0][1:])
175 for group
in phase_groups
[1:]:
178 raise RuntimeException('Phase %s specified more than once' % name
)
179 phase
= test_phase_classes
[name
]
180 phases
.append(phase(main_args
, *group
[1:]))
182 return main_args
, phases
184 main_args
, phases
= collect_phases(sys
.argv
)
188 CompilePhase(main_args
),
190 VerifyPhase(main_args
)
195 json_path
= os
.path
.join(main_args
.build_dir
, json_rel_path
)
197 if main_args
.update_json
:
198 scons(os
.path
.join(json_path
))
200 with
open(json_path
) as f
:
201 test_data
= json
.load(f
)
203 if main_args
.filter_file
:
204 f
= main_args
.filter_file
205 filt
= compile(f
.read(), f
.name
, 'eval')
207 filt
= compile(main_args
.filter, '<string>', 'eval')
210 target
: props
for (target
, props
) in
211 test_data
.iteritems() if eval(filt
, dict(props
))
215 for target
, props
in sorted(filtered_tests
.iteritems()):
216 print('%s.%s' % (target
, main_args
.flavor
))
217 for key
, val
in props
.iteritems():
218 print(' %s: %s' % (key
, val
))
219 print('Total tests: %d' % len(filtered_tests
))
221 tests_to_run
= list([
222 Test(target
, main_args
.flavor
, main_args
.build_dir
, props
) for
223 target
, props
in sorted(filtered_tests
.iteritems())
227 phase
.run(tests_to_run
)