Easily Running SPEC CPU2006 Benchmarks in the gem5 Simulator

Mark Gottscho | Sep 20, 2014 min read

It appears that a good number of people found my articles from 2013 on building gem5 and SPEC CPU2006 benchmarks for Alpha useful! So due to some requests I’ve decided to make an additional post on how to get the SPEC benchmarks and gem5 you set up actually running.

This tutorial will show you how to get individual SPEC CPU2006 Alpha binaries to run inside the gem5 simulator modeling an Alpha system. My host system is Ubuntu Linux x86-64, but any Unix-like OS should work similarly for this tutorial.

Edit September 21, 2014: Added some more steps to the code in spec06_config.py and fixed ARGC check in the run_gem5_alpha_spec06_benchmark.sh file based on feedback from a reader. Thanks and keep the feedback coming!

Edit September 28, 2014: Minor edits that don’t affect correctness of the tutorial.

Edit June 7, 2017: Changed LiveProcess() to Process() in spec06_benchmarks.py to suit newer versions of gem5. Thanks Wenbo for the suggestion!

Note
Some of the source code snippets below might not fit in the page width, and it does not wrap. If this happens, make sure you scroll to the right to see all the code.

The SPEC CPU2006 benchmarks come nicely wrapped out of:q the box with the runspec utility which makes benchmarking systems easier for most users, and helps to ensure valid results across systems. However, this utility doesn’t work when we want to run the workloads in the simulator for two reasons. First, we cross-compiled the benchmarks for Alpha, which means we can’t test the benchmarks on the host system using runspec, unless we are actually running an Alpha box (which is unlikely). Second, gem5 wants a regular application binary input as well as some command-line arguments. To get these, you have to dig pretty deep into the SPEC CPU2006 runspec utility and other wrappers to see exactly how each binary is called.

For example, if you were to run the perlbench SPEC CPU2006 benchmark directly on your host system, you’d do something like this:

runspec --config=my-alpha-hack.cfg --size=ref --noreportable --tune=base --iterations=1 perlbench

If you look into what runspec actually does here, it eventually make a call to the perlbench binary in this sort of manner:

cd $PATH_TO_YOUR_SPEC_CPU2006_INSTALL/benchspec/CPU2006/400.perlbench/run/run_base_ref_my-alpha.0000
perlbench_base.my-alpha -I./lib checkspam.pl 2500 5 25 11 150 1 1 1 1

Basically, all we need to do to get the benchmarks running in gem5 is to somehow get this command line fed into the simulator. This can be a pain, because each benchmark has a long annoying path, and has multiple possible input data sets.

To solve this, I recommend modifying the Python scripts in the gem5 configuration to allow easy programmatic execution of the different benchmarks. Assuming we are running the simulator in system call emulation mode, we will modify the example se.py configuration script to suit our needs. Basically, we will make it so you can run gem5 with individual SPEC CPU2006 benchmarks like this:

cd $PATH_TO_YOUR_GEM5_INSTALL
build/ALPHA/gem5.opt configs/example/spec06_config.py $YOUR_NORMAL_GEM5_CONFIG_PARAMETERS_HERE --benchmark=perlbench

Note the use of the spec06_config.py configuration. This doesn’t exist in the gem5 distribution, so we will have to make it ourselves!

cd $PATH_TO_YOUR_GEM5_INSTALL/configs/example
cp se.py spec06_config.py

Using your favorite text editor of choice (which should be vim! :D), open the new configuration file you created.

At the top, add the following line (don’t worry, we will create spec06_benchmarks.py soon!):

import spec06_benchmarks

Then navigate to the point right after the script adds common options and system call emulation mode options:

# ...snip...
parser = optparse.OptionParser()
Options.addCommonOptions(parser)
Options.addSEOptions(parser)

# NAVIGATE TO THIS POINT

# ...snip...

At this spot, add a new Python command-line parser option to easily pass the benchmark name as the input to the simulator.

parser.add_option("-b", "--benchmark", type="string", default="", help="The SPEC benchmark to be loaded.")
parser.add_option("--benchmark_stdout", type="string", default="", help="Absolute path for stdout redirection for the benchmark.")
parser.add_option("--benchmark_stderr", type="string", default="", help="Absolute path for stderr redirection for the benchmark.")

Now that we have the command line option now it’s time to do something useful with it! Somewhere in the script below the new option you added, and above the part where it sets up process to CPU mappings, we need to do some basic decoding of the input to select the proper benchmark.

At the part in the script where it initializes the multiprocessing and threads part, override it so it is single process, single thread (all SPEC CPU2006 benchmarks are single-thread single apps):

# multiprocesses = []
numThreads = 1

Add these new lines to the script below the numThreads = 1 part:

