Move main control from C++ into Python.

User script now invokes initialization and
simulation loop after building configuration.
These functions are exported from C++ to Python
using SWIG.

SConstruct:
    Set up SWIG builder & scanner.
    Set up symlinking of source files into build directory
    (by not disabling the default behavior).
configs/test/test.py:
    Rewrite to use new script-driven interface.
    Include a sample option.
src/SConscript:
    Set up symlinking of source files into build directory
    (by not disabling the default behavior).
    Add SWIG-generated main_wrap.cc to source list.
src/arch/SConscript:
    Set up symlinking of source files into build directory
    (by not disabling the default behavior).
src/arch/alpha/ev5.cc:
src/arch/alpha/isa/decoder.isa:
src/cpu/o3/alpha_cpu_impl.hh:
src/cpu/trace/opt_cpu.cc:
src/cpu/trace/trace_cpu.cc:
src/sim/pseudo_inst.cc:
src/sim/root.cc:
src/sim/serialize.cc:
src/sim/syscall_emul.cc:
    SimExit() is now exitSimLoop().
src/cpu/base.cc:
    SimExitEvent is now SimLoopExitEvent
src/python/SConscript:
    Add SWIG build command for main.i.
    Use python/m5 in build dir as source for zip archive...
    easy now with file duplication enabled.
src/python/m5/__init__.py:
    - Move copyright notice back to C++ so we can print
    it right away, even for interactive sessions.
    - Get rid of argument parsing code; just provide default
    option descriptors for user script to call optparse with.
    - Don't clutter m5 namespace by sucking in all of m5.config
    and m5.objects.
    - Move instantiate() function here from config.py.
src/python/m5/config.py:
    - Move instantiate() function to __init__.py.
    - Param.Foo deferred type lookups must use m5.objects
    namespace now (not m5).
src/python/m5/objects/AlphaConsole.py:
src/python/m5/objects/AlphaFullCPU.py:
src/python/m5/objects/AlphaTLB.py:
src/python/m5/objects/BadDevice.py:
src/python/m5/objects/BaseCPU.py:
src/python/m5/objects/BaseCache.py:
src/python/m5/objects/Bridge.py:
src/python/m5/objects/Bus.py:
src/python/m5/objects/CoherenceProtocol.py:
src/python/m5/objects/Device.py:
src/python/m5/objects/DiskImage.py:
src/python/m5/objects/Ethernet.py:
src/python/m5/objects/Ide.py:
src/python/m5/objects/IntrControl.py:
src/python/m5/objects/MemObject.py:
src/python/m5/objects/MemTest.py:
src/python/m5/objects/Pci.py:
src/python/m5/objects/PhysicalMemory.py:
src/python/m5/objects/Platform.py:
src/python/m5/objects/Process.py:
src/python/m5/objects/Repl.py:
src/python/m5/objects/Root.py:
src/python/m5/objects/SimConsole.py:
src/python/m5/objects/SimpleDisk.py:
src/python/m5/objects/System.py:
src/python/m5/objects/Tsunami.py:
src/python/m5/objects/Uart.py:
    Fix up imports (m5 namespace no longer includes m5.config).
src/sim/eventq.cc:
src/sim/eventq.hh:
    Support for Python-called simulate() function:
    - Use IsExitEvent flag to signal events that want
    to exit the simulation loop gracefully (instead of
    calling exit() to terminate the process).
    - Modify interface to hand exit event object back to
    caller so it can be inspected for cause.
src/sim/host.hh:
    Add MaxTick constant.
src/sim/main.cc:
    Move copyright notice back to C++ so we can print
    it right away, even for interactive sessions.
    Use PYTHONPATH environment var to set module path
    (instead of clunky code injection method).
    Move main control from here into Python:
    - Separate initialization code and simulation loop
    into separate functions callable from Python.
    - Make Python interpreter invocation more pure (more
    like directly invoking interpreter).
    Add -i and -p flags (only options on binary itself;
    other options processed by Python).
    Import readline package when using interactive mode.
src/sim/sim_events.cc:
    SimExitEvent is now SimLoopExitEvent, and uses
    IsSimExit flag to terminate loop (instead of
    exiting simulator process).
src/sim/sim_events.hh:
    SimExitEvent is now SimLoopExitEvent, and uses
    IsSimExit flag to terminate loop (instead of
    exiting simulator process).
    Get rid of a few unused constructors.
