Simulation.py revision 5311
13569Sgblack@eecs.umich.edu# Copyright (c) 2006-2007 The Regents of The University of Michigan
23569Sgblack@eecs.umich.edu# All rights reserved.
33569Sgblack@eecs.umich.edu#
43569Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
53569Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are
63569Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright
73569Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
83569Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
93569Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
103569Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution;
113569Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its
123569Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from
133569Sgblack@eecs.umich.edu# this software without specific prior written permission.
143569Sgblack@eecs.umich.edu#
153569Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
163569Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
173569Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
183569Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
193569Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
203569Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
213569Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
223569Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
233569Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
243569Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
253569Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
263569Sgblack@eecs.umich.edu#
273569Sgblack@eecs.umich.edu# Authors: Lisa Hsu
283804Ssaidi@eecs.umich.edu
293569Sgblack@eecs.umich.edufrom os import getcwd
303569Sgblack@eecs.umich.edufrom os.path import join as joinpath
313918Ssaidi@eecs.umich.eduimport m5
323918Ssaidi@eecs.umich.edufrom m5.objects import *
333804Ssaidi@eecs.umich.edum5.AddToPath('../common')
343811Ssaidi@eecs.umich.edufrom Caches import L1Cache
353569Sgblack@eecs.umich.edu
363824Ssaidi@eecs.umich.edudef setCPUClass(options):
373811Ssaidi@eecs.umich.edu
383811Ssaidi@eecs.umich.edu    atomic = False
393823Ssaidi@eecs.umich.edu    if options.timing:
403823Ssaidi@eecs.umich.edu        TmpClass = TimingSimpleCPU
413823Ssaidi@eecs.umich.edu    elif options.detailed:
424103Ssaidi@eecs.umich.edu        if not options.caches:
433569Sgblack@eecs.umich.edu            print "O3 CPU must be used with caches"
443804Ssaidi@eecs.umich.edu            sys.exit(1)
453804Ssaidi@eecs.umich.edu        TmpClass = DerivO3CPU
464088Sbinkertn@umich.edu    else:
473569Sgblack@eecs.umich.edu        TmpClass = AtomicSimpleCPU
485034Smilesck@eecs.umich.edu        atomic = True
495358Sgblack@eecs.umich.edu
503881Ssaidi@eecs.umich.edu    CPUClass = None
513804Ssaidi@eecs.umich.edu    test_mem_mode = 'atomic'
523804Ssaidi@eecs.umich.edu
533804Ssaidi@eecs.umich.edu    if not atomic:
545555Snate@binkert.org        if options.checkpoint_restore:
553569Sgblack@eecs.umich.edu            CPUClass = TmpClass
563804Ssaidi@eecs.umich.edu            TmpClass = AtomicSimpleCPU
573918Ssaidi@eecs.umich.edu        else:
583881Ssaidi@eecs.umich.edu            test_mem_mode = 'timing'
593881Ssaidi@eecs.umich.edu
603881Ssaidi@eecs.umich.edu    return (TmpClass, test_mem_mode, CPUClass)
614990Sgblack@eecs.umich.edu
624990Sgblack@eecs.umich.edu
634990Sgblack@eecs.umich.edudef run(options, root, testsys, cpu_class):
644990Sgblack@eecs.umich.edu    if options.maxtick:
654990Sgblack@eecs.umich.edu        maxtick = options.maxtick
664990Sgblack@eecs.umich.edu    elif options.maxtime:
674990Sgblack@eecs.umich.edu        simtime = m5.ticks.seconds(simtime)
684990Sgblack@eecs.umich.edu        print "simulating for: ", simtime
694990Sgblack@eecs.umich.edu        maxtick = simtime
703804Ssaidi@eecs.umich.edu    else:
713569Sgblack@eecs.umich.edu        maxtick = m5.MaxTick
723804Ssaidi@eecs.umich.edu
733804Ssaidi@eecs.umich.edu    if options.checkpoint_dir:
743804Ssaidi@eecs.umich.edu        cptdir = options.checkpoint_dir
753804Ssaidi@eecs.umich.edu    elif m5.options.outdir:
763881Ssaidi@eecs.umich.edu        cptdir = m5.options.outdir
773804Ssaidi@eecs.umich.edu    else:
783804Ssaidi@eecs.umich.edu        cptdir = getcwd()
793804Ssaidi@eecs.umich.edu
803804Ssaidi@eecs.umich.edu    np = options.num_cpus
813804Ssaidi@eecs.umich.edu    max_checkpoints = options.max_checkpoints
823804Ssaidi@eecs.umich.edu    switch_cpus = None
833804Ssaidi@eecs.umich.edu
843569Sgblack@eecs.umich.edu    if cpu_class:
853569Sgblack@eecs.umich.edu        switch_cpus = [cpu_class(defer_registration=True, cpu_id=(np+i))
863804Ssaidi@eecs.umich.edu                       for i in xrange(np)]
873804Ssaidi@eecs.umich.edu
883826Ssaidi@eecs.umich.edu        for i in xrange(np):
893804Ssaidi@eecs.umich.edu            switch_cpus[i].system =  testsys
903804Ssaidi@eecs.umich.edu            if not m5.build_env['FULL_SYSTEM']:
913826Ssaidi@eecs.umich.edu                switch_cpus[i].workload = testsys.cpu[i].workload
923907Ssaidi@eecs.umich.edu            switch_cpus[i].clock = testsys.cpu[0].clock
933826Ssaidi@eecs.umich.edu
943811Ssaidi@eecs.umich.edu        testsys.switch_cpus = switch_cpus
953836Ssaidi@eecs.umich.edu        switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
963915Ssaidi@eecs.umich.edu
973907Ssaidi@eecs.umich.edu    if options.standard_switch:
983881Ssaidi@eecs.umich.edu        switch_cpus = [TimingSimpleCPU(defer_registration=True, cpu_id=(np+i))
993881Ssaidi@eecs.umich.edu                       for i in xrange(np)]
1003881Ssaidi@eecs.umich.edu        switch_cpus_1 = [DerivO3CPU(defer_registration=True, cpu_id=(2*np+i))
1013881Ssaidi@eecs.umich.edu                        for i in xrange(np)]
1023907Ssaidi@eecs.umich.edu
1033881Ssaidi@eecs.umich.edu        for i in xrange(np):
1045555Snate@binkert.org            switch_cpus[i].system =  testsys
1055555Snate@binkert.org            switch_cpus_1[i].system =  testsys
1065555Snate@binkert.org            if not m5.build_env['FULL_SYSTEM']:
1073881Ssaidi@eecs.umich.edu                switch_cpus[i].workload = testsys.cpu[i].workload
1083881Ssaidi@eecs.umich.edu                switch_cpus_1[i].workload = testsys.cpu[i].workload
1093907Ssaidi@eecs.umich.edu            switch_cpus[i].clock = testsys.cpu[0].clock
1103907Ssaidi@eecs.umich.edu            switch_cpus_1[i].clock = testsys.cpu[0].clock
1113907Ssaidi@eecs.umich.edu
1123907Ssaidi@eecs.umich.edu            if not options.caches:
1133907Ssaidi@eecs.umich.edu                # O3 CPU must have a cache to work.
1143907Ssaidi@eecs.umich.edu                switch_cpus_1[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
1153907Ssaidi@eecs.umich.edu                                                         L1Cache(size = '64kB'))
1163907Ssaidi@eecs.umich.edu                switch_cpus_1[i].connectMemPorts(testsys.membus)
1173907Ssaidi@eecs.umich.edu
1183907Ssaidi@eecs.umich.edu
1193907Ssaidi@eecs.umich.edu            testsys.switch_cpus = switch_cpus
1203907Ssaidi@eecs.umich.edu            testsys.switch_cpus_1 = switch_cpus_1
1213907Ssaidi@eecs.umich.edu            switch_cpu_list = [(testsys.cpu[i], switch_cpus[i]) for i in xrange(np)]
1223907Ssaidi@eecs.umich.edu            switch_cpu_list1 = [(switch_cpus[i], switch_cpus_1[i]) for i in xrange(np)]
1233907Ssaidi@eecs.umich.edu
1243907Ssaidi@eecs.umich.edu    m5.instantiate(root)
1253907Ssaidi@eecs.umich.edu
1263907Ssaidi@eecs.umich.edu    if options.checkpoint_restore:
1273907Ssaidi@eecs.umich.edu        from os.path import isdir
1283907Ssaidi@eecs.umich.edu        from os import listdir
1293907Ssaidi@eecs.umich.edu        import re
1303907Ssaidi@eecs.umich.edu
1313881Ssaidi@eecs.umich.edu        if not isdir(cptdir):
1323881Ssaidi@eecs.umich.edu            m5.panic("checkpoint dir %s does not exist!" % cptdir)
1333881Ssaidi@eecs.umich.edu
1343881Ssaidi@eecs.umich.edu        dirs = listdir(cptdir)
1353881Ssaidi@eecs.umich.edu        expr = re.compile('cpt\.([0-9]*)')
1363881Ssaidi@eecs.umich.edu        cpts = []
1373881Ssaidi@eecs.umich.edu        for dir in dirs:
1383881Ssaidi@eecs.umich.edu            match = expr.match(dir)
1393881Ssaidi@eecs.umich.edu            if match:
1403881Ssaidi@eecs.umich.edu                cpts.append(match.group(1))
1413881Ssaidi@eecs.umich.edu
1423881Ssaidi@eecs.umich.edu        cpts.sort(lambda a,b: cmp(long(a), long(b)))
1433907Ssaidi@eecs.umich.edu
1443811Ssaidi@eecs.umich.edu        cpt_num = options.checkpoint_restore
1453826Ssaidi@eecs.umich.edu
1463826Ssaidi@eecs.umich.edu        if cpt_num > len(cpts):
1473826Ssaidi@eecs.umich.edu            m5.panic('Checkpoint %d not found' % cpt_num)
1483826Ssaidi@eecs.umich.edu
1493881Ssaidi@eecs.umich.edu        ## Adjust max tick based on our starting tick
1503881Ssaidi@eecs.umich.edu        maxtick = maxtick - int(cpts[cpt_num - 1])
1513881Ssaidi@eecs.umich.edu
1523881Ssaidi@eecs.umich.edu        ## Restore the checkpoint
1533881Ssaidi@eecs.umich.edu        m5.restoreCheckpoint(root,
1543881Ssaidi@eecs.umich.edu                             joinpath(cptdir, "cpt.%s" % cpts[cpt_num - 1]))
1553881Ssaidi@eecs.umich.edu
1563881Ssaidi@eecs.umich.edu    if options.standard_switch or cpu_class:
1573881Ssaidi@eecs.umich.edu        exit_event = m5.simulate(10000)
1583881Ssaidi@eecs.umich.edu
1593881Ssaidi@eecs.umich.edu        ## when you change to Timing (or Atomic), you halt the system given
1603881Ssaidi@eecs.umich.edu        ## as argument.  When you are finished with the system changes
1613881Ssaidi@eecs.umich.edu        ## (including switchCpus), you must resume the system manually.
1623881Ssaidi@eecs.umich.edu        ## You DON'T need to resume after just switching CPUs if you haven't
1633881Ssaidi@eecs.umich.edu        ## changed anything on the system level.
1643826Ssaidi@eecs.umich.edu
1653826Ssaidi@eecs.umich.edu        m5.changeToTiming(testsys)
1663826Ssaidi@eecs.umich.edu        m5.switchCpus(switch_cpu_list)
1673826Ssaidi@eecs.umich.edu        m5.resume(testsys)
1683826Ssaidi@eecs.umich.edu
1693881Ssaidi@eecs.umich.edu        if options.standard_switch:
1703569Sgblack@eecs.umich.edu            exit_event = m5.simulate(options.warmup)
1713569Sgblack@eecs.umich.edu            m5.drain(testsys)
1723881Ssaidi@eecs.umich.edu            m5.switchCpus(switch_cpu_list1)
1733804Ssaidi@eecs.umich.edu            m5.resume(testsys)
1743881Ssaidi@eecs.umich.edu
1753826Ssaidi@eecs.umich.edu    num_checkpoints = 0
1763881Ssaidi@eecs.umich.edu    exit_cause = ''
1773881Ssaidi@eecs.umich.edu
1783881Ssaidi@eecs.umich.edu    ## Checkpoints being taken via the command line at <when> and at subsequent
1793907Ssaidi@eecs.umich.edu    ## periods of <period>.  Checkpoint instructions received from the benchmark running
1803907Ssaidi@eecs.umich.edu    ## are ignored and skipped in favor of command line checkpoint instructions.
1813929Ssaidi@eecs.umich.edu    if options.take_checkpoints:
1823929Ssaidi@eecs.umich.edu        [when, period] = options.take_checkpoints.split(",", 1)
1833907Ssaidi@eecs.umich.edu        when = int(when)
1843907Ssaidi@eecs.umich.edu        period = int(period)
1853804Ssaidi@eecs.umich.edu
1863804Ssaidi@eecs.umich.edu        exit_event = m5.simulate(when)
1873881Ssaidi@eecs.umich.edu        while exit_event.getCause() == "checkpoint":
1883804Ssaidi@eecs.umich.edu            exit_event = m5.simulate(when - m5.curTick())
1893804Ssaidi@eecs.umich.edu
1903804Ssaidi@eecs.umich.edu        if exit_event.getCause() == "simulate() limit reached":
1913804Ssaidi@eecs.umich.edu            m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
1923804Ssaidi@eecs.umich.edu            num_checkpoints += 1
1933804Ssaidi@eecs.umich.edu
1943804Ssaidi@eecs.umich.edu        sim_ticks = when
1953569Sgblack@eecs.umich.edu        exit_cause = "maximum %d checkpoints dropped" % max_checkpoints
1963863Ssaidi@eecs.umich.edu        while num_checkpoints < max_checkpoints and \
1973863Ssaidi@eecs.umich.edu                exit_event.getCause() == "simulate() limit reached":
1983804Ssaidi@eecs.umich.edu            if (sim_ticks + period) > maxtick:
1995555Snate@binkert.org                exit_event = m5.simulate(maxtick - sim_ticks)
2005555Snate@binkert.org                exit_cause = exit_event.getCause()
2013804Ssaidi@eecs.umich.edu                break
2023804Ssaidi@eecs.umich.edu            else:
2033804Ssaidi@eecs.umich.edu                exit_event = m5.simulate(period)
2043804Ssaidi@eecs.umich.edu                sim_ticks += period
2053804Ssaidi@eecs.umich.edu                while exit_event.getCause() == "checkpoint":
2063569Sgblack@eecs.umich.edu                    exit_event = m5.simulate(sim_ticks - m5.curTick())
2073804Ssaidi@eecs.umich.edu                if exit_event.getCause() == "simulate() limit reached":
2083804Ssaidi@eecs.umich.edu                    m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
2093804Ssaidi@eecs.umich.edu                    num_checkpoints += 1
2105555Snate@binkert.org
2115555Snate@binkert.org        if exit_event.getCause() != "simulate() limit reached":
2123804Ssaidi@eecs.umich.edu            exit_cause = exit_event.getCause();
2133804Ssaidi@eecs.umich.edu
2143804Ssaidi@eecs.umich.edu
2153804Ssaidi@eecs.umich.edu    else: #no checkpoints being taken via this script
2163804Ssaidi@eecs.umich.edu        exit_event = m5.simulate(maxtick)
2173811Ssaidi@eecs.umich.edu
2183811Ssaidi@eecs.umich.edu        while exit_event.getCause() == "checkpoint":
2193804Ssaidi@eecs.umich.edu            m5.checkpoint(root, joinpath(cptdir, "cpt.%d"))
2203804Ssaidi@eecs.umich.edu            num_checkpoints += 1
2215312Sgblack@eecs.umich.edu            if num_checkpoints == max_checkpoints:
2223804Ssaidi@eecs.umich.edu                exit_cause =  "maximum %d checkpoints dropped" % max_checkpoints
2233804Ssaidi@eecs.umich.edu                break
2243804Ssaidi@eecs.umich.edu
2253804Ssaidi@eecs.umich.edu            exit_event = m5.simulate(maxtick - m5.curTick())
2263804Ssaidi@eecs.umich.edu            exit_cause = exit_event.getCause()
2273804Ssaidi@eecs.umich.edu
2283804Ssaidi@eecs.umich.edu    if exit_cause == '':
2293811Ssaidi@eecs.umich.edu        exit_cause = exit_event.getCause()
2303804Ssaidi@eecs.umich.edu    print 'Exiting @ cycle %i because %s' % (m5.curTick(), exit_cause)
2313804Ssaidi@eecs.umich.edu
2323804Ssaidi@eecs.umich.edu