if options.benchmark:
	print 'Selected SPEC_CPU2006 benchmark'
	if options.benchmark == 'perlbench':
		print '--> perlbench'
		process = spec06_benchmarks.perlbench
	elif options.benchmark == 'bzip2':
		print '--> bzip2'
		process = spec06_benchmarks.bzip2
	elif options.benchmark == 'gcc':
		print '--> gcc'
		process = spec06_benchmarks.gcc
	elif options.benchmark == 'bwaves':
		print '--> bwaves'
		process = spec06_benchmarks.bwaves
	elif options.benchmark == 'gamess':
		print '--> gamess'
		process = spec06_benchmarks.gamess
	elif options.benchmark == 'mcf':
		print '--> mcf'
		process = spec06_benchmarks.mcf
	elif options.benchmark == 'milc':
		print '--> milc'
		process = spec06_benchmarks.milc
	elif options.benchmark == 'zeusmp':
		print '--> zeusmp'
		process = spec06_benchmarks.zeusmp
	elif options.benchmark == 'gromacs':
		print '--> gromacs'
		process = spec06_benchmarks.gromacs
	elif options.benchmark == 'cactusADM':
		print '--> cactusADM'
		process = spec06_benchmarks.cactusADM
	elif options.benchmark == 'leslie3d':
		print '--> leslie3d'
		process = spec06_benchmarks.leslie3d
	elif options.benchmark == 'namd':
		print '--> namd'
		process = spec06_benchmarks.namd
	elif options.benchmark == 'gobmk':
		print '--> gobmk'
		process = spec06_benchmarks.gobmk
	elif options.benchmark == 'dealII':
		print '--> dealII'
		process = spec06_benchmarks.dealII
	elif options.benchmark == 'soplex':
		print '--> soplex'
		process = spec06_benchmarks.soplex
	elif options.benchmark == 'povray':
		print '--> povray'
		process = spec06_benchmarks.povray
	elif options.benchmark == 'calculix':
		print '--> calculix'
		process = spec06_benchmarks.calculix
	elif options.benchmark == 'hmmer':
		print '--> hmmer'
		process = spec06_benchmarks.hmmer
	elif options.benchmark == 'sjeng':
		print '--> sjeng'
		process = spec06_benchmarks.sjeng
	elif options.benchmark == 'GemsFDTD':
		print '--> GemsFDTD'
		process = spec06_benchmarks.GemsFDTD
	elif options.benchmark == 'libquantum':
		print '--> libquantum'
		process = spec06_benchmarks.libquantum
	elif options.benchmark == 'h264ref':
		print '--> h264ref'
		process = spec06_benchmarks.h264ref
	elif options.benchmark == 'tonto':
		print '--> tonto'
		process = spec06_benchmarks.tonto
	elif options.benchmark == 'lbm':
		print '--> lbm'
		process = spec06_benchmarks.lbm
	elif options.benchmark == 'omnetpp':
		print '--> omnetpp'
		process = spec06_benchmarks.omnetpp
	elif options.benchmark == 'astar':
		print '--> astar'
		process = spec06_benchmarks.astar
	elif options.benchmark == 'wrf':
		print '--> wrf'
		process = spec06_benchmarks.wrf
	elif options.benchmark == 'sphinx3':
		print '--> sphinx3'
		process = spec06_benchmarks.sphinx3
	elif options.benchmark == 'xalancbmk':
		print '--> xalancbmk'
		process = spec06_benchmarks.xalancbmk
	elif options.benchmark == 'specrand_i':
		print '--> specrand_i'
		process = spec06_benchmarks.specrand_i
	elif options.benchmark == 'specrand_f':
		print '--> specrand_f'
		process = spec06_benchmarks.specrand_f
	else:
		print "No recognized SPEC2006 benchmark selected! Exiting."
		sys.exit(1)
else:
    print >> sys.stderr, "Need --benchmark switch to specify SPEC CPU2006 workload. Exiting!\n"
    sys.exit(1)

# Set process stdout/stderr
if options.benchmark_stdout:
	process.output = options.benchmark_stdout
	print "Process stdout file: " + process.output
if options.benchmark_stderr:
	process.errout = options.benchmark_stderr
	print "Process stderr file: " + process.errout

Then comment out this bit of code in spec06_config.py:

# if options.bench:
#     apps = options.bench.split("-")
#     if len(apps) != options.num_cpus:
#         print "number of benchmarks not equal to set num_cpus!"
#         sys.exit(1)
#
#     for app in apps:
#         try:
#             if buildEnv['TARGET_ISA'] == 'alpha':
#                 exec("workload = %s('alpha', 'tru64', '%s')" % (
#                         app, options.spec_input))
#             elif buildEnv['TARGET_ISA'] == 'arm':
#                 exec("workload = %s('arm_%s', 'linux', '%s')" % (
#                         app, options.arm_iset, options.spec_input))
#             else:
#                 exec("workload = %s(buildEnv['TARGET_ISA', 'linux', '%s')" % (
#                         app, options.spec_input))
#             multiprocesses.append(workload.makeProcess()) # Update June 7, 2017: this used to be workload.makeLiveProcess()
#         except:
#             print >>sys.stderr, "Unable to find workload for %s: %s" % (
#                     buildEnv['TARGET_ISA'], app)
#             sys.exit(1)
# elif options.cmd:
#     multiprocesses, numThreads = get_processes(options)
# else:
#     print >> sys.stderr, "No workload specified. Exiting!\n"
#     sys.exit(1)