src/sim/sim_exit.hh:
    SimExit() is now exitSimLoop().
    Get rid of unused functions.
    Add comments.

--HG--
extra : convert_revision : 280b0d671516b25545a6f24cefa64a68319ff3d4
This commit is contained in:
Steve Reinhardt
2006-06-09 23:01:31 -04:00
parent 5802c46c3b
commit 29e34a739b
51 changed files with 453 additions and 327 deletions

View File

@@ -38,11 +38,8 @@ def join(*args):
Import('env')
# This SConscript is in charge of collecting .py files and generating a zip archive that is appended to the m5 binary.
# Copy .py source files here (relative to src/python in the build
# directory).
pyzip_root = 'zip'
# This SConscript is in charge of collecting .py files and generating
# a zip archive that is appended to the m5 binary.
# List of files & directories to include in the zip file. To include
# a package, list only the root directory of the package, not any
@@ -58,7 +55,7 @@ pyzip_dep_files = []
# Add the specified package to the zip archive. Adds the directory to
# pyzip_files and all included .py files to pyzip_dep_files.
def addPkg(pkgdir):
pyzip_files.append(join(pyzip_root, pkgdir))
pyzip_files.append(pkgdir)
origdir = os.getcwd()
srcdir = join(Dir('.').srcnode().abspath, pkgdir)
os.chdir(srcdir)
@@ -70,10 +67,7 @@ def addPkg(pkgdir):
for f in files:
if f.endswith('.py'):
source = join(pkgdir, path, f)
target = join(pyzip_root, source)
pyzip_dep_files.append(target)
env.CopyFile(target, source)
pyzip_dep_files.append(join(pkgdir, path, f))
os.chdir(origdir)
@@ -81,19 +75,25 @@ def addPkg(pkgdir):
# build_env flags.
def MakeDefinesPyFile(target, source, env):
f = file(str(target[0]), 'w')
print >>f, "import __main__"
print >>f, "__main__.m5_build_env = ",
print >>f, "m5_build_env = ",
print >>f, source[0]
f.close()
optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
env.Command('defines.py', Value(optionDict), MakeDefinesPyFile)
env.Command('m5/defines.py', Value(optionDict), MakeDefinesPyFile)
# Now specify the packages & files for the zip archive.
addPkg('m5')
pyzip_files.append('defines.py')
pyzip_files.append('m5/defines.py')
pyzip_files.append(join(env['ROOT'], 'util/pbs/jobfile.py'))
env.Command(['swig/main_wrap.cc', 'm5/main.py'],
'swig/main.i',
'$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
'-o ${TARGETS[0]} $SOURCES')
pyzip_dep_files.append('m5/main.py')
# Action function to build the zip archive. Uses the PyZipFile module
# included in the standard Python library.
def buildPyZip(target, source, env):

View File

