summaryrefslogtreecommitdiff
path: root/src/python
diff options
context:
space:
mode:
authorSteve Reinhardt <stever@eecs.umich.edu>2006-05-30 13:11:34 -0400
committerSteve Reinhardt <stever@eecs.umich.edu>2006-05-30 13:11:34 -0400
commit0337db3388db335ea23f02f3aa00bca9d483ef1c (patch)
tree8293d1d4e9520acabde7e37bd0a065467147ba87 /src/python
parentd308055afc1ace1f321b76e8a85a9a45165da2ce (diff)
downloadgem5-0337db3388db335ea23f02f3aa00bca9d483ef1c.tar.xz
Link in Python interpreter.
Use embedded zip archive to carry Python code instead of homegrown embedded string/file mechanism. Do argument parsing in Python instead of C++. SConstruct: Add Python interpreter include path & library. Define two new simple builders which copy & concatenate files, respectively, for use by the Python embedded zipfile code. src/SConscript: Encapsulate environment creation in a function. Add code to append Python zip archive to final executable. Eliminate references to obsolete files. src/python/SConscript: Rewrite to generate embedded zip archive of Python code (replacing old "embedded string" mechanism). src/python/m5/__init__.py: Move main arg-parsing loop here (out of C++ main()). src/python/m5/config.py: Minor fix (version incompatibility?). src/sim/main.cc: Invoke embedded Python interpreter to parse args and generate config.ini, replacing C++ arg parsing code. --HG-- extra : convert_revision : 72d21236b2bee139ff39ba4cf031a4a1f8560029
Diffstat (limited to 'src/python')
-rw-r--r--src/python/SConscript226
-rw-r--r--src/python/m5/__init__.py108
-rw-r--r--src/python/m5/config.py2
3 files changed, 169 insertions, 167 deletions
diff --git a/src/python/SConscript b/src/python/SConscript
index 4407e403d..1f2d7fe0e 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -27,126 +27,55 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os, os.path, re, sys
+from zipfile import PyZipFile
-Import('env')
+# handy function for path joins
+def join(*args):
+ return os.path.normpath(os.path.join(*args))
-import scons_helper
-
-def WriteEmbeddedPyFile(target, source, path, name, ext, filename):
- if isinstance(source, str):
- source = file(source, 'r')
-
- if isinstance(target, str):
- target = file(target, 'w')
-
- print >>target, "AddModule(%s, %s, %s, %s, '''\\" % \
- (`path`, `name`, `ext`, `filename`)
-
- for line in source:
- line = line
- # escape existing backslashes
- line = line.replace('\\', '\\\\')
- # escape existing triple quotes
- line = line.replace("'''", r"\'\'\'")
-
- print >>target, line,
-
- print >>target, "''')"
- print >>target
-
-def WriteCFile(target, source, name):
- if isinstance(source, str):
- source = file(source, 'r')
-
- if isinstance(target, str):
- target = file(target, 'w')
-
- print >>target, 'const char %s_string[] = {' % name
-
- count = 0
- from array import array
- try:
- while True:
- foo = array('B')
- foo.fromfile(source, 10000)
- l = [ str(i) for i in foo.tolist() ]
- count += len(l)
- for i in xrange(0,9999,20):
- print >>target, ','.join(l[i:i+20]) + ','
- except EOFError:
- l = [ str(i) for i in foo.tolist() ]
- count += len(l)
- for i in xrange(0,len(l),20):
- print >>target, ','.join(l[i:i+20]) + ','
- print >>target, ','.join(l[i:]) + ','
-
- print >>target, '};'
- print >>target, 'const int %s_length = %d;' % (name, count)
- print >>target
-
-def splitpath(path):
- dir,file = os.path.split(path)
- path = []
- assert(file)
- while dir:
- dir,base = os.path.split(dir)
- path.insert(0, base)
- return path, file
-
-def MakeEmbeddedPyFile(target, source, env):
- target = file(str(target[0]), 'w')
-
- tree = {}
- for src in source:
- src = str(src)
- path,pyfile = splitpath(src)
- node = tree
- for dir in path:
- if not node.has_key(dir):
- node[dir] = { }
- node = node[dir]
-
- name,ext = pyfile.split('.')
- if name == '__init__':
- node['.hasinit'] = True
- node[pyfile] = (src,name,ext,src)
-
- done = False
- while not done:
- done = True
- for name,entry in tree.items():
- if not isinstance(entry, dict): continue
- if entry.has_key('.hasinit'): continue
-
- done = False
- del tree[name]
- for key,val in entry.iteritems():
- if tree.has_key(key):
- raise NameError, \
- "dir already has %s can't add it again" % key
- tree[key] = val
-
- files = []
- def populate(node, path = []):
- names = node.keys()
- names.sort()
- for name in names:
- if name == '.hasinit':
- continue
-
- entry = node[name]
- if isinstance(entry, dict):
- if not entry.has_key('.hasinit'):
- raise NameError, 'package directory missing __init__.py'
- populate(entry, path + [ name ])
- else:
- pyfile,name,ext,filename = entry
- files.append((pyfile, path, name, ext, filename))
- populate(tree)
-
- for pyfile, path, name, ext, filename in files:
- WriteEmbeddedPyFile(target, pyfile, path, name, ext, filename)
+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'
+
+# List of files & directories to include in the zip file. To include
+# a package, list only the root directory of the package, not any
+# internal .py files (else they will get the path stripped off when
+# they are imported into the zip file).
+pyzip_files = []
+
+# List of additional files on which the zip archive depends, but which
+# are not included in pyzip_files... i.e. individual .py files within
+# a package.
+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))
+ origdir = os.getcwd()
+ srcdir = join(Dir('.').srcnode().abspath, pkgdir)
+ os.chdir(srcdir)
+ for path, dirs, files in os.walk('.'):
+ for i,dir in enumerate(dirs):
+ if dir == 'SCCS':
+ del dirs[i]
+ break
+
+ 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)
+
+ os.chdir(origdir)
+
+# Generate Python file that contains a dict specifying the current
+# build_env flags.
def MakeDefinesPyFile(target, source, env):
f = file(str(target[0]), 'w')
print >>f, "import __main__"
@@ -154,54 +83,21 @@ def MakeDefinesPyFile(target, source, env):
print >>f, source[0]
f.close()
-CFileCounter = 0
-def MakePythonCFile(target, source, env):
- global CFileCounter
- target = file(str(target[0]), 'w')
-
- print >>target, '''\
-#include "base/embedfile.hh"
-
-namespace {
-'''
- for src in source:
- src = str(src)
- fname = os.path.basename(src)
- name = 'embedded_file%d' % CFileCounter
- CFileCounter += 1
- WriteCFile(target, src, name)
- print >>target, '''\
-EmbedMap %(name)s("%(fname)s",
- %(name)s_string, %(name)s_length);
-
-''' % locals()
- print >>target, '''\
-
-/* namespace */ }
-'''
-
-# base list of .py files to embed
-embedded_py_files = [ os.path.join(env['ROOT'], 'util/pbs/jobfile.py') ]
-# add all .py files in python/m5
-objpath = os.path.join(env['SRCDIR'], 'python', 'm5')
-for root, dirs, files in os.walk(objpath, topdown=True):
- for i,dir in enumerate(dirs):
- if dir == 'SCCS':
- del dirs[i]
- break
-
- assert(root.startswith(objpath))
- for f in files:
- if f.endswith('.py'):
- embedded_py_files.append(os.path.join(root, f))
-
-embedfile_hh = os.path.join(env['SRCDIR'], 'base/embedfile.hh')
-
optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
env.Command('defines.py', Value(optionDict), MakeDefinesPyFile)
-env.Command('embedded_py.py', embedded_py_files, MakeEmbeddedPyFile)
-env.Depends('embedded_py.cc', embedfile_hh)
-env.Command('embedded_py.cc',
- ['string_importer.py', 'defines.py', 'embedded_py.py'],
- MakePythonCFile)
+# Now specify the packages & files for the zip archive.
+addPkg('m5')
+pyzip_files.append('defines.py')
+pyzip_files.append(join(env['ROOT'], 'util/pbs/jobfile.py'))
+
+# Action function to build the zip archive. Uses the PyZipFile module
+# included in the standard Python library.
+def buildPyZip(target, source, env):
+ pzf = PyZipFile(str(target[0]), 'w')
+ for s in source:
+ pzf.writepy(str(s))
+
+# Add the zip file target to the environment.
+env.Command('m5py.zip', pyzip_files, buildPyZip)
+env.Depends('m5py.zip', pyzip_dep_files)
diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py
index 9bb68a090..06875d1f0 100644
--- a/src/python/m5/__init__.py
+++ b/src/python/m5/__init__.py
@@ -24,7 +24,53 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-import sys, os
+import sys, os, time
+
+import __main__
+
+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)
# define this here so we can use it right away if necessary
def panic(string):
@@ -72,3 +118,63 @@ 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):
+ sys.stdout = file('config.ini', 'w')
+ instantiate(root)
+else:
+ print 'Instantiation skipped: no root object found.'
+
diff --git a/src/python/m5/config.py b/src/python/m5/config.py
index 1e25e0d09..ce7e5a964 100644
--- a/src/python/m5/config.py
+++ b/src/python/m5/config.py
@@ -794,7 +794,7 @@ class ParamFactory(object):
# E.g., Param.Int(5, "number of widgets")
def __call__(self, *args, **kwargs):
- caller_frame = inspect.stack()[1][0]
+ caller_frame = inspect.currentframe().f_back
ptype = None
try:
ptype = eval(self.ptype_str,