And comment this out:

# for i in xrange(np):
#     if options.smt:
#         system.cpu[i].workload = multiprocesses
#     elif len(multiprocesses) == 1:
#         system.cpu[i].workload = multiprocesses[0]
#     else:
#         system.cpu[i].workload = multiprocesses[i]
#
#     if options.fastmem:
#         system.cpu[i].fastmem = True
#
#     if options.simpoint_profile:
#         system.cpu[i].simpoint_profile = True
#         system.cpu[i].simpoint_interval = options.simpoint_interval
#
#     if options.checker:
#         system.cpu[i].addCheckerCpu()
#
#     system.cpu[i].createThreads()

And add this below the latter commented part:

for i in xrange(np):
	system.cpu[i].workload = process
	print process.cmd

Now we are done with spec06_config.py. Let’s create the spec06_benchmarks.py file.

touch $PATH_TO_YOUR_GEM5_INSTALL/configs/example/spec06_benchmarks.py

Paste the following code into spec06_benchmarks.py. The code isn’t polished, but it worked for me to get running quickly. Note that for each benchmark there are multiple possible command line arguments (inputs). For each gem5 run I only use one benchmark with one input. With this code, by default each benchmark will use the first reference input. If you wish to use a different one, simply swap the appropriate commented lines for that benchmark.

Also note that I was not able to get every benchmark working for various reasons that I forgot (I did this over a year ago). Those are marked in the source below. You can probably hack a quick fix.

import m5
from m5.objects import *

# These three directory paths are not currently used.
#gem5_dir = '<FULL_PATH_TO_YOUR_GEM5_INSTALL>'
#spec_dir = '<FULL_PATH_TO_YOUR_SPEC_CPU2006_INSTALL>'
#out_dir = '<FULL_PATH_TO_DESIRED_OUTPUT_DIRECTORY>'

alpha_suffix = '_base.my-alpha'

#temp
#binary_dir = spec_dir
#data_dir = spec_dir

#400.perlbench
perlbench = Process() # Update June 7, 2017: This used to be LiveProcess()
perlbench.executable =  'perlbench' + alpha_suffix
# TEST CMDS
#perlbench.cmd = [perlbench.executable] + ['-I.', '-I./lib', 'attrs.pl']
# REF CMDS
perlbench.cmd = [perlbench.executable] + ['-I./lib', 'checkspam.pl', '2500', '5', '25', '11', '150', '1', '1', '1', '1']
#perlbench.cmd = [perlbench.executable] + ['-I./lib', 'diffmail.pl', '4', '800', '10', '17', '19', '300']
#perlbench.cmd = [perlbench.executable] + ['-I./lib', 'splitmail.pl', '1600', '12', '26', '16', '4500']
#perlbench.output = out_dir+'perlbench.out'

#401.bzip2
bzip2 = Process() # Update June 7, 2017: This used to be LiveProcess()
bzip2.executable =  'bzip2' + alpha_suffix
# TEST CMDS
#bzip2.cmd = [bzip2.executable] + ['input.program', '5']
# REF CMDS
bzip2.cmd = [bzip2.executable] + ['input.source', '280']
#bzip2.cmd = [bzip2.executable] + ['chicken.jpg', '30']
#bzip2.cmd = [bzip2.executable] + ['liberty.jpg', '30']
#bzip2.cmd = [bzip2.executable] + ['input.program', '280']
#bzip2.cmd = [bzip2.executable] + ['text.html', '280']
#bzip2.cmd = [bzip2.executable] + ['input.combined', '200']
#bzip2.output = out_dir + 'bzip2.out'

#403.gcc
gcc = Process() # Update June 7, 2017: This used to be LiveProcess()
gcc.executable = 'gcc' + alpha_suffix
# TEST CMDS
#gcc.cmd = [gcc.executable] + ['cccp.i', '-o', 'cccp.s']
# REF CMDS
gcc.cmd = [gcc.executable] + ['166.i', '-o', '166.s']
#gcc.cmd = [gcc.executable] + ['200.i', '-o', '200.s']
#gcc.cmd = [gcc.executable] + ['c-typeck.i', '-o', 'c-typeck.s']
#gcc.cmd = [gcc.executable] + ['cp-decl.i', '-o', 'cp-decl.s']
#gcc.cmd = [gcc.executable] + ['expr.i', '-o', 'expr.s']
#gcc.cmd = [gcc.executable] + ['expr2.i', '-o', 'expr2.s']
#gcc.cmd = [gcc.executable] + ['g23.i', '-o', 'g23.s']
#gcc.cmd = [gcc.executable] + ['s04.i', '-o', 's04.s']
#gcc.cmd = [gcc.executable] + ['scilab.i', '-o', 'scilab.s']
#gcc.output = out_dir + 'gcc.out'

