__init__.py revision 4123
11736SN/A# Copyright (c) 2005 The Regents of The University of Michigan
21736SN/A# All rights reserved.
31736SN/A#
41736SN/A# Redistribution and use in source and binary forms, with or without
51736SN/A# modification, are permitted provided that the following conditions are
61736SN/A# met: redistributions of source code must retain the above copyright
71736SN/A# notice, this list of conditions and the following disclaimer;
81736SN/A# redistributions in binary form must reproduce the above copyright
91736SN/A# notice, this list of conditions and the following disclaimer in the
101736SN/A# documentation and/or other materials provided with the distribution;
111736SN/A# neither the name of the copyright holders nor the names of its
121736SN/A# contributors may be used to endorse or promote products derived from
131736SN/A# this software without specific prior written permission.
141736SN/A#
151736SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
161736SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
171736SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
181736SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
191736SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
201736SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
211736SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
221736SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
231736SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
241736SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
251736SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262665Ssaidi@eecs.umich.edu#
272665Ssaidi@eecs.umich.edu# Authors: Nathan Binkert
282665Ssaidi@eecs.umich.edu#          Steve Reinhardt
291736SN/A
304123Sbinkertn@umich.eduimport atexit
314123Sbinkertn@umich.eduimport os
324123Sbinkertn@umich.eduimport sys
332655Sstever@eecs.umich.edu
342667Sstever@eecs.umich.edu# import the SWIG-wrapped main C++ functions
353624Sbinkertn@umich.eduimport internal
362667Sstever@eecs.umich.edu# import a few SWIG-wrapped items (those that are likely to be used
372667Sstever@eecs.umich.edu# directly by user scripts) completely into this module for
382667Sstever@eecs.umich.edu# convenience
394123Sbinkertn@umich.edufrom internal.event import SimLoopExitEvent
402655Sstever@eecs.umich.edu
412667Sstever@eecs.umich.edu# import the m5 compile options
422667Sstever@eecs.umich.eduimport defines
431530SN/A
443511Shsul@eecs.umich.edu# define a MaxTick parameter
453511Shsul@eecs.umich.eduMaxTick = 2**63 - 1
463511Shsul@eecs.umich.edu
471530SN/A# define this here so we can use it right away if necessary
481530SN/Adef panic(string):
491530SN/A    print >>sys.stderr, 'panic:', string
501530SN/A    sys.exit(1)
511530SN/A
523105Sstever@eecs.umich.edu# force scalars to one-element lists for uniformity
532969Sktlim@umich.edudef makeList(objOrList):
542969Sktlim@umich.edu    if isinstance(objOrList, list):
552969Sktlim@umich.edu        return objOrList
562969Sktlim@umich.edu    return [objOrList]
572969Sktlim@umich.edu
582667Sstever@eecs.umich.edu# Prepend given directory to system module search path.  We may not
592667Sstever@eecs.umich.edu# need this anymore if we can structure our config library more like a
602667Sstever@eecs.umich.edu# Python package.
611692SN/Adef AddToPath(path):
621869SN/A    # if it's a relative path and we know what directory the current
631869SN/A    # python script is in, make the path relative to that directory.
641869SN/A    if not os.path.isabs(path) and sys.path[0]:
651869SN/A        path = os.path.join(sys.path[0], path)
661692SN/A    path = os.path.realpath(path)
671869SN/A    # sys.path[0] should always refer to the current script's directory,
681869SN/A    # so place the new dir right after that.
691869SN/A    sys.path.insert(1, path)
701581SN/A
711530SN/A# make a SmartDict out of the build options for our local use
721530SN/Aimport smartdict
731530SN/Abuild_env = smartdict.SmartDict()
742667Sstever@eecs.umich.edubuild_env.update(defines.m5_build_env)
751530SN/A
761530SN/A# make a SmartDict out of the OS environment too
771530SN/Aenv = smartdict.SmartDict()
781530SN/Aenv.update(os.environ)
791530SN/A
802667Sstever@eecs.umich.edu# The final hook to generate .ini files.  Called from the user script
812667Sstever@eecs.umich.edu# once the config is built.
822667Sstever@eecs.umich.edudef instantiate(root):
833101Sstever@eecs.umich.edu    params.ticks_per_sec = float(root.clock.frequency)
843105Sstever@eecs.umich.edu    root.unproxy_all()
852667Sstever@eecs.umich.edu    # ugly temporary hack to get output to config.ini
862762Sstever@eecs.umich.edu    sys.stdout = file(os.path.join(options.outdir, 'config.ini'), 'w')
872667Sstever@eecs.umich.edu    root.print_ini()
882667Sstever@eecs.umich.edu    sys.stdout.close() # close config.ini
892667Sstever@eecs.umich.edu    sys.stdout = sys.__stdout__ # restore to original
904123Sbinkertn@umich.edu
914123Sbinkertn@umich.edu    # load config.ini into C++
924123Sbinkertn@umich.edu    internal.core.loadIniFile(resolveSimObject)
934123Sbinkertn@umich.edu
944123Sbinkertn@umich.edu    # Initialize the global statistics
954123Sbinkertn@umich.edu    internal.stats.initSimStats()
964123Sbinkertn@umich.edu
972738Sstever@eecs.umich.edu    root.createCCObject()
982738Sstever@eecs.umich.edu    root.connectPorts()
994123Sbinkertn@umich.edu
1004123Sbinkertn@umich.edu    # Do a second pass to finish initializing the sim objects
1014123Sbinkertn@umich.edu    internal.sim_object.initAll()
1024123Sbinkertn@umich.edu
1034123Sbinkertn@umich.edu    # Do a third pass to initialize statistics
1044123Sbinkertn@umich.edu    internal.sim_object.regAllStats()
1054123Sbinkertn@umich.edu
1064123Sbinkertn@umich.edu    # Check to make sure that the stats package is properly initialized
1074123Sbinkertn@umich.edu    internal.stats.check()
1084123Sbinkertn@umich.edu
1094123Sbinkertn@umich.edu    # Reset to put the stats in a consistent state.
1104123Sbinkertn@umich.edu    internal.stats.reset()
1114123Sbinkertn@umich.edu
1124123Sbinkertn@umich.edudef doDot(root):
1134123Sbinkertn@umich.edu    dot = pydot.Dot()
1144123Sbinkertn@umich.edu    instance.outputDot(dot)
1154123Sbinkertn@umich.edu    dot.orientation = "portrait"
1164123Sbinkertn@umich.edu    dot.size = "8.5,11"
1174123Sbinkertn@umich.edu    dot.ranksep="equally"
1184123Sbinkertn@umich.edu    dot.rank="samerank"
1194123Sbinkertn@umich.edu    dot.write("config.dot")
1204123Sbinkertn@umich.edu    dot.write_ps("config.ps")
1214123Sbinkertn@umich.edu
1224123Sbinkertn@umich.eduneed_resume = []
1234123Sbinkertn@umich.eduneed_startup = True
1244123Sbinkertn@umich.edudef simulate(*args, **kwargs):
1254123Sbinkertn@umich.edu    global need_resume, need_startup
1264123Sbinkertn@umich.edu
1274123Sbinkertn@umich.edu    if need_startup:
1284123Sbinkertn@umich.edu        internal.core.SimStartup()
1294123Sbinkertn@umich.edu        need_startup = False
1304123Sbinkertn@umich.edu
1314123Sbinkertn@umich.edu    for root in need_resume:
1324123Sbinkertn@umich.edu        resume(root)
1334123Sbinkertn@umich.edu    need_resume = []
1344123Sbinkertn@umich.edu
1354123Sbinkertn@umich.edu    return internal.event.simulate(*args, **kwargs)
1361527SN/A
1372667Sstever@eecs.umich.edu# Export curTick to user script.
1382667Sstever@eecs.umich.edudef curTick():
1394123Sbinkertn@umich.edu    return internal.event.cvar.curTick
1401511SN/A
1412667Sstever@eecs.umich.edu# register our C++ exit callback function with Python
1424123Sbinkertn@umich.eduatexit.register(internal.core.doExitCleanup)
1434123Sbinkertn@umich.eduatexit.register(internal.stats.dump)
1442655Sstever@eecs.umich.edu
1452860Sktlim@umich.edu# This loops until all objects have been fully drained.
1462839Sktlim@umich.edudef doDrain(root):
1472860Sktlim@umich.edu    all_drained = drain(root)
1482860Sktlim@umich.edu    while (not all_drained):
1492860Sktlim@umich.edu        all_drained = drain(root)
1502860Sktlim@umich.edu
1512860Sktlim@umich.edu# Tries to drain all objects.  Draining might not be completed unless
1522860Sktlim@umich.edu# all objects return that they are drained on the first call.  This is
1532860Sktlim@umich.edu# because as objects drain they may cause other objects to no longer
1542860Sktlim@umich.edu# be drained.
1552860Sktlim@umich.edudef drain(root):
1562860Sktlim@umich.edu    all_drained = False
1574123Sbinkertn@umich.edu    drain_event = internal.event.createCountedDrain()
1582839Sktlim@umich.edu    unready_objects = root.startDrain(drain_event, True)
1592839Sktlim@umich.edu    # If we've got some objects that can't drain immediately, then simulate
1602797Sktlim@umich.edu    if unready_objects > 0:
1612839Sktlim@umich.edu        drain_event.setCount(unready_objects)
1622797Sktlim@umich.edu        simulate()
1632860Sktlim@umich.edu    else:
1642860Sktlim@umich.edu        all_drained = True
1654123Sbinkertn@umich.edu    internal.event.cleanupCountedDrain(drain_event)
1662860Sktlim@umich.edu    return all_drained
1672797Sktlim@umich.edu
1682797Sktlim@umich.edudef resume(root):
1692797Sktlim@umich.edu    root.resume()
1702797Sktlim@umich.edu
1712868Sktlim@umich.edudef checkpoint(root, dir):
1722797Sktlim@umich.edu    if not isinstance(root, objects.Root):
1734123Sbinkertn@umich.edu        raise TypeError, "Checkpoint must be called on a root object."
1742839Sktlim@umich.edu    doDrain(root)
1752797Sktlim@umich.edu    print "Writing checkpoint"
1764123Sbinkertn@umich.edu    internal.sim_object.serializeAll(dir)
1772797Sktlim@umich.edu    resume(root)
1782797Sktlim@umich.edu
1792868Sktlim@umich.edudef restoreCheckpoint(root, dir):
1802797Sktlim@umich.edu    print "Restoring from checkpoint"
1814123Sbinkertn@umich.edu    internal.sim_object.unserializeAll(dir)
1824123Sbinkertn@umich.edu    need_resume.append(root)
1832797Sktlim@umich.edu
1842797Sktlim@umich.edudef changeToAtomic(system):
1853203Shsul@eecs.umich.edu    if not isinstance(system, objects.Root) and not isinstance(system, objects.System):
1862797Sktlim@umich.edu        raise TypeError, "Object is not a root or system object.  Checkpoint must be "
1872797Sktlim@umich.edu        "called on a root object."
1882839Sktlim@umich.edu    doDrain(system)
1892797Sktlim@umich.edu    print "Changing memory mode to atomic"
1904123Sbinkertn@umich.edu    system.changeTiming(internal.sim_object.SimObject.Atomic)
1912797Sktlim@umich.edu
1922797Sktlim@umich.edudef changeToTiming(system):
1933203Shsul@eecs.umich.edu    if not isinstance(system, objects.Root) and not isinstance(system, objects.System):
1942797Sktlim@umich.edu        raise TypeError, "Object is not a root or system object.  Checkpoint must be "
1952797Sktlim@umich.edu        "called on a root object."
1962839Sktlim@umich.edu    doDrain(system)
1972797Sktlim@umich.edu    print "Changing memory mode to timing"
1984123Sbinkertn@umich.edu    system.changeTiming(internal.sim_object.SimObject.Timing)
1992797Sktlim@umich.edu
2002797Sktlim@umich.edudef switchCpus(cpuList):
2013203Shsul@eecs.umich.edu    print "switching cpus"
2022797Sktlim@umich.edu    if not isinstance(cpuList, list):
2032797Sktlim@umich.edu        raise RuntimeError, "Must pass a list to this function"
2042797Sktlim@umich.edu    for i in cpuList:
2052797Sktlim@umich.edu        if not isinstance(i, tuple):
2062797Sktlim@umich.edu            raise RuntimeError, "List must have tuples of (oldCPU,newCPU)"
2072797Sktlim@umich.edu
2082797Sktlim@umich.edu    [old_cpus, new_cpus] = zip(*cpuList)
2092797Sktlim@umich.edu
2102797Sktlim@umich.edu    for cpu in old_cpus:
2112797Sktlim@umich.edu        if not isinstance(cpu, objects.BaseCPU):
2123504Sktlim@umich.edu            raise TypeError, "%s is not of type BaseCPU" % cpu
2132797Sktlim@umich.edu    for cpu in new_cpus:
2142797Sktlim@umich.edu        if not isinstance(cpu, objects.BaseCPU):
2153504Sktlim@umich.edu            raise TypeError, "%s is not of type BaseCPU" % cpu
2162797Sktlim@umich.edu
2172839Sktlim@umich.edu    # Drain all of the individual CPUs
2184123Sbinkertn@umich.edu    drain_event = internal.event.createCountedDrain()
2192797Sktlim@umich.edu    unready_cpus = 0
2202797Sktlim@umich.edu    for old_cpu in old_cpus:
2212839Sktlim@umich.edu        unready_cpus += old_cpu.startDrain(drain_event, False)
2222839Sktlim@umich.edu    # If we've got some objects that can't drain immediately, then simulate
2232797Sktlim@umich.edu    if unready_cpus > 0:
2242839Sktlim@umich.edu        drain_event.setCount(unready_cpus)
2252797Sktlim@umich.edu        simulate()
2264123Sbinkertn@umich.edu    internal.event.cleanupCountedDrain(drain_event)
2272797Sktlim@umich.edu    # Now all of the CPUs are ready to be switched out
2282797Sktlim@umich.edu    for old_cpu in old_cpus:
2292797Sktlim@umich.edu        old_cpu._ccObject.switchOut()
2302797Sktlim@umich.edu    index = 0
2312797Sktlim@umich.edu    for new_cpu in new_cpus:
2322797Sktlim@umich.edu        new_cpu.takeOverFrom(old_cpus[index])
2332797Sktlim@umich.edu        new_cpu._ccObject.resume()
2342797Sktlim@umich.edu        index += 1
2353101Sstever@eecs.umich.edu
2364123Sbinkertn@umich.edudef dumpStats():
2374123Sbinkertn@umich.edu    print 'Dumping stats'
2384123Sbinkertn@umich.edu    internal.stats.dump()
2394123Sbinkertn@umich.edu
2404123Sbinkertn@umich.edudef resetStats():
2414123Sbinkertn@umich.edu    print 'Resetting stats'
2424123Sbinkertn@umich.edu    internal.stats.reset()
2434123Sbinkertn@umich.edu
2443101Sstever@eecs.umich.edu# Since we have so many mutual imports in this package, we should:
2453101Sstever@eecs.umich.edu# 1. Put all intra-package imports at the *bottom* of the file, unless
2463101Sstever@eecs.umich.edu#    they're absolutely needed before that (for top-level statements
2473101Sstever@eecs.umich.edu#    or class attributes).  Imports of "trivial" packages that don't
2483101Sstever@eecs.umich.edu#    import other packages (e.g., 'smartdict') can be at the top.
2493101Sstever@eecs.umich.edu# 2. Never use 'from foo import *' on an intra-package import since
2503101Sstever@eecs.umich.edu#    you can get the wrong result if foo is only partially imported
2513101Sstever@eecs.umich.edu#    at the point you do that (i.e., because foo is in the middle of
2523101Sstever@eecs.umich.edu#    importing *you*).
2533102Sstever@eecs.umich.edufrom main import options
2543101Sstever@eecs.umich.eduimport objects
2553101Sstever@eecs.umich.eduimport params
2563102Sstever@eecs.umich.edufrom SimObject import resolveSimObject
257