Simulation.py revision 7489
113481Sgiacomo.travaglini@arm.com# Copyright (c) 2006-2008 The Regents of The University of Michigan
213481Sgiacomo.travaglini@arm.com# All rights reserved.
313481Sgiacomo.travaglini@arm.com#
413481Sgiacomo.travaglini@arm.com# Redistribution and use in source and binary forms, with or without
513481Sgiacomo.travaglini@arm.com# modification, are permitted provided that the following conditions are
613481Sgiacomo.travaglini@arm.com# met: redistributions of source code must retain the above copyright
713481Sgiacomo.travaglini@arm.com# notice, this list of conditions and the following disclaimer;
813481Sgiacomo.travaglini@arm.com# redistributions in binary form must reproduce the above copyright
913481Sgiacomo.travaglini@arm.com# notice, this list of conditions and the following disclaimer in the
1013481Sgiacomo.travaglini@arm.com# documentation and/or other materials provided with the distribution;
1113481Sgiacomo.travaglini@arm.com# neither the name of the copyright holders nor the names of its
1213481Sgiacomo.travaglini@arm.com# contributors may be used to endorse or promote products derived from
1313481Sgiacomo.travaglini@arm.com# this software without specific prior written permission.
1413481Sgiacomo.travaglini@arm.com#
1513481Sgiacomo.travaglini@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1613481Sgiacomo.travaglini@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1713481Sgiacomo.travaglini@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1813481Sgiacomo.travaglini@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1913481Sgiacomo.travaglini@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2013481Sgiacomo.travaglini@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2113481Sgiacomo.travaglini@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2213481Sgiacomo.travaglini@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2313481Sgiacomo.travaglini@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2413481Sgiacomo.travaglini@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2513481Sgiacomo.travaglini@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2613481Sgiacomo.travaglini@arm.com#
2713481Sgiacomo.travaglini@arm.com# Authors: Lisa Hsu
2813481Sgiacomo.travaglini@arm.com
2913481Sgiacomo.travaglini@arm.comfrom os import getcwd
3013481Sgiacomo.travaglini@arm.comfrom os.path import join as joinpath
3113481Sgiacomo.travaglini@arm.com
3213481Sgiacomo.travaglini@arm.comimport m5
3313481Sgiacomo.travaglini@arm.comfrom m5.defines import buildEnv
3413481Sgiacomo.travaglini@arm.comfrom m5.objects import *
3513481Sgiacomo.travaglini@arm.comfrom m5.util import *
3613481Sgiacomo.travaglini@arm.com
3713481Sgiacomo.travaglini@arm.comaddToPath('../common')
3813481Sgiacomo.travaglini@arm.com
3913481Sgiacomo.travaglini@arm.comdef setCPUClass(options):
4013481Sgiacomo.travaglini@arm.com
4113481Sgiacomo.travaglini@arm.com    atomic = False
4213481Sgiacomo.travaglini@arm.com    if options.timing:
4313481Sgiacomo.travaglini@arm.com        class TmpClass(TimingSimpleCPU): pass
4413481Sgiacomo.travaglini@arm.com    elif options.detailed:
4513481Sgiacomo.travaglini@arm.com        if not options.caches:
4613481Sgiacomo.travaglini@arm.com            print "O3 CPU must be used with caches"
4713481Sgiacomo.travaglini@arm.com            sys.exit(1)
4813481Sgiacomo.travaglini@arm.com        class TmpClass(DerivO3CPU): pass
4913481Sgiacomo.travaglini@arm.com    elif options.inorder:
5013481Sgiacomo.travaglini@arm.com        if not options.caches:
5113481Sgiacomo.travaglini@arm.com            print "InOrder CPU must be used with caches"
5213481Sgiacomo.travaglini@arm.com            sys.exit(1)
5313481Sgiacomo.travaglini@arm.com        class TmpClass(InOrderCPU): pass
5413481Sgiacomo.travaglini@arm.com    else:
5513481Sgiacomo.travaglini@arm.com        class TmpClass(AtomicSimpleCPU): pass
5613481Sgiacomo.travaglini@arm.com        atomic = True
5713481Sgiacomo.travaglini@arm.com
5813481Sgiacomo.travaglini@arm.com    CPUClass = None
5913481Sgiacomo.travaglini@arm.com    test_mem_mode = 'atomic'
6013481Sgiacomo.travaglini@arm.com
6113481Sgiacomo.travaglini@arm.com    if not atomic:
6213481Sgiacomo.travaglini@arm.com        if options.checkpoint_restore != None or options.fast_forward:
6313481Sgiacomo.travaglini@arm.com            CPUClass = TmpClass
6413481Sgiacomo.travaglini@arm.com            class TmpClass(AtomicSimpleCPU): pass
6513481Sgiacomo.travaglini@arm.com        else:
6613481Sgiacomo.travaglini@arm.com            test_mem_mode = 'timing'
6713481Sgiacomo.travaglini@arm.com
6813481Sgiacomo.travaglini@arm.com    return (TmpClass, test_mem_mode, CPUClass)
6913481Sgiacomo.travaglini@arm.com
7013481Sgiacomo.travaglini@arm.com
7113481Sgiacomo.travaglini@arm.comdef run(options, root, testsys, cpu_class):
7213481Sgiacomo.travaglini@arm.com    if options.maxtick:
7313481Sgiacomo.travaglini@arm.com        maxtick = options.maxtick
7413481Sgiacomo.travaglini@arm.com    elif options.maxtime:
7513481Sgiacomo.travaglini@arm.com        simtime = m5.ticks.seconds(simtime)
7613481Sgiacomo.travaglini@arm.com        print "simulating for: ", simtime
7713481Sgiacomo.travaglini@arm.com        maxtick = simtime
7813481Sgiacomo.travaglini@arm.com    else:
7913481Sgiacomo.travaglini@arm.com        maxtick = m5.MaxTick
8013481Sgiacomo.travaglini@arm.com
8113481Sgiacomo.travaglini@arm.com    if options.checkpoint_dir:
8213481Sgiacomo.travaglini@arm.com        cptdir = options.checkpoint_dir
8313481Sgiacomo.travaglini@arm.com    elif m5.options.outdir:
8413481Sgiacomo.travaglini@arm.com        cptdir = m5.options.outdir
8513481Sgiacomo.travaglini@arm.com    else:
8613481Sgiacomo.travaglini@arm.com        cptdir = getcwd()
8713481Sgiacomo.travaglini@arm.com
8813481Sgiacomo.travaglini@arm.com    if options.fast_forward and options.checkpoint_restore != None:
8913481Sgiacomo.travaglini@arm.com        fatal("Can't specify both --fast-forward and --checkpoint-restore")
9013481Sgiacomo.travaglini@arm.com
9113481Sgiacomo.travaglini@arm.com    if options.standard_switch and not options.caches:
9213481Sgiacomo.travaglini@arm.com        fatal("Must specify --caches when using --standard-switch")
9313481Sgiacomo.travaglini@arm.com
9413481Sgiacomo.travaglini@arm.com    np = options.num_cpus
9513481Sgiacomo.travaglini@arm.com    max_checkpoints = options.max_checkpoints
9613481Sgiacomo.travaglini@arm.com    switch_cpus = None
9713481Sgiacomo.travaglini@arm.com
9813481Sgiacomo.travaglini@arm.com    if options.prog_intvl:
9913481Sgiacomo.travaglini@arm.com        for i in xrange(np):
10013481Sgiacomo.travaglini@arm.com            testsys.cpu[i].progress_interval = options.prog_intvl
10113481Sgiacomo.travaglini@arm.com
10213481Sgiacomo.travaglini@arm.com    if options.maxinsts:
10313481Sgiacomo.travaglini@arm.com        for i in xrange(np):
10413481Sgiacomo.travaglini@arm.com            testsys.cpu[i].max_insts_any_thread = options.maxinsts
10513481Sgiacomo.travaglini@arm.com
10613481Sgiacomo.travaglini@arm.com    if cpu_class:
10713481Sgiacomo.travaglini@arm.com        switch_cpus = [cpu_class(defer_registration=True, cpu_id=(np+i))
10813481Sgiacomo.travaglini@arm.com                       for i in xrange(np)]
10913481Sgiacomo.travaglini@arm.com
11013481Sgiacomo.travaglini@arm.com        for i in xrange(np):
11113481Sgiacomo.travaglini@arm.com            if options.fast_forward:
11213481Sgiacomo.travaglini@arm.com                testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
11313481Sgiacomo.travaglini@arm.com            switch_cpus[i].system =  testsys
11413481Sgiacomo.travaglini@arm.com            if not buildEnv['FULL_SYSTEM']:
11513481Sgiacomo.travaglini@arm.com                switch_cpus[i].workload = testsys.cpu[i].workload
11613481Sgiacomo.travaglini@arm.com            switch_cpus[i].clock = testsys.cpu[0].clock
11713481Sgiacomo.travaglini@arm.com            # simulation period
11813481Sgiacomo.travaglini@arm.com            if options.max_inst:
11913481Sgiacomo.travaglini@arm.com                switch_cpus[i].max_insts_any_thread = options.max_inst
12013481Sgiacomo.travaglini@arm.com
12113481Sgiacomo.travaglini@arm.com        testsys.switch_cpus = switch_cpus
12213481Sgiacomo.travaglini@arm.com        switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
12313481Sgiacomo.travaglini@arm.com
12413481Sgiacomo.travaglini@arm.com    if options.standard_switch:
12513481Sgiacomo.travaglini@arm.com        switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i))
12613481Sgiacomo.travaglini@arm.com                       for i in xrange(np)]
12713481Sgiacomo.travaglini@arm.com        switch_cpus_1 = [DerivO3CPU(defer_registration=True, cpu_id=(2*np+i))
12813481Sgiacomo.travaglini@arm.com                        for i in xrange(np)]
12913481Sgiacomo.travaglini@arm.com
13013481Sgiacomo.travaglini@arm.com        for i in xrange(np):
13113481Sgiacomo.travaglini@arm.com            switch_cpus[i].system =  testsys
13213481Sgiacomo.travaglini@arm.com            switch_cpus_1[i].system =  testsys
13313481Sgiacomo.travaglini@arm.com            if not buildEnv['FULL_SYSTEM']:
13413481Sgiacomo.travaglini@arm.com                switch_cpus[i].workload = testsys.cpu[i].workload
13513481Sgiacomo.travaglini@arm.com                switch_cpus_1[i].workload = testsys.cpu[i].workload
13613481Sgiacomo.travaglini@arm.com            switch_cpus[i].clock = testsys.cpu[0].clock
13713481Sgiacomo.travaglini@arm.com            switch_cpus_1[i].clock = testsys.cpu[0].clock
13813481Sgiacomo.travaglini@arm.com
13913481Sgiacomo.travaglini@arm.com            # if restoring, make atomic cpu simulate only a few instructions
14013481Sgiacomo.travaglini@arm.com            if options.checkpoint_restore != None:
14113481Sgiacomo.travaglini@arm.com                testsys.cpu[i].max_insts_any_thread = 1
14213481Sgiacomo.travaglini@arm.com            # Fast forward to specified location if we are not restoring
14313481Sgiacomo.travaglini@arm.com            elif options.fast_forward:
14413481Sgiacomo.travaglini@arm.com                testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
14513481Sgiacomo.travaglini@arm.com            # Fast forward to a simpoint (warning: time consuming)
14613481Sgiacomo.travaglini@arm.com            elif options.simpoint:
14713481Sgiacomo.travaglini@arm.com                if testsys.cpu[i].workload[0].simpoint == 0:
14813481Sgiacomo.travaglini@arm.com                    fatal('simpoint not found')
14913481Sgiacomo.travaglini@arm.com                testsys.cpu[i].max_insts_any_thread = \
15013481Sgiacomo.travaglini@arm.com                    testsys.cpu[i].workload[0].simpoint
15113481Sgiacomo.travaglini@arm.com            # No distance specified, just switch
15213481Sgiacomo.travaglini@arm.com            else:
15313481Sgiacomo.travaglini@arm.com                testsys.cpu[i].max_insts_any_thread = 1
15413481Sgiacomo.travaglini@arm.com
15513481Sgiacomo.travaglini@arm.com            # warmup period
15613481Sgiacomo.travaglini@arm.com            if options.warmup_insts:
15713481Sgiacomo.travaglini@arm.com                switch_cpus[i].max_insts_any_thread =  options.warmup_insts
15813481Sgiacomo.travaglini@arm.com
15913481Sgiacomo.travaglini@arm.com            # simulation period
16013481Sgiacomo.travaglini@arm.com            if options.max_inst:
16113481Sgiacomo.travaglini@arm.com                switch_cpus_1[i].max_insts_any_thread = options.max_inst
16213481Sgiacomo.travaglini@arm.com
16313481Sgiacomo.travaglini@arm.com            if not options.caches:
16413481Sgiacomo.travaglini@arm.com                # O3 CPU must have a cache to work.
16513481Sgiacomo.travaglini@arm.com                print "O3 CPU must be used with caches"
16613481Sgiacomo.travaglini@arm.com                sys.exit(1)
16713481Sgiacomo.travaglini@arm.com
16813481Sgiacomo.travaglini@arm.com            testsys.switch_cpus = switch_cpus
16913481Sgiacomo.travaglini@arm.com            testsys.switch_cpus_1 = switch_cpus_1
17013481Sgiacomo.travaglini@arm.com            switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
17113481Sgiacomo.travaglini@arm.com            switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)]
17213481Sgiacomo.travaglini@arm.com
17313481Sgiacomo.travaglini@arm.com    # set the checkpoint in the cpu before m5.instantiate is called
17413481Sgiacomo.travaglini@arm.com    if options.take_checkpoints != None and \
17513481Sgiacomo.travaglini@arm.com           (options.simpoint or options.at_instruction):
17613481Sgiacomo.travaglini@arm.com        offset = int(options.take_checkpoints)
17713481Sgiacomo.travaglini@arm.com        # Set an instruction break point
17813481Sgiacomo.travaglini@arm.com        if options.simpoint:
17913481Sgiacomo.travaglini@arm.com            for i in xrange(np):
18013481Sgiacomo.travaglini@arm.com                if testsys.cpu[i].workload[0].simpoint == 0:
18113481Sgiacomo.travaglini@arm.com                    fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
18213481Sgiacomo.travaglini@arm.com                checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
18313481Sgiacomo.travaglini@arm.com                testsys.cpu[i].max_insts_any_thread = checkpoint_inst
18413481Sgiacomo.travaglini@arm.com                # used for output below
18513481Sgiacomo.travaglini@arm.com                options.take_checkpoints = checkpoint_inst
18613481Sgiacomo.travaglini@arm.com        else:
18713481Sgiacomo.travaglini@arm.com            options.take_checkpoints = offset
18813481Sgiacomo.travaglini@arm.com            # Set all test cpus with the right number of instructions
18913481Sgiacomo.travaglini@arm.com            # for the upcoming simulation
19013481Sgiacomo.travaglini@arm.com            for i in xrange(np):
19113481Sgiacomo.travaglini@arm.com                testsys.cpu[i].max_insts_any_thread = offset
19213481Sgiacomo.travaglini@arm.com
19313481Sgiacomo.travaglini@arm.com    m5.instantiate(root)
19413481Sgiacomo.travaglini@arm.com
19513481Sgiacomo.travaglini@arm.com    if options.checkpoint_restore != None:
19613481Sgiacomo.travaglini@arm.com        from os.path import isdir, exists
19713481Sgiacomo.travaglini@arm.com        from os import listdir
19813481Sgiacomo.travaglini@arm.com        import re
19913481Sgiacomo.travaglini@arm.com
20013481Sgiacomo.travaglini@arm.com        if not isdir(cptdir):
20113481Sgiacomo.travaglini@arm.com            fatal("checkpoint dir %s does not exist!", cptdir)
20213481Sgiacomo.travaglini@arm.com
20313481Sgiacomo.travaglini@arm.com        if options.at_instruction:
20413481Sgiacomo.travaglini@arm.com            checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % \
20513481Sgiacomo.travaglini@arm.com                    (options.bench, options.checkpoint_restore))
20613481Sgiacomo.travaglini@arm.com            if not exists(checkpoint_dir):
20713481Sgiacomo.travaglini@arm.com                fatal("Unable to find checkpoint directory %s", checkpoint_dir)
20813481Sgiacomo.travaglini@arm.com
20913481Sgiacomo.travaglini@arm.com            print "Restoring checkpoint ..."
21013481Sgiacomo.travaglini@arm.com            m5.restoreCheckpoint(root, checkpoint_dir)
21113481Sgiacomo.travaglini@arm.com            print "Done."
21213481Sgiacomo.travaglini@arm.com        elif options.simpoint:
21313481Sgiacomo.travaglini@arm.com            # assume workload 0 has the simpoint
21413481Sgiacomo.travaglini@arm.com            if testsys.cpu[0].workload[0].simpoint == 0:
21513481Sgiacomo.travaglini@arm.com                fatal('Unable to find simpoint')
21613481Sgiacomo.travaglini@arm.com
21713481Sgiacomo.travaglini@arm.com            options.checkpoint_restore += \
21813481Sgiacomo.travaglini@arm.com                int(testsys.cpu[0].workload[0].simpoint)
21913481Sgiacomo.travaglini@arm.com
22013481Sgiacomo.travaglini@arm.com            checkpoint_dir = joinpath(cptdir, "cpt.%s.%d" % \
22113481Sgiacomo.travaglini@arm.com                    (options.bench, options.checkpoint_restore))
22213481Sgiacomo.travaglini@arm.com            if not exists(checkpoint_dir):
22313481Sgiacomo.travaglini@arm.com                fatal("Unable to find checkpoint directory %s.%s",
22413481Sgiacomo.travaglini@arm.com                      options.bench, options.checkpoint_restore)
22513481Sgiacomo.travaglini@arm.com
22613481Sgiacomo.travaglini@arm.com            print "Restoring checkpoint ..."
22713481Sgiacomo.travaglini@arm.com            m5.restoreCheckpoint(root,checkpoint_dir)
22813481Sgiacomo.travaglini@arm.com            print "Done."
22913481Sgiacomo.travaglini@arm.com        else:
23013481Sgiacomo.travaglini@arm.com            dirs = listdir(cptdir)
23113481Sgiacomo.travaglini@arm.com            expr = re.compile('cpt\.([0-9]*)')
23213481Sgiacomo.travaglini@arm.com            cpts = []
23313481Sgiacomo.travaglini@arm.com            for dir in dirs:
23413481Sgiacomo.travaglini@arm.com                match = expr.match(dir)
23513481Sgiacomo.travaglini@arm.com                if match:
23613481Sgiacomo.travaglini@arm.com                    cpts.append(match.group(1))
23713481Sgiacomo.travaglini@arm.com
23813481Sgiacomo.travaglini@arm.com            cpts.sort(lambda a,b: cmp(long(a), long(b)))
23913481Sgiacomo.travaglini@arm.com
24013481Sgiacomo.travaglini@arm.com            cpt_num = options.checkpoint_restore
24113481Sgiacomo.travaglini@arm.com
24213481Sgiacomo.travaglini@arm.com            if cpt_num > len(cpts):
24313481Sgiacomo.travaglini@arm.com                fatal('Checkpoint %d not found', cpt_num)
24413481Sgiacomo.travaglini@arm.com
24513481Sgiacomo.travaglini@arm.com            ## Adjust max tick based on our starting tick
24613481Sgiacomo.travaglini@arm.com            maxtick = maxtick - int(cpts[cpt_num - 1])
24713481Sgiacomo.travaglini@arm.com
24813481Sgiacomo.travaglini@arm.com            ## Restore the checkpoint
24913481Sgiacomo.travaglini@arm.com            m5.restoreCheckpoint(root,
25013481Sgiacomo.travaglini@arm.com                    joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1]))
25113481Sgiacomo.travaglini@arm.com
25213481Sgiacomo.travaglini@arm.com    if options.standard_switch or cpu_class:
25313481Sgiacomo.travaglini@arm.com        if options.standard_switch:
25413481Sgiacomo.travaglini@arm.com            print "Switch at instruction count:%s" % \
25513481Sgiacomo.travaglini@arm.com                    str(testsys.cpu[0].max_insts_any_thread)
25613481Sgiacomo.travaglini@arm.com            exit_event = m5.simulate()
25713481Sgiacomo.travaglini@arm.com        elif cpu_class and options.fast_forward:
25813481Sgiacomo.travaglini@arm.com            print "Switch at instruction count:%s" % \
25913481Sgiacomo.travaglini@arm.com                    str(testsys.cpu[0].max_insts_any_thread)
26013481Sgiacomo.travaglini@arm.com            exit_event = m5.simulate()
26113481Sgiacomo.travaglini@arm.com        else:
26213481Sgiacomo.travaglini@arm.com            print "Switch at curTick count:%s" % str(10000)
26313481Sgiacomo.travaglini@arm.com            exit_event = m5.simulate(10000)
26413481Sgiacomo.travaglini@arm.com        print "Switched CPUS @ cycle = %s" % (m5.curTick())
26513481Sgiacomo.travaglini@arm.com
26613481Sgiacomo.travaglini@arm.com        # when you change to Timing (or Atomic), you halt the system
26713481Sgiacomo.travaglini@arm.com        # given as argument.  When you are finished with the system
26813481Sgiacomo.travaglini@arm.com        # changes (including switchCpus), you must resume the system
26913481Sgiacomo.travaglini@arm.com        # manually.  You DON'T need to resume after just switching
27013481Sgiacomo.travaglini@arm.com        # CPUs if you haven't changed anything on the system level.
27113481Sgiacomo.travaglini@arm.com
27213481Sgiacomo.travaglini@arm.com        m5.changeToTiming(testsys)
27313481Sgiacomo.travaglini@arm.com        m5.switchCpus(switch_cpu_list)
27413481Sgiacomo.travaglini@arm.com        m5.resume(testsys)
27513481Sgiacomo.travaglini@arm.com
27613481Sgiacomo.travaglini@arm.com        if options.standard_switch:
27713481Sgiacomo.travaglini@arm.com            print "Switch at instruction count:%d" % \
27813481Sgiacomo.travaglini@arm.com                    (testsys.switch_cpus[0].max_insts_any_thread)
27913481Sgiacomo.travaglini@arm.com
28013481Sgiacomo.travaglini@arm.com            #warmup instruction count may have already been set
28113481Sgiacomo.travaglini@arm.com            if options.warmup_insts:
28213481Sgiacomo.travaglini@arm.com                exit_event = m5.simulate()
28313481Sgiacomo.travaglini@arm.com            else:
28413481Sgiacomo.travaglini@arm.com                exit_event = m5.simulate(options.warmup)
28513481Sgiacomo.travaglini@arm.com            print "Switching CPUS @ cycle = %s" % (m5.curTick())
28613481Sgiacomo.travaglini@arm.com            print "Simulation ends instruction count:%d" % \
28713481Sgiacomo.travaglini@arm.com                    (testsys.switch_cpus_1[0].max_insts_any_thread)
28813481Sgiacomo.travaglini@arm.com            m5.drain(testsys)
28913481Sgiacomo.travaglini@arm.com            m5.switchCpus(switch_cpu_list1)
29013481Sgiacomo.travaglini@arm.com            m5.resume(testsys)
29113481Sgiacomo.travaglini@arm.com
29213481Sgiacomo.travaglini@arm.com    num_checkpoints = 0
29313481Sgiacomo.travaglini@arm.com    exit_cause = ''
29413481Sgiacomo.travaglini@arm.com
29513481Sgiacomo.travaglini@arm.com    # If we're taking and restoring checkpoints, use checkpoint_dir
29613481Sgiacomo.travaglini@arm.com    # option only for finding the checkpoints to restore from.  This
29713481Sgiacomo.travaglini@arm.com    # lets us test checkpointing by restoring from one set of
29813481Sgiacomo.travaglini@arm.com    # checkpoints, generating a second set, and then comparing them.
29913481Sgiacomo.travaglini@arm.com    if options.take_checkpoints and options.checkpoint_restore:
30013481Sgiacomo.travaglini@arm.com        if m5.options.outdir:
30113481Sgiacomo.travaglini@arm.com            cptdir = m5.options.outdir
30213481Sgiacomo.travaglini@arm.com        else:
30313481Sgiacomo.travaglini@arm.com            cptdir = getcwd()
30413481Sgiacomo.travaglini@arm.com
30513481Sgiacomo.travaglini@arm.com    # Checkpoints being taken via the command line at <when> and at
30613481Sgiacomo.travaglini@arm.com    # subsequent periods of <period>.  Checkpoint instructions
30713481Sgiacomo.travaglini@arm.com    # received from the benchmark running are ignored and skipped in
30813481Sgiacomo.travaglini@arm.com    # favor of command line checkpoint instructions.
30913481Sgiacomo.travaglini@arm.com    if options.take_checkpoints != None :
31013481Sgiacomo.travaglini@arm.com        if options.at_instruction or options.simpoint:
31113481Sgiacomo.travaglini@arm.com            checkpoint_inst = int(options.take_checkpoints)
31213481Sgiacomo.travaglini@arm.com
31313481Sgiacomo.travaglini@arm.com            # maintain correct offset if we restored from some instruction
31413481Sgiacomo.travaglini@arm.com            if options.checkpoint_restore != None:
31513481Sgiacomo.travaglini@arm.com                checkpoint_inst += options.checkpoint_restore
31613481Sgiacomo.travaglini@arm.com
31713481Sgiacomo.travaglini@arm.com            print "Creating checkpoint at inst:%d" % (checkpoint_inst)
31813481Sgiacomo.travaglini@arm.com            exit_event = m5.simulate()
31913481Sgiacomo.travaglini@arm.com            print "exit cause = %s" % (exit_event.getCause())
32013481Sgiacomo.travaglini@arm.com
32113481Sgiacomo.travaglini@arm.com            # skip checkpoint instructions should they exist
32213481Sgiacomo.travaglini@arm.com            while exit_event.getCause() == "checkpoint":
32313481Sgiacomo.travaglini@arm.com                exit_event = m5.simulate()
32413481Sgiacomo.travaglini@arm.com
32513481Sgiacomo.travaglini@arm.com            if exit_event.getCause() == \
32613481Sgiacomo.travaglini@arm.com                   "a thread reached the max instruction count":
32713481Sgiacomo.travaglini@arm.com                m5.checkpoint(root, joinpath(cptdir, "cpt.%s.%d" % \
32813481Sgiacomo.travaglini@arm.com                        (options.bench, checkpoint_inst)))
32913481Sgiacomo.travaglini@arm.com                print "Checkpoint written."
33013481Sgiacomo.travaglini@arm.com                num_checkpoints += 1
33113481Sgiacomo.travaglini@arm.com
33213481Sgiacomo.travaglini@arm.com            if exit_event.getCause() == "user interrupt received":
33313481Sgiacomo.travaglini@arm.com                exit_cause = exit_event.getCause();
334        else:
335            when, period = options.take_checkpoints.split(",", 1)
336            when = int(when)
337            period = int(period)
338
339            exit_event = m5.simulate(when)
340            while exit_event.getCause() == "checkpoint":
341                exit_event = m5.simulate(when - m5.curTick())
342
343            if exit_event.getCause() == "simulate() limit reached":
344                m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
345                num_checkpoints += 1
346
347            sim_ticks = when
348            exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
349            while num_checkpoints < max_checkpoints and \
350                    exit_event.getCause() == "simulate() limit reached":
351                if (sim_ticks + period) > maxtick:
352                    exit_event = m5.simulate(maxtick - sim_ticks)
353                    exit_cause = exit_event.getCause()
354                    break
355                else:
356                    exit_event = m5.simulate(period)
357                    sim_ticks += period
358                    while exit_event.getCause() == "checkpoint":
359                        exit_event = m5.simulate(sim_ticks - m5.curTick())
360                    if exit_event.getCause() == "simulate() limit reached":
361                        m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
362                        num_checkpoints += 1
363
364            if exit_event.getCause() != "simulate() limit reached":
365                exit_cause = exit_event.getCause();
366
367    else: # no checkpoints being taken via this script
368        if options.fast_forward:
369            m5.stats.reset()
370        print "**** REAL SIMULATION ****"
371        exit_event = m5.simulate(maxtick)
372
373        while exit_event.getCause() == "checkpoint":
374            m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
375            num_checkpoints += 1
376            if num_checkpoints == max_checkpoints:
377                exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
378                break
379
380            exit_event = m5.simulate(maxtick - m5.curTick())
381            exit_cause = exit_event.getCause()
382
383    if exit_cause == '':
384        exit_cause = exit_event.getCause()
385    print 'Exiting @ cycle %i because %s' % (m5.curTick(), exit_cause)
386
387    if options.checkpoint_at_end:
388        m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
389
390