#410.bwaves
bwaves = Process() # Update June 7, 2017: This used to be LiveProcess()
bwaves.executable = 'bwaves' + alpha_suffix
# TEST CMDS
#bwaves.cmd = [bwaves.executable]
# REF CMDS
bwaves.cmd = [bwaves.executable]
#bwaves.output = out_dir + 'bwaves.out'

#416.gamess
gamess = Process() # Update June 7, 2017: This used to be LiveProcess()
gamess.executable = 'gamess' + alpha_suffix
# TEST CMDS
#gamess.cmd = [gamess.executable]
#gamess.input = 'exam29.config'
# REF CMDS
gamess.cmd = [gamess.executable]
gamess.input = 'cytosine.2.config'
#gamess.cmd = [gamess.executable]
#gamess.input = 'h2ocu2+.gradient.config'
#gamess.cmd = [gamess.executable]
#gamess.input = 'triazolium.config'
#gamess.output = out_dir + 'gamess.out'

#429.mcf
mcf = Process() # Update June 7, 2017: This used to be LiveProcess()
mcf.executable =  'mcf' + alpha_suffix
# TEST CMDS
#mcf.cmd = [mcf.executable] + ['inp.in']
# REF CMDS
mcf.cmd = [mcf.executable] + ['inp.in']
#mcf.output = out_dir + 'mcf.out'

#433.milc
milc = Process() # Update June 7, 2017: This used to be LiveProcess()
milc.executable = 'milc' + alpha_suffix
# TEST CMDS
#milc.cmd = [milc.executable]
#milc.input = 'su3imp.in'
# REF CMDS
milc.cmd = [milc.executable]
milc.input = 'su3imp.in'
#milc.output = out_dir + 'milc.out'

#434.zeusmp
zeusmp = Process() # Update June 7, 2017: This used to be LiveProcess()
zeusmp.executable = 'zeusmp' + alpha_suffix
# TEST CMDS
#zeusmp.cmd = [zeusmp.executable]
# REF CMDS
zeusmp.cmd = [zeusmp.executable]
#zeusmp.output = out_dir + 'zeusmp.out'

#435.gromacs
gromacs = Process() # Update June 7, 2017: This used to be LiveProcess()
gromacs.executable = 'gromacs' + alpha_suffix
# TEST CMDS
#gromacs.cmd = [gromacs.executable] + ['-silent','-deffnm', 'gromacs', '-nice','0']
# REF CMDS
gromacs.cmd = [gromacs.executable] + ['-silent','-deffnm', 'gromacs', '-nice','0']
#gromacs.output = out_dir + 'gromacs.out'

#436.cactusADM
cactusADM = Process() # Update June 7, 2017: This used to be LiveProcess()
cactusADM.executable = 'cactusADM' + alpha_suffix
# TEST CMDS
#cactusADM.cmd = [cactusADM.executable] + ['benchADM.par']
# REF CMDS
cactusADM.cmd = [cactusADM.executable] + ['benchADM.par']
#cactusADM.output = out_dir + 'cactusADM.out'

#437.leslie3d
leslie3d = Process() # Update June 7, 2017: This used to be LiveProcess()
leslie3d.executable = 'leslie3d' + alpha_suffix
# TEST CMDS
#leslie3d.cmd = [leslie3d.executable]
#leslie3d.input = 'leslie3d.in'
# REF CMDS
leslie3d.cmd = [leslie3d.executable]
leslie3d.input = 'leslie3d.in'
#leslie3d.output = out_dir + 'leslie3d.out'

#444.namd
namd = Process() # Update June 7, 2017: This used to be LiveProcess()
namd.executable = 'namd' + alpha_suffix
# TEST CMDS
#namd.cmd = [namd.executable] + ['--input', 'namd.input', '--output', 'namd.out', '--iterations', '1']
# REF CMDS
namd.cmd = [namd.executable] + ['--input', 'namd.input', '--output', 'namd.out', '--iterations', '38']
#namd.output = out_dir + 'namd.out'

#445.gobmk
gobmk = Process() # Update June 7, 2017: This used to be LiveProcess()
gobmk.executable = 'gobmk' + alpha_suffix
# TEST CMDS
#gobmk.cmd = [gobmk.executable] + ['--quiet','--mode', 'gtp']
#gobmk.input = 'dniwog.tst'
# REF CMDS
gobmk.cmd = [gobmk.executable] + ['--quiet','--mode', 'gtp']
gobmk.input = '13x13.tst'
#gobmk.cmd = [gobmk.executable] + ['--quiet','--mode', 'gtp']
#gobmk.input = 'nngs.tst'
#gobmk.cmd = [gobmk.executable] + ['--quiet','--mode', 'gtp']
#gobmk.input = 'score2.tst'
#gobmk.cmd = [gobmk.executable] + ['--quiet','--mode', 'gtp']
#gobmk.input = 'trevorc.tst'
#gobmk.cmd = [gobmk.executable] + ['--quiet','--mode', 'gtp']
#gobmk.input = 'trevord.tst'
#gobmk.output = out_dir + 'gobmk.out'

