simulate.py revision 9342:6fec8f26e56d
112469Sglenn.bergmans@arm.com# Copyright (c) 2012 ARM Limited
212469Sglenn.bergmans@arm.com# All rights reserved.
312469Sglenn.bergmans@arm.com#
412469Sglenn.bergmans@arm.com# The license below extends only to copyright in the software and shall
512469Sglenn.bergmans@arm.com# not be construed as granting a license to any other intellectual
612469Sglenn.bergmans@arm.com# property including but not limited to intellectual property relating
712469Sglenn.bergmans@arm.com# to a hardware implementation of the functionality of the software
812469Sglenn.bergmans@arm.com# licensed hereunder.  You may use the software subject to the license
912469Sglenn.bergmans@arm.com# terms below provided that you ensure that this notice is replicated
1012469Sglenn.bergmans@arm.com# unmodified and in its entirety in all distributions of the software,
1112469Sglenn.bergmans@arm.com# modified or unmodified, in source code or in binary form.
1212469Sglenn.bergmans@arm.com#
1312469Sglenn.bergmans@arm.com# Copyright (c) 2005 The Regents of The University of Michigan
1412469Sglenn.bergmans@arm.com# Copyright (c) 2010 Advanced Micro Devices, Inc.
1512469Sglenn.bergmans@arm.com# All rights reserved.
1612469Sglenn.bergmans@arm.com#
1712469Sglenn.bergmans@arm.com# Redistribution and use in source and binary forms, with or without
1812469Sglenn.bergmans@arm.com# modification, are permitted provided that the following conditions are
1912469Sglenn.bergmans@arm.com# met: redistributions of source code must retain the above copyright
2012469Sglenn.bergmans@arm.com# notice, this list of conditions and the following disclaimer;
2112469Sglenn.bergmans@arm.com# redistributions in binary form must reproduce the above copyright
2212469Sglenn.bergmans@arm.com# notice, this list of conditions and the following disclaimer in the
2312469Sglenn.bergmans@arm.com# documentation and/or other materials provided with the distribution;
2412469Sglenn.bergmans@arm.com# neither the name of the copyright holders nor the names of its
2512469Sglenn.bergmans@arm.com# contributors may be used to endorse or promote products derived from
2612469Sglenn.bergmans@arm.com# this software without specific prior written permission.
2712469Sglenn.bergmans@arm.com#
2812469Sglenn.bergmans@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2912469Sglenn.bergmans@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3012469Sglenn.bergmans@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3112469Sglenn.bergmans@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3212469Sglenn.bergmans@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3312469Sglenn.bergmans@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3412469Sglenn.bergmans@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3512469Sglenn.bergmans@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3612469Sglenn.bergmans@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3712469Sglenn.bergmans@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3813719Sandreas.sandberg@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3913719Sandreas.sandberg@arm.com#
4013719Sandreas.sandberg@arm.com# Authors: Nathan Binkert
4113719Sandreas.sandberg@arm.com#          Steve Reinhardt
4212469Sglenn.bergmans@arm.com
4312469Sglenn.bergmans@arm.comimport atexit
4412469Sglenn.bergmans@arm.comimport os
4512469Sglenn.bergmans@arm.comimport sys
4612469Sglenn.bergmans@arm.com
4712469Sglenn.bergmans@arm.com# import the SWIG-wrapped main C++ functions
4812469Sglenn.bergmans@arm.comimport internal
4912469Sglenn.bergmans@arm.comimport core
5012469Sglenn.bergmans@arm.comimport stats
5112469Sglenn.bergmans@arm.comimport SimObject
5212469Sglenn.bergmans@arm.comimport ticks
5312469Sglenn.bergmans@arm.comimport objects
5412469Sglenn.bergmans@arm.comfrom m5.util.dot_writer import do_dot
5512469Sglenn.bergmans@arm.comfrom m5.internal.stats import updateEvents as updateStatEvents
5612469Sglenn.bergmans@arm.com
5712469Sglenn.bergmans@arm.comfrom util import fatal
5812469Sglenn.bergmans@arm.comfrom util import attrdict
5912469Sglenn.bergmans@arm.com
6012469Sglenn.bergmans@arm.com# define a MaxTick parameter
6112469Sglenn.bergmans@arm.comMaxTick = 2**63 - 1
6212469Sglenn.bergmans@arm.com
6312469Sglenn.bergmans@arm.com# The final hook to generate .ini files.  Called from the user script
6412469Sglenn.bergmans@arm.com# once the config is built.
6512469Sglenn.bergmans@arm.comdef instantiate(ckpt_dir=None):
6612469Sglenn.bergmans@arm.com    from m5 import options
6712469Sglenn.bergmans@arm.com
6812469Sglenn.bergmans@arm.com    root = objects.Root.getInstance()
6912469Sglenn.bergmans@arm.com
7012469Sglenn.bergmans@arm.com    if not root:
7112469Sglenn.bergmans@arm.com        fatal("Need to instantiate Root() before calling instantiate()")
7212469Sglenn.bergmans@arm.com
7312469Sglenn.bergmans@arm.com    # we need to fix the global frequency
7412469Sglenn.bergmans@arm.com    ticks.fixGlobalFrequency()
7512469Sglenn.bergmans@arm.com
7612469Sglenn.bergmans@arm.com    # Make sure SimObject-valued params are in the configuration
7712469Sglenn.bergmans@arm.com    # hierarchy so we catch them with future descendants() walks
7812469Sglenn.bergmans@arm.com    for obj in root.descendants(): obj.adoptOrphanParams()
7912469Sglenn.bergmans@arm.com
8012469Sglenn.bergmans@arm.com    # Unproxy in sorted order for determinism
8112469Sglenn.bergmans@arm.com    for obj in root.descendants(): obj.unproxyParams()
8212469Sglenn.bergmans@arm.com
8312469Sglenn.bergmans@arm.com    if options.dump_config:
8412469Sglenn.bergmans@arm.com        ini_file = file(os.path.join(options.outdir, options.dump_config), 'w')
8512469Sglenn.bergmans@arm.com        # Print ini sections in sorted order for easier diffing
8612469Sglenn.bergmans@arm.com        for obj in sorted(root.descendants(), key=lambda o: o.path()):
8712469Sglenn.bergmans@arm.com            obj.print_ini(ini_file)
8812469Sglenn.bergmans@arm.com        ini_file.close()
8912469Sglenn.bergmans@arm.com
9012469Sglenn.bergmans@arm.com    if options.json_config:
9112469Sglenn.bergmans@arm.com        try:
9212469Sglenn.bergmans@arm.com            import json
9312469Sglenn.bergmans@arm.com            json_file = file(os.path.join(options.outdir, options.json_config), 'w')
9412469Sglenn.bergmans@arm.com            d = root.get_config_as_dict()
9512469Sglenn.bergmans@arm.com            json.dump(d, json_file, indent=4)
9612469Sglenn.bergmans@arm.com            json_file.close()
9712469Sglenn.bergmans@arm.com        except ImportError:
9812469Sglenn.bergmans@arm.com            pass
9912469Sglenn.bergmans@arm.com
10012469Sglenn.bergmans@arm.com    do_dot(root, options.outdir, options.dot_config)
10112469Sglenn.bergmans@arm.com
10212469Sglenn.bergmans@arm.com    # Initialize the global statistics
10312469Sglenn.bergmans@arm.com    stats.initSimStats()
10412469Sglenn.bergmans@arm.com
10512469Sglenn.bergmans@arm.com    # Create the C++ sim objects and connect ports
10612469Sglenn.bergmans@arm.com    for obj in root.descendants(): obj.createCCObject()
10712469Sglenn.bergmans@arm.com    for obj in root.descendants(): obj.connectPorts()
10812469Sglenn.bergmans@arm.com
10912469Sglenn.bergmans@arm.com    # Do a second pass to finish initializing the sim objects
11012469Sglenn.bergmans@arm.com    for obj in root.descendants(): obj.init()
11112469Sglenn.bergmans@arm.com
11212469Sglenn.bergmans@arm.com    # Do a third pass to initialize statistics
11312469Sglenn.bergmans@arm.com    for obj in root.descendants(): obj.regStats()
11412469Sglenn.bergmans@arm.com
11512469Sglenn.bergmans@arm.com    # We're done registering statistics.  Enable the stats package now.
11612469Sglenn.bergmans@arm.com    stats.enable()
11712469Sglenn.bergmans@arm.com
11812469Sglenn.bergmans@arm.com    # Restore checkpoint (if any)
11912469Sglenn.bergmans@arm.com    if ckpt_dir:
12012469Sglenn.bergmans@arm.com        ckpt = internal.core.getCheckpoint(ckpt_dir)
12112469Sglenn.bergmans@arm.com        internal.core.unserializeGlobals(ckpt);
12212469Sglenn.bergmans@arm.com        for obj in root.descendants(): obj.loadState(ckpt)
12312469Sglenn.bergmans@arm.com        need_resume.append(root)
12412469Sglenn.bergmans@arm.com    else:
12512469Sglenn.bergmans@arm.com        for obj in root.descendants(): obj.initState()
12612469Sglenn.bergmans@arm.com
12712469Sglenn.bergmans@arm.com    # Check to see if any of the stat events are in the past after resuming from
12812469Sglenn.bergmans@arm.com    # a checkpoint, If so, this call will shift them to be at a valid time.
12912469Sglenn.bergmans@arm.com    updateStatEvents()
13012469Sglenn.bergmans@arm.com
13112469Sglenn.bergmans@arm.com    # Reset to put the stats in a consistent state.
13212469Sglenn.bergmans@arm.com    stats.reset()
13312469Sglenn.bergmans@arm.com
13412469Sglenn.bergmans@arm.comneed_resume = []
13512469Sglenn.bergmans@arm.comneed_startup = True
13612469Sglenn.bergmans@arm.comdef simulate(*args, **kwargs):
13712469Sglenn.bergmans@arm.com    global need_resume, need_startup
13812469Sglenn.bergmans@arm.com
13912469Sglenn.bergmans@arm.com    if need_startup:
14012469Sglenn.bergmans@arm.com        root = objects.Root.getInstance()
14112469Sglenn.bergmans@arm.com        for obj in root.descendants(): obj.startup()
14212469Sglenn.bergmans@arm.com        need_startup = False
14312469Sglenn.bergmans@arm.com
14412469Sglenn.bergmans@arm.com    for root in need_resume:
14512469Sglenn.bergmans@arm.com        resume(root)
14612469Sglenn.bergmans@arm.com    need_resume = []
14712469Sglenn.bergmans@arm.com
14812469Sglenn.bergmans@arm.com    return internal.event.simulate(*args, **kwargs)
14912469Sglenn.bergmans@arm.com
15012469Sglenn.bergmans@arm.com# Export curTick to user script.
15112469Sglenn.bergmans@arm.comdef curTick():
15212469Sglenn.bergmans@arm.com    return internal.core.curTick()
15312469Sglenn.bergmans@arm.com
15412469Sglenn.bergmans@arm.com# Python exit handlers happen in reverse order.  We want to dump stats last.
15512469Sglenn.bergmans@arm.comatexit.register(stats.dump)
15612469Sglenn.bergmans@arm.com
15712469Sglenn.bergmans@arm.com# register our C++ exit callback function with Python
15812469Sglenn.bergmans@arm.comatexit.register(internal.core.doExitCleanup)
15912469Sglenn.bergmans@arm.com
16012469Sglenn.bergmans@arm.com# This loops until all objects have been fully drained.
16112469Sglenn.bergmans@arm.comdef doDrain(root):
16212469Sglenn.bergmans@arm.com    all_drained = drain(root)
16312469Sglenn.bergmans@arm.com    while (not all_drained):
16412469Sglenn.bergmans@arm.com        all_drained = drain(root)
16512469Sglenn.bergmans@arm.com
16612469Sglenn.bergmans@arm.com# Tries to drain all objects.  Draining might not be completed unless
16712469Sglenn.bergmans@arm.com# all objects return that they are drained on the first call.  This is
16812469Sglenn.bergmans@arm.com# because as objects drain they may cause other objects to no longer
16912469Sglenn.bergmans@arm.com# be drained.
17012469Sglenn.bergmans@arm.comdef drain(root):
17112469Sglenn.bergmans@arm.com    all_drained = False
17212469Sglenn.bergmans@arm.com    dm = internal.drain.createDrainManager()
17312469Sglenn.bergmans@arm.com    unready_objs = sum(obj.drain(dm) for obj in root.descendants())
17412469Sglenn.bergmans@arm.com    # If we've got some objects that can't drain immediately, then simulate
17512469Sglenn.bergmans@arm.com    if unready_objs > 0:
17612469Sglenn.bergmans@arm.com        dm.setCount(unready_objs)
17712469Sglenn.bergmans@arm.com        simulate()
17812469Sglenn.bergmans@arm.com    else:
17912469Sglenn.bergmans@arm.com        all_drained = True
18012469Sglenn.bergmans@arm.com    internal.drain.cleanupDrainManager(dm)
18112469Sglenn.bergmans@arm.com    return all_drained
18212469Sglenn.bergmans@arm.com
18312469Sglenn.bergmans@arm.comdef resume(root):
18412469Sglenn.bergmans@arm.com    for obj in root.descendants(): obj.drainResume()
18512469Sglenn.bergmans@arm.com
18612469Sglenn.bergmans@arm.comdef checkpoint(dir):
18712469Sglenn.bergmans@arm.com    root = objects.Root.getInstance()
18812469Sglenn.bergmans@arm.com    if not isinstance(root, objects.Root):
18912469Sglenn.bergmans@arm.com        raise TypeError, "Checkpoint must be called on a root object."
19012469Sglenn.bergmans@arm.com    doDrain(root)
19112469Sglenn.bergmans@arm.com    print "Writing checkpoint"
19212469Sglenn.bergmans@arm.com    internal.core.serializeAll(dir)
19312469Sglenn.bergmans@arm.com    resume(root)
19412469Sglenn.bergmans@arm.com
19512469Sglenn.bergmans@arm.comdef changeToAtomic(system):
19612469Sglenn.bergmans@arm.com    if not isinstance(system, (objects.Root, objects.System)):
19712469Sglenn.bergmans@arm.com        raise TypeError, "Parameter of type '%s'.  Must be type %s or %s." % \
19812469Sglenn.bergmans@arm.com              (type(system), objects.Root, objects.System)
19912469Sglenn.bergmans@arm.com    if system.getMemoryMode() != objects.params.atomic:
20012469Sglenn.bergmans@arm.com        doDrain(system)
20112469Sglenn.bergmans@arm.com        print "Changing memory mode to atomic"
20212469Sglenn.bergmans@arm.com        system.setMemoryMode(objects.params.atomic)
20312469Sglenn.bergmans@arm.com
20412469Sglenn.bergmans@arm.comdef changeToTiming(system):
20512469Sglenn.bergmans@arm.com    if not isinstance(system, (objects.Root, objects.System)):
20612469Sglenn.bergmans@arm.com        raise TypeError, "Parameter of type '%s'.  Must be type %s or %s." % \
20712469Sglenn.bergmans@arm.com              (type(system), objects.Root, objects.System)
20812469Sglenn.bergmans@arm.com
20912469Sglenn.bergmans@arm.com    if system.getMemoryMode() != objects.params.timing:
21012469Sglenn.bergmans@arm.com        doDrain(system)
21112469Sglenn.bergmans@arm.com        print "Changing memory mode to timing"
21212469Sglenn.bergmans@arm.com        system.setMemoryMode(objects.params.timing)
21312469Sglenn.bergmans@arm.com
21412469Sglenn.bergmans@arm.comdef switchCpus(cpuList):
21512469Sglenn.bergmans@arm.com    print "switching cpus"
21612469Sglenn.bergmans@arm.com    if not isinstance(cpuList, list):
21712469Sglenn.bergmans@arm.com        raise RuntimeError, "Must pass a list to this function"
21812469Sglenn.bergmans@arm.com    for item in cpuList:
21912469Sglenn.bergmans@arm.com        if not isinstance(item, tuple) or len(item) != 2:
22012469Sglenn.bergmans@arm.com            raise RuntimeError, "List must have tuples of (oldCPU,newCPU)"
22112469Sglenn.bergmans@arm.com
22212469Sglenn.bergmans@arm.com    for old_cpu, new_cpu in cpuList:
22312469Sglenn.bergmans@arm.com        if not isinstance(old_cpu, objects.BaseCPU):
22412469Sglenn.bergmans@arm.com            raise TypeError, "%s is not of type BaseCPU" % old_cpu
22512469Sglenn.bergmans@arm.com        if not isinstance(new_cpu, objects.BaseCPU):
22612469Sglenn.bergmans@arm.com            raise TypeError, "%s is not of type BaseCPU" % new_cpu
22712469Sglenn.bergmans@arm.com
22812469Sglenn.bergmans@arm.com    # Now all of the CPUs are ready to be switched out
22912469Sglenn.bergmans@arm.com    for old_cpu, new_cpu in cpuList:
23012469Sglenn.bergmans@arm.com        old_cpu.switchOut()
23112469Sglenn.bergmans@arm.com
23212469Sglenn.bergmans@arm.com    for old_cpu, new_cpu in cpuList:
23312469Sglenn.bergmans@arm.com        new_cpu.takeOverFrom(old_cpu)
23412469Sglenn.bergmans@arm.com
23512469Sglenn.bergmans@arm.comfrom internal.core import disableAllListeners
23612469Sglenn.bergmans@arm.com