112771Sqtt2@cornell.edu#!/usr/bin/env python 212771Sqtt2@cornell.edu 312771Sqtt2@cornell.edu# Copyright (c) 2018, Cornell University 412771Sqtt2@cornell.edu# All rights reserved. 512771Sqtt2@cornell.edu# 612771Sqtt2@cornell.edu# Redistribution and use in source and binary forms, with or 712771Sqtt2@cornell.edu# without modification, are permitted provided that the following 812771Sqtt2@cornell.edu# conditions are met: 912771Sqtt2@cornell.edu# 1012771Sqtt2@cornell.edu# Redistributions of source code must retain the above copyright 1112771Sqtt2@cornell.edu# notice, this list of conditions and the following disclaimer. 1212771Sqtt2@cornell.edu# 1312771Sqtt2@cornell.edu# Redistributions in binary form must reproduce the above 1412771Sqtt2@cornell.edu# copyright notice, this list of conditions and the following 1512771Sqtt2@cornell.edu# disclaimer in the documentation and/or other materials provided 1612771Sqtt2@cornell.edu# with the distribution. 1712771Sqtt2@cornell.edu# 1812771Sqtt2@cornell.edu# Neither the name of Cornell University nor the names of its 1912771Sqtt2@cornell.edu# contributors may be used to endorse or promote products derived 2012771Sqtt2@cornell.edu# from this software without specific prior written permission. 2112771Sqtt2@cornell.edu# 2212771Sqtt2@cornell.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 2312771Sqtt2@cornell.edu# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 2412771Sqtt2@cornell.edu# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 2512771Sqtt2@cornell.edu# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2612771Sqtt2@cornell.edu# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 2712771Sqtt2@cornell.edu# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2812771Sqtt2@cornell.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2912771Sqtt2@cornell.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 3012771Sqtt2@cornell.edu# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 3112771Sqtt2@cornell.edu# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3212771Sqtt2@cornell.edu# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3312771Sqtt2@cornell.edu# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3412771Sqtt2@cornell.edu# POSSIBILITY OF SUCH DAMAGE. 3512771Sqtt2@cornell.edu# 3612771Sqtt2@cornell.edu# Authors: Tuan Ta 3712771Sqtt2@cornell.edu 3812771Sqtt2@cornell.eduimport os 3912771Sqtt2@cornell.eduimport sys 4012771Sqtt2@cornell.eduimport argparse 4112771Sqtt2@cornell.eduimport subprocess 4212771Sqtt2@cornell.edu 4312771Sqtt2@cornell.edufrom multiprocessing import Pool 4412771Sqtt2@cornell.edu 4512771Sqtt2@cornell.eduimport clusterjob 4612771Sqtt2@cornell.edufrom clusterjob import * 4712771Sqtt2@cornell.edu 4812771Sqtt2@cornell.edu#------------------------------------------------------------------------- 4912771Sqtt2@cornell.edu# utility function to run a process 5012771Sqtt2@cornell.edu#------------------------------------------------------------------------- 5112771Sqtt2@cornell.edudef execute(cmd): 5212771Sqtt2@cornell.edu try: 5312771Sqtt2@cornell.edu return subprocess.check_output(cmd, shell=True) 5412771Sqtt2@cornell.edu except subprocess.CalledProcessError, err: 5512771Sqtt2@cornell.edu print "ERROR: " + err.output 5612771Sqtt2@cornell.edu 5712771Sqtt2@cornell.edu#------------------------------------------------------------------------- 5812771Sqtt2@cornell.edu# Input options 5912771Sqtt2@cornell.edu#------------------------------------------------------------------------- 6012771Sqtt2@cornell.edu 6112771Sqtt2@cornell.edu# general options 6212771Sqtt2@cornell.eduparser = argparse.ArgumentParser(description='run RISC-V assembly tests') 6312771Sqtt2@cornell.eduparser.add_argument('--max-tick', 6412771Sqtt2@cornell.edu help = 'maximum simulated tick', 6512771Sqtt2@cornell.edu type = int, 6612771Sqtt2@cornell.edu default = 10000000000) 6712771Sqtt2@cornell.eduparser.add_argument('--num-cpus', 6812771Sqtt2@cornell.edu help = 'number of CPUs\ 6912771Sqtt2@cornell.edu (some tests require at least 4 CPUs)', 7012771Sqtt2@cornell.edu type = int, 7112771Sqtt2@cornell.edu default = 4) 7212771Sqtt2@cornell.eduparser.add_argument('--ruby', 7312771Sqtt2@cornell.edu help = 'Use Ruby memory?', 7412771Sqtt2@cornell.edu action = 'store_true') 7512771Sqtt2@cornell.edu 7612771Sqtt2@cornell.eduargs = parser.parse_args() 7712771Sqtt2@cornell.edu 7812771Sqtt2@cornell.edu# convert all paths to absolute paths 7912771Sqtt2@cornell.edutest_dir = os.path.abspath('../../bin/riscv/') 8012771Sqtt2@cornell.edutest_summary_out = './test-summary.out' 8112771Sqtt2@cornell.edu 8212771Sqtt2@cornell.edu#------------------------------------------------------------------------- 8312771Sqtt2@cornell.edu# gem5 variables 8412771Sqtt2@cornell.edu#------------------------------------------------------------------------- 8512771Sqtt2@cornell.edugem5_dir = os.path.abspath('../../../../../') 8612771Sqtt2@cornell.edugem5_bin = os.path.join(gem5_dir, 'build', 'RISCV', 'gem5.opt') 8712771Sqtt2@cornell.educonfig = os.path.join(gem5_dir, 'configs', 'example', 'se.py') 8812771Sqtt2@cornell.edu 8912771Sqtt2@cornell.edu# list of CPU models to be tested 9012771Sqtt2@cornell.educpu_models = ['AtomicSimpleCPU', 9112771Sqtt2@cornell.edu 'TimingSimpleCPU', 9212771Sqtt2@cornell.edu 'MinorCPU', 9312771Sqtt2@cornell.edu 'DerivO3CPU'] 9412771Sqtt2@cornell.edu 9512771Sqtt2@cornell.edu# get a list of test binaries in the given directory 9612771Sqtt2@cornell.edutests = [] 9712771Sqtt2@cornell.edufor line in execute("ls %s/*" % (test_dir)).splitlines(): 9812771Sqtt2@cornell.edu if line: 9912771Sqtt2@cornell.edu tests.append(line.split('/')[-1]) 10012771Sqtt2@cornell.edu 10112771Sqtt2@cornell.edu# total number of tests to run 10212771Sqtt2@cornell.edun_tests = len(tests) * len(cpu_models) 10312771Sqtt2@cornell.edu 10412771Sqtt2@cornell.edu# make a list of jobs 10512771Sqtt2@cornell.edujob_cmds = [] 10612771Sqtt2@cornell.edujob_names = [] 10712771Sqtt2@cornell.edufor test in tests: 10812771Sqtt2@cornell.edu for model in cpu_models: 10912771Sqtt2@cornell.edu test_name = test + '-' + model 11012771Sqtt2@cornell.edu job_names.append(test_name) 11112771Sqtt2@cornell.edu job_cmds.append([gem5_bin, 11212771Sqtt2@cornell.edu config, 11312771Sqtt2@cornell.edu '-m', str(args.max_tick), 11412771Sqtt2@cornell.edu '--cpu-type', model, 11512771Sqtt2@cornell.edu '-n', str(args.num_cpus), 11612771Sqtt2@cornell.edu '-c', test_dir + '/' + test, 11712771Sqtt2@cornell.edu '--ruby' if args.ruby else '--caches', 11812771Sqtt2@cornell.edu ]) 11912771Sqtt2@cornell.edu 12012771Sqtt2@cornell.edu# execute all jobs 12112771Sqtt2@cornell.edujob_pool = Pool(processes = n_tests) 12212771Sqtt2@cornell.edujob_outputs = job_pool.map(subprocess.call, job_cmds) 12312771Sqtt2@cornell.edujob_pool.close() 12412771Sqtt2@cornell.edu 12512771Sqtt2@cornell.edu# process job outputs 12612771Sqtt2@cornell.edufile = open(test_summary_out, "w") 12712771Sqtt2@cornell.edu 12812771Sqtt2@cornell.edujob_outputs = zip(job_names, job_outputs) 12912771Sqtt2@cornell.edufor entry in job_outputs: 13012771Sqtt2@cornell.edu # a negative return value indicates that the job was terminated 13112771Sqtt2@cornell.edu # by a signal 13212771Sqtt2@cornell.edu # a positive return value indicates that the job exited with a return 13312771Sqtt2@cornell.edu # value 13412771Sqtt2@cornell.edu if entry[1] < 0: 13512771Sqtt2@cornell.edu file.write("%-50s failed - signal = %d\n" % (entry[0], -1 * entry[1])) 13612771Sqtt2@cornell.edu elif entry[1] > 0: 13712771Sqtt2@cornell.edu file.write("%-50s failed - status = %d\n" % (entry[0], entry[1])) 13812771Sqtt2@cornell.edu else: 13912771Sqtt2@cornell.edu file.write("%-50s passed\n" % (entry[0])) 14012771Sqtt2@cornell.edu 14112771Sqtt2@cornell.edufile.close() 142