#447.dealII
####### NOT WORKING #########
dealII = Process() # Update June 7, 2017: This used to be LiveProcess()
dealII.executable = 'dealII' + alpha_suffix
# TEST CMDS
####### NOT WORKING #########
#dealII.cmd = [gobmk.executable]+['8']
# REF CMDS
####### NOT WORKING #########
#dealII.output = out_dir + 'dealII.out'

#450.soplex
soplex = Process() # Update June 7, 2017: This used to be LiveProcess()
soplex.executable = 'soplex' + alpha_suffix
# TEST CMDS
#soplex.cmd = [soplex.executable] + ['-m10000', 'test.mps']
# REF CMDS
soplex.cmd = [soplex.executable] + ['-m45000', 'pds-50.mps']
#soplex.cmd = [soplex.executable] + ['-m3500', 'ref.mps']
#soplex.output = out_dir + 'soplex.out'

#453.povray
povray = Process() # Update June 7, 2017: This used to be LiveProcess()
povray.executable = 'povray' + alpha_suffix
# TEST CMDS
#povray.cmd = [povray.executable] + ['SPEC-benchmark-test.ini']
# REF CMDS
povray.cmd = [povray.executable] + ['SPEC-benchmark-ref.ini']
#povray.output = out_dir + 'povray.out'

#454.calculix
calculix = Process() # Update June 7, 2017: This used to be LiveProcess()
calculix.executable = 'calculix' + alpha_suffix
# TEST CMDS
#calculix.cmd = [calculix.executable] + ['-i', 'beampic']
# REF CMDS
calculix.cmd = [calculix.executable] + ['-i', 'hyperviscoplastic']
#calculix.output = out_dir + 'calculix.out'

#456.hmmer
hmmer = Process() # Update June 7, 2017: This used to be LiveProcess()
hmmer.executable = 'hmmer' + alpha_suffix
# TEST CMDS
#hmmer.cmd = [hmmer.executable] + ['--fixed', '0', '--mean', '325', '--num', '45000', '--sd', '200', '--seed', '0', 'bombesin.hmm']
# REF CMDS
hmmer.cmd = [hmmer.executable] + ['nph3.hmm', 'swiss41']
#hmmer.cmd = [hmmer.executable] + ['--fixed', '0', '--mean', '500', '--num', '500000', '--sd', '350', '--seed', '0', 'retro.hmm']
#hmmer.output = out_dir + 'hmmer.out'

#458.sjeng
sjeng = Process() # Update June 7, 2017: This used to be LiveProcess()
sjeng.executable = 'sjeng' + alpha_suffix
# TEST CMDS
#sjeng.cmd = [sjeng.executable] + ['test.txt']
# REF CMDS
sjeng.cmd = [sjeng.executable] + ['ref.txt']
#sjeng.output = out_dir + 'sjeng.out'

#459.GemsFDTD
GemsFDTD = Process() # Update June 7, 2017: This used to be LiveProcess()
GemsFDTD.executable = 'GemsFDTD' + alpha_suffix
# TEST CMDS
#GemsFDTD.cmd = [GemsFDTD.executable]
# REF CMDS
GemsFDTD.cmd = [GemsFDTD.executable]
#GemsFDTD.output = out_dir + 'GemsFDTD.out'

#462.libquantum
libquantum = Process() # Update June 7, 2017: This used to be LiveProcess()
libquantum.executable = 'libquantum' + alpha_suffix
# TEST CMDS
#libquantum.cmd = [libquantum.executable] + ['33','5']
# REF CMDS [UPDATE 10/2/2015]: Sparsh Mittal has pointed out the correct input for libquantum should be 1397 and 8, not 1297 and 8. Thanks!
libquantum.cmd = [libquantum.executable] + ['1397','8']
#libquantum.output = out_dir + 'libquantum.out'

#464.h264ref
h264ref = Process() # Update June 7, 2017: This used to be LiveProcess()
h264ref.executable = 'h264ref' + alpha_suffix
# TEST CMDS
#h264ref.cmd = [h264ref.executable] + ['-d', 'foreman_test_encoder_baseline.cfg']
# REF CMDS
h264ref.cmd = [h264ref.executable] + ['-d', 'foreman_ref_encoder_baseline.cfg']
#h264ref.cmd = [h264ref.executable] + ['-d', 'foreman_ref_encoder_main.cfg']
#h264ref.cmd = [h264ref.executable] + ['-d', 'sss_encoder_main.cfg']
#h264ref.output = out_dir + 'h264ref.out'

#465.tonto
tonto = Process() # Update June 7, 2017: This used to be LiveProcess()
tonto.executable = 'tonto' + alpha_suffix
# TEST CMDS
#tonto.cmd = [tonto.executable]
# REF CMDS
tonto.cmd = [tonto.executable]
#tonto.output = out_dir + 'tonto.out'