@@ -27,69 +27,26 @@
# Authors: Nathan Binkert
# Steve Reinhardt
import sys, os, time
import sys, os, time, atexit, optparse
import __main__
# import the SWIG-wrapped main C++ functions
import main
# import a few SWIG-wrapped items (those that are likely to be used
# directly by user scripts) completely into this module for
# convenience
from main import simulate, SimLoopExitEvent
briefCopyright = '''
Copyright (c) 2001-2006
The Regents of The University of Michigan
All Rights Reserved
'''
fullCopyright = '''
Copyright (c) 2001-2006
The Regents of The University of Michigan
All Rights Reserved
Permission is granted to use, copy, create derivative works and
redistribute this software and such derivative works for any purpose,
so long as the copyright notice above, this grant of permission, and
the disclaimer below appear in all copies made; and so long as the
name of The University of Michigan is not used in any advertising or
publicity pertaining to the use or distribution of this software
without specific, written prior authorization.
THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT
WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR
IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF
THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES,
INCLUDING DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION
WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
'''
def sayHello(f):
print >> f, "M5 Simulator System"
print >> f, briefCopyright
print >> f, "M5 compiled on", __main__.compileDate
hostname = os.environ.get('HOSTNAME')
if not hostname:
hostname = os.environ.get('HOST')
if hostname:
print >> f, "M5 executing on", hostname
print >> f, "M5 simulation started", time.ctime()
sayHello(sys.stderr)
# import the m5 compile options
import defines
# define this here so we can use it right away if necessary
def panic(string):
print >>sys.stderr, 'panic:', string
sys.exit(1)
def m5execfile(f, global_dict):
# copy current sys.path
oldpath = sys.path[:]
# push file's directory onto front of path
sys.path.insert(0, os.path.abspath(os.path.dirname(f)))
execfile(f, global_dict)
# restore original path
sys.path = oldpath
# Prepend given directory to system module search path.
# Prepend given directory to system module search path. We may not
# need this anymore if we can structure our config library more like a
# Python package.
def AddToPath(path):
# if it's a relative path and we know what directory the current
# python script is in, make the path relative to that directory.
@@ -100,84 +57,58 @@ def AddToPath(path):
# so place the new dir right after that.
sys.path.insert(1, path)
# find the m5 compile options: must be specified as a dict in
# __main__.m5_build_env.
import __main__
if not hasattr(__main__, 'm5_build_env'):
panic("__main__ must define m5_build_env")
# Callback to set trace flags. Not necessarily the best way to do
# things in the long run (particularly if we change how these global
# options are handled).
def setTraceFlags(option, opt_str, value, parser):
objects.Trace.flags = value
# Standard optparse options. Need to be explicitly included by the
# user script when it calls optparse.OptionParser().
standardOptions = [
optparse.make_option("--traceflags", type="string", action="callback",
callback=setTraceFlags)
]
# make a SmartDict out of the build options for our local use
import smartdict
build_env = smartdict.SmartDict()
build_env.update(__main__.m5_build_env)
build_env.update(defines.m5_build_env)
# make a SmartDict out of the OS environment too
env = smartdict.SmartDict()
env.update(os.environ)
# import the main m5 config code
from config import *
# import the built-in object definitions
from objects import *
args_left = sys.argv[1:]
configfile_found = False
while args_left:
arg = args_left.pop(0)
if arg.startswith('--'):
# if arg starts with '--', parse as a special python option
# of the format --<python var>=<string value>
try:
(var, val) = arg.split('=', 1)
except ValueError:
panic("Could not parse configuration argument '%s'\n"
"Expecting --<variable>=<value>\n" % arg);
eval("%s = %s" % (var, repr(val)))
elif arg.startswith('-'):
# if the arg starts with '-', it should be a simulator option
# with a format similar to getopt.
optchar = arg[1]
if len(arg) > 2:
args_left.insert(0, arg[2:])
if optchar == 'd':
outdir = args_left.pop(0)
elif optchar == 'h':
showBriefHelp(sys.stderr)
sys.exit(1)
elif optchar == 'E':
env_str = args_left.pop(0)
split_result = env_str.split('=', 1)
var = split_result[0]
if len(split_result == 2):
val = split_result[1]
else:
val = True
env[var] = val
elif optchar == 'I':
AddToPath(args_left.pop(0))
elif optchar == 'P':
eval(args_left.pop(0))
else:
showBriefHelp(sys.stderr)
panic("invalid argument '%s'\n" % arg_str)
else:
# In any other case, treat the option as a configuration file
# name and load it.
if not arg.endswith('.py'):
panic("Config file '%s' must end in '.py'\n" % arg)
configfile_found = True
m5execfile(arg, globals())
if not configfile_found:
panic("no configuration file specified!")
if globals().has_key('root') and isinstance(root, Root):
# The final hook to generate .ini files. Called from the user script
# once the config is built.
def instantiate(root):
config.ticks_per_sec = float(root.clock.frequency)
# ugly temporary hack to get output to config.ini
sys.stdout = file('config.ini', 'w')
instantiate(root)
else:
print 'Instantiation skipped: no root object found.'
root.print_ini()
sys.stdout.close() # close config.ini
sys.stdout = sys.__stdout__ # restore to original
main.initialize() # load config.ini into C++ and process it
noDot = True # temporary until we fix dot
if not noDot:
dot = pydot.Dot()
instance.outputDot(dot)
dot.orientation = "portrait"
dot.size = "8.5,11"
dot.ranksep="equally"
dot.rank="samerank"
dot.write("config.dot")
dot.write_ps("config.ps")
# Export curTick to user script.
def curTick():
return main.cvar.curTick
# register our C++ exit callback function with Python
atexit.register(main.doExitCleanup)
# This import allows user scripts to reference 'm5.objects.Foo' after
# just doing an 'import m5' (without an 'import m5.objects'). May not
# matter since most scripts will probably 'from m5.objects import *'.
import objects

View File

