__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