X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=configs%2Fcommon%2FSimulation.py;h=e53c755c6c09e1e5528158eaa29966641cd1a8bc;hb=e53de444f665fcb406c75648674ddc4224127515;hp=434fe8369c274c87a27f7cb0c84d795aed6c8684;hpb=03229f25759898ea2f82ef3e4fe761c452a49701;p=gem5.git diff --git a/configs/common/Simulation.py b/configs/common/Simulation.py index 434fe8369..e53c755c6 100644 --- a/configs/common/Simulation.py +++ b/configs/common/Simulation.py @@ -1,3 +1,15 @@ +# Copyright (c) 2012-2013 ARM Limited +# All rights reserved +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # Copyright (c) 2006-2008 The Regents of The University of Michigan # Copyright (c) 2010 Advanced Micro Devices, Inc. # All rights reserved. @@ -24,69 +36,402 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Authors: Lisa Hsu +from __future__ import print_function +from __future__ import absolute_import + +import six +import sys from os import getcwd from os.path import join as joinpath +from common import CpuConfig +from common import ObjectList + import m5 from m5.defines import buildEnv from m5.objects import * from m5.util import * +if six.PY3: + long = int + addToPath('../common') +def getCPUClass(cpu_type): + """Returns the required cpu class and the mode of operation.""" + cls = ObjectList.cpu_list.get(cpu_type) + return cls, cls.memory_mode() + def setCPUClass(options): + """Returns two cpu classes and the initial mode of operation. - atomic = False - if options.cpu_type == "timing": - class TmpClass(TimingSimpleCPU): pass - elif options.cpu_type == "detailed": - if not options.caches: - print "O3 CPU must be used with caches" - sys.exit(1) - class TmpClass(DerivO3CPU): pass - elif options.cpu_type == "inorder": - if not options.caches: - print "InOrder CPU must be used with caches" - sys.exit(1) - class TmpClass(InOrderCPU): pass - else: - class TmpClass(AtomicSimpleCPU): pass - atomic = True + Restoring from a checkpoint or fast forwarding through a benchmark + can be done using one type of cpu, and then the actual + simulation can be carried out using another type. This function + returns these two types of cpus and the initial mode of operation + depending on the options provided. + """ + TmpClass, test_mem_mode = getCPUClass(options.cpu_type) CPUClass = None - test_mem_mode = 'atomic' + if TmpClass.require_caches() and \ + not options.caches and not options.ruby: + fatal("%s must be used with caches" % options.cpu_type) + + if options.checkpoint_restore != None: + if options.restore_with_cpu != options.cpu_type: + CPUClass = TmpClass + TmpClass, test_mem_mode = getCPUClass(options.restore_with_cpu) + elif options.fast_forward: + CPUClass = TmpClass + TmpClass = AtomicSimpleCPU + test_mem_mode = 'atomic' + + # Ruby only supports atomic accesses in noncaching mode + if test_mem_mode == 'atomic' and options.ruby: + warn("Memory mode will be changed to atomic_noncaching") + test_mem_mode = 'atomic_noncaching' + + return (TmpClass, test_mem_mode, CPUClass) + +def setMemClass(options): + """Returns a memory controller class.""" + + return ObjectList.mem_list.get(options.mem_type) + +def setWorkCountOptions(system, options): + if options.work_item_id != None: + system.work_item_id = options.work_item_id + if options.num_work_ids != None: + system.num_work_ids = options.num_work_ids + if options.work_begin_cpu_id_exit != None: + system.work_begin_cpu_id_exit = options.work_begin_cpu_id_exit + if options.work_end_exit_count != None: + system.work_end_exit_count = options.work_end_exit_count + if options.work_end_checkpoint_count != None: + system.work_end_ckpt_count = options.work_end_checkpoint_count + if options.work_begin_exit_count != None: + system.work_begin_exit_count = options.work_begin_exit_count + if options.work_begin_checkpoint_count != None: + system.work_begin_ckpt_count = options.work_begin_checkpoint_count + if options.work_cpus_checkpoint_count != None: + system.work_cpus_ckpt_count = options.work_cpus_checkpoint_count + +def findCptDir(options, cptdir, testsys): + """Figures out the directory from which the checkpointed state is read. + + There are two different ways in which the directories holding checkpoints + can be named -- + 1. cpt.. + 2. cpt. + + This function parses through the options to figure out which one of the + above should be used for selecting the checkpoint, and then figures out + the appropriate directory. + """ + + from os.path import isdir, exists + from os import listdir + import re + + if not isdir(cptdir): + fatal("checkpoint dir %s does not exist!", cptdir) + + cpt_starttick = 0 + if options.at_instruction or options.simpoint: + inst = options.checkpoint_restore + if options.simpoint: + # assume workload 0 has the simpoint + if testsys.cpu[0].workload[0].simpoint == 0: + fatal('Unable to find simpoint') + inst += int(testsys.cpu[0].workload[0].simpoint) + + checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % (options.bench, inst)) + if not exists(checkpoint_dir): + fatal("Unable to find checkpoint directory %s", checkpoint_dir) + + elif options.restore_simpoint_checkpoint: + # Restore from SimPoint checkpoints + # Assumes that the checkpoint dir names are formatted as follows: + dirs = listdir(cptdir) + expr = re.compile('cpt\.simpoint_(\d+)_inst_(\d+)' + + '_weight_([\d\.e\-]+)_interval_(\d+)_warmup_(\d+)') + cpts = [] + for dir in dirs: + match = expr.match(dir) + if match: + cpts.append(dir) + cpts.sort() + + cpt_num = options.checkpoint_restore + if cpt_num > len(cpts): + fatal('Checkpoint %d not found', cpt_num) + checkpoint_dir = joinpath(cptdir, cpts[cpt_num - 1]) + match = expr.match(cpts[cpt_num - 1]) + if match: + index = int(match.group(1)) + start_inst = int(match.group(2)) + weight_inst = float(match.group(3)) + interval_length = int(match.group(4)) + warmup_length = int(match.group(5)) + print("Resuming from", checkpoint_dir) + simpoint_start_insts = [] + simpoint_start_insts.append(warmup_length) + simpoint_start_insts.append(warmup_length + interval_length) + testsys.cpu[0].simpoint_start_insts = simpoint_start_insts + if testsys.switch_cpus != None: + testsys.switch_cpus[0].simpoint_start_insts = simpoint_start_insts + + print("Resuming from SimPoint", end=' ') + print("#%d, start_inst:%d, weight:%f, interval:%d, warmup:%d" % + (index, start_inst, weight_inst, interval_length, warmup_length)) - if not atomic: + else: + dirs = listdir(cptdir) + expr = re.compile('cpt\.([0-9]+)') + cpts = [] + for dir in dirs: + match = expr.match(dir) + if match: + cpts.append(match.group(1)) + + cpts.sort(lambda a,b: cmp(long(a), long(b))) + + cpt_num = options.checkpoint_restore + if cpt_num > len(cpts): + fatal('Checkpoint %d not found', cpt_num) + + cpt_starttick = int(cpts[cpt_num - 1]) + checkpoint_dir = joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1]) + + return cpt_starttick, checkpoint_dir + +def scriptCheckpoints(options, maxtick, cptdir): + if options.at_instruction or options.simpoint: + checkpoint_inst = int(options.take_checkpoints) + + # maintain correct offset if we restored from some instruction if options.checkpoint_restore != None: - if options.restore_with_cpu != options.cpu_type: - CPUClass = TmpClass - class TmpClass(AtomicSimpleCPU): pass + checkpoint_inst += options.checkpoint_restore + + print("Creating checkpoint at inst:%d" % (checkpoint_inst)) + exit_event = m5.simulate() + exit_cause = exit_event.getCause() + print("exit cause = %s" % exit_cause) + + # skip checkpoint instructions should they exist + while exit_cause == "checkpoint": + exit_event = m5.simulate() + exit_cause = exit_event.getCause() + + if exit_cause == "a thread reached the max instruction count": + m5.checkpoint(joinpath(cptdir, "cpt.%s.%d" % \ + (options.bench, checkpoint_inst))) + print("Checkpoint written.") + + else: + when, period = options.take_checkpoints.split(",", 1) + when = int(when) + period = int(period) + num_checkpoints = 0 + + exit_event = m5.simulate(when - m5.curTick()) + exit_cause = exit_event.getCause() + while exit_cause == "checkpoint": + exit_event = m5.simulate(when - m5.curTick()) + exit_cause = exit_event.getCause() + + if exit_cause == "simulate() limit reached": + m5.checkpoint(joinpath(cptdir, "cpt.%d")) + num_checkpoints += 1 + + sim_ticks = when + max_checkpoints = options.max_checkpoints + + while num_checkpoints < max_checkpoints and \ + exit_cause == "simulate() limit reached": + if (sim_ticks + period) > maxtick: + exit_event = m5.simulate(maxtick - sim_ticks) + exit_cause = exit_event.getCause() + break else: - if options.restore_with_cpu != "atomic": - test_mem_mode = 'timing' + exit_event = m5.simulate(period) + exit_cause = exit_event.getCause() + sim_ticks += period + while exit_event.getCause() == "checkpoint": + exit_event = m5.simulate(sim_ticks - m5.curTick()) + if exit_event.getCause() == "simulate() limit reached": + m5.checkpoint(joinpath(cptdir, "cpt.%d")) + num_checkpoints += 1 - elif options.fast_forward: - CPUClass = TmpClass - class TmpClass(AtomicSimpleCPU): pass + return exit_event + +def benchCheckpoints(options, maxtick, cptdir): + exit_event = m5.simulate(maxtick - m5.curTick()) + exit_cause = exit_event.getCause() + + num_checkpoints = 0 + max_checkpoints = options.max_checkpoints + + while exit_cause == "checkpoint": + m5.checkpoint(joinpath(cptdir, "cpt.%d")) + num_checkpoints += 1 + if num_checkpoints == max_checkpoints: + exit_cause = "maximum %d checkpoints dropped" % max_checkpoints + break + + exit_event = m5.simulate(maxtick - m5.curTick()) + exit_cause = exit_event.getCause() + + return exit_event + +# Set up environment for taking SimPoint checkpoints +# Expecting SimPoint files generated by SimPoint 3.2 +def parseSimpointAnalysisFile(options, testsys): + import re + + simpoint_filename, weight_filename, interval_length, warmup_length = \ + options.take_simpoint_checkpoints.split(",", 3) + print("simpoint analysis file:", simpoint_filename) + print("simpoint weight file:", weight_filename) + print("interval length:", interval_length) + print("warmup length:", warmup_length) + + interval_length = int(interval_length) + warmup_length = int(warmup_length) + + # Simpoint analysis output starts interval counts with 0. + simpoints = [] + simpoint_start_insts = [] + + # Read in SimPoint analysis files + simpoint_file = open(simpoint_filename) + weight_file = open(weight_filename) + while True: + line = simpoint_file.readline() + if not line: + break + m = re.match("(\d+)\s+(\d+)", line) + if m: + interval = int(m.group(1)) else: - test_mem_mode = 'timing' + fatal('unrecognized line in simpoint file!') + + line = weight_file.readline() + if not line: + fatal('not enough lines in simpoint weight file!') + m = re.match("([0-9\.e\-]+)\s+(\d+)", line) + if m: + weight = float(m.group(1)) + else: + fatal('unrecognized line in simpoint weight file!') - return (TmpClass, test_mem_mode, CPUClass) + if (interval * interval_length - warmup_length > 0): + starting_inst_count = \ + interval * interval_length - warmup_length + actual_warmup_length = warmup_length + else: + # Not enough room for proper warmup + # Just starting from the beginning + starting_inst_count = 0 + actual_warmup_length = interval * interval_length + simpoints.append((interval, weight, starting_inst_count, + actual_warmup_length)) -def run(options, root, testsys, cpu_class): - if options.maxtick: - maxtick = options.maxtick - elif options.maxtime: - simtime = m5.ticks.seconds(simtime) - print "simulating for: ", simtime - maxtick = simtime - else: - maxtick = m5.MaxTick + # Sort SimPoints by starting inst count + simpoints.sort(key=lambda obj: obj[2]) + for s in simpoints: + interval, weight, starting_inst_count, actual_warmup_length = s + print(str(interval), str(weight), starting_inst_count, + actual_warmup_length) + simpoint_start_insts.append(starting_inst_count) + print("Total # of simpoints:", len(simpoints)) + testsys.cpu[0].simpoint_start_insts = simpoint_start_insts + + return (simpoints, interval_length) + +def takeSimpointCheckpoints(simpoints, interval_length, cptdir): + num_checkpoints = 0 + index = 0 + last_chkpnt_inst_count = -1 + for simpoint in simpoints: + interval, weight, starting_inst_count, actual_warmup_length = simpoint + if starting_inst_count == last_chkpnt_inst_count: + # checkpoint starting point same as last time + # (when warmup period longer than starting point) + exit_cause = "simpoint starting point found" + code = 0 + else: + exit_event = m5.simulate() + + # skip checkpoint instructions should they exist + while exit_event.getCause() == "checkpoint": + print("Found 'checkpoint' exit event...ignoring...") + exit_event = m5.simulate() + + exit_cause = exit_event.getCause() + code = exit_event.getCode() + + if exit_cause == "simpoint starting point found": + m5.checkpoint(joinpath(cptdir, + "cpt.simpoint_%02d_inst_%d_weight_%f_interval_%d_warmup_%d" + % (index, starting_inst_count, weight, interval_length, + actual_warmup_length))) + print("Checkpoint #%d written. start inst:%d weight:%f" % + (num_checkpoints, starting_inst_count, weight)) + num_checkpoints += 1 + last_chkpnt_inst_count = starting_inst_count + else: + break + index += 1 + + print('Exiting @ tick %i because %s' % (m5.curTick(), exit_cause)) + print("%d checkpoints taken" % num_checkpoints) + sys.exit(code) + +def restoreSimpointCheckpoint(): + exit_event = m5.simulate() + exit_cause = exit_event.getCause() + + if exit_cause == "simpoint starting point found": + print("Warmed up! Dumping and resetting stats!") + m5.stats.dump() + m5.stats.reset() + + exit_event = m5.simulate() + exit_cause = exit_event.getCause() + + if exit_cause == "simpoint starting point found": + print("Done running SimPoint!") + sys.exit(exit_event.getCode()) + + print('Exiting @ tick %i because %s' % (m5.curTick(), exit_cause)) + sys.exit(exit_event.getCode()) + +def repeatSwitch(testsys, repeat_switch_cpu_list, maxtick, switch_freq): + print("starting switch loop") + while True: + exit_event = m5.simulate(switch_freq) + exit_cause = exit_event.getCause() + + if exit_cause != "simulate() limit reached": + return exit_event + + m5.switchCpus(testsys, repeat_switch_cpu_list) + + tmp_cpu_list = [] + for old_cpu, new_cpu in repeat_switch_cpu_list: + tmp_cpu_list.append((new_cpu, old_cpu)) + repeat_switch_cpu_list = tmp_cpu_list + + if (maxtick - m5.curTick()) <= switch_freq: + exit_event = m5.simulate(maxtick - m5.curTick()) + return exit_event + +def run(options, root, testsys, cpu_class): if options.checkpoint_dir: cptdir = options.checkpoint_dir elif m5.options.outdir: @@ -100,55 +445,108 @@ def run(options, root, testsys, cpu_class): if options.standard_switch and not options.caches: fatal("Must specify --caches when using --standard-switch") + if options.standard_switch and options.repeat_switch: + fatal("Can't specify both --standard-switch and --repeat-switch") + + if options.repeat_switch and options.take_checkpoints: + fatal("Can't specify both --repeat-switch and --take-checkpoints") + np = options.num_cpus - max_checkpoints = options.max_checkpoints switch_cpus = None if options.prog_interval: - for i in xrange(np): + for i in range(np): testsys.cpu[i].progress_interval = options.prog_interval if options.maxinsts: - for i in xrange(np): + for i in range(np): testsys.cpu[i].max_insts_any_thread = options.maxinsts if cpu_class: - switch_cpus = [cpu_class(defer_registration=True, cpu_id=(np+i)) - for i in xrange(np)] + switch_cpus = [cpu_class(switched_out=True, cpu_id=(i)) + for i in range(np)] - for i in xrange(np): + for i in range(np): if options.fast_forward: testsys.cpu[i].max_insts_any_thread = int(options.fast_forward) - switch_cpus[i].system = testsys - if not buildEnv['FULL_SYSTEM']: - switch_cpus[i].workload = testsys.cpu[i].workload - switch_cpus[i].clock = testsys.cpu[0].clock + switch_cpus[i].system = testsys + switch_cpus[i].workload = testsys.cpu[i].workload + switch_cpus[i].clk_domain = testsys.cpu[i].clk_domain + switch_cpus[i].progress_interval = \ + testsys.cpu[i].progress_interval + switch_cpus[i].isa = testsys.cpu[i].isa # simulation period if options.maxinsts: switch_cpus[i].max_insts_any_thread = options.maxinsts + # Add checker cpu if selected + if options.checker: + switch_cpus[i].addCheckerCpu() + if options.bp_type: + bpClass = ObjectList.bp_list.get(options.bp_type) + switch_cpus[i].branchPred = bpClass() + if options.indirect_bp_type: + IndirectBPClass = ObjectList.indirect_bp_list.get( + options.indirect_bp_type) + switch_cpus[i].branchPred.indirectBranchPred = \ + IndirectBPClass() + + # If elastic tracing is enabled attach the elastic trace probe + # to the switch CPUs + if options.elastic_trace_en: + CpuConfig.config_etrace(cpu_class, switch_cpus, options) testsys.switch_cpus = switch_cpus - switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)] + switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in range(np)] - if options.standard_switch: - if not options.caches: - # O3 CPU must have a cache to work. - print "O3 CPU must be used with caches" + if options.repeat_switch: + switch_class = getCPUClass(options.cpu_type)[0] + if switch_class.require_caches() and \ + not options.caches: + print("%s: Must be used with caches" % str(switch_class)) + sys.exit(1) + if not switch_class.support_take_over(): + print("%s: CPU switching not supported" % str(switch_class)) sys.exit(1) - switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i)) - for i in xrange(np)] - switch_cpus_1 = [DerivO3CPU(defer_registration=True, cpu_id=(2*np+i)) - for i in xrange(np)] + repeat_switch_cpus = [switch_class(switched_out=True, \ + cpu_id=(i)) for i in range(np)] + + for i in range(np): + repeat_switch_cpus[i].system = testsys + repeat_switch_cpus[i].workload = testsys.cpu[i].workload + repeat_switch_cpus[i].clk_domain = testsys.cpu[i].clk_domain + repeat_switch_cpus[i].isa = testsys.cpu[i].isa + + if options.maxinsts: + repeat_switch_cpus[i].max_insts_any_thread = options.maxinsts + + if options.checker: + repeat_switch_cpus[i].addCheckerCpu() - for i in xrange(np): + testsys.repeat_switch_cpus = repeat_switch_cpus + + if cpu_class: + repeat_switch_cpu_list = [(switch_cpus[i], repeat_switch_cpus[i]) + for i in range(np)] + else: + repeat_switch_cpu_list = [(testsys.cpu[i], repeat_switch_cpus[i]) + for i in range(np)] + + if options.standard_switch: + switch_cpus = [TimingSimpleCPU(switched_out=True, cpu_id=(i)) + for i in range(np)] + switch_cpus_1 = [DerivO3CPU(switched_out=True, cpu_id=(i)) + for i in range(np)] + + for i in range(np): switch_cpus[i].system = testsys switch_cpus_1[i].system = testsys - if not buildEnv['FULL_SYSTEM']: - switch_cpus[i].workload = testsys.cpu[i].workload - switch_cpus_1[i].workload = testsys.cpu[i].workload - switch_cpus[i].clock = testsys.cpu[0].clock - switch_cpus_1[i].clock = testsys.cpu[0].clock + switch_cpus[i].workload = testsys.cpu[i].workload + switch_cpus_1[i].workload = testsys.cpu[i].workload + switch_cpus[i].clk_domain = testsys.cpu[i].clk_domain + switch_cpus_1[i].clk_domain = testsys.cpu[i].clk_domain + switch_cpus[i].isa = testsys.cpu[i].isa + switch_cpus_1[i].isa = testsys.cpu[i].isa # if restoring, make atomic cpu simulate only a few instructions if options.checkpoint_restore != None: @@ -174,10 +572,19 @@ def run(options, root, testsys, cpu_class): if options.maxinsts: switch_cpus_1[i].max_insts_any_thread = options.maxinsts + # attach the checker cpu if selected + if options.checker: + switch_cpus[i].addCheckerCpu() + switch_cpus_1[i].addCheckerCpu() + testsys.switch_cpus = switch_cpus testsys.switch_cpus_1 = switch_cpus_1 - switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)] - switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)] + switch_cpu_list = [ + (testsys.cpu[i], switch_cpus[i]) for i in range(np) + ] + switch_cpu_list1 = [ + (switch_cpus[i], switch_cpus_1[i]) for i in range(np) + ] # set the checkpoint in the cpu before m5.instantiate is called if options.take_checkpoints != None and \ @@ -185,7 +592,7 @@ def run(options, root, testsys, cpu_class): offset = int(options.take_checkpoints) # Set an instruction break point if options.simpoint: - for i in xrange(np): + for i in range(np): if testsys.cpu[i].workload[0].simpoint == 0: fatal('no simpoint for testsys.cpu[%d].workload[0]', i) checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset @@ -196,187 +603,134 @@ def run(options, root, testsys, cpu_class): options.take_checkpoints = offset # Set all test cpus with the right number of instructions # for the upcoming simulation - for i in xrange(np): + for i in range(np): testsys.cpu[i].max_insts_any_thread = offset - checkpoint_dir = None - if options.checkpoint_restore != None: - from os.path import isdir, exists - from os import listdir - import re - - if not isdir(cptdir): - fatal("checkpoint dir %s does not exist!", cptdir) - - if options.at_instruction or options.simpoint: - inst = options.checkpoint_restore - if options.simpoint: - # assume workload 0 has the simpoint - if testsys.cpu[0].workload[0].simpoint == 0: - fatal('Unable to find simpoint') - inst += int(testsys.cpu[0].workload[0].simpoint) - - checkpoint_dir = joinpath(cptdir, - "cpt.%s.%s" % (options.bench, inst)) - if not exists(checkpoint_dir): - fatal("Unable to find checkpoint directory %s", checkpoint_dir) - else: - dirs = listdir(cptdir) - expr = re.compile('cpt\.([0-9]*)') - cpts = [] - for dir in dirs: - match = expr.match(dir) - if match: - cpts.append(match.group(1)) - - cpts.sort(lambda a,b: cmp(long(a), long(b))) - - cpt_num = options.checkpoint_restore - - if cpt_num > len(cpts): - fatal('Checkpoint %d not found', cpt_num) - - ## Adjust max tick based on our starting tick - maxtick = maxtick - int(cpts[cpt_num - 1]) - checkpoint_dir = joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1]) + if options.take_simpoint_checkpoints != None: + simpoints, interval_length = parseSimpointAnalysisFile(options, testsys) + checkpoint_dir = None + if options.checkpoint_restore: + cpt_starttick, checkpoint_dir = findCptDir(options, cptdir, testsys) + root.apply_config(options.param) m5.instantiate(checkpoint_dir) + # Initialization is complete. If we're not in control of simulation + # (that is, if we're a slave simulator acting as a component in another + # 'master' simulator) then we're done here. The other simulator will + # call simulate() directly. --initialize-only is used to indicate this. + if options.initialize_only: + return + + # Handle the max tick settings now that tick frequency was resolved + # during system instantiation + # NOTE: the maxtick variable here is in absolute ticks, so it must + # include any simulated ticks before a checkpoint + explicit_maxticks = 0 + maxtick_from_abs = m5.MaxTick + maxtick_from_rel = m5.MaxTick + maxtick_from_maxtime = m5.MaxTick + if options.abs_max_tick: + maxtick_from_abs = options.abs_max_tick + explicit_maxticks += 1 + if options.rel_max_tick: + maxtick_from_rel = options.rel_max_tick + if options.checkpoint_restore: + # NOTE: this may need to be updated if checkpoints ever store + # the ticks per simulated second + maxtick_from_rel += cpt_starttick + if options.at_instruction or options.simpoint: + warn("Relative max tick specified with --at-instruction or" \ + " --simpoint\n These options don't specify the " \ + "checkpoint start tick, so assuming\n you mean " \ + "absolute max tick") + explicit_maxticks += 1 + if options.maxtime: + maxtick_from_maxtime = m5.ticks.fromSeconds(options.maxtime) + explicit_maxticks += 1 + if explicit_maxticks > 1: + warn("Specified multiple of --abs-max-tick, --rel-max-tick, --maxtime."\ + " Using least") + maxtick = min([maxtick_from_abs, maxtick_from_rel, maxtick_from_maxtime]) + + if options.checkpoint_restore != None and maxtick < cpt_starttick: + fatal("Bad maxtick (%d) specified: " \ + "Checkpoint starts starts from tick: %d", maxtick, cpt_starttick) + if options.standard_switch or cpu_class: if options.standard_switch: - print "Switch at instruction count:%s" % \ - str(testsys.cpu[0].max_insts_any_thread) + print("Switch at instruction count:%s" % + str(testsys.cpu[0].max_insts_any_thread)) exit_event = m5.simulate() elif cpu_class and options.fast_forward: - print "Switch at instruction count:%s" % \ - str(testsys.cpu[0].max_insts_any_thread) + print("Switch at instruction count:%s" % + str(testsys.cpu[0].max_insts_any_thread)) exit_event = m5.simulate() else: - print "Switch at curTick count:%s" % str(10000) + print("Switch at curTick count:%s" % str(10000)) exit_event = m5.simulate(10000) - print "Switched CPUS @ tick %s" % (m5.curTick()) + print("Switched CPUS @ tick %s" % (m5.curTick())) - # when you change to Timing (or Atomic), you halt the system - # given as argument. When you are finished with the system - # changes (including switchCpus), you must resume the system - # manually. You DON'T need to resume after just switching - # CPUs if you haven't changed anything on the system level. - - m5.changeToTiming(testsys) - m5.switchCpus(switch_cpu_list) - m5.resume(testsys) + m5.switchCpus(testsys, switch_cpu_list) if options.standard_switch: - print "Switch at instruction count:%d" % \ - (testsys.switch_cpus[0].max_insts_any_thread) + print("Switch at instruction count:%d" % + (testsys.switch_cpus[0].max_insts_any_thread)) #warmup instruction count may have already been set if options.warmup_insts: exit_event = m5.simulate() else: - exit_event = m5.simulate(options.warmup) - print "Switching CPUS @ tick %s" % (m5.curTick()) - print "Simulation ends instruction count:%d" % \ - (testsys.switch_cpus_1[0].max_insts_any_thread) - m5.drain(testsys) - m5.switchCpus(switch_cpu_list1) - m5.resume(testsys) - - num_checkpoints = 0 - exit_cause = '' + exit_event = m5.simulate(options.standard_switch) + print("Switching CPUS @ tick %s" % (m5.curTick())) + print("Simulation ends instruction count:%d" % + (testsys.switch_cpus_1[0].max_insts_any_thread)) + m5.switchCpus(testsys, switch_cpu_list1) # If we're taking and restoring checkpoints, use checkpoint_dir # option only for finding the checkpoints to restore from. This # lets us test checkpointing by restoring from one set of # checkpoints, generating a second set, and then comparing them. - if options.take_checkpoints and options.checkpoint_restore: + if (options.take_checkpoints or options.take_simpoint_checkpoints) \ + and options.checkpoint_restore: + if m5.options.outdir: cptdir = m5.options.outdir else: cptdir = getcwd() - # Checkpoints being taken via the command line at and at - # subsequent periods of . Checkpoint instructions - # received from the benchmark running are ignored and skipped in - # favor of command line checkpoint instructions. if options.take_checkpoints != None : - if options.at_instruction or options.simpoint: - checkpoint_inst = int(options.take_checkpoints) - - # maintain correct offset if we restored from some instruction - if options.checkpoint_restore != None: - checkpoint_inst += options.checkpoint_restore - - print "Creating checkpoint at inst:%d" % (checkpoint_inst) - exit_event = m5.simulate() - print "exit cause = %s" % (exit_event.getCause()) - - # skip checkpoint instructions should they exist - while exit_event.getCause() == "checkpoint": - exit_event = m5.simulate() + # Checkpoints being taken via the command line at and at + # subsequent periods of . Checkpoint instructions + # received from the benchmark running are ignored and skipped in + # favor of command line checkpoint instructions. + exit_event = scriptCheckpoints(options, maxtick, cptdir) - if exit_event.getCause() == \ - "a thread reached the max instruction count": - m5.checkpoint(joinpath(cptdir, "cpt.%s.%d" % \ - (options.bench, checkpoint_inst))) - print "Checkpoint written." - num_checkpoints += 1 + # Take SimPoint checkpoints + elif options.take_simpoint_checkpoints != None: + takeSimpointCheckpoints(simpoints, interval_length, cptdir) - if exit_event.getCause() == "user interrupt received": - exit_cause = exit_event.getCause(); - else: - when, period = options.take_checkpoints.split(",", 1) - when = int(when) - period = int(period) - - exit_event = m5.simulate(when) - while exit_event.getCause() == "checkpoint": - exit_event = m5.simulate(when - m5.curTick()) + # Restore from SimPoint checkpoints + elif options.restore_simpoint_checkpoint != None: + restoreSimpointCheckpoint() - if exit_event.getCause() == "simulate() limit reached": - m5.checkpoint(joinpath(cptdir, "cpt.%d")) - num_checkpoints += 1 - - sim_ticks = when - exit_cause = "maximum %d checkpoints dropped" % max_checkpoints - while num_checkpoints < max_checkpoints and \ - exit_event.getCause() == "simulate() limit reached": - if (sim_ticks + period) > maxtick: - exit_event = m5.simulate(maxtick - sim_ticks) - exit_cause = exit_event.getCause() - break - else: - exit_event = m5.simulate(period) - sim_ticks += period - while exit_event.getCause() == "checkpoint": - exit_event = m5.simulate(sim_ticks - m5.curTick()) - if exit_event.getCause() == "simulate() limit reached": - m5.checkpoint(joinpath(cptdir, "cpt.%d")) - num_checkpoints += 1 - - if exit_event.getCause() != "simulate() limit reached": - exit_cause = exit_event.getCause(); - - else: # no checkpoints being taken via this script + else: if options.fast_forward: m5.stats.reset() - print "**** REAL SIMULATION ****" - exit_event = m5.simulate(maxtick) + print("**** REAL SIMULATION ****") - while exit_event.getCause() == "checkpoint": - m5.checkpoint(joinpath(cptdir, "cpt.%d")) - num_checkpoints += 1 - if num_checkpoints == max_checkpoints: - exit_cause = "maximum %d checkpoints dropped" % max_checkpoints - break - - exit_event = m5.simulate(maxtick - m5.curTick()) - exit_cause = exit_event.getCause() - - if exit_cause == '': - exit_cause = exit_event.getCause() - print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_cause) + # If checkpoints are being taken, then the checkpoint instruction + # will occur in the benchmark code it self. + if options.repeat_switch and maxtick > options.repeat_switch: + exit_event = repeatSwitch(testsys, repeat_switch_cpu_list, + maxtick, options.repeat_switch) + else: + exit_event = benchCheckpoints(options, maxtick, cptdir) + print('Exiting @ tick %i because %s' % + (m5.curTick(), exit_event.getCause())) if options.checkpoint_at_end: m5.checkpoint(joinpath(cptdir, "cpt.%d")) + if exit_event.getCode() != 0: + print("Simulated exit code not 0! Exit code is", exit_event.getCode())