#470.lbm
lbm = Process() # Update June 7, 2017: This used to be LiveProcess()
lbm.executable = 'lbm' + alpha_suffix
# TEST CMDS
#lbm.cmd = [lbm.executable] + ['20', 'reference.dat', '0', '1', '100_100_130_cf_a.of']
# REF CMDS
lbm.cmd = [lbm.executable] + ['300', 'reference.dat', '0', '0', '100_100_130_ldc.of']
#lbm.output = out_dir + 'lbm.out'

#471.omnetpp
omnetpp = Process() # Update June 7, 2017: This used to be LiveProcess()
omnetpp.executable = 'omnetpp' + alpha_suffix
# TEST CMDS
#omnetpp.cmd = [omnetpp.executable] + ['omnetpp.ini']
# REF CMDS
omnetpp.cmd = [omnetpp.executable] + ['omnetpp.ini']
#omnetpp.output = out_dir + 'omnetpp.out'

#473.astar
astar = Process() # Update June 7, 2017: This used to be LiveProcess()
astar.executable = 'astar' + alpha_suffix
# TEST CMDS
#astar.cmd = [astar.executable] + ['lake.cfg']
# REF CMDS
astar.cmd = [astar.executable] + ['rivers.cfg']
#astar.output = out_dir + 'astar.out'

#481.wrf
wrf = Process() # Update June 7, 2017: This used to be LiveProcess()
wrf.executable = 'wrf' + alpha_suffix
# TEST CMDS
#wrf.cmd = [wrf.executable]
# REF CMDS
wrf.cmd = [wrf.executable]
#wrf.output = out_dir + 'wrf.out'

#482.sphinx3
sphinx3 = Process() # Update June 7, 2017: This used to be LiveProcess()
sphinx3.executable = 'sphinx_livepretend' + alpha_suffix
# TEST CMDS
#sphinx3.cmd = [sphinx3.executable] + ['ctlfile', '.', 'args.an4']
# REF CMDS
sphinx3.cmd = [sphinx3.executable] + ['ctlfile', '.', 'args.an4']
#sphinx3.output = out_dir + 'sphinx3.out'

#483.xalancbmk
######## NOT WORKING ###########
xalancbmk = Process() # Update June 7, 2017: This used to be LiveProcess()
xalancbmk.executable = 'xalancbmk' + alpha_suffix
# TEST CMDS
######## NOT WORKING ###########
#xalancbmk.cmd = [xalancbmk.executable] + ['-v','test.xml','xalanc.xsl']
# REF CMDS
######## NOT WORKING ###########
#xalancbmk.output = out_dir + 'xalancbmk.out'

#998.specrand
specrand_i = Process() # Update June 7, 2017: This used to be LiveProcess()
specrand_i.executable = 'specrand' + alpha_suffix
# TEST CMDS
#specrand_i.cmd = [specrand_i.executable] + ['324342', '24239']
# REF CMDS
specrand_i.cmd = [specrand_i.executable] + ['1255432124', '234923']
#specrand_i.output = out_dir + 'specrand_i.out'

#999.specrand
specrand_f = Process() # Update June 7, 2017: This used to be LiveProcess()
specrand_f.executable = 'specrand' + alpha_suffix
# TEST CMDS
#specrand_f.cmd = [specrand_f.executable] + ['324342', '24239']
# REF CMDS
specrand_f.cmd = [specrand_f.executable] + ['1255432124', '234923']
#specrand_f.output = out_dir + 'specrand_f.out'

However, we still have a problem: gem5 does not know the path to the SPEC binary and its input. I solved it using a wrapper shell script around the gem5 call. I’ve provided the full script here.

Create a new file wherever you’d like to launch the simulator. This will probably be in the root directory of the gem5 installation.

cd $PATH_TO_YOUR_GEM5_INSTALL
touch run_gem5_alpha_spec06_benchmark.sh

Paste the following code into run_gem5_alpha_spec06_benchmark.sh:

#!/bin/bash
#
# run_gem5_alpha_spec06_benchmark.sh
# Author: Mark Gottscho Email: mgottscho@ucla.edu
# Copyright (C) 2014 Mark Gottscho
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.


############ DIRECTORY VARIABLES: MODIFY ACCORDINGLY #############
GEM5_DIR=<PATH_TO_YOUR_GEM5_INSTALL>							# Install location of gem5
SPEC_DIR=<PATH_TO_YOUR_SPEC_CPU2006_INSTALL>					# Install location of your SPEC2006 benchmarks
##################################################################

