diff --git a/SConstruct b/SConstruct index 792cb7554..f7798b25e 100644 --- a/SConstruct +++ b/SConstruct @@ -424,11 +424,42 @@ scanners.append(CPPScanner("SwigScan", [ ".i" ], "CPPPATH", swig_inc_re)) # replace the scanners list that has what we want env['SCANNERS'] = scanners +# Add a custom Check function to the Configure context so that we can +# figure out if the compiler adds leading underscores to global +# variables. This is needed for the autogenerated asm files that we +# use for embedding the python code. +def CheckLeading(context): + context.Message("Checking for leading underscore in global variables...") + # 1) Define a global variable called x from asm so the C compiler + # won't change the symbol at all. + # 2) Declare that variable. + # 3) Use the variable + # + # If the compiler prepends an underscore, this will successfully + # link because the external symbol 'x' will be called '_x' which + # was defined by the asm statement. If the compiler does not + # prepend an underscore, this will not successfully link because + # '_x' will have been defined by assembly, while the C portion of + # the code will be trying to use 'x' + ret = context.TryLink(''' + asm(".globl _x; _x: .byte 0"); + extern int x; + int main() { return x; } + ''', extension=".c") + context.env.Append(LEADING_UNDERSCORE=ret) + context.Result(ret) + return ret + # Platform-specific configuration. Note again that we assume that all # builds under a given build root run on the same host platform. conf = Configure(env, conf_dir = joinpath(build_root, '.scons_config'), - log_file = joinpath(build_root, 'scons_config.log')) + log_file = joinpath(build_root, 'scons_config.log'), + custom_tests = { 'CheckLeading' : CheckLeading }) + +# Check for leading underscores. Don't really need to worry either +# way so don't need to check the return code. +conf.CheckLeading() # Check if we should compile a 64 bit binary on Mac OS X/Darwin try: @@ -596,9 +627,6 @@ sticky_opts.AddOptions( BoolOption('USE_MYSQL', 'Use MySQL for stats output', have_mysql), BoolOption('USE_FENV', 'Use 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 +637,7 @@ nonsticky_opts.AddOptions( 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 index ad1fe76a9..36cbbfa78 100644 --- 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,39 +60,54 @@ 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 # -cc_sources = [] +cc_lib_sources = [] def Source(source): - '''Add a C/C++ source file to the build''' + '''Add a source file to the libm5 build''' if not isinstance(source, SCons.Node.FS.File): source = File(source) - cc_sources.append(source) + cc_lib_sources.append(source) + +cc_bin_sources = [] +def BinSource(source): + '''Add a source file to the m5 binary build''' + if not isinstance(source, SCons.Node.FS.File): + source = File(source) + + cc_bin_sources.append(source) py_sources = [] def PySource(package, source): @@ -129,6 +146,7 @@ def SwigSource(package, source): # Children should have access Export('Source') +Export('BinSource') Export('PySource') Export('SimObject') Export('SwigSource') @@ -259,7 +277,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 +569,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 +815,95 @@ 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. All .py files that have been indicated by a +# PySource() call in a SConscript need to be embedded into the M5 +# library. To do that, we compile the file to byte code, marshal the +# byte code, compress it, and then generate an assembly file that +# inserts the result into the data section with symbols indicating the +# beginning, and end (and with the size at the end) +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, and stick it into an asm file so the code appears + as just bytes with a label in the data section''' - 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 + + # Some C/C++ compilers prepend an underscore to global symbol + # names, so if they're going to do that, we need to prepend that + # leading underscore to globals in the assembly file. + if env['LEADING_UNDERSCORE']: + sym = '_' + pysource.symname + else: + sym = pysource.symname + + step = 16 + print >>dst, ".data" + print >>dst, ".globl %s_beg" % sym + print >>dst, ".globl %s_end" % sym + print >>dst, "%s_beg:" % sym + 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:" % sym + print >>dst, ".long %d" % len(marshalled) -py_compiled = [] -py_zip_depends = [] 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)) +# Generate init_python.cc which creates a bunch of EmbeddedPyModule +# structs that describe the embedded python code. One such struct +# contains information about the importer that python uses to get at +# the embedded files, and then there's a list of all of the rest that +# the importer uses to load the rest on demand. +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') -# Add the zip file target to the environment. -m5zip = File('m5py.zip') -env.Command(m5zip, py_compiled, buildPyZip) -env.Depends(m5zip, py_zip_depends) + def dump_mod(sym, endchar=','): + 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 }%s' % (sym, endchar) + + 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 embeddedPyImporter = " + dump_mod("PyEMB_importer", endchar=';'); + print >>dst + + print >>dst, "const EmbeddedPyModule embeddedPyModules[] = {" + for i,sym in enumerate(source): + sym = sym.get_contents() + if sym == "PyEMB_importer": + # Skip the importer since we've already exported it + continue + dump_mod(sym) + print >>dst, " { 0, 0, 0, 0, 0, 0 }" + print >>dst, "};" + +symbols = [Value(s.symname) for s in py_sources] +env.Command('sim/init_python.cc', symbols, pythonInit) +Source('sim/init_python.cc') ######################################################################## # @@ -873,18 +944,28 @@ def makeEnv(label, objsfx, strip = False, **kwargs): 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_lib_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(s) for s in cc_bin_sources] + 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 index 32bab4526..94119c77d 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -34,6 +34,7 @@ Import('*') 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 index 000000000..fe099fdb8 --- /dev/null +++ b/src/python/importer.py @@ -0,0 +1,80 @@ +# 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 + +# Simple importer that allows python to import data from a dict of +# code objects. The keys are the module path, and the items are the +# filename and bytecode of the file. +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 the importer is created and initialized in its own + # little sandbox (in init.cc), the globals that were available + # when the importer module was loaded and CodeImporter was + # defined are not available when load_module is actually + # called. Soooo, the imports must live here. + import imp + import os + import sys + mod = imp.new_module(fullname) + sys.modules[fullname] = mod + + try: + 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__ + except Exception: + del sys.modules[fullname] + raise + + return mod + +# Create an importer and add it to the meta_path so future imports can +# use it. There's currently nothing in the importer, but calls to +# add_module can be used to add code. +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 index f21bb362e..7b071bccd 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -91,7 +91,7 @@ else: 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/sim/SConscript b/src/sim/SConscript index c9e4415f5..3e6adb85a 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -40,7 +40,8 @@ Source('core.cc') Source('debug.cc') Source('eventq.cc') Source('faults.cc') -Source('main.cc') +Source('init.cc') +BinSource('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 index 000000000..804389dae --- /dev/null +++ b/src/sim/init.cc @@ -0,0 +1,202 @@ +/* + * 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 +#include +#include + +#include +#include +#include + +#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); +} + +/* + * M5 can do several special things when various signals are sent. + * None are mandatory. + */ +void +initSignals() +{ + // Floating point exceptions may happen on misspeculated paths, so + // ignore them + signal(SIGFPE, SIG_IGN); + + // We use SIGTRAP sometimes for debugging + signal(SIGTRAP, SIG_IGN); + + // Dump intermediate stats + signal(SIGUSR1, dumpStatsHandler); + + // Dump intermediate stats and reset them + signal(SIGUSR2, dumprstStatsHandler); + + // Exit cleanly on Interrupt (Ctrl-C) + signal(SIGINT, exitNowHandler); + + // Print out cycle number on abort + signal(SIGABRT, abortHandler); +} + +/* + * Uncompress and unmarshal the code object stored in the + * EmbeddedPyModule + */ +PyObject * +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); + + return PyMarshal_ReadObjectFromString((char *)marshalled, pymod->mlen); +} + +// The python library is totally messed up with respect to constness, +// so make a simple macro to make life a little easier +#define PyCC(x) (const_cast(x)) + +/* + * Load and initialize all of the python parts of M5, including Swig + * and the embedded module importer. + */ +int +initM5Python() +{ + extern void initSwig(); + + // initialize SWIG modules. initSwig() is autogenerated and calls + // all of the individual swig initialization functions. + initSwig(); + + // Load the importer module + PyObject *code = getCode(&embeddedPyImporter); + PyObject *module = PyImport_ExecCodeModule(PyCC("importer"), code); + if (!module) { + PyErr_Print(); + return 1; + } + + // Load the rest of the embedded python files into the embedded + // python importer + const EmbeddedPyModule *pymod = &embeddedPyModules[0]; + while (pymod->filename) { + PyObject *code = getCode(pymod); + PyObject *result = PyObject_CallMethod(module, PyCC("add_module"), + PyCC("ssO"), pymod->filename, pymod->modpath, code); + if (!result) { + PyErr_Print(); + return 1; + } + Py_DECREF(result); + ++pymod; + } + + return 0; +} + +/* + * Start up the M5 simulator. This mostly vectors into the python + * main function. + */ +int +m5Main(int argc, char **argv) +{ + PySys_SetArgv(argc, argv); + + // We have to set things up in the special __main__ module + PyObject *module = PyImport_AddModule(PyCC("__main__")); + if (module == NULL) + panic("Could not import __main__"); + PyObject *dict = PyModule_GetDict(module); + + // import the main m5 module + PyObject *result; + result = PyRun_String("import m5", Py_file_input, dict, dict); + if (!result) { + PyErr_Print(); + return 1; + } + Py_DECREF(result); + + // Start m5 + result = PyRun_String("m5.main()", Py_file_input, dict, dict); + if (!result) { + PyErr_Print(); + return 1; + } + Py_DECREF(result); + + return 0; +} diff --git a/src/python/swig/init.hh b/src/sim/init.hh similarity index 74% rename from src/python/swig/init.hh rename to src/sim/init.hh index 23d2c19a9..b0f29bf30 100644 --- a/src/python/swig/init.hh +++ b/src/sim/init.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 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 @@ -28,9 +28,27 @@ * Authors: Nathan Binkert */ -#ifndef __PYTHON_SWIG_INIT_HH__ -#define __PYTHON_SWIG_INIT_HH__ +#ifndef __SIM_INIT_HH__ +#define __SIM_INIT_HH__ -void init_swig(); +/* + * Data structure describing an embedded python file. + */ +struct EmbeddedPyModule +{ + const char *filename; + const char *modpath; + const char *code; + const char *code_end; + int zlen; + int mlen; +}; -#endif // __PYTHON_SWIG_INIT_HH__ +extern const EmbeddedPyModule embeddedPyImporter; +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 index baca556a0..d674e0cff 100644 --- 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,33 @@ */ #include -#include -#include -#include - -#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("__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; -} +#include "sim/init.hh" +// 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; + + // Initialize m5 special signal handling. + 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(python_home)); - // initialize embedded Python interpreter Py_Initialize(); - PySys_SetArgv(argc, argv); - // initialize SWIG modules - init_swig(); + // Initialize the embedded m5 python library + ret = initM5Python(); - int ret = python_main(); + if (ret == 0) { + // start m5 + ret = m5Main(argc, argv); + } // clean up Python intepreter. Py_Finalize();