tests.py revision 11542:ecd058e3dcbe
12330SN/A#!/usr/bin/env python 22330SN/A# 32330SN/A# Copyright (c) 2016 ARM Limited 42330SN/A# All rights reserved 52330SN/A# 62330SN/A# The license below extends only to copyright in the software and shall 72330SN/A# not be construed as granting a license to any other intellectual 82330SN/A# property including but not limited to intellectual property relating 92330SN/A# to a hardware implementation of the functionality of the software 102330SN/A# licensed hereunder. You may use the software subject to the license 112330SN/A# terms below provided that you ensure that this notice is replicated 122330SN/A# unmodified and in its entirety in all distributions of the software, 132330SN/A# modified or unmodified, in source code or in binary form. 142330SN/A# 152330SN/A# Redistribution and use in source and binary forms, with or without 162330SN/A# modification, are permitted provided that the following conditions are 172330SN/A# met: redistributions of source code must retain the above copyright 182330SN/A# notice, this list of conditions and the following disclaimer; 192330SN/A# redistributions in binary form must reproduce the above copyright 202330SN/A# notice, this list of conditions and the following disclaimer in the 212330SN/A# documentation and/or other materials provided with the distribution; 222330SN/A# neither the name of the copyright holders nor the names of its 232330SN/A# contributors may be used to endorse or promote products derived from 242330SN/A# this software without specific prior written permission. 252330SN/A# 262330SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 272689Sktlim@umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 282689Sktlim@umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 292330SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 302292SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 312292SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 322292SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 332292SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 342980Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 352362SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 362680Sktlim@umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 372292SN/A# 382678Sktlim@umich.edu# Authors: Andreas Sandberg 392683Sktlim@umich.edu 402683Sktlim@umich.edufrom abc import ABCMeta, abstractmethod 412678Sktlim@umich.eduimport os 422678Sktlim@umich.edufrom collections import namedtuple 432292SN/Afrom units import * 442292SN/Afrom results import TestResult 452292SN/Aimport shutil 462292SN/A 473548Sgblack@eecs.umich.edu_test_base = os.path.join(os.path.dirname(__file__), "..") 483548Sgblack@eecs.umich.edu 493548Sgblack@eecs.umich.eduClassicConfig = namedtuple("ClassicConfig", ( 503548Sgblack@eecs.umich.edu "category", 512330SN/A "mode", 522292SN/A "workload", 532292SN/A "isa", 543402Sktlim@umich.edu "os", 552862Sktlim@umich.edu "config", 563486Sktlim@umich.edu)) 573402Sktlim@umich.edu 582862Sktlim@umich.edu# There are currently two "classes" of test 592330SN/A# configurations. Architecture-specific ones and generic ones 602330SN/A# (typically SE mode tests). In both cases, the configuration name 612330SN/A# matches a file in tests/configs/ that will be picked up by the test 622330SN/A# runner (run.py). 632330SN/A# 642330SN/A# Architecture specific configurations are listed in the arch_configs 652292SN/A# dictionary. This is indexed by a (cpu architecture, gpu 662683Sktlim@umich.edu# architecture) tuple. GPU architecture is optional and may be None. 672683Sktlim@umich.edu# 682292SN/A# Generic configurations are listed in the generic_configs tuple. 693402Sktlim@umich.edu# 702292SN/A# When discovering available test cases, this script look uses the 713402Sktlim@umich.edu# test list as a list of /candidate/ configurations. A configuration 723402Sktlim@umich.edu# is only used if a test has a reference output for that 732292SN/A# configuration. In addition to the base configurations from 742683Sktlim@umich.edu# arch_configs and generic_configs, a Ruby configuration may be 753486Sktlim@umich.edu# appended to the base name (this is probed /in addition/ to the 763486Sktlim@umich.edu# original name. See get_tests() for details. 772862Sktlim@umich.edu# 782862Sktlim@umich.eduarch_configs = { 792862Sktlim@umich.edu ("alpha", None) : ( 802862Sktlim@umich.edu 'tsunami-simple-atomic', 812683Sktlim@umich.edu 'tsunami-simple-timing', 822683Sktlim@umich.edu 'tsunami-simple-atomic-dual', 832683Sktlim@umich.edu 'tsunami-simple-timing-dual', 842683Sktlim@umich.edu 'twosys-tsunami-simple-atomic', 852683Sktlim@umich.edu 'tsunami-o3', 'tsunami-o3-dual', 862683Sktlim@umich.edu 'tsunami-minor', 'tsunami-minor-dual', 872683Sktlim@umich.edu 'tsunami-switcheroo-full', 882683Sktlim@umich.edu ), 892683Sktlim@umich.edu 902683Sktlim@umich.edu ("arm", None) : ( 912683Sktlim@umich.edu 'simple-atomic-dummychecker', 922683Sktlim@umich.edu 'o3-timing-checker', 932683Sktlim@umich.edu 'realview-simple-atomic', 943686Sktlim@umich.edu 'realview-simple-atomic-dual', 953675Sktlim@umich.edu 'realview-simple-atomic-checkpoint', 963686Sktlim@umich.edu 'realview-simple-timing', 973675Sktlim@umich.edu 'realview-simple-timing-dual', 983686Sktlim@umich.edu 'realview-o3', 993675Sktlim@umich.edu 'realview-o3-checker', 1002683Sktlim@umich.edu 'realview-o3-dual', 1012683Sktlim@umich.edu 'realview-minor', 1022683Sktlim@umich.edu 'realview-minor-dual', 1032683Sktlim@umich.edu 'realview-switcheroo-atomic', 1042683Sktlim@umich.edu 'realview-switcheroo-timing', 1052683Sktlim@umich.edu 'realview-switcheroo-o3', 1062683Sktlim@umich.edu 'realview-switcheroo-full', 1072683Sktlim@umich.edu 'realview64-simple-atomic', 1083548Sgblack@eecs.umich.edu 'realview64-simple-atomic-checkpoint', 1092683Sktlim@umich.edu 'realview64-simple-atomic-dual', 1102690Sktlim@umich.edu 'realview64-simple-timing', 1112690Sktlim@umich.edu 'realview64-simple-timing-dual', 1122683Sktlim@umich.edu 'realview64-o3', 1132683Sktlim@umich.edu 'realview64-o3-checker', 1142690Sktlim@umich.edu 'realview64-o3-dual', 1152690Sktlim@umich.edu 'realview64-minor', 1162683Sktlim@umich.edu 'realview64-minor-dual', 1172683Sktlim@umich.edu 'realview64-switcheroo-atomic', 1182683Sktlim@umich.edu 'realview64-switcheroo-timing', 1192683Sktlim@umich.edu 'realview64-switcheroo-o3', 1203402Sktlim@umich.edu 'realview64-switcheroo-full', 1212683Sktlim@umich.edu ), 1222683Sktlim@umich.edu 1232683Sktlim@umich.edu ("sparc", None) : ( 1242683Sktlim@umich.edu 't1000-simple-atomic', 1252683Sktlim@umich.edu 't1000-simple-x86', 1262678Sktlim@umich.edu ), 1272292SN/A 1282683Sktlim@umich.edu ("timing", None) : ( 1292683Sktlim@umich.edu 'pc-simple-atomic', 1302292SN/A 'pc-simple-timing', 1312683Sktlim@umich.edu 'pc-o3-timing', 1322683Sktlim@umich.edu 'pc-switcheroo-full', 1332683Sktlim@umich.edu ), 1342683Sktlim@umich.edu 1352683Sktlim@umich.edu ("x86", "hsail") : ( 1362683Sktlim@umich.edu 'gpu', 1372683Sktlim@umich.edu ), 1382683Sktlim@umich.edu} 1392683Sktlim@umich.edu 1402683Sktlim@umich.edugeneric_configs = ( 1412683Sktlim@umich.edu 'simple-atomic', 1422683Sktlim@umich.edu 'simple-atomic-mp', 1432683Sktlim@umich.edu 'simple-timing', 1442683Sktlim@umich.edu 'simple-timing-mp', 1452683Sktlim@umich.edu 1462683Sktlim@umich.edu 'minor-timing', 1472683Sktlim@umich.edu 'minor-timing-mp', 1482683Sktlim@umich.edu 1492683Sktlim@umich.edu 'o3-timing', 1503673Srdreslin@umich.edu 'o3-timing-mt', 1513675Sktlim@umich.edu 'o3-timing-mp', 1523675Sktlim@umich.edu 1533675Sktlim@umich.edu 'rubytest', 1543486Sktlim@umich.edu 'memcheck', 1552683Sktlim@umich.edu 'memtest', 1562683Sktlim@umich.edu 'memtest-filter', 1572683Sktlim@umich.edu 'tgen-simple-mem', 1582683Sktlim@umich.edu 'tgen-dram-ctrl', 1592683Sktlim@umich.edu 1602683Sktlim@umich.edu 'learning-gem5-p1-simple', 1612683Sktlim@umich.edu 'learning-gem5-p1-two-level', 1622683Sktlim@umich.edu) 1632683Sktlim@umich.edu 1642683Sktlim@umich.eduall_categories = ("quick", "long") 1652683Sktlim@umich.eduall_modes = ("fs", "se") 1662683Sktlim@umich.edu 1672683Sktlim@umich.educlass Test(object): 1682683Sktlim@umich.edu """Test case base class. 1692683Sktlim@umich.edu 1702683Sktlim@umich.edu Test cases consists of one or more test units that are run in two 1712683Sktlim@umich.edu phases. A run phase (units produced by run_units() and a verify 1722683Sktlim@umich.edu phase (units from verify_units()). The verify phase is skipped if 1733402Sktlim@umich.edu the run phase fails. 1743402Sktlim@umich.edu 1753402Sktlim@umich.edu """ 1762683Sktlim@umich.edu 1772683Sktlim@umich.edu __metaclass__ = ABCMeta 1782292SN/A 1792292SN/A def __init__(self, name): 1802292SN/A self.test_name = name 1812292SN/A 1822292SN/A @abstractmethod 1832690Sktlim@umich.edu def ref_files(self): 1842683Sktlim@umich.edu """Get a list of reference files used by this test case""" 1852683Sktlim@umich.edu pass 1862292SN/A 1872683Sktlim@umich.edu @abstractmethod 1882683Sktlim@umich.edu def run_units(self): 1892292SN/A """Units (typically RunGem5 instances) that describe the run phase of 1902292SN/A this test. 1912683Sktlim@umich.edu 1922292SN/A """ 1932292SN/A pass 1942292SN/A 1952292SN/A @abstractmethod 1962292SN/A def verify_units(self): 1973548Sgblack@eecs.umich.edu """Verify the output from the run phase (see run_units()).""" 1982683Sktlim@umich.edu pass 1992683Sktlim@umich.edu 2002683Sktlim@umich.edu @abstractmethod 2012683Sktlim@umich.edu def update_ref(self): 2022683Sktlim@umich.edu """Update reference files with files from a test run""" 2032683Sktlim@umich.edu pass 2042683Sktlim@umich.edu 2052683Sktlim@umich.edu def run(self): 2062292SN/A """Run this test case and return a list of results""" 2072678Sktlim@umich.edu 2082678Sktlim@umich.edu run_results = [ u.run() for u in self.run_units() ] 2092292SN/A run_ok = all([not r.skipped() and r for r in run_results ]) 2102292SN/A 2112292SN/A verify_results = [ 2122292SN/A u.run() if run_ok else u.skip() 2132292SN/A for u in self.verify_units() 2142292SN/A ] 2152330SN/A 2162330SN/A return TestResult(self.test_name, 2172330SN/A run_results=run_results, 2182683Sktlim@umich.edu verify_results=verify_results) 2192683Sktlim@umich.edu 2202683Sktlim@umich.edu def __str__(self): 2212683Sktlim@umich.edu return self.test_name 2222292SN/A 2233276Sgblack@eecs.umich.educlass ClassicTest(Test): 2243276Sgblack@eecs.umich.edu # The diff ignore list contains all files that shouldn't be diffed 2253276Sgblack@eecs.umich.edu # using DiffOutFile. These files typically use special-purpose 2263276Sgblack@eecs.umich.edu # diff tools (e.g., DiffStatFile). 2273276Sgblack@eecs.umich.edu diff_ignore_files = ( 2283276Sgblack@eecs.umich.edu # Stat files use a special stat differ 2293276Sgblack@eecs.umich.edu "stats.txt", 2303276Sgblack@eecs.umich.edu ) 2313276Sgblack@eecs.umich.edu 2323276Sgblack@eecs.umich.edu # These files should never be included in the list of 2332690Sktlim@umich.edu # reference files. This list should include temporary files 2342292SN/A # and other files that we don't care about. 2352292SN/A ref_ignore_files = ( 2362292SN/A ) 2372292SN/A 2382292SN/A def __init__(self, gem5, output_dir, config_tuple, 2392292SN/A timeout=None, 2402292SN/A skip=False, skip_diff_out=False, skip_diff_stat=False): 2412292SN/A 2422292SN/A super(ClassicTest, self).__init__("/".join(config_tuple)) 2432292SN/A 2442292SN/A ct = config_tuple 2452292SN/A 2462292SN/A self.gem5 = os.path.abspath(gem5) 2472292SN/A self.script = os.path.join(_test_base, "run.py") 2482292SN/A self.config_tuple = ct 2492292SN/A self.timeout = timeout 2502292SN/A 2512292SN/A self.output_dir = output_dir 2522292SN/A self.ref_dir = os.path.join(_test_base, 2532292SN/A ct.category, ct.mode, ct.workload, 2542292SN/A "ref", ct.isa, ct.os, ct.config) 2552292SN/A self.skip_run = skip 2562292SN/A self.skip_diff_out = skip or skip_diff_out 2572292SN/A self.skip_diff_stat = skip or skip_diff_stat 2582292SN/A 259 def ref_files(self): 260 ref_dir = os.path.abspath(self.ref_dir) 261 for root, dirs, files in os.walk(ref_dir, topdown=False): 262 for f in files: 263 fpath = os.path.join(root[len(ref_dir) + 1:], f) 264 if fpath not in ClassicTest.ref_ignore_files: 265 yield fpath 266 267 def run_units(self): 268 args = [ 269 self.script, 270 "/".join(self.config_tuple), 271 ] 272 273 return [ 274 RunGem5(self.gem5, args, 275 ref_dir=self.ref_dir, test_dir=self.output_dir, 276 skip=self.skip_run), 277 ] 278 279 def verify_units(self): 280 return [ 281 DiffStatFile(ref_dir=self.ref_dir, test_dir=self.output_dir, 282 skip=self.skip_diff_stat) 283 ] + [ 284 DiffOutFile(f, 285 ref_dir=self.ref_dir, test_dir=self.output_dir, 286 skip=self.skip_diff_out) 287 for f in self.ref_files() 288 if f not in ClassicTest.diff_ignore_files 289 ] 290 291 def update_ref(self): 292 for fname in self.ref_files(): 293 shutil.copy( 294 os.path.join(self.output_dir, fname), 295 os.path.join(self.ref_dir, fname)) 296 297def parse_test_filter(test_filter): 298 wildcards = ("", "*") 299 300 _filter = list(test_filter.split("/")) 301 if len(_filter) > 3: 302 raise RuntimeError("Illegal test filter string") 303 _filter += [ "", ] * (3 - len(_filter)) 304 305 isa, cat, mode = _filter 306 307 if isa in wildcards: 308 raise RuntimeError("No ISA specified") 309 310 cat = all_categories if cat in wildcards else (cat, ) 311 mode = all_modes if mode in wildcards else (mode, ) 312 313 return isa, cat, mode 314 315def get_tests(isa, 316 categories=all_categories, modes=all_modes, 317 ruby_protocol=None, gpu_isa=None): 318 319 # Generate a list of candidate configs 320 configs = list(arch_configs.get((isa, gpu_isa), [])) 321 322 if (isa, gpu_isa) == ("x86", "hsail"): 323 if ruby_protocol == "GPU_RfO": 324 configs += ['gpu-randomtest'] 325 else: 326 configs += generic_configs 327 328 if ruby_protocol == 'MI_example': 329 configs += [ "%s-ruby" % (c, ) for c in configs ] 330 elif ruby_protocol is not None: 331 # Override generic ISA configs when using Ruby (excluding 332 # MI_example which is included in all ISAs by default). This 333 # reduces the number of generic tests we re-run for when 334 # compiling Ruby targets. 335 configs = [ "%s-ruby-%s" % (c, ruby_protocol) for c in configs ] 336 337 # /(quick|long)/(fs|se)/workload/ref/arch/guest/config/ 338 for conf_script in configs: 339 for cat in categories: 340 for mode in modes: 341 mode_dir = os.path.join(_test_base, cat, mode) 342 if not os.path.exists(mode_dir): 343 continue 344 345 for workload in os.listdir(mode_dir): 346 isa_dir = os.path.join(mode_dir, workload, "ref", isa) 347 if not os.path.isdir(isa_dir): 348 continue 349 350 for _os in os.listdir(isa_dir): 351 test_dir = os.path.join(isa_dir, _os, conf_script) 352 if not os.path.exists(test_dir) or \ 353 os.path.exists(os.path.join(test_dir, "skip")): 354 continue 355 356 yield ClassicConfig(cat, mode, workload, isa, _os, 357 conf_script) 358