ARGC=$# # Get number of arguments excluding arg0 (the script itself). Check for help message condition.
if [[ "$ARGC" != 2 ]]; then # Bad number of arguments.
 	echo "run_gem5_alpha_spec06_benchmark.sh  Copyright (C) 2014 Mark Gottscho"
   echo "This program comes with ABSOLUTELY NO WARRANTY; for details see <https://www.gnu.org/licenses/>."
   echo "This is free software, and you are welcome to redistribute it under certain conditions; see <https://www.gnu.org/licenses/> for details."
   echo ""
	echo "Author: Mark Gottscho"
	echo "mgottscho@ucla.edu"
	echo ""
	echo "This script runs a single gem5 simulation of a single SPEC CPU2006 benchmark for Alpha ISA."
	echo ""
	echo "USAGE: run_gem5_alpha_spec06_benchmark.sh <BENCHMARK> <OUTPUT_DIR>"
	echo "EXAMPLE: ./run_gem5_alpha_spec06_benchmark.sh bzip2 /FULL/PATH/TO/output_dir"
	echo ""
	echo "A single --help help or -h argument will bring this message back."
	exit
fi

# Get command line input. We will need to check these.
BENCHMARK=$1					# Benchmark name, e.g. bzip2
OUTPUT_DIR=$2					# Directory to place run output. Make sure this exists!

######################### BENCHMARK CODENAMES ####################
PERLBENCH_CODE=400.perlbench
BZIP2_CODE=401.bzip2
GCC_CODE=403.gcc
BWAVES_CODE=410.bwaves
GAMESS_CODE=416.gamess
MCF_CODE=429.mcf
MILC_CODE=433.milc
ZEUSMP_CODE=434.zeusmp
GROMACS_CODE=435.gromacs
CACTUSADM_CODE=436.cactusADM
LESLIE3D_CODE=437.leslie3d
NAMD_CODE=444.namd
GOBMK_CODE=445.gobmk
DEALII_CODE=447.dealII
SOPLEX_CODE=450.soplex
POVRAY_CODE=453.povray
CALCULIX_CODE=454.calculix
HMMER_CODE=456.hmmer
SJENG_CODE=458.sjeng
GEMSFDTD_CODE=459.GemsFDTD
LIBQUANTUM_CODE=462.libquantum
H264REF_CODE=464.h264ref
TONTO_CODE=465.tonto
LBM_CODE=470.lbm
OMNETPP_CODE=471.omnetpp
ASTAR_CODE=473.astar
WRF_CODE=481.wrf
SPHINX3_CODE=482.sphinx3
XALANCBMK_CODE=483.xalancbmk
SPECRAND_INT_CODE=998.specrand
SPECRAND_FLOAT_CODE=999.specrand
##################################################################

# Check BENCHMARK input
#################### BENCHMARK CODE MAPPING ######################
BENCHMARK_CODE="none"

if [[ "$BENCHMARK" == "perlbench" ]]; then
	BENCHMARK_CODE=$PERLBENCH_CODE
fi
if [[ "$BENCHMARK" == "bzip2" ]]; then
	BENCHMARK_CODE=$BZIP2_CODE
fi
if [[ "$BENCHMARK" == "gcc" ]]; then
	BENCHMARK_CODE=$GCC_CODE
fi
if [[ "$BENCHMARK" == "bwaves" ]]; then
	BENCHMARK_CODE=$BWAVES_CODE
fi
if [[ "$BENCHMARK" == "gamess" ]]; then
	BENCHMARK_CODE=$GAMESS_CODE
fi
if [[ "$BENCHMARK" == "mcf" ]]; then
	BENCHMARK_CODE=$MCF_CODE
fi
if [[ "$BENCHMARK" == "milc" ]]; then
	BENCHMARK_CODE=$MILC_CODE
fi
if [[ "$BENCHMARK" == "zeusmp" ]]; then
	BENCHMARK_CODE=$ZEUSMP_CODE
fi
if [[ "$BENCHMARK" == "gromacs" ]]; then
	BENCHMARK_CODE=$GROMACS_CODE
fi
if [[ "$BENCHMARK" == "cactusADM" ]]; then
	BENCHMARK_CODE=$CACTUSADM_CODE
fi
if [[ "$BENCHMARK" == "leslie3d" ]]; then
	BENCHMARK_CODE=$LESLIE3D_CODE
fi
if [[ "$BENCHMARK" == "namd" ]]; then
	BENCHMARK_CODE=$NAMD_CODE
fi
if [[ "$BENCHMARK" == "gobmk" ]]; then
	BENCHMARK_CODE=$GOBMK_CODE
fi
if [[ "$BENCHMARK" == "dealII" ]]; then # DOES NOT WORK
	BENCHMARK_CODE=$DEALII_CODE
fi
if [[ "$BENCHMARK" == "soplex" ]]; then
	BENCHMARK_CODE=$SOPLEX_CODE
fi
if [[ "$BENCHMARK" == "povray" ]]; then
	BENCHMARK_CODE=$POVRAY_CODE
fi
if [[ "$BENCHMARK" == "calculix" ]]; then
	BENCHMARK_CODE=$CALCULIX_CODE
fi
if [[ "$BENCHMARK" == "hmmer" ]]; then
	BENCHMARK_CODE=$HMMER_CODE
fi
if [[ "$BENCHMARK" == "sjeng" ]]; then
	BENCHMARK_CODE=$SJENG_CODE
fi
if [[ "$BENCHMARK" == "GemsFDTD" ]]; then
	BENCHMARK_CODE=$GEMSFDTD_CODE
