Simulation.py revision 5370
12623SN/A# Copyright (c) 2006-2008 The Regents of The University of Michigan
22623SN/A# All rights reserved.
32623SN/A#
42623SN/A# Redistribution and use in source and binary forms, with or without
52623SN/A# modification, are permitted provided that the following conditions are
62623SN/A# met: redistributions of source code must retain the above copyright
72623SN/A# notice, this list of conditions and the following disclaimer;
82623SN/A# redistributions in binary form must reproduce the above copyright
92623SN/A# notice, this list of conditions and the following disclaimer in the
102623SN/A# documentation and/or other materials provided with the distribution;
112623SN/A# neither the name of the copyright holders nor the names of its
122623SN/A# contributors may be used to endorse or promote products derived from
132623SN/A# this software without specific prior written permission.
142623SN/A#
152623SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162623SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
172623SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
182623SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
192623SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
202623SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
212623SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
222623SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
232623SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
242623SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
252623SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262623SN/A#
272665Ssaidi@eecs.umich.edu# Authors: Lisa Hsu
282665Ssaidi@eecs.umich.edu
292623SN/Afrom os import getcwd
302623SN/Afrom os.path import join as joinpath
313170Sstever@eecs.umich.eduimport m5
323806Ssaidi@eecs.umich.edufrom m5.objects import *
332623SN/Am5.AddToPath('../common')
344040Ssaidi@eecs.umich.edufrom Caches import L1Cache
356658Snate@binkert.org
362623SN/Adef setCPUClass(options):
372623SN/A
383348Sbinkertn@umich.edu    atomic = False
393348Sbinkertn@umich.edu    if options.timing:
404762Snate@binkert.org        class TmpClass(TimingSimpleCPU): pass
417678Sgblack@eecs.umich.edu    elif options.detailed:
422901Ssaidi@eecs.umich.edu        if not options.caches:
432623SN/A            print "O3 CPU must be used with caches"
442623SN/A            sys.exit(1)
452623SN/A        class TmpClass(DerivO3CPU): pass
462623SN/A    else:
472623SN/A        class TmpClass(AtomicSimpleCPU): pass
485606Snate@binkert.org        atomic = True
492623SN/A
502623SN/A    CPUClass = None
512623SN/A    test_mem_mode = 'atomic'
522623SN/A
532623SN/A    if not atomic:
542623SN/A        if options.checkpoint_restore != None or options.fast_forward:
552623SN/A            CPUClass = TmpClass
562623SN/A            class TmpClass(AtomicSimpleCPU): pass
572623SN/A        else:
582623SN/A            test_mem_mode = 'timing'
592623SN/A
605336Shines@cs.fsu.edu    return (TmpClass, test_mem_mode, CPUClass)
612623SN/A
624873Sstever@eecs.umich.edu
632623SN/Adef run(options, root, testsys, cpu_class):
642623SN/A    if options.maxtick:
652856Srdreslin@umich.edu        maxtick = options.maxtick
666227Snate@binkert.org    elif options.maxtime:
672856Srdreslin@umich.edu        simtime = m5.ticks.seconds(simtime)
682856Srdreslin@umich.edu        print "simulating for: ", simtime
692856Srdreslin@umich.edu        maxtick = simtime
702856Srdreslin@umich.edu    else:
712856Srdreslin@umich.edu        maxtick = m5.MaxTick
724968Sacolyte@umich.edu
734968Sacolyte@umich.edu    if options.checkpoint_dir:
744968Sacolyte@umich.edu        cptdir = options.checkpoint_dir
754968Sacolyte@umich.edu    elif m5.options.outdir:
762856Srdreslin@umich.edu        cptdir = m5.options.outdir
772856Srdreslin@umich.edu    else:
782856Srdreslin@umich.edu        cptdir = getcwd()
792623SN/A
802623SN/A    if options.fast_forward and options.checkpoint_restore != None:
812623SN/A        m5.panic("Error: Can't specify both --fast-forward and --checkpoint-restore")
822623SN/A
832623SN/A    if options.standard_switch and not cpu_class:
842623SN/A        m5.panic("Error: Must specify CPU to switch to for --standard-switch (almost always detailed (-d))")
856221Snate@binkert.org
866221Snate@binkert.org    np = options.num_cpus
872680Sktlim@umich.edu    max_checkpoints = options.max_checkpoints
882623SN/A    switch_cpus = None
892623SN/A
905714Shsul@eecs.umich.edu    if cpu_class:
912623SN/A        switch_cpus = [cpu_class(defer_registration=True, cpu_id=(np+i))
922623SN/A                       for i in xrange(np)]
934968Sacolyte@umich.edu
944968Sacolyte@umich.edu        for i in xrange(np):
954968Sacolyte@umich.edu            if options.fast_forward:
964968Sacolyte@umich.edu                testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
974968Sacolyte@umich.edu            switch_cpus[i].system =  testsys
984968Sacolyte@umich.edu            if not m5.build_env['FULL_SYSTEM']:
995714Shsul@eecs.umich.edu                switch_cpus[i].workload = testsys.cpu[i].workload
1005712Shsul@eecs.umich.edu            switch_cpus[i].clock = testsys.cpu[0].clock
1015712Shsul@eecs.umich.edu            # simulation period
1025712Shsul@eecs.umich.edu            if options.max_inst:
1032623SN/A                switch_cpus[i].max_insts_any_thread = options.max_inst
1042623SN/A
1052623SN/A        testsys.switch_cpus = switch_cpus
1063349Sbinkertn@umich.edu        switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
1072623SN/A
1083184Srdreslin@umich.edu    if options.standard_switch:
1092623SN/A        switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i))
1102623SN/A                       for i in xrange(np)]
1112623SN/A        switch_cpus_1 = [DerivO3CPU(defer_registration=True, cpu_id=(2*np+i))
1122623SN/A                        for i in xrange(np)]
1133349Sbinkertn@umich.edu
1142623SN/A        for i in xrange(np):
1153310Srdreslin@umich.edu            switch_cpus[i].system =  testsys
1163649Srdreslin@umich.edu            switch_cpus_1[i].system =  testsys
1172623SN/A            if not m5.build_env['FULL_SYSTEM']:
1182623SN/A                switch_cpus[i].workload = testsys.cpu[i].workload
1192623SN/A                switch_cpus_1[i].workload = testsys.cpu[i].workload
1203349Sbinkertn@umich.edu            switch_cpus[i].clock = testsys.cpu[0].clock
1212623SN/A            switch_cpus_1[i].clock = testsys.cpu[0].clock
1223184Srdreslin@umich.edu
1233184Srdreslin@umich.edu            # if restoring, make atomic cpu simulate only a few instructions
1242623SN/A            if options.checkpoint_restore != None:
1252623SN/A                testsys.cpu[i].max_insts_any_thread = 1
1262623SN/A            # Fast forward to specified location if we are not restoring
1272623SN/A            elif options.fast_forward:
1282623SN/A                testsys.cpu[i].max_insts_any_thread = int(options.fast_forward)
1293647Srdreslin@umich.edu            # Fast forward to a simpoint (warning: time consuming)
1303647Srdreslin@umich.edu            elif options.simpoint:
1313647Srdreslin@umich.edu                if testsys.cpu[i].workload[0].simpoint == None:
1323647Srdreslin@umich.edu                    m5.panic('simpoint not found')
1333647Srdreslin@umich.edu                testsys.cpu[i].max_insts_any_thread = \
1342626SN/A                    testsys.cpu[i].workload[0].simpoint
1353647Srdreslin@umich.edu            # No distance specified, just switch
1362626SN/A            else:
1372623SN/A                testsys.cpu[i].max_insts_any_thread = 1
1382623SN/A
1392623SN/A            # warmup period
1402657Ssaidi@eecs.umich.edu            if options.warmup_insts:
1412623SN/A                switch_cpus[i].max_insts_any_thread =  options.warmup_insts
1422623SN/A
1432623SN/A            # simulation period
1442623SN/A            if options.max_inst:
1452623SN/A                switch_cpus_1[i].max_insts_any_thread = options.max_inst
1464192Sktlim@umich.edu
1474192Sktlim@umich.edu            if not options.caches:
1484192Sktlim@umich.edu                # O3 CPU must have a cache to work.
1494192Sktlim@umich.edu                switch_cpus_1[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
1504192Sktlim@umich.edu                                                         L1Cache(size = '64kB'))
1514192Sktlim@umich.edu                switch_cpus_1[i].connectMemPorts(testsys.membus)
1524192Sktlim@umich.edu
1534192Sktlim@umich.edu            testsys.switch_cpus = switch_cpus
1545497Ssaidi@eecs.umich.edu            testsys.switch_cpus_1 = switch_cpus_1
1554192Sktlim@umich.edu            switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
1564192Sktlim@umich.edu            switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)]
1572623SN/A
1585529Snate@binkert.org    # set the checkpoint in the cpu before m5.instantiate is called
1596078Sgblack@eecs.umich.edu    if options.take_checkpoints != None and \
1605487Snate@binkert.org           (options.simpoint or options.at_instruction):
1615487Snate@binkert.org        offset = int(options.take_checkpoints)
1624968Sacolyte@umich.edu        # Set an instruction break point
1634968Sacolyte@umich.edu        if options.simpoint:
1642623SN/A            for i in xrange(np):
1652623SN/A                if testsys.cpu[i].workload[0].simpoint == None:
1662623SN/A                    m5.panic('no simpoint for testsys.cpu[%d].workload[0]' % i)
1673647Srdreslin@umich.edu                checkpoint_inst = int(testsys.cpu[i].workload[0].simpoint) + offset
1683647Srdreslin@umich.edu                testsys.cpu[i].max_insts_any_thread = checkpoint_inst
1693647Srdreslin@umich.edu                # used for output below
1702623SN/A                options.take_checkpoints = checkpoint_inst
1712623SN/A        else:
1722623SN/A            options.take_checkpoints = offset
1732623SN/A            # Set all test cpus with the right number of instructions
1742623SN/A            # for the upcoming simulation
1756775SBrad.Beckmann@amd.com            for i in xrange(np):
1766775SBrad.Beckmann@amd.com                testsys.cpu[i].max_insts_any_thread = offset
1776775SBrad.Beckmann@amd.com
1782623SN/A    m5.instantiate(root)
1792623SN/A
1802623SN/A    if options.checkpoint_restore != None:
1812623SN/A        from os.path import isdir, exists
1822623SN/A        from os import listdir
1832915Sktlim@umich.edu        import re
1842915Sktlim@umich.edu
1856078Sgblack@eecs.umich.edu        if not isdir(cptdir):
1863145Shsul@eecs.umich.edu            m5.panic("checkpoint dir %s does not exist!" % cptdir)
1872623SN/A
1882623SN/A        if options.at_instruction:
1892623SN/A            checkpoint_dir = joinpath(cptdir, "cpt.%s.%s" % \
1902623SN/A                    (options.bench, options.checkpoint_restore))
1912623SN/A            if not exists(checkpoint_dir):
1922623SN/A                m5.panic("Unable to find checkpoint directory %s" % \
1932623SN/A                         checkpoint_dir)
1942915Sktlim@umich.edu
1952915Sktlim@umich.edu            print "Restoring checkpoint ..."
1966078Sgblack@eecs.umich.edu            m5.restoreCheckpoint(root, checkpoint_dir)
1973145Shsul@eecs.umich.edu            print "Done."
1982915Sktlim@umich.edu        elif options.simpoint:
1992915Sktlim@umich.edu            # assume workload 0 has the simpoint
2002915Sktlim@umich.edu            if testsys.cpu[0].workload[0].simpoint == None:
2012915Sktlim@umich.edu                m5.panic('Unable to find simpoint')
2022915Sktlim@umich.edu
2032915Sktlim@umich.edu            options.checkpoint_restore += \
2045220Ssaidi@eecs.umich.edu                int(testsys.cpu[0].workload[0].simpoint)
2055220Ssaidi@eecs.umich.edu
2065220Ssaidi@eecs.umich.edu            checkpoint_dir = joinpath(cptdir, "cpt.%s.%d" % \
2074940Snate@binkert.org                    (options.bench, options.checkpoint_restore))
2085220Ssaidi@eecs.umich.edu            if not exists(checkpoint_dir):
2093324Shsul@eecs.umich.edu                m5.panic("Unable to find checkpoint directory %s.%s" % \
2105220Ssaidi@eecs.umich.edu                        (options.bench, options.checkpoint_restore))
2115220Ssaidi@eecs.umich.edu
2125606Snate@binkert.org            print "Restoring checkpoint ..."
2135606Snate@binkert.org            m5.restoreCheckpoint(root,checkpoint_dir)
2142915Sktlim@umich.edu            print "Done."
2152623SN/A        else:
2162623SN/A            dirs = listdir(cptdir)
2172623SN/A            expr = re.compile('cpt\.([0-9]*)')
2182798Sktlim@umich.edu            cpts = []
2192623SN/A            for dir in dirs:
2205496Ssaidi@eecs.umich.edu                match = expr.match(dir)
2212798Sktlim@umich.edu                if match:
2222623SN/A                    cpts.append(match.group(1))
2232798Sktlim@umich.edu
2242623SN/A            cpts.sort(lambda a,b: cmp(long(a), long(b)))
2252623SN/A
2262623SN/A            cpt_num = options.checkpoint_restore
2272623SN/A
2282623SN/A            if cpt_num > len(cpts):
2292623SN/A                m5.panic('Checkpoint %d not found' % cpt_num)
2304192Sktlim@umich.edu
2312623SN/A            ## Adjust max tick based on our starting tick
2322623SN/A            maxtick = maxtick - int(cpts[cpt_num - 1])
2332623SN/A
2342680Sktlim@umich.edu            ## Restore the checkpoint
2352623SN/A            m5.restoreCheckpoint(root,
2366221Snate@binkert.org                    joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1]))
2376221Snate@binkert.org
2382680Sktlim@umich.edu    if options.standard_switch or cpu_class:
2392680Sktlim@umich.edu        if options.standard_switch:
2402623SN/A            print "Switch at instruction count:%s" % \
2415606Snate@binkert.org                    str(testsys.cpu[0].max_insts_any_thread)
2422623SN/A            exit_event = m5.simulate()
2432623SN/A        elif cpu_class and options.fast_forward:
2442623SN/A            print "Switch at instruction count:%s" % \
2453512Sktlim@umich.edu                    str(testsys.cpu[0].max_insts_any_thread)
2463512Sktlim@umich.edu            exit_event = m5.simulate()
2473512Sktlim@umich.edu        else:
2485169Ssaidi@eecs.umich.edu            print "Switch at curTick count:%s" % str(10000)
2495712Shsul@eecs.umich.edu            exit_event = m5.simulate(10000)
2505712Shsul@eecs.umich.edu        print "Switched CPUS @ cycle = %s" % (m5.curTick())
2515712Shsul@eecs.umich.edu
2522623SN/A        # when you change to Timing (or Atomic), you halt the system
2532623SN/A        # given as argument.  When you are finished with the system
2542623SN/A        # changes (including switchCpus), you must resume the system
2552623SN/A        # manually.  You DON'T need to resume after just switching
2562623SN/A        # CPUs if you haven't changed anything on the system level.
2572623SN/A
2584940Snate@binkert.org        m5.changeToTiming(testsys)
2594940Snate@binkert.org        m5.switchCpus(switch_cpu_list)
2602623SN/A        m5.resume(testsys)
2612683Sktlim@umich.edu
2622623SN/A        if options.standard_switch:
2632623SN/A            print "Switch at instruction count:%d" % \
2642623SN/A                    (testsys.switch_cpus[0].max_insts_any_thread)
2652623SN/A
2662623SN/A            #warmup instruction count may have already been set
2675101Ssaidi@eecs.umich.edu            if options.warmup_insts:
2683686Sktlim@umich.edu                exit_event = m5.simulate()
2693430Sgblack@eecs.umich.edu            else:
2705606Snate@binkert.org                exit_event = m5.simulate(options.warmup)
2712623SN/A            print "Switching CPUS @ cycle = %s" % (m5.curTick())
2722623SN/A            print "Simulation ends instruction count:%d" % \
2732623SN/A                    (testsys.switch_cpus_1[0].max_insts_any_thread)
2742623SN/A            m5.drain(testsys)
2752623SN/A            m5.switchCpus(switch_cpu_list1)
2762623SN/A            m5.resume(testsys)
2772623SN/A
2784940Snate@binkert.org    num_checkpoints = 0
2794940Snate@binkert.org    exit_cause = ''
2802623SN/A
2812683Sktlim@umich.edu    # Checkpoints being taken via the command line at <when> and at
2822623SN/A    # subsequent periods of <period>.  Checkpoint instructions
2836043Sgblack@eecs.umich.edu    # received from the benchmark running are ignored and skipped in
2846043Sgblack@eecs.umich.edu    # favor of command line checkpoint instructions.
2856043Sgblack@eecs.umich.edu    if options.take_checkpoints != None :
2862623SN/A        if options.at_instruction or options.simpoint:
2872626SN/A            checkpoint_inst = int(options.take_checkpoints)
2882626SN/A
2892626SN/A            # maintain correct offset if we restored from some instruction
2902626SN/A            if options.checkpoint_restore != None:
2915606Snate@binkert.org                checkpoint_inst += options.checkpoint_restore
2922623SN/A
2932623SN/A            print "Creating checkpoint at inst:%d" % (checkpoint_inst)
2942623SN/A            exit_event = m5.simulate()
2952623SN/A            print "exit cause = %s" % (exit_event.getCause())
2962623SN/A
2972623SN/A            # skip checkpoint instructions should they exist
2982623SN/A            while exit_event.getCause() == "checkpoint":
2997520Sgblack@eecs.umich.edu                exit_event = m5.simulate()
3007520Sgblack@eecs.umich.edu
3012623SN/A            if exit_event.getCause() == \
3023169Sstever@eecs.umich.edu                   "a thread reached the max instruction count":
3034870Sstever@eecs.umich.edu                m5.checkpoint(root, joinpath(cptdir, "cpt.%s.%d" % \
3042623SN/A                        (options.bench, checkpoint_inst)))
3052623SN/A                print "Checkpoint written."
3062623SN/A                num_checkpoints += 1
3072623SN/A
3082623SN/A            if exit_event.getCause() == "user interrupt received":
3094999Sgblack@eecs.umich.edu                exit_cause = exit_event.getCause();
3106227Snate@binkert.org        else:
3114999Sgblack@eecs.umich.edu            when, period = options.take_checkpoints.split(",", 1)
3127520Sgblack@eecs.umich.edu            when = int(when)
3132623SN/A            period = int(period)
3144999Sgblack@eecs.umich.edu
3154999Sgblack@eecs.umich.edu            exit_event = m5.simulate(when)
3167520Sgblack@eecs.umich.edu            while exit_event.getCause() == "checkpoint":
3174999Sgblack@eecs.umich.edu                exit_event = m5.simulate(when - m5.curTick())
3187520Sgblack@eecs.umich.edu
3197520Sgblack@eecs.umich.edu            if exit_event.getCause() == "simulate() limit reached":
3204999Sgblack@eecs.umich.edu                m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
3214999Sgblack@eecs.umich.edu                num_checkpoints += 1
3224999Sgblack@eecs.umich.edu
3237520Sgblack@eecs.umich.edu            sim_ticks = when
3247720Sgblack@eecs.umich.edu            exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
3254999Sgblack@eecs.umich.edu            while num_checkpoints < max_checkpoints and \
3264999Sgblack@eecs.umich.edu                    exit_event.getCause() == "simulate() limit reached":
3276023Snate@binkert.org                if (sim_ticks + period) > maxtick:
3284999Sgblack@eecs.umich.edu                    exit_event = m5.simulate(maxtick - sim_ticks)
3294999Sgblack@eecs.umich.edu                    exit_cause = exit_event.getCause()
3306623Sgblack@eecs.umich.edu                    break
3314999Sgblack@eecs.umich.edu                else:
3326102Sgblack@eecs.umich.edu                    exit_event = m5.simulate(period)
3334999Sgblack@eecs.umich.edu                    sim_ticks += period
3347520Sgblack@eecs.umich.edu                    while exit_event.getCause() == "checkpoint":
3354999Sgblack@eecs.umich.edu                        exit_event = m5.simulate(sim_ticks - m5.curTick())
3364999Sgblack@eecs.umich.edu                    if exit_event.getCause() == "simulate() limit reached":
3374999Sgblack@eecs.umich.edu                        m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
3384999Sgblack@eecs.umich.edu                        num_checkpoints += 1
3394999Sgblack@eecs.umich.edu
3404999Sgblack@eecs.umich.edu            if exit_event.getCause() != "simulate() limit reached":
3414999Sgblack@eecs.umich.edu                exit_cause = exit_event.getCause();
3424999Sgblack@eecs.umich.edu
3434999Sgblack@eecs.umich.edu    else: # no checkpoints being taken via this script
3444999Sgblack@eecs.umich.edu        if options.fast_forward:
3455012Sgblack@eecs.umich.edu            m5.stats.reset()
3464999Sgblack@eecs.umich.edu        print "**** REAL SIMULATION ****"
3474999Sgblack@eecs.umich.edu        exit_event = m5.simulate(maxtick)
3486102Sgblack@eecs.umich.edu
3494999Sgblack@eecs.umich.edu        while exit_event.getCause() == "checkpoint":
3504999Sgblack@eecs.umich.edu            m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
3514968Sacolyte@umich.edu            num_checkpoints += 1
3524986Ssaidi@eecs.umich.edu            if num_checkpoints == max_checkpoints:
3534999Sgblack@eecs.umich.edu                exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
3546739Sgblack@eecs.umich.edu                break
3556739Sgblack@eecs.umich.edu
3566739Sgblack@eecs.umich.edu            exit_event = m5.simulate(maxtick - m5.curTick())
3576739Sgblack@eecs.umich.edu            exit_cause = exit_event.getCause()
3586739Sgblack@eecs.umich.edu
3596739Sgblack@eecs.umich.edu    if exit_cause == '':
3606739Sgblack@eecs.umich.edu        exit_cause = exit_event.getCause()
3616739Sgblack@eecs.umich.edu    print 'Exiting @ cycle %i because %s' % (m5.curTick(), exit_cause)
3624999Sgblack@eecs.umich.edu
3634999Sgblack@eecs.umich.edu