Simulation.py revision 9867:650fc966ed78
15952Ssaidi@eecs.umich.edu# Copyright (c) 2012-2013 ARM Limited
25952Ssaidi@eecs.umich.edu# All rights reserved
35952Ssaidi@eecs.umich.edu#
45952Ssaidi@eecs.umich.edu# The license below extends only to copyright in the software and shall
55952Ssaidi@eecs.umich.edu# not be construed as granting a license to any other intellectual
65952Ssaidi@eecs.umich.edu# property including but not limited to intellectual property relating
75952Ssaidi@eecs.umich.edu# to a hardware implementation of the functionality of the software
85952Ssaidi@eecs.umich.edu# licensed hereunder.  You may use the software subject to the license
95952Ssaidi@eecs.umich.edu# terms below provided that you ensure that this notice is replicated
105952Ssaidi@eecs.umich.edu# unmodified and in its entirety in all distributions of the software,
115952Ssaidi@eecs.umich.edu# modified or unmodified, in source code or in binary form.
125952Ssaidi@eecs.umich.edu#
135952Ssaidi@eecs.umich.edu# Copyright (c) 2006-2008 The Regents of The University of Michigan
145952Ssaidi@eecs.umich.edu# Copyright (c) 2010 Advanced Micro Devices, Inc.
155952Ssaidi@eecs.umich.edu# All rights reserved.
165952Ssaidi@eecs.umich.edu#
175952Ssaidi@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
185952Ssaidi@eecs.umich.edu# modification, are permitted provided that the following conditions are
195952Ssaidi@eecs.umich.edu# met: redistributions of source code must retain the above copyright
205952Ssaidi@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
215952Ssaidi@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
225952Ssaidi@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
235952Ssaidi@eecs.umich.edu# documentation and/or other materials provided with the distribution;
245952Ssaidi@eecs.umich.edu# neither the name of the copyright holders nor the names of its
255952Ssaidi@eecs.umich.edu# contributors may be used to endorse or promote products derived from
265952Ssaidi@eecs.umich.edu# this software without specific prior written permission.
275952Ssaidi@eecs.umich.edu#
285952Ssaidi@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
295952Ssaidi@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
305952Ssaidi@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
315952Ssaidi@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
325952Ssaidi@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
335952Ssaidi@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
348229Snate@binkert.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
358229Snate@binkert.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
366216Snate@binkert.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
376216Snate@binkert.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
386216Snate@binkert.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
398229Snate@binkert.org#
406216Snate@binkert.org# Authors: Lisa Hsu
416216Snate@binkert.org
426216Snate@binkert.orgimport sys
435952Ssaidi@eecs.umich.edufrom os import getcwd
446658Snate@binkert.orgfrom os.path import join as joinpath
455952Ssaidi@eecs.umich.edu
465952Ssaidi@eecs.umich.eduimport CpuConfig
475952Ssaidi@eecs.umich.eduimport MemConfig
485952Ssaidi@eecs.umich.edu
495952Ssaidi@eecs.umich.eduimport m5
505952Ssaidi@eecs.umich.edufrom m5.defines import buildEnv
515952Ssaidi@eecs.umich.edufrom m5.objects import *
525952Ssaidi@eecs.umich.edufrom m5.util import *
535952Ssaidi@eecs.umich.edu
545952Ssaidi@eecs.umich.eduaddToPath('../common')
555952Ssaidi@eecs.umich.edu
565952Ssaidi@eecs.umich.edudef getCPUClass(cpu_type):
576002Snate@binkert.org    """Returns the required cpu class and the mode of operation."""
585952Ssaidi@eecs.umich.edu    cls = CpuConfig.get(cpu_type)
595952Ssaidi@eecs.umich.edu    return cls, cls.memory_mode()
605952Ssaidi@eecs.umich.edu
615952Ssaidi@eecs.umich.edudef setCPUClass(options):
625952Ssaidi@eecs.umich.edu    """Returns two cpu classes and the initial mode of operation.
635952Ssaidi@eecs.umich.edu
645952Ssaidi@eecs.umich.edu       Restoring from a checkpoint or fast forwarding through a benchmark
655952Ssaidi@eecs.umich.edu       can be done using one type of cpu, and then the actual
665952Ssaidi@eecs.umich.edu       simulation can be carried out using another type. This function
675952Ssaidi@eecs.umich.edu       returns these two types of cpus and the initial mode of operation
685952Ssaidi@eecs.umich.edu       depending on the options provided.
695952Ssaidi@eecs.umich.edu    """
705952Ssaidi@eecs.umich.edu
715952Ssaidi@eecs.umich.edu    TmpClass, test_mem_mode = getCPUClass(options.cpu_type)
725952Ssaidi@eecs.umich.edu    CPUClass = None
735952Ssaidi@eecs.umich.edu    if TmpClass.require_caches() and \
745952Ssaidi@eecs.umich.edu            not options.caches and not options.ruby:
755952Ssaidi@eecs.umich.edu        fatal("%s must be used with caches" % options.cpu_type)
765952Ssaidi@eecs.umich.edu
775952Ssaidi@eecs.umich.edu    if options.checkpoint_restore != None:
785952Ssaidi@eecs.umich.edu        if options.restore_with_cpu != options.cpu_type:
795952Ssaidi@eecs.umich.edu            CPUClass = TmpClass
805952Ssaidi@eecs.umich.edu            TmpClass, test_mem_mode = getCPUClass(options.restore_with_cpu)
815952Ssaidi@eecs.umich.edu    elif options.fast_forward:
825952Ssaidi@eecs.umich.edu        CPUClass = TmpClass
835952Ssaidi@eecs.umich.edu        TmpClass = AtomicSimpleCPU
845952Ssaidi@eecs.umich.edu        test_mem_mode = 'atomic'
855952Ssaidi@eecs.umich.edu
865952Ssaidi@eecs.umich.edu    return (TmpClass, test_mem_mode, CPUClass)
875952Ssaidi@eecs.umich.edu
885952Ssaidi@eecs.umich.edudef setMemClass(options):
895952Ssaidi@eecs.umich.edu    """Returns a memory controller class."""
905952Ssaidi@eecs.umich.edu
915952Ssaidi@eecs.umich.edu    return MemConfig.get(options.mem_type)
925952Ssaidi@eecs.umich.edu
935952Ssaidi@eecs.umich.edudef setWorkCountOptions(system, options):
945952Ssaidi@eecs.umich.edu    if options.work_item_id != None:
955952Ssaidi@eecs.umich.edu        system.work_item_id = options.work_item_id
965952Ssaidi@eecs.umich.edu    if options.work_begin_cpu_id_exit != None:
975952Ssaidi@eecs.umich.edu        system.work_begin_cpu_id_exit = options.work_begin_cpu_id_exit
985952Ssaidi@eecs.umich.edu    if options.work_end_exit_count != None:
995952Ssaidi@eecs.umich.edu        system.work_end_exit_count = options.work_end_exit_count
1005952Ssaidi@eecs.umich.edu    if options.work_end_checkpoint_count != None:
1015952Ssaidi@eecs.umich.edu        system.work_end_ckpt_count = options.work_end_checkpoint_count
1025952Ssaidi@eecs.umich.edu    if options.work_begin_exit_count != None:
1035952Ssaidi@eecs.umich.edu        system.work_begin_exit_count = options.work_begin_exit_count
1045952Ssaidi@eecs.umich.edu    if options.work_begin_checkpoint_count != None:
1055952Ssaidi@eecs.umich.edu        system.work_begin_ckpt_count = options.work_begin_checkpoint_count
1065952Ssaidi@eecs.umich.edu    if options.work_cpus_checkpoint_count != None:
1075952Ssaidi@eecs.umich.edu        system.work_cpus_ckpt_count = options.work_cpus_checkpoint_count
1085952Ssaidi@eecs.umich.edu
1095952Ssaidi@eecs.umich.edudef findCptDir(options, cptdir, testsys):
1105952Ssaidi@eecs.umich.edu    """Figures out the directory from which the checkpointed state is read.
1115952Ssaidi@eecs.umich.edu
1125952Ssaidi@eecs.umich.edu    There are two different ways in which the directories holding checkpoints
1135952Ssaidi@eecs.umich.edu    can be named --
1145952Ssaidi@eecs.umich.edu    1. cpt.<benchmark name>.<instruction count when the checkpoint was taken>
1155952Ssaidi@eecs.umich.edu    2. cpt.<some number, usually the tick value when the checkpoint was taken>
1165952Ssaidi@eecs.umich.edu
1175952Ssaidi@eecs.umich.edu    This function parses through the options to figure out which one of the
1185952Ssaidi@eecs.umich.edu    above should be used for selecting the checkpoint, and then figures out
1195952Ssaidi@eecs.umich.edu    the appropriate directory.
1205952Ssaidi@eecs.umich.edu    """
1215952Ssaidi@eecs.umich.edu
1225952Ssaidi@eecs.umich.edu    from os.path import isdir, exists
1235952Ssaidi@eecs.umich.edu    from os import listdir
1245952Ssaidi@eecs.umich.edu    import re
1255952Ssaidi@eecs.umich.edu
1265952Ssaidi@eecs.umich.edu    if not isdir(cptdir):
1275952Ssaidi@eecs.umich.edu        fatal("checkpoint dir %s does not exist!", cptdir)
1285952Ssaidi@eecs.umich.edu
1295952Ssaidi@eecs.umich.edu    cpt_starttick = 0
1305952Ssaidi@eecs.umich.edu    if options.at_instruction or options.simpoint:
1315952Ssaidi@eecs.umich.edu        inst = options.checkpoint_restore
1325952Ssaidi@eecs.umich.edu        if options.simpoint:
1335952Ssaidi@eecs.umich.edu            # assume workload 0 has the simpoint
1345952Ssaidi@eecs.umich.edu            if testsys.cpu[0].workload[0].simpoint == 0:
1355952Ssaidi@eecs.umich.edu                fatal('Unable to find simpoint')
1365952Ssaidi@eecs.umich.edu            inst += int(testsys.cpu[0].workload[0].simpoint)
1375952Ssaidi@eecs.umich.edu
1385952Ssaidi@eecs.umich.edu        checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % (options.bench, inst))
1395952Ssaidi@eecs.umich.edu        if not exists(checkpoint_dir):
1405952Ssaidi@eecs.umich.edu            fatal("Unable to find checkpoint directory %s", checkpoint_dir)
1415952Ssaidi@eecs.umich.edu    else:
1425952Ssaidi@eecs.umich.edu        dirs = listdir(cptdir)
1435952Ssaidi@eecs.umich.edu        expr = re.compile('cpt\.([0-9]*)')
1445952Ssaidi@eecs.umich.edu        cpts = []
1455952Ssaidi@eecs.umich.edu        for dir in dirs:
1465952Ssaidi@eecs.umich.edu            match = expr.match(dir)
1475952Ssaidi@eecs.umich.edu            if match:
1485952Ssaidi@eecs.umich.edu                cpts.append(match.group(1))
1495952Ssaidi@eecs.umich.edu
1505952Ssaidi@eecs.umich.edu        cpts.sort(lambda a,b: cmp(long(a), long(b)))
1515952Ssaidi@eecs.umich.edu
1525952Ssaidi@eecs.umich.edu        cpt_num = options.checkpoint_restore
1535952Ssaidi@eecs.umich.edu        if cpt_num > len(cpts):
1545952Ssaidi@eecs.umich.edu            fatal('Checkpoint %d not found', cpt_num)
1555952Ssaidi@eecs.umich.edu
1565952Ssaidi@eecs.umich.edu        cpt_starttick = int(cpts[cpt_num - 1])
1575952Ssaidi@eecs.umich.edu        checkpoint_dir = joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1])
1585952Ssaidi@eecs.umich.edu
1595952Ssaidi@eecs.umich.edu    return cpt_starttick, checkpoint_dir
1605952Ssaidi@eecs.umich.edu
1615952Ssaidi@eecs.umich.edudef scriptCheckpoints(options, maxtick, cptdir):
1625952Ssaidi@eecs.umich.edu    if options.at_instruction or options.simpoint:
1635952Ssaidi@eecs.umich.edu        checkpoint_inst = int(options.take_checkpoints)
1645952Ssaidi@eecs.umich.edu
1655952Ssaidi@eecs.umich.edu        # maintain correct offset if we restored from some instruction
1665952Ssaidi@eecs.umich.edu        if options.checkpoint_restore != None:
1675952Ssaidi@eecs.umich.edu            checkpoint_inst += options.checkpoint_restore
1685952Ssaidi@eecs.umich.edu
1695952Ssaidi@eecs.umich.edu        print "Creating checkpoint at inst:%d" % (checkpoint_inst)
1705952Ssaidi@eecs.umich.edu        exit_event = m5.simulate()
1715952Ssaidi@eecs.umich.edu        exit_cause = exit_event.getCause()
1725952Ssaidi@eecs.umich.edu        print "exit cause = %s" % exit_cause
1735952Ssaidi@eecs.umich.edu
1745952Ssaidi@eecs.umich.edu        # skip checkpoint instructions should they exist
1755952Ssaidi@eecs.umich.edu        while exit_cause == "checkpoint":
1765952Ssaidi@eecs.umich.edu            exit_event = m5.simulate()
1775952Ssaidi@eecs.umich.edu            exit_cause = exit_event.getCause()
1785952Ssaidi@eecs.umich.edu
1795952Ssaidi@eecs.umich.edu        if exit_cause == "a thread reached the max instruction count":
1805952Ssaidi@eecs.umich.edu            m5.checkpoint(joinpath(cptdir, "cpt.%s.%d" % \
1815952Ssaidi@eecs.umich.edu                    (options.bench, checkpoint_inst)))
1825952Ssaidi@eecs.umich.edu            print "Checkpoint written."
1835952Ssaidi@eecs.umich.edu
1845952Ssaidi@eecs.umich.edu    else:
1855952Ssaidi@eecs.umich.edu        when, period = options.take_checkpoints.split(",", 1)
1865952Ssaidi@eecs.umich.edu        when = int(when)
1875952Ssaidi@eecs.umich.edu        period = int(period)
1885952Ssaidi@eecs.umich.edu        num_checkpoints = 0
1895952Ssaidi@eecs.umich.edu
1905952Ssaidi@eecs.umich.edu        exit_event = m5.simulate(when - m5.curTick())
1915952Ssaidi@eecs.umich.edu        exit_cause = exit_event.getCause()
1925952Ssaidi@eecs.umich.edu        while exit_cause == "checkpoint":
1935952Ssaidi@eecs.umich.edu            exit_event = m5.simulate(when - m5.curTick())
1945952Ssaidi@eecs.umich.edu            exit_cause = exit_event.getCause()
1955952Ssaidi@eecs.umich.edu
1965952Ssaidi@eecs.umich.edu        if exit_cause == "simulate() limit reached":
1975952Ssaidi@eecs.umich.edu            m5.checkpoint(joinpath(cptdir, "cpt.%d"))
1985952Ssaidi@eecs.umich.edu            num_checkpoints += 1
1995952Ssaidi@eecs.umich.edu
2005952Ssaidi@eecs.umich.edu        sim_ticks = when
2015952Ssaidi@eecs.umich.edu        max_checkpoints = options.max_checkpoints
2025952Ssaidi@eecs.umich.edu
2035952Ssaidi@eecs.umich.edu        while num_checkpoints < max_checkpoints and \
2045952Ssaidi@eecs.umich.edu                exit_cause == "simulate() limit reached":
2055952Ssaidi@eecs.umich.edu            if (sim_ticks + period) > maxtick:
2065952Ssaidi@eecs.umich.edu                exit_event = m5.simulate(maxtick - sim_ticks)
2075952Ssaidi@eecs.umich.edu                exit_cause = exit_event.getCause()
2085952Ssaidi@eecs.umich.edu                break
2095952Ssaidi@eecs.umich.edu            else:
2105952Ssaidi@eecs.umich.edu                exit_event = m5.simulate(period)
2115952Ssaidi@eecs.umich.edu                exit_cause = exit_event.getCause()
2125952Ssaidi@eecs.umich.edu                sim_ticks += period
2135952Ssaidi@eecs.umich.edu                while exit_event.getCause() == "checkpoint":
2145952Ssaidi@eecs.umich.edu                    exit_event = m5.simulate(sim_ticks - m5.curTick())
2155952Ssaidi@eecs.umich.edu                if exit_event.getCause() == "simulate() limit reached":
2165952Ssaidi@eecs.umich.edu                    m5.checkpoint(joinpath(cptdir, "cpt.%d"))
2175952Ssaidi@eecs.umich.edu                    num_checkpoints += 1
2185952Ssaidi@eecs.umich.edu
2195952Ssaidi@eecs.umich.edu    return exit_event
2205952Ssaidi@eecs.umich.edu
2215952Ssaidi@eecs.umich.edudef benchCheckpoints(options, maxtick, cptdir):
2225952Ssaidi@eecs.umich.edu    exit_event = m5.simulate(maxtick - m5.curTick())
2235952Ssaidi@eecs.umich.edu    exit_cause = exit_event.getCause()
2245952Ssaidi@eecs.umich.edu
2255952Ssaidi@eecs.umich.edu    num_checkpoints = 0
2265952Ssaidi@eecs.umich.edu    max_checkpoints = options.max_checkpoints
2275952Ssaidi@eecs.umich.edu
2285952Ssaidi@eecs.umich.edu    while exit_cause == "checkpoint":
2295952Ssaidi@eecs.umich.edu        m5.checkpoint(joinpath(cptdir, "cpt.%d"))
2305952Ssaidi@eecs.umich.edu        num_checkpoints += 1
2315952Ssaidi@eecs.umich.edu        if num_checkpoints == max_checkpoints:
2325952Ssaidi@eecs.umich.edu            exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
2335952Ssaidi@eecs.umich.edu            break
2345952Ssaidi@eecs.umich.edu
2355952Ssaidi@eecs.umich.edu        exit_event = m5.simulate(maxtick - m5.curTick())
2365952Ssaidi@eecs.umich.edu        exit_cause = exit_event.getCause()
2375952Ssaidi@eecs.umich.edu
2385952Ssaidi@eecs.umich.edu    return exit_event
2395952Ssaidi@eecs.umich.edu
2405952Ssaidi@eecs.umich.edudef repeatSwitch(testsys, repeat_switch_cpu_list, maxtick, switch_freq):
2415952Ssaidi@eecs.umich.edu    print "starting switch loop"
2425952Ssaidi@eecs.umich.edu    while True:
2435952Ssaidi@eecs.umich.edu        exit_event = m5.simulate(switch_freq)
2445952Ssaidi@eecs.umich.edu        exit_cause = exit_event.getCause()
2455952Ssaidi@eecs.umich.edu
2465952Ssaidi@eecs.umich.edu        if exit_cause != "simulate() limit reached":
2475952Ssaidi@eecs.umich.edu            return exit_event
2485952Ssaidi@eecs.umich.edu
2495952Ssaidi@eecs.umich.edu        m5.switchCpus(testsys, repeat_switch_cpu_list)
2505952Ssaidi@eecs.umich.edu
2515952Ssaidi@eecs.umich.edu        tmp_cpu_list = []
2525952Ssaidi@eecs.umich.edu        for old_cpu, new_cpu in repeat_switch_cpu_list:
2535952Ssaidi@eecs.umich.edu            tmp_cpu_list.append((new_cpu, old_cpu))
2545952Ssaidi@eecs.umich.edu        repeat_switch_cpu_list = tmp_cpu_list
2555952Ssaidi@eecs.umich.edu
2565952Ssaidi@eecs.umich.edu        if (maxtick - m5.curTick()) <= switch_freq:
2575952Ssaidi@eecs.umich.edu            exit_event = m5.simulate(maxtick - m5.curTick())
2585952Ssaidi@eecs.umich.edu            return exit_event
2595952Ssaidi@eecs.umich.edu
2605952Ssaidi@eecs.umich.edudef run(options, root, testsys, cpu_class):
2615952Ssaidi@eecs.umich.edu    if options.checkpoint_dir:
2625952Ssaidi@eecs.umich.edu        cptdir = options.checkpoint_dir
2635952Ssaidi@eecs.umich.edu    elif m5.options.outdir:
2645952Ssaidi@eecs.umich.edu        cptdir = m5.options.outdir
2655952Ssaidi@eecs.umich.edu    else:
2665952Ssaidi@eecs.umich.edu        cptdir = getcwd()
2675952Ssaidi@eecs.umich.edu
2685952Ssaidi@eecs.umich.edu    if options.fast_forward and options.checkpoint_restore != None:
2695952Ssaidi@eecs.umich.edu        fatal("Can't specify both --fast-forward and --checkpoint-restore")
2705952Ssaidi@eecs.umich.edu
2715952Ssaidi@eecs.umich.edu    if options.standard_switch and not options.caches:
2725952Ssaidi@eecs.umich.edu        fatal("Must specify --caches when using --standard-switch")
2735952Ssaidi@eecs.umich.edu
2745952Ssaidi@eecs.umich.edu    if options.standard_switch and options.repeat_switch:
2755952Ssaidi@eecs.umich.edu        fatal("Can't specify both --standard-switch and --repeat-switch")
2765952Ssaidi@eecs.umich.edu
2775952Ssaidi@eecs.umich.edu    if options.repeat_switch and options.take_checkpoints:
2785952Ssaidi@eecs.umich.edu        fatal("Can't specify both --repeat-switch and --take-checkpoints")
2795952Ssaidi@eecs.umich.edu
2805952Ssaidi@eecs.umich.edu    np = options.num_cpus
2815952Ssaidi@eecs.umich.edu    switch_cpus = None
2825952Ssaidi@eecs.umich.edu
2835952Ssaidi@eecs.umich.edu    if options.prog_interval:
2845952Ssaidi@eecs.umich.edu        for i in xrange(np):
2855952Ssaidi@eecs.umich.edu            testsys.cpu[i].progress_interval = options.prog_interval
2865952Ssaidi@eecs.umich.edu
2875952Ssaidi@eecs.umich.edu    if options.maxinsts:
2885952Ssaidi@eecs.umich.edu        for i in xrange(np):
2895952Ssaidi@eecs.umich.edu            testsys.cpu[i].max_insts_any_thread = options.maxinsts
2905952Ssaidi@eecs.umich.edu
2915952Ssaidi@eecs.umich.edu    if cpu_class:
2925952Ssaidi@eecs.umich.edu        switch_cpus = [cpu_class(switched_out=True, cpu_id=(i))
2935952Ssaidi@eecs.umich.edu                       for i in xrange(np)]
2945952Ssaidi@eecs.umich.edu
2955952Ssaidi@eecs.umich.edu        for i in xrange(np):
2965952Ssaidi@eecs.umich.edu            if options.fast_forward:
2975952Ssaidi@eecs.umich.edu                testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
2985952Ssaidi@eecs.umich.edu            switch_cpus[i].system =  testsys
2995952Ssaidi@eecs.umich.edu            switch_cpus[i].workload = testsys.cpu[i].workload
3005952Ssaidi@eecs.umich.edu            switch_cpus[i].clk_domain = testsys.cpu[i].clk_domain
3015952Ssaidi@eecs.umich.edu            # simulation period
3025952Ssaidi@eecs.umich.edu            if options.maxinsts:
3035952Ssaidi@eecs.umich.edu                switch_cpus[i].max_insts_any_thread = options.maxinsts
3045952Ssaidi@eecs.umich.edu            # Add checker cpu if selected
3055952Ssaidi@eecs.umich.edu            if options.checker:
3065952Ssaidi@eecs.umich.edu                switch_cpus[i].addCheckerCpu()
3075952Ssaidi@eecs.umich.edu
3085952Ssaidi@eecs.umich.edu        testsys.switch_cpus = switch_cpus
3095952Ssaidi@eecs.umich.edu        switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
3105952Ssaidi@eecs.umich.edu
3115952Ssaidi@eecs.umich.edu    if options.repeat_switch:
3125952Ssaidi@eecs.umich.edu        switch_class = getCPUClass(options.cpu_type)[0]
3135952Ssaidi@eecs.umich.edu        if switch_class.require_caches() and \
3145952Ssaidi@eecs.umich.edu                not options.caches:
3155952Ssaidi@eecs.umich.edu            print "%s: Must be used with caches" % str(switch_class)
3165952Ssaidi@eecs.umich.edu            sys.exit(1)
3175952Ssaidi@eecs.umich.edu        if not switch_class.support_take_over():
3185952Ssaidi@eecs.umich.edu            print "%s: CPU switching not supported" % str(switch_class)
3195952Ssaidi@eecs.umich.edu            sys.exit(1)
3205952Ssaidi@eecs.umich.edu
3215952Ssaidi@eecs.umich.edu        repeat_switch_cpus = [switch_class(switched_out=True, \
3225952Ssaidi@eecs.umich.edu                                               cpu_id=(i)) for i in xrange(np)]
3235952Ssaidi@eecs.umich.edu
3245952Ssaidi@eecs.umich.edu        for i in xrange(np):
3255952Ssaidi@eecs.umich.edu            repeat_switch_cpus[i].system = testsys
3265952Ssaidi@eecs.umich.edu            repeat_switch_cpus[i].workload = testsys.cpu[i].workload
3275952Ssaidi@eecs.umich.edu            repeat_switch_cpus[i].clk_domain = testsys.cpu[i].clk_domain
3285952Ssaidi@eecs.umich.edu
3295952Ssaidi@eecs.umich.edu            if options.maxinsts:
3305952Ssaidi@eecs.umich.edu                repeat_switch_cpus[i].max_insts_any_thread = options.maxinsts
3315952Ssaidi@eecs.umich.edu
3325952Ssaidi@eecs.umich.edu            if options.checker:
3335952Ssaidi@eecs.umich.edu                repeat_switch_cpus[i].addCheckerCpu()
3345952Ssaidi@eecs.umich.edu
3355952Ssaidi@eecs.umich.edu        testsys.repeat_switch_cpus = repeat_switch_cpus
3365952Ssaidi@eecs.umich.edu
3375952Ssaidi@eecs.umich.edu        if cpu_class:
3385952Ssaidi@eecs.umich.edu            repeat_switch_cpu_list = [(switch_cpus[i], repeat_switch_cpus[i])
3395952Ssaidi@eecs.umich.edu                                      for i in xrange(np)]
3405952Ssaidi@eecs.umich.edu        else:
3415952Ssaidi@eecs.umich.edu            repeat_switch_cpu_list = [(testsys.cpu[i], repeat_switch_cpus[i])
3425952Ssaidi@eecs.umich.edu                                      for i in xrange(np)]
3435952Ssaidi@eecs.umich.edu
3445952Ssaidi@eecs.umich.edu    if options.standard_switch:
3455952Ssaidi@eecs.umich.edu        switch_cpus = [TimingSimpleCPU(switched_out=True, cpu_id=(i))
3465952Ssaidi@eecs.umich.edu                       for i in xrange(np)]
3475952Ssaidi@eecs.umich.edu        switch_cpus_1 = [DerivO3CPU(switched_out=True, cpu_id=(i))
3485952Ssaidi@eecs.umich.edu                        for i in xrange(np)]
3495952Ssaidi@eecs.umich.edu
3505952Ssaidi@eecs.umich.edu        for i in xrange(np):
3515952Ssaidi@eecs.umich.edu            switch_cpus[i].system =  testsys
3525952Ssaidi@eecs.umich.edu            switch_cpus_1[i].system =  testsys
3535952Ssaidi@eecs.umich.edu            switch_cpus[i].workload = testsys.cpu[i].workload
3545952Ssaidi@eecs.umich.edu            switch_cpus_1[i].workload = testsys.cpu[i].workload
3555952Ssaidi@eecs.umich.edu            switch_cpus[i].clk_domain = testsys.cpu[i].clk_domain
3565952Ssaidi@eecs.umich.edu            switch_cpus_1[i].clk_domain = testsys.cpu[i].clk_domain
3575952Ssaidi@eecs.umich.edu
3585952Ssaidi@eecs.umich.edu            # if restoring, make atomic cpu simulate only a few instructions
3595952Ssaidi@eecs.umich.edu            if options.checkpoint_restore != None:
3605952Ssaidi@eecs.umich.edu                testsys.cpu[i].max_insts_any_thread = 1
3615952Ssaidi@eecs.umich.edu            # Fast forward to specified location if we are not restoring
3625952Ssaidi@eecs.umich.edu            elif options.fast_forward:
3635952Ssaidi@eecs.umich.edu                testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
3645952Ssaidi@eecs.umich.edu            # Fast forward to a simpoint (warning: time consuming)
3655952Ssaidi@eecs.umich.edu            elif options.simpoint:
3665952Ssaidi@eecs.umich.edu                if testsys.cpu[i].workload[0].simpoint == 0:
3675952Ssaidi@eecs.umich.edu                    fatal('simpoint not found')
3685952Ssaidi@eecs.umich.edu                testsys.cpu[i].max_insts_any_thread = \
3695952Ssaidi@eecs.umich.edu                    testsys.cpu[i].workload[0].simpoint
3705952Ssaidi@eecs.umich.edu            # No distance specified, just switch
3715952Ssaidi@eecs.umich.edu            else:
3725952Ssaidi@eecs.umich.edu                testsys.cpu[i].max_insts_any_thread = 1
3735952Ssaidi@eecs.umich.edu
3745952Ssaidi@eecs.umich.edu            # warmup period
3755952Ssaidi@eecs.umich.edu            if options.warmup_insts:
3765952Ssaidi@eecs.umich.edu                switch_cpus[i].max_insts_any_thread =  options.warmup_insts
3775952Ssaidi@eecs.umich.edu
3785952Ssaidi@eecs.umich.edu            # simulation period
3795952Ssaidi@eecs.umich.edu            if options.maxinsts:
3805952Ssaidi@eecs.umich.edu                switch_cpus_1[i].max_insts_any_thread = options.maxinsts
3815952Ssaidi@eecs.umich.edu
3825952Ssaidi@eecs.umich.edu            # attach the checker cpu if selected
3835952Ssaidi@eecs.umich.edu            if options.checker:
3845952Ssaidi@eecs.umich.edu                switch_cpus[i].addCheckerCpu()
3855952Ssaidi@eecs.umich.edu                switch_cpus_1[i].addCheckerCpu()
3865952Ssaidi@eecs.umich.edu
3875952Ssaidi@eecs.umich.edu        testsys.switch_cpus = switch_cpus
3885952Ssaidi@eecs.umich.edu        testsys.switch_cpus_1 = switch_cpus_1
3895952Ssaidi@eecs.umich.edu        switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
3905952Ssaidi@eecs.umich.edu        switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)]
3915952Ssaidi@eecs.umich.edu
3925952Ssaidi@eecs.umich.edu    # set the checkpoint in the cpu before m5.instantiate is called
3935952Ssaidi@eecs.umich.edu    if options.take_checkpoints != None and \
3945952Ssaidi@eecs.umich.edu           (options.simpoint or options.at_instruction):
3955952Ssaidi@eecs.umich.edu        offset = int(options.take_checkpoints)
3965952Ssaidi@eecs.umich.edu        # Set an instruction break point
3975952Ssaidi@eecs.umich.edu        if options.simpoint:
3985952Ssaidi@eecs.umich.edu            for i in xrange(np):
3995952Ssaidi@eecs.umich.edu                if testsys.cpu[i].workload[0].simpoint == 0:
4005952Ssaidi@eecs.umich.edu                    fatal('no simpoint for testsys.cpu[%d].workload[0]', i)
4015952Ssaidi@eecs.umich.edu                checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
4025952Ssaidi@eecs.umich.edu                testsys.cpu[i].max_insts_any_thread = checkpoint_inst
4035952Ssaidi@eecs.umich.edu                # used for output below
4045952Ssaidi@eecs.umich.edu                options.take_checkpoints = checkpoint_inst
4055952Ssaidi@eecs.umich.edu        else:
4065952Ssaidi@eecs.umich.edu            options.take_checkpoints = offset
4075952Ssaidi@eecs.umich.edu            # Set all test cpus with the right number of instructions
4085952Ssaidi@eecs.umich.edu            # for the upcoming simulation
4095952Ssaidi@eecs.umich.edu            for i in xrange(np):
4105952Ssaidi@eecs.umich.edu                testsys.cpu[i].max_insts_any_thread = offset
4117823Ssteve.reinhardt@amd.com
4125952Ssaidi@eecs.umich.edu    checkpoint_dir = None
4135952Ssaidi@eecs.umich.edu    if options.checkpoint_restore:
4145952Ssaidi@eecs.umich.edu        cpt_starttick, checkpoint_dir = findCptDir(options, cptdir, testsys)
4155952Ssaidi@eecs.umich.edu    m5.instantiate(checkpoint_dir)
4165952Ssaidi@eecs.umich.edu
4175952Ssaidi@eecs.umich.edu    # Handle the max tick settings now that tick frequency was resolved
4185952Ssaidi@eecs.umich.edu    # during system instantiation
4195952Ssaidi@eecs.umich.edu    # NOTE: the maxtick variable here is in absolute ticks, so it must
4205952Ssaidi@eecs.umich.edu    # include any simulated ticks before a checkpoint
4215952Ssaidi@eecs.umich.edu    explicit_maxticks = 0
4225952Ssaidi@eecs.umich.edu    maxtick_from_abs = m5.MaxTick
4235952Ssaidi@eecs.umich.edu    maxtick_from_rel = m5.MaxTick
4245952Ssaidi@eecs.umich.edu    maxtick_from_maxtime = m5.MaxTick
4255952Ssaidi@eecs.umich.edu    if options.abs_max_tick:
4265952Ssaidi@eecs.umich.edu        maxtick_from_abs = options.abs_max_tick
4275952Ssaidi@eecs.umich.edu        explicit_maxticks += 1
4285952Ssaidi@eecs.umich.edu    if options.rel_max_tick:
4295952Ssaidi@eecs.umich.edu        maxtick_from_rel = options.rel_max_tick
4305952Ssaidi@eecs.umich.edu        if options.checkpoint_restore:
4315952Ssaidi@eecs.umich.edu            # NOTE: this may need to be updated if checkpoints ever store
4325952Ssaidi@eecs.umich.edu            # the ticks per simulated second
4335952Ssaidi@eecs.umich.edu            maxtick_from_rel += cpt_starttick
4345952Ssaidi@eecs.umich.edu            if options.at_instruction or options.simpoint:
4355952Ssaidi@eecs.umich.edu                warn("Relative max tick specified with --at-instruction or" \
4365952Ssaidi@eecs.umich.edu                     " --simpoint\n      These options don't specify the " \
4375952Ssaidi@eecs.umich.edu                     "checkpoint start tick, so assuming\n      you mean " \
4385952Ssaidi@eecs.umich.edu                     "absolute max tick")
4395952Ssaidi@eecs.umich.edu        explicit_maxticks += 1
4405952Ssaidi@eecs.umich.edu    if options.maxtime:
4415952Ssaidi@eecs.umich.edu        maxtick_from_maxtime = m5.ticks.fromSeconds(options.maxtime)
4425952Ssaidi@eecs.umich.edu        explicit_maxticks += 1
4435952Ssaidi@eecs.umich.edu    if explicit_maxticks > 1:
4445952Ssaidi@eecs.umich.edu        warn("Specified multiple of --abs-max-tick, --rel-max-tick, --maxtime."\
4455952Ssaidi@eecs.umich.edu             " Using least")
4465952Ssaidi@eecs.umich.edu    maxtick = min([maxtick_from_abs, maxtick_from_rel, maxtick_from_maxtime])
4475952Ssaidi@eecs.umich.edu
4485952Ssaidi@eecs.umich.edu    if options.checkpoint_restore != None and maxtick < cpt_starttick:
4495952Ssaidi@eecs.umich.edu        fatal("Bad maxtick (%d) specified: " \
4505952Ssaidi@eecs.umich.edu              "Checkpoint starts starts from tick: %d", maxtick, cpt_starttick)
4515952Ssaidi@eecs.umich.edu
4525952Ssaidi@eecs.umich.edu    if options.standard_switch or cpu_class:
4535952Ssaidi@eecs.umich.edu        if options.standard_switch:
4545952Ssaidi@eecs.umich.edu            print "Switch at instruction count:%s" % \
4555952Ssaidi@eecs.umich.edu                    str(testsys.cpu[0].max_insts_any_thread)
4565952Ssaidi@eecs.umich.edu            exit_event = m5.simulate()
4575952Ssaidi@eecs.umich.edu        elif cpu_class and options.fast_forward:
4585952Ssaidi@eecs.umich.edu            print "Switch at instruction count:%s" % \
4595952Ssaidi@eecs.umich.edu                    str(testsys.cpu[0].max_insts_any_thread)
4605952Ssaidi@eecs.umich.edu            exit_event = m5.simulate()
4615952Ssaidi@eecs.umich.edu        else:
4625952Ssaidi@eecs.umich.edu            print "Switch at curTick count:%s" % str(10000)
4635952Ssaidi@eecs.umich.edu            exit_event = m5.simulate(10000)
4645952Ssaidi@eecs.umich.edu        print "Switched CPUS @ tick %s" % (m5.curTick())
4655952Ssaidi@eecs.umich.edu
4665952Ssaidi@eecs.umich.edu        m5.switchCpus(testsys, switch_cpu_list)
4675952Ssaidi@eecs.umich.edu
4685952Ssaidi@eecs.umich.edu        if options.standard_switch:
4695952Ssaidi@eecs.umich.edu            print "Switch at instruction count:%d" % \
4705952Ssaidi@eecs.umich.edu                    (testsys.switch_cpus[0].max_insts_any_thread)
4715952Ssaidi@eecs.umich.edu
4725952Ssaidi@eecs.umich.edu            #warmup instruction count may have already been set
4735952Ssaidi@eecs.umich.edu            if options.warmup_insts:
4745952Ssaidi@eecs.umich.edu                exit_event = m5.simulate()
4755952Ssaidi@eecs.umich.edu            else:
4765952Ssaidi@eecs.umich.edu                exit_event = m5.simulate(options.standard_switch)
4775952Ssaidi@eecs.umich.edu            print "Switching CPUS @ tick %s" % (m5.curTick())
4785952Ssaidi@eecs.umich.edu            print "Simulation ends instruction count:%d" % \
4795952Ssaidi@eecs.umich.edu                    (testsys.switch_cpus_1[0].max_insts_any_thread)
4805952Ssaidi@eecs.umich.edu            m5.switchCpus(testsys, switch_cpu_list1)
4815952Ssaidi@eecs.umich.edu
4825952Ssaidi@eecs.umich.edu    # If we're taking and restoring checkpoints, use checkpoint_dir
4835952Ssaidi@eecs.umich.edu    # option only for finding the checkpoints to restore from.  This
4845952Ssaidi@eecs.umich.edu    # lets us test checkpointing by restoring from one set of
4855952Ssaidi@eecs.umich.edu    # checkpoints, generating a second set, and then comparing them.
4865952Ssaidi@eecs.umich.edu    if options.take_checkpoints and options.checkpoint_restore:
4875952Ssaidi@eecs.umich.edu        if m5.options.outdir:
4885952Ssaidi@eecs.umich.edu            cptdir = m5.options.outdir
4895952Ssaidi@eecs.umich.edu        else:
4905952Ssaidi@eecs.umich.edu            cptdir = getcwd()
4915952Ssaidi@eecs.umich.edu
4925952Ssaidi@eecs.umich.edu    if options.take_checkpoints != None :
4935952Ssaidi@eecs.umich.edu        # Checkpoints being taken via the command line at <when> and at
4945952Ssaidi@eecs.umich.edu        # subsequent periods of <period>.  Checkpoint instructions
4955952Ssaidi@eecs.umich.edu        # received from the benchmark running are ignored and skipped in
4965952Ssaidi@eecs.umich.edu        # favor of command line checkpoint instructions.
4975952Ssaidi@eecs.umich.edu        exit_event = scriptCheckpoints(options, maxtick, cptdir)
4985952Ssaidi@eecs.umich.edu    else:
4995952Ssaidi@eecs.umich.edu        if options.fast_forward:
5005952Ssaidi@eecs.umich.edu            m5.stats.reset()
5015952Ssaidi@eecs.umich.edu        print "**** REAL SIMULATION ****"
5025952Ssaidi@eecs.umich.edu
5035952Ssaidi@eecs.umich.edu        # If checkpoints are being taken, then the checkpoint instruction
5045952Ssaidi@eecs.umich.edu        # will occur in the benchmark code it self.
5055952Ssaidi@eecs.umich.edu        if options.repeat_switch and maxtick > options.repeat_switch:
5065952Ssaidi@eecs.umich.edu            exit_event = repeatSwitch(testsys, repeat_switch_cpu_list,
5075952Ssaidi@eecs.umich.edu                                      maxtick, options.repeat_switch)
5085952Ssaidi@eecs.umich.edu        else:
5095952Ssaidi@eecs.umich.edu            exit_event = benchCheckpoints(options, maxtick, cptdir)
5105952Ssaidi@eecs.umich.edu
5115952Ssaidi@eecs.umich.edu    print 'Exiting @ tick %i because %s' % (m5.curTick(), exit_event.getCause())
5125952Ssaidi@eecs.umich.edu    if options.checkpoint_at_end:
5135952Ssaidi@eecs.umich.edu        m5.checkpoint(joinpath(cptdir, "cpt.%d"))
5145952Ssaidi@eecs.umich.edu
5155952Ssaidi@eecs.umich.edu    if not m5.options.interactive:
5165952Ssaidi@eecs.umich.edu        sys.exit(exit_event.getCode())
5175952Ssaidi@eecs.umich.edu