Simulation.py revision 9221:4f54b0f229b5
18926Sandreas.hansson@arm.com# Copyright (c) 2006-2008 The Regents of The University of Michigan
27586SAli.Saidi@arm.com# Copyright (c) 2010 Advanced Micro Devices, Inc.
37586SAli.Saidi@arm.com# All rights reserved.
47586SAli.Saidi@arm.com#
57586SAli.Saidi@arm.com# Redistribution and use in source and binary forms, with or without
67586SAli.Saidi@arm.com# modification, are permitted provided that the following conditions are
77586SAli.Saidi@arm.com# met: redistributions of source code must retain the above copyright
87586SAli.Saidi@arm.com# notice, this list of conditions and the following disclaimer;
97586SAli.Saidi@arm.com# redistributions in binary form must reproduce the above copyright
107586SAli.Saidi@arm.com# notice, this list of conditions and the following disclaimer in the
117586SAli.Saidi@arm.com# documentation and/or other materials provided with the distribution;
127586SAli.Saidi@arm.com# neither the name of the copyright holders nor the names of its
133970Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from
143005Sstever@eecs.umich.edu# this software without specific prior written permission.
153005Sstever@eecs.umich.edu#
163005Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173005Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183005Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193005Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203005Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213005Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223005Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233005Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243005Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253005Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263005Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273005Sstever@eecs.umich.edu#
283005Sstever@eecs.umich.edu# Authors: Lisa Hsu
293005Sstever@eecs.umich.edu
303005Sstever@eecs.umich.edufrom os import getcwd
313005Sstever@eecs.umich.edufrom os.path import join as joinpath
323005Sstever@eecs.umich.edu
333005Sstever@eecs.umich.eduimport m5
343005Sstever@eecs.umich.edufrom m5.defines import buildEnv
353005Sstever@eecs.umich.edufrom m5.objects import *
363005Sstever@eecs.umich.edufrom m5.util import *
373005Sstever@eecs.umich.edufrom O3_ARM_v7a import *
383005Sstever@eecs.umich.edu
393005Sstever@eecs.umich.eduaddToPath('../common')
403005Sstever@eecs.umich.edu
416654Snate@binkert.orgdef getCPUClass(cpu_type):
426654Snate@binkert.org    """Returns the required cpu class and the mode of operation.
432889SN/A    """
442710SN/A
456654Snate@binkert.org    if cpu_type == "timing":
466654Snate@binkert.org        return TimingSimpleCPU, 'timing'
476654Snate@binkert.org    elif cpu_type == "detailed":
485457Ssaidi@eecs.umich.edu        return DerivO3CPU, 'timing'
496654Snate@binkert.org    elif cpu_type == "arm_detailed":
506654Snate@binkert.org        return O3_ARM_v7a_3, 'timing'
512934SN/A    elif cpu_type == "inorder":
522549SN/A        return InOrderCPU, 'timing'
532995SN/A    else:
543395Shsul@eecs.umich.edu        return AtomicSimpleCPU, 'atomic'
556981SLisa.Hsu@amd.com
563448Shsul@eecs.umich.edudef setCPUClass(options):
578920Snilay@cs.wisc.edu    """Returns two cpu classes and the initial mode of operation.
583444Sktlim@umich.edu
592889SN/A       Restoring from a checkpoint or fast forwarding through a benchmark
608920Snilay@cs.wisc.edu       can be done using one type of cpu, and then the actual
618920Snilay@cs.wisc.edu       simulation can be carried out using another type. This function
623322Shsul@eecs.umich.edu       returns these two types of cpus and the initial mode of operation
632710SN/A       depending on the options provided.
642710SN/A    """
652710SN/A
662710SN/A    if options.cpu_type == "detailed" or \
672710SN/A       options.cpu_type == "arm_detailed" or \
682710SN/A       options.cpu_type == "inorder" :
693322Shsul@eecs.umich.edu        if not options.caches and not options.ruby:
703304Sstever@eecs.umich.edu            fatal("O3/Inorder CPU must be used with caches")
713322Shsul@eecs.umich.edu
723322Shsul@eecs.umich.edu    TmpClass, test_mem_mode = getCPUClass(options.cpu_type)
733304Sstever@eecs.umich.edu    CPUClass = None
743481Shsul@eecs.umich.edu
753481Shsul@eecs.umich.edu    if options.checkpoint_restore != None:
762566SN/A        if options.restore_with_cpu != options.cpu_type:
779129Sandreas.hansson@arm.com            CPUClass = TmpClass
789129Sandreas.hansson@arm.com            TmpClass, test_mem_mode = getCPUClass(options.restore_with_cpu)
792995SN/A    elif options.fast_forward:
802995SN/A        CPUClass = TmpClass
813304Sstever@eecs.umich.edu        TmpClass = AtomicSimpleCPU
823304Sstever@eecs.umich.edu        test_mem_mode = 'atomic'
833304Sstever@eecs.umich.edu
842995SN/A    return (TmpClass, test_mem_mode, CPUClass)
852995SN/A
862995SN/Adef setWorkCountOptions(system, options):
872917SN/A    if options.work_item_id != None:
882995SN/A        system.work_item_id = options.work_item_id
898956Sjayneel@cs.wisc.edu    if options.work_begin_cpu_id_exit != None:
902995SN/A        system.work_begin_cpu_id_exit = options.work_begin_cpu_id_exit
918956Sjayneel@cs.wisc.edu    if options.work_end_exit_count != None:
923304Sstever@eecs.umich.edu        system.work_end_exit_count = options.work_end_exit_count
936135Sgblack@eecs.umich.edu    if options.work_end_checkpoint_count != None:
946135Sgblack@eecs.umich.edu        system.work_end_ckpt_count = options.work_end_checkpoint_count
956654Snate@binkert.org    if options.work_begin_exit_count != None:
963819Shsul@eecs.umich.edu        system.work_begin_exit_count = options.work_begin_exit_count
976654Snate@binkert.org    if options.work_begin_checkpoint_count != None:
985222Sksewell@umich.edu        system.work_begin_ckpt_count = options.work_begin_checkpoint_count
996654Snate@binkert.org    if options.work_cpus_checkpoint_count != None:
1003819Shsul@eecs.umich.edu        system.work_cpus_ckpt_count = options.work_cpus_checkpoint_count
1016654Snate@binkert.org
1027925Sgblack@eecs.umich.edudef findCptDir(options, maxtick, cptdir, testsys):
1037586SAli.Saidi@arm.com    """Figures out the directory from which the checkpointed state is read.
1048061SAli.Saidi@ARM.com
1058061SAli.Saidi@ARM.com    There are two different ways in which the directories holding checkpoints
1068061SAli.Saidi@ARM.com    can be named --
1073819Shsul@eecs.umich.edu    1. cpt.<benchmark name>.<instruction count when the checkpoint was taken>
1089059Snilay@cs.wisc.edu    2. cpt.<some number, usually the tick value when the checkpoint was taken>
1093819Shsul@eecs.umich.edu
1103873Sbinkertn@umich.edu    This function parses through the options to figure out which one of the
1113873Sbinkertn@umich.edu    above should be used for selecting the checkpoint, and then figures out
1123873Sbinkertn@umich.edu    the appropriate directory.
1133873Sbinkertn@umich.edu
1143873Sbinkertn@umich.edu    It also sets the value of the maximum tick value till which the simulation
1153873Sbinkertn@umich.edu    will run.
1168659SAli.Saidi@ARM.com    """
1178659SAli.Saidi@ARM.com
1186995Sgblack@eecs.umich.edu    from os.path import isdir, exists
1193668Srdreslin@umich.edu    from os import listdir
1206636Ssteve.reinhardt@amd.com    import re
1219288Sandreas.hansson@arm.com
1229408Sandreas.hansson@arm.com    if not isdir(cptdir):
1238839Sandreas.hansson@arm.com        fatal("checkpoint dir %s does not exist!", cptdir)
1248839Sandreas.hansson@arm.com
1258713Sandreas.hansson@arm.com    if options.at_instruction or options.simpoint:
1269408Sandreas.hansson@arm.com        inst = options.checkpoint_restore
1278839Sandreas.hansson@arm.com        if options.simpoint:
1288839Sandreas.hansson@arm.com            # assume workload 0 has the simpoint
1295142Ssaidi@eecs.umich.edu            if testsys.cpu[0].workload[0].simpoint == 0:
1308926Sandreas.hansson@arm.com                fatal('Unable to find simpoint')
1319317Sandreas.hansson@arm.com            inst += int(testsys.cpu[0].workload[0].simpoint)
1329317Sandreas.hansson@arm.com
1339317Sandreas.hansson@arm.com        checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % (options.bench, inst))
1349317Sandreas.hansson@arm.com        if not exists(checkpoint_dir):
1359317Sandreas.hansson@arm.com            fatal("Unable to find checkpoint directory %s", checkpoint_dir)
1368926Sandreas.hansson@arm.com    else:
1373312Sstever@eecs.umich.edu        dirs = listdir(cptdir)
1384968Sacolyte@umich.edu        expr = re.compile('cpt\.([0-9]*)')
1398926Sandreas.hansson@arm.com        cpts = []
1408887Sgeoffrey.blake@arm.com        for dir in dirs:
1418887Sgeoffrey.blake@arm.com            match = expr.match(dir)
1429384SAndreas.Sandberg@arm.com            if match:
1438887Sgeoffrey.blake@arm.com                cpts.append(match.group(1))
1448887Sgeoffrey.blake@arm.com
1454968Sacolyte@umich.edu        cpts.sort(lambda a,b: cmp(long(a), long(b)))
1463005Sstever@eecs.umich.edu
1476654Snate@binkert.org        cpt_num = options.checkpoint_restore
1483819Shsul@eecs.umich.edu        if cpt_num > len(cpts):
1496654Snate@binkert.org            fatal('Checkpoint %d not found', cpt_num)
1505222Sksewell@umich.edu
1516654Snate@binkert.org        maxtick = maxtick - int(cpts[cpt_num - 1])
1523819Shsul@eecs.umich.edu        checkpoint_dir = joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1])
1536654Snate@binkert.org
1546135Sgblack@eecs.umich.edu    return maxtick, checkpoint_dir
1557586SAli.Saidi@arm.com
1568661SAli.Saidi@ARM.comdef scriptCheckpoints(options, maxtick, cptdir):
1578661SAli.Saidi@ARM.com    if options.at_instruction or options.simpoint:
1583322Shsul@eecs.umich.edu        checkpoint_inst = int(options.take_checkpoints)
1599384SAndreas.Sandberg@arm.com
1608863Snilay@cs.wisc.edu        # maintain correct offset if we restored from some instruction
1617876Sgblack@eecs.umich.edu        if options.checkpoint_restore != None:
1624968Sacolyte@umich.edu            checkpoint_inst += options.checkpoint_restore
1638926Sandreas.hansson@arm.com
1644837Ssaidi@eecs.umich.edu        print "Creating checkpoint at inst:%d" % (checkpoint_inst)
1654837Ssaidi@eecs.umich.edu        exit_event = m5.simulate()
1669408Sandreas.hansson@arm.com        exit_cause = exit_event.getCause()
1679164Sandreas.hansson@arm.com        print "exit cause = %s" % exit_cause
1689408Sandreas.hansson@arm.com
1698845Sandreas.hansson@arm.com        # skip checkpoint instructions should they exist
1708845Sandreas.hansson@arm.com        while exit_cause == "checkpoint":
1714837Ssaidi@eecs.umich.edu            exit_event = m5.simulate()
1728659SAli.Saidi@ARM.com            exit_cause = exit_event.getCause()
1738801Sgblack@eecs.umich.edu
1743005Sstever@eecs.umich.edu        if exit_cause == "a thread reached the max instruction count":
1758801Sgblack@eecs.umich.edu            m5.checkpoint(joinpath(cptdir, "cpt.%s.%d" % \
1763005Sstever@eecs.umich.edu                    (options.bench, checkpoint_inst)))
1773005Sstever@eecs.umich.edu            print "Checkpoint written."
1783005Sstever@eecs.umich.edu
1792566SN/A    else:
1807861Sgblack@eecs.umich.edu        when, period = options.take_checkpoints.split(",", 1)
1817861Sgblack@eecs.umich.edu        when = int(when)
1827861Sgblack@eecs.umich.edu        period = int(period)
1838635Schris.emmons@arm.com        num_checkpoints = 0
1848635Schris.emmons@arm.com
1858635Schris.emmons@arm.com        exit_event = m5.simulate(when)
1869061Snilay@cs.wisc.edu        exit_cause = exit_event.getCause()
1873481Shsul@eecs.umich.edu        while exit_cause == "checkpoint":
188            exit_event = m5.simulate(when - m5.curTick())
189            exit_cause = exit_event.getCause()
190
191        if exit_cause == "simulate() limit reached":
192            m5.checkpoint(joinpath(cptdir, "cpt.%d"))
193            num_checkpoints += 1
194
195        sim_ticks = when
196        max_checkpoints = options.max_checkpoints
197
198        while num_checkpoints < max_checkpoints and \
199                exit_cause == "simulate() limit reached":
200            if (sim_ticks + period) > maxtick:
201                exit_event = m5.simulate(maxtick - sim_ticks)
202                exit_cause = exit_event.getCause()
203                break
204            else:
205                exit_event = m5.simulate(period)
206                exit_cause = exit_event.getCause()
207                sim_ticks += period
208                while exit_event.getCause() == "checkpoint":
209                    exit_event = m5.simulate(sim_ticks - m5.curTick())
210                if exit_event.getCause() == "simulate() limit reached":
211                    m5.checkpoint(joinpath(cptdir, "cpt.%d"))
212                    num_checkpoints += 1
213
214    return exit_cause
215
216def benchCheckpoints(options, maxtick, cptdir):
217    exit_event = m5.simulate(maxtick)
218    exit_cause = exit_event.getCause()
219
220    num_checkpoints = 0
221    max_checkpoints = options.max_checkpoints
222
223    while exit_cause == "checkpoint":
224        m5.checkpoint(joinpath(cptdir, "cpt.%d"))
225        num_checkpoints += 1
226        if num_checkpoints == max_checkpoints:
227            exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
228            break
229
230        exit_event = m5.simulate(maxtick - m5.curTick())
231        exit_cause = exit_event.getCause()
232
233    return exit_cause
234
235def repeatSwitch(testsys, repeat_switch_cpu_list, maxtick, switch_freq):
236    print "starting switch loop"
237    while True:
238        exit_event = m5.simulate(switch_freq)
239        exit_cause = exit_event.getCause()
240
241        if exit_cause != "simulate() limit reached":
242            return exit_cause
243
244        print "draining the system"
245        m5.doDrain(testsys)
246        m5.switchCpus(repeat_switch_cpu_list)
247        m5.resume(testsys)
248
249        tmp_cpu_list = []
250        for old_cpu, new_cpu in repeat_switch_cpu_list:
251            tmp_cpu_list.append((new_cpu, old_cpu))
252        repeat_switch_cpu_list = tmp_cpu_list
253
254        if (maxtick - m5.curTick()) <= switch_freq:
255            exit_event = m5.simulate(maxtick - m5.curTick())
256            return exit_event.getCause()
257
258def run(options, root, testsys, cpu_class):
259    if options.maxtick:
260        maxtick = options.maxtick
261    elif options.maxtime:
262        simtime = m5.ticks.seconds(simtime)
263        print "simulating for: ", simtime
264        maxtick = simtime
265    else:
266        maxtick = m5.MaxTick
267
268    if options.checkpoint_dir:
269        cptdir = options.checkpoint_dir
270    elif m5.options.outdir:
271        cptdir = m5.options.outdir
272    else:
273        cptdir = getcwd()
274
275    if options.fast_forward and options.checkpoint_restore != None:
276        fatal("Can't specify both --fast-forward and --checkpoint-restore")
277
278    if options.standard_switch and not options.caches:
279        fatal("Must specify --caches when using --standard-switch")
280
281    if options.standard_switch and options.repeat_switch:
282        fatal("Can't specify both --standard-switch and --repeat-switch")
283
284    if options.repeat_switch and options.take_checkpoints:
285        fatal("Can't specify both --repeat-switch and --take-checkpoints")
286
287    np = options.num_cpus
288    switch_cpus = None
289
290    if options.prog_interval:
291        for i in xrange(np):
292            testsys.cpu[i].progress_interval = options.prog_interval
293
294    if options.maxinsts:
295        for i in xrange(np):
296            testsys.cpu[i].max_insts_any_thread = options.maxinsts
297
298    if cpu_class:
299        switch_cpus = [cpu_class(defer_registration=True, cpu_id=(i))
300                       for i in xrange(np)]
301
302        for i in xrange(np):
303            if options.fast_forward:
304                testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
305            switch_cpus[i].system =  testsys
306            switch_cpus[i].workload = testsys.cpu[i].workload
307            switch_cpus[i].clock = testsys.cpu[i].clock
308            # simulation period
309            if options.maxinsts:
310                switch_cpus[i].max_insts_any_thread = options.maxinsts
311            # Add checker cpu if selected
312            if options.checker:
313                switch_cpus[i].addCheckerCpu()
314
315        testsys.switch_cpus = switch_cpus
316        switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
317
318    if options.repeat_switch:
319        if options.cpu_type == "arm_detailed":
320            if not options.caches:
321                print "O3 CPU must be used with caches"
322                sys.exit(1)
323
324            repeat_switch_cpus = [O3_ARM_v7a_3(defer_registration=True, \
325                                  cpu_id=(i)) for i in xrange(np)]
326        elif options.cpu_type == "detailed":
327            if not options.caches:
328                print "O3 CPU must be used with caches"
329                sys.exit(1)
330
331            repeat_switch_cpus = [DerivO3CPU(defer_registration=True, \
332                                  cpu_id=(i)) for i in xrange(np)]
333        elif options.cpu_type == "inorder":
334            print "inorder CPU switching not supported"
335            sys.exit(1)
336        elif options.cpu_type == "timing":
337            repeat_switch_cpus = [TimingSimpleCPU(defer_registration=True, \
338                                  cpu_id=(i)) for i in xrange(np)]
339        else:
340            repeat_switch_cpus = [AtomicSimpleCPU(defer_registration=True, \
341                                  cpu_id=(i)) for i in xrange(np)]
342
343        for i in xrange(np):
344            repeat_switch_cpus[i].system = testsys
345            repeat_switch_cpus[i].workload = testsys.cpu[i].workload
346            repeat_switch_cpus[i].clock = testsys.cpu[i].clock
347
348            if options.maxinsts:
349                repeat_switch_cpus[i].max_insts_any_thread = options.maxinsts
350
351            if options.checker:
352                repeat_switch_cpus[i].addCheckerCpu()
353
354        testsys.repeat_switch_cpus = repeat_switch_cpus
355
356        if cpu_class:
357            repeat_switch_cpu_list = [(switch_cpus[i], repeat_switch_cpus[i])
358                                      for i in xrange(np)]
359        else:
360            repeat_switch_cpu_list = [(testsys.cpu[i], repeat_switch_cpus[i])
361                                      for i in xrange(np)]
362
363    if options.standard_switch:
364        switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(i))
365                       for i in xrange(np)]
366        switch_cpus_1 = [DerivO3CPU(defer_registration=True, cpu_id=(i))
367                        for i in xrange(np)]
368
369        for i in xrange(np):
370            switch_cpus[i].system =  testsys
371            switch_cpus_1[i].system =  testsys
372            switch_cpus[i].workload = testsys.cpu[i].workload
373            switch_cpus_1[i].workload = testsys.cpu[i].workload
374            switch_cpus[i].clock = testsys.cpu[i].clock
375            switch_cpus_1[i].clock = testsys.cpu[i].clock
376
377            # if restoring, make atomic cpu simulate only a few instructions
378            if options.checkpoint_restore != None:
379                testsys.cpu[i].max_insts_any_thread = 1
380            # Fast forward to specified location if we are not restoring
381            elif options.fast_forward:
382                testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
383            # Fast forward to a simpoint (warning: time consuming)
384            elif options.simpoint:
385                if testsys.cpu[i].workload[0].simpoint == 0:
386                    fatal('simpoint not found')
387                testsys.cpu[i].max_insts_any_thread = \
388                    testsys.cpu[i].workload[0].simpoint
389            # No distance specified, just switch
390            else:
391                testsys.cpu[i].max_insts_any_thread = 1
392
393            # warmup period
394            if options.warmup_insts:
395                switch_cpus[i].max_insts_any_thread =  options.warmup_insts
396
397            # simulation period
398            if options.maxinsts:
399                switch_cpus_1[i].max_insts_any_thread = options.maxinsts
400
401            # attach the checker cpu if selected
402            if options.checker:
403                switch_cpus[i].addCheckerCpu()
404                switch_cpus_1[i].addCheckerCpu()
405
406        testsys.switch_cpus = switch_cpus
407        testsys.switch_cpus_1 = switch_cpus_1
408        switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
409        switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)]
410
411    # set the checkpoint in the cpu before m5.instantiate is called
412    if options.take_checkpoints != None and \
413           (options.simpoint or options.at_instruction):
414        offset = int(options.take_checkpoints)
415        # Set an instruction break point
416        if options.simpoint:
417            for i in xrange(np):
418                if testsys.cpu[i].workload[0].simpoint == 0:
419                    fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
420                checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
421                testsys.cpu[i].max_insts_any_thread = checkpoint_inst
422                # used for output below
423                options.take_checkpoints = checkpoint_inst
424        else:
425            options.take_checkpoints = offset
426            # Set all test cpus with the right number of instructions
427            # for the upcoming simulation
428            for i in xrange(np):
429                testsys.cpu[i].max_insts_any_thread = offset
430
431    checkpoint_dir = None
432    if options.checkpoint_restore != None:
433        maxtick, checkpoint_dir = findCptDir(options, maxtick, cptdir, testsys)
434    m5.instantiate(checkpoint_dir)
435
436    if options.standard_switch or cpu_class:
437        if options.standard_switch:
438            print "Switch at instruction count:%s" % \
439                    str(testsys.cpu[0].max_insts_any_thread)
440            exit_event = m5.simulate()
441        elif cpu_class and options.fast_forward:
442            print "Switch at instruction count:%s" % \
443                    str(testsys.cpu[0].max_insts_any_thread)
444            exit_event = m5.simulate()
445        else:
446            print "Switch at curTick count:%s" % str(10000)
447            exit_event = m5.simulate(10000)
448        print "Switched CPUS @ tick %s" % (m5.curTick())
449
450        # when you change to Timing (or Atomic), you halt the system
451        # given as argument.  When you are finished with the system
452        # changes (including switchCpus), you must resume the system
453        # manually.  You DON'T need to resume after just switching
454        # CPUs if you haven't changed anything on the system level.
455
456        m5.doDrain(testsys)
457        m5.changeToTiming(testsys)
458        m5.switchCpus(switch_cpu_list)
459        m5.resume(testsys)
460
461        if options.standard_switch:
462            print "Switch at instruction count:%d" % \
463                    (testsys.switch_cpus[0].max_insts_any_thread)
464
465            #warmup instruction count may have already been set
466            if options.warmup_insts:
467                exit_event = m5.simulate()
468            else:
469                exit_event = m5.simulate(options.standard_switch)
470            print "Switching CPUS @ tick %s" % (m5.curTick())
471            print "Simulation ends instruction count:%d" % \
472                    (testsys.switch_cpus_1[0].max_insts_any_thread)
473            m5.doDrain(testsys)
474            m5.switchCpus(switch_cpu_list1)
475            m5.resume(testsys)
476
477    # If we're taking and restoring checkpoints, use checkpoint_dir
478    # option only for finding the checkpoints to restore from.  This
479    # lets us test checkpointing by restoring from one set of
480    # checkpoints, generating a second set, and then comparing them.
481    if options.take_checkpoints and options.checkpoint_restore:
482        if m5.options.outdir:
483            cptdir = m5.options.outdir
484        else:
485            cptdir = getcwd()
486
487    if options.take_checkpoints != None :
488        # Checkpoints being taken via the command line at <when> and at
489        # subsequent periods of <period>.  Checkpoint instructions
490        # received from the benchmark running are ignored and skipped in
491        # favor of command line checkpoint instructions.
492        exit_cause = scriptCheckpoints(options, maxtick, cptdir)
493    else:
494        if options.fast_forward:
495            m5.stats.reset()
496        print "**** REAL SIMULATION ****"
497
498        # If checkpoints are being taken, then the checkpoint instruction
499        # will occur in the benchmark code it self.
500        if options.repeat_switch and maxtick > options.repeat_switch:
501            exit_cause = repeatSwitch(testsys, repeat_switch_cpu_list,
502                                      maxtick, options.repeat_switch)
503        else:
504            exit_cause = benchCheckpoints(options, maxtick, cptdir)
505
506    print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_cause)
507    if options.checkpoint_at_end:
508        m5.checkpoint(joinpath(cptdir, "cpt.%d"))
509