__init__.py revision 2865
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 302667Sstever@eecs.umich.eduimport sys, os, time, atexit, optparse 312655Sstever@eecs.umich.edu 322667Sstever@eecs.umich.edu# import the SWIG-wrapped main C++ functions 332763Sstever@eecs.umich.eduimport cc_main 342667Sstever@eecs.umich.edu# import a few SWIG-wrapped items (those that are likely to be used 352667Sstever@eecs.umich.edu# directly by user scripts) completely into this module for 362667Sstever@eecs.umich.edu# convenience 372797Sktlim@umich.edufrom cc_main import simulate, SimLoopExitEvent, setCheckpointDir 382655Sstever@eecs.umich.edu 392667Sstever@eecs.umich.edu# import the m5 compile options 402667Sstever@eecs.umich.eduimport defines 411530SN/A 421530SN/A# define this here so we can use it right away if necessary 431530SN/Adef panic(string): 441530SN/A print >>sys.stderr, 'panic:', string 451530SN/A sys.exit(1) 461530SN/A 472667Sstever@eecs.umich.edu# Prepend given directory to system module search path. We may not 482667Sstever@eecs.umich.edu# need this anymore if we can structure our config library more like a 492667Sstever@eecs.umich.edu# Python package. 501692SN/Adef AddToPath(path): 511869SN/A # if it's a relative path and we know what directory the current 521869SN/A # python script is in, make the path relative to that directory. 531869SN/A if not os.path.isabs(path) and sys.path[0]: 541869SN/A path = os.path.join(sys.path[0], path) 551692SN/A path = os.path.realpath(path) 561869SN/A # sys.path[0] should always refer to the current script's directory, 571869SN/A # so place the new dir right after that. 581869SN/A sys.path.insert(1, path) 591581SN/A 602667Sstever@eecs.umich.edu 612762Sstever@eecs.umich.edu# The m5 module's pointer to the parsed options object 622762Sstever@eecs.umich.eduoptions = None 632762Sstever@eecs.umich.edu 642762Sstever@eecs.umich.edu 652762Sstever@eecs.umich.edu# User should call this function after calling parse_args() to pass 662762Sstever@eecs.umich.edu# parsed standard option values back into the m5 module for 672762Sstever@eecs.umich.edu# processing. 682762Sstever@eecs.umich.edudef setStandardOptions(_options): 692762Sstever@eecs.umich.edu # Set module global var 702762Sstever@eecs.umich.edu global options 712762Sstever@eecs.umich.edu options = _options 722762Sstever@eecs.umich.edu # tell C++ about output directory 732763Sstever@eecs.umich.edu cc_main.setOutputDir(options.outdir) 742762Sstever@eecs.umich.edu 752667Sstever@eecs.umich.edu# Callback to set trace flags. Not necessarily the best way to do 762667Sstever@eecs.umich.edu# things in the long run (particularly if we change how these global 772667Sstever@eecs.umich.edu# options are handled). 782667Sstever@eecs.umich.edudef setTraceFlags(option, opt_str, value, parser): 792667Sstever@eecs.umich.edu objects.Trace.flags = value 802667Sstever@eecs.umich.edu 812728Sktlim@umich.edudef setTraceStart(option, opt_str, value, parser): 822728Sktlim@umich.edu objects.Trace.start = value 832728Sktlim@umich.edu 842759Sktlim@umich.edudef setTraceFile(option, opt_str, value, parser): 852759Sktlim@umich.edu objects.Trace.file = value 862728Sktlim@umich.edu 872767Sktlim@umich.edudef noPCSymbol(option, opt_str, value, parser): 882767Sktlim@umich.edu objects.ExecutionTrace.pc_symbol = False 892759Sktlim@umich.edu 902767Sktlim@umich.edudef noPrintCycle(option, opt_str, value, parser): 912767Sktlim@umich.edu objects.ExecutionTrace.print_cycle = False 922759Sktlim@umich.edu 932767Sktlim@umich.edudef noPrintOpclass(option, opt_str, value, parser): 942767Sktlim@umich.edu objects.ExecutionTrace.print_opclass = False 952759Sktlim@umich.edu 962767Sktlim@umich.edudef noPrintThread(option, opt_str, value, parser): 972767Sktlim@umich.edu objects.ExecutionTrace.print_thread = False 982759Sktlim@umich.edu 992767Sktlim@umich.edudef noPrintEA(option, opt_str, value, parser): 1002767Sktlim@umich.edu objects.ExecutionTrace.print_effaddr = False 1012759Sktlim@umich.edu 1022767Sktlim@umich.edudef noPrintData(option, opt_str, value, parser): 1032767Sktlim@umich.edu objects.ExecutionTrace.print_data = False 1042759Sktlim@umich.edu 1052759Sktlim@umich.edudef printFetchseq(option, opt_str, value, parser): 1062767Sktlim@umich.edu objects.ExecutionTrace.print_fetchseq = True 1072759Sktlim@umich.edu 1082759Sktlim@umich.edudef printCpseq(option, opt_str, value, parser): 1092767Sktlim@umich.edu objects.ExecutionTrace.print_cpseq = True 1102759Sktlim@umich.edu 1112759Sktlim@umich.edudef dumpOnExit(option, opt_str, value, parser): 1122767Sktlim@umich.edu objects.Trace.dump_on_exit = True 1132759Sktlim@umich.edu 1142759Sktlim@umich.edudef debugBreak(option, opt_str, value, parser): 1152759Sktlim@umich.edu objects.Debug.break_cycles = value 1162728Sktlim@umich.edu 1172728Sktlim@umich.edudef statsTextFile(option, opt_str, value, parser): 1182728Sktlim@umich.edu objects.Statistics.text_file = value 1192728Sktlim@umich.edu 1202667Sstever@eecs.umich.edu# Standard optparse options. Need to be explicitly included by the 1212667Sstever@eecs.umich.edu# user script when it calls optparse.OptionParser(). 1222667Sstever@eecs.umich.edustandardOptions = [ 1232762Sstever@eecs.umich.edu optparse.make_option("--outdir", type="string", default="."), 1242667Sstever@eecs.umich.edu optparse.make_option("--traceflags", type="string", action="callback", 1252728Sktlim@umich.edu callback=setTraceFlags), 1262728Sktlim@umich.edu optparse.make_option("--tracestart", type="int", action="callback", 1272728Sktlim@umich.edu callback=setTraceStart), 1282759Sktlim@umich.edu optparse.make_option("--tracefile", type="string", action="callback", 1292759Sktlim@umich.edu callback=setTraceFile), 1302767Sktlim@umich.edu optparse.make_option("--nopcsymbol", 1312767Sktlim@umich.edu action="callback", callback=noPCSymbol, 1322767Sktlim@umich.edu help="Disable PC symbols in trace output"), 1332767Sktlim@umich.edu optparse.make_option("--noprintcycle", 1342767Sktlim@umich.edu action="callback", callback=noPrintCycle, 1352767Sktlim@umich.edu help="Don't print cycle numbers in trace output"), 1362767Sktlim@umich.edu optparse.make_option("--noprintopclass", 1372767Sktlim@umich.edu action="callback", callback=noPrintOpclass, 1382767Sktlim@umich.edu help="Don't print op class type in trace output"), 1392767Sktlim@umich.edu optparse.make_option("--noprintthread", 1402767Sktlim@umich.edu action="callback", callback=noPrintThread, 1412767Sktlim@umich.edu help="Don't print thread number in trace output"), 1422767Sktlim@umich.edu optparse.make_option("--noprinteffaddr", 1432767Sktlim@umich.edu action="callback", callback=noPrintEA, 1442767Sktlim@umich.edu help="Don't print effective address in trace output"), 1452767Sktlim@umich.edu optparse.make_option("--noprintdata", 1462767Sktlim@umich.edu action="callback", callback=noPrintData, 1472767Sktlim@umich.edu help="Don't print result data in trace output"), 1482767Sktlim@umich.edu optparse.make_option("--printfetchseq", 1492759Sktlim@umich.edu action="callback", callback=printFetchseq, 1502759Sktlim@umich.edu help="Print fetch sequence numbers in trace output"), 1512767Sktlim@umich.edu optparse.make_option("--printcpseq", 1522759Sktlim@umich.edu action="callback", callback=printCpseq, 1532759Sktlim@umich.edu help="Print correct path sequence numbers in trace output"), 1542767Sktlim@umich.edu optparse.make_option("--dumponexit", 1552759Sktlim@umich.edu action="callback", callback=dumpOnExit, 1562759Sktlim@umich.edu help="Dump trace buffer on exit"), 1572759Sktlim@umich.edu optparse.make_option("--debugbreak", type="int", metavar="CYCLE", 1582759Sktlim@umich.edu action="callback", callback=debugBreak, 1592759Sktlim@umich.edu help="Cycle to create a breakpoint"), 1602728Sktlim@umich.edu optparse.make_option("--statsfile", type="string", action="callback", 1612728Sktlim@umich.edu callback=statsTextFile, metavar="FILE", 1622728Sktlim@umich.edu help="Sets the output file for the statistics") 1632667Sstever@eecs.umich.edu ] 1641530SN/A 1651530SN/A# make a SmartDict out of the build options for our local use 1661530SN/Aimport smartdict 1671530SN/Abuild_env = smartdict.SmartDict() 1682667Sstever@eecs.umich.edubuild_env.update(defines.m5_build_env) 1691530SN/A 1701530SN/A# make a SmartDict out of the OS environment too 1711530SN/Aenv = smartdict.SmartDict() 1721530SN/Aenv.update(os.environ) 1731530SN/A 1742738Sstever@eecs.umich.edu 1752738Sstever@eecs.umich.edu# Function to provide to C++ so it can look up instances based on paths 1762738Sstever@eecs.umich.edudef resolveSimObject(name): 1772738Sstever@eecs.umich.edu obj = config.instanceDict[name] 1782740Sstever@eecs.umich.edu return obj.getCCObject() 1792738Sstever@eecs.umich.edu 1802667Sstever@eecs.umich.edu# The final hook to generate .ini files. Called from the user script 1812667Sstever@eecs.umich.edu# once the config is built. 1822667Sstever@eecs.umich.edudef instantiate(root): 1832667Sstever@eecs.umich.edu config.ticks_per_sec = float(root.clock.frequency) 1842667Sstever@eecs.umich.edu # ugly temporary hack to get output to config.ini 1852762Sstever@eecs.umich.edu sys.stdout = file(os.path.join(options.outdir, 'config.ini'), 'w') 1862667Sstever@eecs.umich.edu root.print_ini() 1872667Sstever@eecs.umich.edu sys.stdout.close() # close config.ini 1882667Sstever@eecs.umich.edu sys.stdout = sys.__stdout__ # restore to original 1892763Sstever@eecs.umich.edu cc_main.loadIniFile(resolveSimObject) # load config.ini into C++ 1902738Sstever@eecs.umich.edu root.createCCObject() 1912738Sstever@eecs.umich.edu root.connectPorts() 1922763Sstever@eecs.umich.edu cc_main.finalInit() 1932667Sstever@eecs.umich.edu noDot = True # temporary until we fix dot 1942667Sstever@eecs.umich.edu if not noDot: 1952667Sstever@eecs.umich.edu dot = pydot.Dot() 1962667Sstever@eecs.umich.edu instance.outputDot(dot) 1972667Sstever@eecs.umich.edu dot.orientation = "portrait" 1982667Sstever@eecs.umich.edu dot.size = "8.5,11" 1992667Sstever@eecs.umich.edu dot.ranksep="equally" 2002667Sstever@eecs.umich.edu dot.rank="samerank" 2012667Sstever@eecs.umich.edu dot.write("config.dot") 2022667Sstever@eecs.umich.edu dot.write_ps("config.ps") 2031527SN/A 2042667Sstever@eecs.umich.edu# Export curTick to user script. 2052667Sstever@eecs.umich.edudef curTick(): 2062763Sstever@eecs.umich.edu return cc_main.cvar.curTick 2071511SN/A 2082667Sstever@eecs.umich.edu# register our C++ exit callback function with Python 2092763Sstever@eecs.umich.eduatexit.register(cc_main.doExitCleanup) 2102655Sstever@eecs.umich.edu 2112667Sstever@eecs.umich.edu# This import allows user scripts to reference 'm5.objects.Foo' after 2122667Sstever@eecs.umich.edu# just doing an 'import m5' (without an 'import m5.objects'). May not 2132667Sstever@eecs.umich.edu# matter since most scripts will probably 'from m5.objects import *'. 2142667Sstever@eecs.umich.eduimport objects 2152797Sktlim@umich.edu 2162860Sktlim@umich.edu# This loops until all objects have been fully drained. 2172839Sktlim@umich.edudef doDrain(root): 2182860Sktlim@umich.edu all_drained = drain(root) 2192860Sktlim@umich.edu while (not all_drained): 2202860Sktlim@umich.edu all_drained = drain(root) 2212860Sktlim@umich.edu 2222860Sktlim@umich.edu# Tries to drain all objects. Draining might not be completed unless 2232860Sktlim@umich.edu# all objects return that they are drained on the first call. This is 2242860Sktlim@umich.edu# because as objects drain they may cause other objects to no longer 2252860Sktlim@umich.edu# be drained. 2262860Sktlim@umich.edudef drain(root): 2272860Sktlim@umich.edu all_drained = False 2282839Sktlim@umich.edu drain_event = cc_main.createCountedDrain() 2292839Sktlim@umich.edu unready_objects = root.startDrain(drain_event, True) 2302839Sktlim@umich.edu # If we've got some objects that can't drain immediately, then simulate 2312797Sktlim@umich.edu if unready_objects > 0: 2322839Sktlim@umich.edu drain_event.setCount(unready_objects) 2332797Sktlim@umich.edu simulate() 2342860Sktlim@umich.edu else: 2352860Sktlim@umich.edu all_drained = True 2362839Sktlim@umich.edu cc_main.cleanupCountedDrain(drain_event) 2372860Sktlim@umich.edu return all_drained 2382797Sktlim@umich.edu 2392797Sktlim@umich.edudef resume(root): 2402797Sktlim@umich.edu root.resume() 2412797Sktlim@umich.edu 2422797Sktlim@umich.edudef checkpoint(root): 2432797Sktlim@umich.edu if not isinstance(root, objects.Root): 2442797Sktlim@umich.edu raise TypeError, "Object is not a root object. Checkpoint must be called on a root object." 2452839Sktlim@umich.edu doDrain(root) 2462797Sktlim@umich.edu print "Writing checkpoint" 2472797Sktlim@umich.edu cc_main.serializeAll() 2482797Sktlim@umich.edu resume(root) 2492797Sktlim@umich.edu 2502797Sktlim@umich.edudef restoreCheckpoint(root): 2512797Sktlim@umich.edu print "Restoring from checkpoint" 2522797Sktlim@umich.edu cc_main.unserializeAll() 2532865Sktlim@umich.edu resume(root) 2542797Sktlim@umich.edu 2552797Sktlim@umich.edudef changeToAtomic(system): 2562797Sktlim@umich.edu if not isinstance(system, objects.Root) and not isinstance(system, System): 2572797Sktlim@umich.edu raise TypeError, "Object is not a root or system object. Checkpoint must be " 2582797Sktlim@umich.edu "called on a root object." 2592839Sktlim@umich.edu doDrain(system) 2602797Sktlim@umich.edu print "Changing memory mode to atomic" 2612797Sktlim@umich.edu system.changeTiming(cc_main.SimObject.Atomic) 2622797Sktlim@umich.edu resume(system) 2632797Sktlim@umich.edu 2642797Sktlim@umich.edudef changeToTiming(system): 2652797Sktlim@umich.edu if not isinstance(system, objects.Root) and not isinstance(system, System): 2662797Sktlim@umich.edu raise TypeError, "Object is not a root or system object. Checkpoint must be " 2672797Sktlim@umich.edu "called on a root object." 2682839Sktlim@umich.edu doDrain(system) 2692797Sktlim@umich.edu print "Changing memory mode to timing" 2702797Sktlim@umich.edu system.changeTiming(cc_main.SimObject.Timing) 2712797Sktlim@umich.edu resume(system) 2722797Sktlim@umich.edu 2732797Sktlim@umich.edudef switchCpus(cpuList): 2742797Sktlim@umich.edu if not isinstance(cpuList, list): 2752797Sktlim@umich.edu raise RuntimeError, "Must pass a list to this function" 2762797Sktlim@umich.edu for i in cpuList: 2772797Sktlim@umich.edu if not isinstance(i, tuple): 2782797Sktlim@umich.edu raise RuntimeError, "List must have tuples of (oldCPU,newCPU)" 2792797Sktlim@umich.edu 2802797Sktlim@umich.edu [old_cpus, new_cpus] = zip(*cpuList) 2812797Sktlim@umich.edu 2822797Sktlim@umich.edu for cpu in old_cpus: 2832797Sktlim@umich.edu if not isinstance(cpu, objects.BaseCPU): 2842797Sktlim@umich.edu raise TypeError, "%s is not of type BaseCPU", cpu 2852797Sktlim@umich.edu for cpu in new_cpus: 2862797Sktlim@umich.edu if not isinstance(cpu, objects.BaseCPU): 2872797Sktlim@umich.edu raise TypeError, "%s is not of type BaseCPU", cpu 2882797Sktlim@umich.edu 2892839Sktlim@umich.edu # Drain all of the individual CPUs 2902839Sktlim@umich.edu drain_event = cc_main.createCountedDrain() 2912797Sktlim@umich.edu unready_cpus = 0 2922797Sktlim@umich.edu for old_cpu in old_cpus: 2932839Sktlim@umich.edu unready_cpus += old_cpu.startDrain(drain_event, False) 2942839Sktlim@umich.edu # If we've got some objects that can't drain immediately, then simulate 2952797Sktlim@umich.edu if unready_cpus > 0: 2962839Sktlim@umich.edu drain_event.setCount(unready_cpus) 2972797Sktlim@umich.edu simulate() 2982839Sktlim@umich.edu cc_main.cleanupCountedDrain(drain_event) 2992797Sktlim@umich.edu # Now all of the CPUs are ready to be switched out 3002797Sktlim@umich.edu for old_cpu in old_cpus: 3012797Sktlim@umich.edu old_cpu._ccObject.switchOut() 3022797Sktlim@umich.edu index = 0 3032797Sktlim@umich.edu print "Switching CPUs" 3042797Sktlim@umich.edu for new_cpu in new_cpus: 3052797Sktlim@umich.edu new_cpu.takeOverFrom(old_cpus[index]) 3062797Sktlim@umich.edu new_cpu._ccObject.resume() 3072797Sktlim@umich.edu index += 1 308