# HG changeset patch
# User Nathan Binkert <[EMAIL PROTECTED]>
# Date 1217734987 25200
# Node ID 37ac7a23ded9099d7f8d6c340ec6efb10baa9a15
# Parent  70caf53d9d7c1504c6732b97ba190cb3c8f14b46
libm5: Create a libm5 static library for embedding m5.

This should allow m5 to be more easily embedded into other simulators.
The m5 binary adds a simple main function which then calls into the m5
libarary to start the simulation. In order to make this work
correctly, it was necessary embed python code directly into the
library instead of the zipfile hack.  This is because you can't just
append the zipfile to the end of a library the way you can a binary.
As a result, Python files that are part of the m5 simulator are now
compile, marshalled, compressed, and then inserted into the library's
data section with a certain symbol name.  Additionally, a new Importer
was needed to allow python to get at the embedded python code.

Small additional changes include:
- Get rid of the PYTHONHOME stuff since I don't think anyone ever used
it, and it just confuses things.  Easy enough to add back if I'm wrong.
- Create a few new functions that are key to initializing and running
the simulator: initSignals, initM5Python, m5Main.

The original code for creating libm5 was inspired by a patch Michael
Adler, though the code here was done by me.

diff --git a/SConstruct b/SConstruct
--- a/SConstruct
+++ b/SConstruct
@@ -596,9 +596,6 @@ sticky_opts.AddOptions(
     BoolOption('USE_MYSQL', 'Use MySQL for stats output', have_mysql),
     BoolOption('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv),
     BoolOption('USE_CHECKER', 'Use checker for detailed CPU models', False),
-    ('PYTHONHOME',
-     'Override the default PYTHONHOME for this system (use with caution)',
-     '%s:%s' % (sys.prefix, sys.exec_prefix)),
     )
 
 nonsticky_opts.AddOptions(
@@ -609,7 +606,7 @@ env.ExportOptions = ['FULL_SYSTEM', 'ALP
 env.ExportOptions = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \
                      'USE_MYSQL', 'NO_FAST_ALLOC', 'FAST_ALLOC_DEBUG', \
                      'FAST_ALLOC_STATS', 'SS_COMPATIBLE_FP', \
-                     'USE_CHECKER', 'PYTHONHOME', 'TARGET_ISA']
+                     'USE_CHECKER', 'TARGET_ISA']
 
 # Define a handy 'no-op' action
 def no_action(target, source, env):
diff --git a/src/SConscript b/src/SConscript
--- a/src/SConscript
+++ b/src/SConscript
@@ -28,11 +28,13 @@
 #
 # Authors: Nathan Binkert
 
+import array
 import imp
+import marshal
 import os
-import py_compile
+import re
 import sys
-import zipfile
+import zlib
 
 from os.path import basename, exists, isdir, isfile, join as joinpath
 
@@ -58,28 +60,34 @@ def sort_list(_list):
     return _list
 
 class PySourceFile(object):
+    invalid_sym_char = re.compile('[^A-z0-9_]')
     def __init__(self, package, source):
         filename = str(source)
         pyname = basename(filename)
         assert pyname.endswith('.py')
         name = pyname[:-3]
-        path = package.split('.')
+        if package:
+            path = package.split('.')
+        else:
+            path = []
         modpath = path
         if name != '__init__':
             modpath += [name]
         modpath = '.'.join(modpath)
 
-        arcpath = package.split('.') + [ pyname + 'c' ]
+        arcpath = path + [ pyname ]
         arcname = joinpath(*arcpath)
 
-        self.source = source
+        self.tnode = source
+        self.snode = source.srcnode()
         self.pyname = pyname
-        self.srcpath = source.srcnode().abspath
         self.package = package
         self.modpath = modpath
         self.arcname = arcname
         self.filename = filename
         self.compiled = File(filename + 'c')
+        self.assembly = File(filename + '.s')
+        self.symname = "_PyEMB_" + self.invalid_sym_char.sub('_', modpath)
 
 ########################################################################
 # Code for adding source files of various types
@@ -91,6 +99,17 @@ def Source(source):
         source = File(source)
 
     cc_sources.append(source)
+
+cc_main = []
+def SourceMain(source):
+    '''Add a C/C++ source file holding main() to the build'''
+    if not isinstance(source, SCons.Node.FS.File):
+        source = File(source)
+
+    if (cc_main != []):
+        print "Error: Multiple instances of SourceMain() declared"
+
+    cc_main.append(source)
 
 py_sources = []
 def PySource(package, source):
@@ -129,6 +148,7 @@ def SwigSource(package, source):
 
 # Children should have access
 Export('Source')
+Export('SourceMain')
 Export('PySource')
 Export('SimObject')
 Export('SwigSource')
@@ -259,7 +279,7 @@ class DictImporter(object):
 
 py_modules = {}
 for source in py_sources:
-    py_modules[source.modpath] = source.srcpath
+    py_modules[source.modpath] = source.snode.abspath
 
 # install the python importer so we can grab stuff from the source
 # tree itself.  We can't have SimObjects added after this point or
@@ -551,14 +571,14 @@ def makeSwigInit(target, source, env):
     for module in source:
         print >>f, '    void init_%s();' % module.get_contents()
     print >>f, '}'
-    print >>f, 'void init_swig() {'
+    print >>f, 'void initSwig() {'
     for module in source:
         print >>f, '    init_%s();' % module.get_contents()
     print >>f, '}'
     f.close()
 
-env.Command('swig/init.cc', swig_modules, makeSwigInit)
-Source('swig/init.cc')
+env.Command('python/swig/init.cc', swig_modules, makeSwigInit)
+Source('python/swig/init.cc')
 
 # Generate traceflags.py
 def traceFlagsPy(target, source, env):
@@ -797,42 +817,72 @@ env.Command('base/program_info.cc',
             Value(str(SCons.Node.FS.default_fs.SConstruct_dir)),
             programInfo)
 
-# Build the zip file
-def compilePyFile(target, source, env):
-    '''Action function to compile a .py into a .pyc'''
-    py_compile.compile(str(source[0]), str(target[0]))
+#embed python files
+py_sources_tnodes = {}
+for pysource in py_sources:
+    py_sources_tnodes[pysource.tnode] = pysource
 
-def buildPyZip(target, source, env):
-    '''Action function to build the zip archive.  Uses the
-    PyZipFile module included in the standard Python library.'''
+def objectifyPyFile(target, source, env):
+    '''Action function to compile a .py into a code object, marshal it,
+    compress it'''
 
-    py_compiled = {}
-    for s in py_sources:
-        compname = str(s.compiled)
-        assert compname not in py_compiled
-        py_compiled[compname] = s
+    src = file(str(source[0]), 'r').read()
+    dst = file(str(target[0]), 'w')
 
-    zf = zipfile.ZipFile(str(target[0]), 'w')
-    for s in source:
-        zipname = str(s)
-        arcname = py_compiled[zipname].arcname
-        zf.write(zipname, arcname)
-    zf.close()
+    pysource = py_sources_tnodes[source[0]]
+    compiled = compile(src, pysource.snode.path, 'exec')
+    marshalled = marshal.dumps(compiled)
+    compressed = zlib.compress(marshalled)
+    data = compressed
 
-py_compiled = []
-py_zip_depends = []
+    step = 16
+    print >>dst, ".data"
+    print >>dst, ".globl %s_beg" % pysource.symname
+    print >>dst, ".globl %s_end" % pysource.symname
+    print >>dst, "%s_beg:" % pysource.symname
+    for i in xrange(0, len(data), step):
+        x = array.array('B', data[i:i+step])
+        print >>dst, ".byte", ','.join([str(d) for d in x])
+    print >>dst, "%s_end:" % pysource.symname
+    print >>dst, ".int %d" % len(marshalled)
+
+py_sources_symbols = {}
+for pysource in py_sources:
+    py_sources_symbols[pysource.symname] = pysource
+def pythonInit(target, source, env):
+    dst = file(str(target[0]), 'w')
+
+    def dump_mod(sym):
+        pysource = py_sources_symbols[sym]
+        print >>dst, '    { "%s",' % pysource.arcname
+        print >>dst, '      "%s",' % pysource.modpath
+        print >>dst, '       %s_beg, %s_end,' % (sym, sym)
+        print >>dst, '       %s_end - %s_beg,' % (sym, sym)
+        print >>dst, '       *(int *)%s_end }, '  % sym
+    
+    print >>dst, '#include "sim/init.hh"'
+
+    for sym in source:
+        sym = sym.get_contents()
+        print >>dst, "extern const char %s_beg[], %s_end[];" % (sym, sym)
+
+    print >>dst, "const EmbeddedPyModule embeddedPyModules[] = {"
+    dump_mod("_PyEMB_importer");
+    for i,sym in enumerate(source):
+        sym = sym.get_contents()
+        if sym == "_PyEMB_importer":
+            continue
+        dump_mod(sym)
+    print >>dst, "    { 0, 0, 0, 0, 0, 0 }"
+    print >>dst, "};"
+
 for source in py_sources:
-    env.Command(source.compiled, source.source, compilePyFile)
-    py_compiled.append(source.compiled)
+    env.Command(source.assembly, source.tnode, objectifyPyFile)
+    Source(source.assembly)
 
-    # make the zipfile depend on the archive name so that the archive
-    # is rebuilt if the name changes
-    py_zip_depends.append(Value(source.arcname))
-
-# Add the zip file target to the environment.
-m5zip = File('m5py.zip')
-env.Command(m5zip, py_compiled, buildPyZip)
-env.Depends(m5zip, py_zip_depends)
+symbols = [Value(s.symname) for s in py_sources]
+env.Command('sim/init_python.cc', symbols, pythonInit)
+Source('sim/init_python.cc')
 
 ########################################################################
 #
@@ -873,18 +923,28 @@ def makeEnv(label, objsfx, strip = False
     newEnv = env.Copy(OBJSUFFIX=objsfx)
     newEnv.Label = label
     newEnv.Append(**kwargs)
+
+    # First make a library of everything but main() so other programs can
+    # link against m5.
+    #
+    # SCons doesn't know to append a library suffix when there is a '.' in the
+    # name.  Use '_' instead.
+    m5lib = newEnv.Library('m5_' + label, make_objs(cc_sources, newEnv))
+
+    # Now link a stub with main() and the library.
     exe = 'm5.' + label  # final executable
-    bin = exe + '.bin'   # executable w/o appended Python zip archive
-    newEnv.Program(bin, make_objs(cc_sources, newEnv))
+    objects = newEnv.Object(cc_main) + m5lib
     if strip:
-        stripped_bin = bin + '.stripped'
+        unstripped_exe = exe + '.unstripped'
+        newEnv.Program(unstripped_exe, objects)
         if sys.platform == 'sunos5':
             cmd = 'cp $SOURCE $TARGET; strip $TARGET'
         else:
             cmd = 'strip $SOURCE -o $TARGET'
-        newEnv.Command(stripped_bin, bin, cmd)
-        bin = stripped_bin
-    targets = newEnv.Concat(exe, [bin, 'm5py.zip'])
+        targets = newEnv.Command(exe, unstripped_exe, cmd)
+    else:
+        targets = newEnv.Program(exe, objects)
+            
     newEnv.M5Binary = targets[0]
     envList.append(newEnv)
 
diff --git a/src/python/SConscript b/src/python/SConscript
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -34,6 +34,7 @@ Source('swig/pyevent.cc')
 Source('swig/pyevent.cc')
 Source('swig/pyobject.cc')
 
+PySource('', 'importer.py')
 PySource('m5', 'm5/__init__.py')
 PySource('m5', 'm5/SimObject.py')
 PySource('m5', 'm5/config.py')
diff --git a/src/python/importer.py b/src/python/importer.py
new file mode 100644
--- /dev/null
+++ b/src/python/importer.py
@@ -0,0 +1,67 @@
+# Copyright (c) 2008 The Hewlett-Packard Development Company
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+class CodeImporter(object):
+    def __init__(self):
+        self.modules = {}
+
+    def add_module(self, filename, modpath, code):
+        if modpath in self.modules:
+            raise AttributeError, "%s already found in importer"
+
+        self.modules[modpath] = (filename, code)
+
+    def find_module(self, fullname, path):
+        if fullname in self.modules:
+            return self
+
+        return None
+
+    def load_module(self, fullname):
+        # because of the way that the modules are initialized in
+        # init.cc, the imports must live here within this function
+        import imp
+        import os
+        import sys
+        mod = imp.new_module(fullname)
+        sys.modules[fullname] = mod
+
+        mod.__loader__ = self
+        srcfile,code = self.modules[fullname]
+        if os.path.basename(srcfile) == '__init__.py':
+            mod.__path__ = fullname.split('.')
+        mod.__file__ = srcfile
+
+        exec code in mod.__dict__
+
+        return mod
+
+import sys
+importer = CodeImporter()
+add_module = importer.add_module
+sys.meta_path.append(importer)
diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py
--- a/src/python/m5/__init__.py
+++ b/src/python/m5/__init__.py
@@ -91,7 +91,7 @@ if running_m5:
 if running_m5:
     from event import *
     from simulate import *
-    from main import options
+    from main import options, main
     import stats
 
 import SimObject
diff --git a/src/python/swig/init.hh b/src/python/swig/init.hh
deleted file mode 100644
--- a/src/python/swig/init.hh
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Nathan Binkert
- */
-
-#ifndef __PYTHON_SWIG_INIT_HH__
-#define __PYTHON_SWIG_INIT_HH__
-
-void init_swig();
-
-#endif // __PYTHON_SWIG_INIT_HH__
diff --git a/src/sim/SConscript b/src/sim/SConscript
--- a/src/sim/SConscript
+++ b/src/sim/SConscript
@@ -40,7 +40,8 @@ Source('debug.cc')
 Source('debug.cc')
 Source('eventq.cc')
 Source('faults.cc')
-Source('main.cc')
+Source('init.cc')
+SourceMain('main.cc')
 Source('root.cc')
 Source('serialize.cc')
 Source('sim_events.cc')
diff --git a/src/sim/init.cc b/src/sim/init.cc
new file mode 100644
--- /dev/null
+++ b/src/sim/init.cc
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2000-2005 The Regents of The University of Michigan
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#include <Python.h>
+#include <marshal.h>
+#include <signal.h>
+
+#include <iostream>
+#include <string>
+#include <zlib.h>
+
+#include "base/cprintf.hh"
+#include "base/misc.hh"
+#include "sim/async.hh"
+#include "sim/core.hh"
+#include "sim/host.hh"
+#include "sim/init.hh"
+
+using namespace std;
+
+/// Stats signal handler.
+void
+dumpStatsHandler(int sigtype)
+{
+    async_event = true;
+    async_statdump = true;
+}
+
+void
+dumprstStatsHandler(int sigtype)
+{
+    async_event = true;
+    async_statdump = true;
+    async_statreset = true;
+}
+
+/// Exit signal handler.
+void
+exitNowHandler(int sigtype)
+{
+    async_event = true;
+    async_exit = true;
+}
+
+/// Abort signal handler.
+void
+abortHandler(int sigtype)
+{
+    ccprintf(cerr, "Program aborted at cycle %d\n", curTick);
+}
+
+void
+initSignals()
+{
+    signal(SIGFPE, SIG_IGN);           // may occur on misspeculated paths
+    signal(SIGTRAP, SIG_IGN);
+    signal(SIGUSR1, dumpStatsHandler);         // dump intermediate stats
+    signal(SIGUSR2, dumprstStatsHandler);      // dump and reset stats
+    signal(SIGINT, exitNowHandler);            // dump final stats and exit
+    signal(SIGABRT, abortHandler);
+}
+
+PyCodeObject *
+getCode(const EmbeddedPyModule *pymod)
+{
+    assert(pymod->zlen == pymod->code_end - pymod->code);
+    Bytef *marshalled = new Bytef[pymod->mlen];
+    uLongf unzlen = pymod->mlen;
+    int ret = uncompress(marshalled, &unzlen, (const Bytef *)pymod->code,
+        pymod->zlen);
+    if (ret != Z_OK)
+        panic("Could not uncompress code: %s\n", zError(ret));
+    assert(unzlen == pymod->mlen);
+
+    PyObject *code =
+        PyMarshal_ReadObjectFromString((char *)marshalled, pymod->mlen);
+
+    return reinterpret_cast<PyCodeObject *>(code);
+}
+
+int
+initM5Python()
+{
+    extern void initSwig();
+
+    // initialize SWIG modules
+    initSwig();
+
+    const EmbeddedPyModule *pymod = &embeddedPyModules[0];
+
+    PyCodeObject *impcode = getCode(pymod++);
+    PyObject *module = PyImport_AddModule(const_cast<char*>("__main__"));
+    if (module == NULL)
+        panic("Could not import __main__");
+    PyObject *dict = PyModule_GetDict(module);
+
+    PyObject *result = PyEval_EvalCode(impcode, dict, dict);
+    if (!result) {
+        PyErr_Print();
+        return 1;
+    }
+    Py_DECREF(result);
+
+    while (pymod->filename) {
+        PyCodeObject *code = getCode(pymod);
+        PyObject *result = PyObject_CallMethod(module,
+                const_cast<char *>("add_module"), const_cast<char *>("ssO"),
+                pymod->filename, pymod->modpath, code);
+        if (!result) {
+            PyErr_Print();
+            return 1;
+        }
+        Py_DECREF(result);
+        ++pymod;
+    }
+
+    return 0;
+}
+
+int
+m5Main(int argc, char **argv)
+{
+    PySys_SetArgv(argc, argv);
+
+    PyObject *module = PyImport_AddModule(const_cast<char*>("__main__"));
+    if (module == NULL)
+        panic("Could not import __main__");
+
+    PyObject *dict = PyModule_GetDict(module);
+
+    PyObject *result;
+    result = PyRun_String("import m5", Py_file_input, dict, dict);
+    if (!result) {
+        PyErr_Print();
+        return 1;
+    }
+    Py_DECREF(result);
+
+    result = PyRun_String("m5.main()", Py_file_input, dict, dict);
+    if (!result) {
+        PyErr_Print();
+        return 1;
+    }
+    Py_DECREF(result);
+
+    if (Py_FlushLine())
+        PyErr_Clear();
+
+    return 0;
+}
diff --git a/src/sim/init.hh b/src/sim/init.hh
new file mode 100644
--- /dev/null
+++ b/src/sim/init.hh
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#ifndef __SIM_INIT_HH__
+#define __SIM_INIT_HH__
+
+struct EmbeddedPyModule
+{
+    const char *filename;
+    const char *modpath;
+    const char *code;
+    const char *code_end;
+    int zlen;
+    int mlen;
+};
+
+extern const EmbeddedPyModule embeddedPyModules[];
+
+void initSignals();
+int initM5Python();
+int m5Main(int argc, char **argv);
+
+#endif // __SIM_INIT_HH__
diff --git a/src/sim/main.cc b/src/sim/main.cc
--- a/src/sim/main.cc
+++ b/src/sim/main.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005 The Regents of The University of Michigan
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -29,125 +29,28 @@
  */
 
 #include <Python.h>
-#include <signal.h>
 
-#include <iostream>
-#include <string>
+#include "sim/init.hh"
 
-#include "base/cprintf.hh"
-#include "base/misc.hh"
-#include "config/pythonhome.hh"
-#include "python/swig/init.hh"
-#include "sim/async.hh"
-#include "sim/host.hh"
-#include "sim/core.hh"
-
-using namespace std;
-
-/// Stats signal handler.
-void
-dumpStatsHandler(int sigtype)
-{
-    async_event = true;
-    async_statdump = true;
-}
-
-void
-dumprstStatsHandler(int sigtype)
-{
-    async_event = true;
-    async_statdump = true;
-    async_statreset = true;
-}
-
-/// Exit signal handler.
-void
-exitNowHandler(int sigtype)
-{
-    async_event = true;
-    async_exit = true;
-}
-
-/// Abort signal handler.
-void
-abortHandler(int sigtype)
-{
-    ccprintf(cerr, "Program aborted at cycle %d\n", curTick);
-}
-
-int
-python_main()
-{
-    PyObject *module;
-    PyObject *dict;
-    PyObject *result;
-
-    module = PyImport_AddModule(const_cast<char*>("__main__"));
-    if (module == NULL)
-        fatal("Could not import __main__");
-
-    dict = PyModule_GetDict(module);
-
-    result = PyRun_String("import m5.main", Py_file_input, dict, dict);
-    if (!result) {
-        PyErr_Print();
-        return 1;
-    }
-    Py_DECREF(result);
-
-    result = PyRun_String("m5.main.main()", Py_file_input, dict, dict);
-    if (!result) {
-        PyErr_Print();
-        return 1;
-    }
-    Py_DECREF(result);
-
-    if (Py_FlushLine())
-        PyErr_Clear();
-
-    return 0;
-}
-
+// main() is now pretty stripped down and just sets up python and then
+// calls initM5Python which loads the various embedded python modules
+// into the python environment and then starts things running by
+// calling m5Main.
 int
 main(int argc, char **argv)
 {
-    signal(SIGFPE, SIG_IGN);           // may occur on misspeculated paths
-    signal(SIGTRAP, SIG_IGN);
-    signal(SIGUSR1, dumpStatsHandler);         // dump intermediate stats
-    signal(SIGUSR2, dumprstStatsHandler);      // dump and reset stats
-    signal(SIGINT, exitNowHandler);            // dump final stats and exit
-    signal(SIGABRT, abortHandler);
+    int ret;
+
+    initSignals();
 
     Py_SetProgramName(argv[0]);
 
-    // default path to m5 python code is the currently executing
-    // file... Python ZipImporter will find embedded zip archive.
-    // The M5_ARCHIVE environment variable can be used to override this.
-    char *m5_archive = getenv("M5_ARCHIVE");
-    string pythonpath = m5_archive ? m5_archive : argv[0];
-
-    char *oldpath = getenv("PYTHONPATH");
-    if (oldpath != NULL) {
-        pythonpath += ":";
-        pythonpath += oldpath;
-    }
-
-    if (setenv("PYTHONPATH", pythonpath.c_str(), true) == -1)
-        fatal("setenv: %s\n", strerror(errno));
-
-    const char *python_home = getenv("PYTHONHOME");
-    if (!python_home)
-        python_home = PYTHONHOME;
-    Py_SetPythonHome(const_cast<char*>(python_home));
-
     // initialize embedded Python interpreter
     Py_Initialize();
-    PySys_SetArgv(argc, argv);
 
-    // initialize SWIG modules
-    init_swig();
-
-    int ret = python_main();
+    ret = initM5Python();
+    if (ret == 0)
+        ret = m5Main(argc, argv);
 
     // clean up Python intepreter.
     Py_Finalize();
_______________________________________________
m5-dev mailing list
m5-dev@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to