fi
if [[ "$BENCHMARK" == "libquantum" ]]; then
	BENCHMARK_CODE=$LIBQUANTUM_CODE
fi
if [[ "$BENCHMARK" == "h264ref" ]]; then
	BENCHMARK_CODE=$H264REF_CODE
fi
if [[ "$BENCHMARK" == "tonto" ]]; then
	BENCHMARK_CODE=$TONTO_CODE
fi
if [[ "$BENCHMARK" == "lbm" ]]; then
	BENCHMARK_CODE=$LBM_CODE
fi
if [[ "$BENCHMARK" == "omnetpp" ]]; then
	BENCHMARK_CODE=$OMNETPP_CODE
fi
if [[ "$BENCHMARK" == "astar" ]]; then
	BENCHMARK_CODE=$ASTAR_CODE
fi
if [[ "$BENCHMARK" == "wrf" ]]; then
	BENCHMARK_CODE=$WRF_CODE
fi
if [[ "$BENCHMARK" == "sphinx3" ]]; then
	BENCHMARK_CODE=$SPHINX3_CODE
fi
if [[ "$BENCHMARK" == "xalancbmk" ]]; then # DOES NOT WORK
	BENCHMARK_CODE=$XALANCBMK_CODE
fi
if [[ "$BENCHMARK" == "specrand_i" ]]; then
	BENCHMARK_CODE=$SPECRAND_INT_CODE
fi
if [[ "$BENCHMARK" == "specrand_f" ]]; then
	BENCHMARK_CODE=$SPECRAND_FLOAT_CODE
fi

# Sanity check
if [[ "$BENCHMARK_CODE" == "none" ]]; then
	echo "Input benchmark selection $BENCHMARK did not match any known SPEC CPU2006 benchmarks! Exiting."
	exit 1
fi
##################################################################

# Check OUTPUT_DIR existence
if [[ !(-d "$OUTPUT_DIR") ]]; then
	echo "Output directory $OUTPUT_DIR does not exist! Exiting."
	exit 1
fi

RUN_DIR=$SPEC_DIR/benchspec/CPU2006/$BENCHMARK_CODE/run/run_base_ref\_my-alpha.0000		# Run directory for the selected SPEC benchmark
SCRIPT_OUT=$OUTPUT_DIR/runscript.log																	# File log for this script's stdout henceforth

################## REPORT SCRIPT CONFIGURATION ###################

echo "Command line:"								| tee $SCRIPT_OUT
echo "$0 $*"										| tee -a $SCRIPT_OUT
echo "================= Hardcoded directories ==================" | tee -a $SCRIPT_OUT
echo "GEM5_DIR:                                     $GEM5_DIR" | tee -a $SCRIPT_OUT
echo "SPEC_DIR:                                     $SPEC_DIR" | tee -a $SCRIPT_OUT
echo "==================== Script inputs =======================" | tee -a $SCRIPT_OUT
echo "BENCHMARK:                                    $BENCHMARK" | tee -a $SCRIPT_OUT
echo "OUTPUT_DIR:                                   $OUTPUT_DIR" | tee -a $SCRIPT_OUT
echo "==========================================================" | tee -a $SCRIPT_OUT
##################################################################


#################### LAUNCH GEM5 SIMULATION ######################
echo ""
echo "Changing to SPEC benchmark runtime directory:	$RUN_DIR" | tee -a $SCRIPT_OUT
cd $RUN_DIR

echo "" | tee -a $SCRIPT_OUT
echo "" | tee -a $SCRIPT_OUT
echo "--------- Here goes nothing! Starting gem5! ------------" | tee -a $SCRIPT_OUT
echo "" | tee -a $SCRIPT_OUT
echo "" | tee -a $SCRIPT_OUT

# Actually launch gem5!
$GEM5_DIR/build/ALPHA/gem5.opt --outdir=$OUTPUT_DIR $GEM5_DIR/configs/example/spec06_config.py --benchmark=$BENCHMARK --benchmark_stdout=$OUTPUT_DIR/$BENCHMARK.out --benchmark_stderr=$OUTPUT_DIR/$BENCHMARK.err <YOUR_SIMULATOR_OPTIONS_HERE> | tee -a $SCRIPT_OUT

With all this code in place, all you should need to do now is to run gem5 like so:

cd $PATH_TO_YOUR_GEM5_INSTALL
./run_gem5_alpha_spec06_benchmark.sh <BENCHMARK_NAME> <FULL_PATH_TO_OUTPUT_DIRECTORY>

That’s it! If you have problems getting this to work, please feel free to respond to this post. Furthermore, if you find a bug in this code, please post as well so it can be fixed for others. I have modified the scripts somewhat in order to remove content directly related to conducting my research, so I may have left out something important. If you found this post helpful, please share it with others who would benefit. Finally, if you have any requests for other computer engineering and/or research-related tutorials, please feel free to contact me. Happy simulating! =]

comments powered by Disqus