@@ -728,7 +728,7 @@ class ParamDesc(object):
def __getattr__(self, attr):
if attr == 'ptype':
try:
ptype = eval(self.ptype_str, m5.__dict__)
ptype = eval(self.ptype_str, m5.objects.__dict__)
if not isinstance(ptype, type):
panic("Param qualifier is not a type: %s" % self.ptype)
self.ptype = ptype
@@ -1290,23 +1290,6 @@ AllMemory = AddrRange(0, MaxAddr)
#####################################################################
# The final hook to generate .ini files. Called from configuration
# script once config is built.
def instantiate(root):
global ticks_per_sec
ticks_per_sec = float(root.clock.frequency)
root.print_ini()
noDot = True # temporary until we fix dot
if not noDot:
dot = pydot.Dot()
instance.outputDot(dot)
dot.orientation = "portrait"
dot.size = "8.5,11"
dot.ranksep="equally"
dot.rank="samerank"
dot.write("config.dot")
dot.write_ps("config.ps")
# __all__ defines the list of symbols that get exported when
# 'from config import *' is invoked. Try to keep this reasonably
# short to avoid polluting other namespaces.
@@ -1322,5 +1305,5 @@ __all__ = ['SimObject', 'ParamContext', 'Param', 'VectorParam',
'NetworkBandwidth', 'MemoryBandwidth',
'Range', 'AddrRange', 'MaxAddr', 'MaxTick', 'AllMemory',
'Null', 'NULL',
'NextEthernetAddr', 'instantiate']
'NextEthernetAddr']

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
from Device import BasicPioDevice
class AlphaConsole(BasicPioDevice):

View File

@@ -1,4 +1,5 @@
from m5 import *
from m5 import build_env
from m5.config import *
from BaseCPU import BaseCPU
class DerivAlphaFullCPU(BaseCPU):

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
class AlphaTLB(SimObject):
type = 'AlphaTLB'
abstract = True

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
from Device import BasicPioDevice
class BadDevice(BasicPioDevice):

View File

@@ -1,4 +1,6 @@
from m5 import *
from m5 import build_env
from m5.config import *
class BaseCPU(SimObject):
type = 'BaseCPU'
abstract = True

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
from BaseMem import BaseMem
class Prefetch(Enum): vals = ['none', 'tagged', 'stride', 'ghb']

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
from MemObject import MemObject
class Bridge(MemObject):

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
from MemObject import MemObject
class Bus(MemObject):

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
class Coherence(Enum): vals = ['uni', 'msi', 'mesi', 'mosi', 'moesi']
class CoherenceProtocol(SimObject):

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
from MemObject import MemObject
class PioDevice(MemObject):

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
class DiskImage(SimObject):
type = 'DiskImage'
abstract = True

View File

@@ -1,4 +1,5 @@
from m5 import *
from m5 import build_env
from m5.config import *
from Device import DmaDevice
from Pci import PciDevice

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
from Pci import PciDevice
class IdeID(Enum): vals = ['master', 'slave']

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
class IntrControl(SimObject):
type = 'IntrControl'
cpu = Param.BaseCPU(Parent.any, "the cpu")

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
class MemObject(SimObject):
type = 'MemObject'

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
class MemTest(SimObject):
type = 'MemTest'
cache = Param.BaseCache("L1 cache")

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
from Device import BasicPioDevice, DmaDevice
class PciConfigData(SimObject):

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
from MemObject import *
class PhysicalMemory(MemObject):

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
class Platform(SimObject):
type = 'Platform'
abstract = True

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
class Process(SimObject):
type = 'Process'
abstract = True

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
class Repl(SimObject):
type = 'Repl'
abstract = True

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
from Serialize import Serialize
from Statistics import Statistics
from Trace import Trace

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
class ConsoleListener(SimObject):
type = 'ConsoleListener'
port = Param.TcpPort(3456, "listen port")

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
class SimpleDisk(SimObject):
type = 'SimpleDisk'
disk = Param.DiskImage("Disk Image")

View File

@@ -1,4 +1,5 @@
from m5 import *
from m5 import build_env
from m5.config import *
class System(SimObject):
type = 'System'

View File

@@ -1,4 +1,4 @@
from m5 import *
from m5.config import *
from Device import BasicPioDevice
from Platform import Platform

View File

@@ -1,4 +1,5 @@
from m5 import *
from m5 import build_env
from m5.config import *
from Device import BasicPioDevice
class Uart(BasicPioDevice):