From 0337db3388db335ea23f02f3aa00bca9d483ef1c Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 30 May 2006 13:11:34 -0400 Subject: 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 --- src/sim/main.cc | 198 ++++++++------------------------------------------------ 1 file changed, 26 insertions(+), 172 deletions(-) (limited to 'src/sim/main.cc') diff --git a/src/sim/main.cc b/src/sim/main.cc index aecc171ed..a4e8a1f77 100644 --- a/src/sim/main.cc +++ b/src/sim/main.cc @@ -29,6 +29,8 @@ /// /// @file sim/main.cc /// +#include // must be before system headers... see Python docs + #include #include #include @@ -40,8 +42,6 @@ #include #include -#include "base/copyright.hh" -#include "base/embedfile.hh" #include "base/inifile.hh" #include "base/misc.hh" #include "base/output.hh" @@ -51,7 +51,6 @@ #include "base/time.hh" #include "cpu/base.hh" #include "cpu/smt.hh" -#include "python/pyconfig.hh" #include "sim/async.hh" #include "sim/builder.hh" #include "sim/configfile.hh" @@ -111,50 +110,6 @@ abortHandler(int sigtype) /// Simulator executable name char *myProgName = ""; -/// Show brief help message. -void -showBriefHelp(ostream &out) -{ - char *prog = basename(myProgName); - - ccprintf(out, "Usage:\n"); - ccprintf(out, -"%s [-d ] [-E [=]] [-I ] [-P ]\n" -" [--=] \n" -"\n" -" -d set the output directory to \n" -" -E set the environment variable to (or 'True')\n" -" -I add the directory to python's path\n" -" -P execute directly in the configuration\n" -" --var=val set the python variable to ''\n" -" config file name (ends in .py)\n\n", - prog); - - ccprintf(out, "%s -X\n -X extract embedded files\n\n", prog); - ccprintf(out, "%s -h\n -h print short help\n\n", prog); -} - -/// Print welcome message. -void -sayHello(ostream &out) -{ - extern const char *compileDate; // from date.cc - - ccprintf(out, "M5 Simulator System\n"); - // display copyright - ccprintf(out, "%s\n", briefCopyright); - ccprintf(out, "M5 compiled on %d\n", compileDate); - - char *host = getenv("HOSTNAME"); - if (!host) - host = getenv("HOST"); - - if (host) - ccprintf(out, "M5 executing on %s\n", host); - - ccprintf(out, "M5 simulation started %s\n", Time::start); -} - /// /// Echo the command line for posterity in such a way that it can be /// used to rerun the same simulation (given the same .ini files). @@ -191,19 +146,7 @@ echoCommandLine(int argc, char **argv, ostream &out) out << endl << endl; } -char * -getOptionString(int &index, int argc, char **argv) -{ - char *option = argv[index] + 2; - if (*option != '\0') - return option; - - // We didn't find an argument, it must be in the next variable. - if (++index >= argc) - panic("option string for option '%s' not found", argv[index - 1]); - - return argv[index]; -} +#include "config/python_build_env.hh" int main(int argc, char **argv) @@ -218,121 +161,37 @@ main(int argc, char **argv) signal(SIGINT, exitNowHandler); // dump final stats and exit signal(SIGABRT, abortHandler); - bool configfile_found = false; - PythonConfig pyconfig; - string outdir; - - if (argc < 2) { - showBriefHelp(cerr); - exit(1); - } - - sayHello(cerr); - - // Parse command-line options. - // Since most of the complex options are handled through the - // config database, we don't mess with getopts, and just parse - // manually. - for (int i = 1; i < argc; ++i) { - char *arg_str = argv[i]; - - // if arg starts with '--', parse as a special python option - // of the format --=, if the arg - // starts with '-', it should be a simulator option with a - // format similar to getopt. In any other case, treat the - // option as a configuration file name and load it. - if (arg_str[0] == '-' && arg_str[1] == '-') { - string str = &arg_str[2]; - string var, val; - - if (!split_first(str, var, val, '=')) - panic("Could not parse configuration argument '%s'\n" - "Expecting --=\n", arg_str); - - pyconfig.setVariable(var, val); - } else if (arg_str[0] == '-') { - char *option; - string var, val; - - // switch on second char - switch (arg_str[1]) { - case 'd': - outdir = getOptionString(i, argc, argv); - break; - - case 'h': - showBriefHelp(cerr); - exit(1); - - case 'E': - option = getOptionString(i, argc, argv); - if (!split_first(option, var, val, '=')) - val = "True"; - - if (setenv(var.c_str(), val.c_str(), true) == -1) - panic("setenv: %s\n", strerror(errno)); - break; - - case 'I': - option = getOptionString(i, argc, argv); - pyconfig.addPath(option); - break; - - case 'P': - option = getOptionString(i, argc, argv); - pyconfig.writeLine(option); - break; - - case 'X': { - list lst; - EmbedMap::all(lst); - list::iterator i = lst.begin(); - list::iterator end = lst.end(); - - while (i != end) { - cprintf("Embedded File: %s\n", i->name); - cout.write(i->data, i->length); - ++i; - } - - return 0; - } - - default: - showBriefHelp(cerr); - panic("invalid argument '%s'\n", arg_str); - } - } else { - string file(arg_str); - string base, ext; + // Python embedded interpreter invocation + Py_SetProgramName(argv[0]); + const char *fileName = Py_GetProgramFullPath(); + Py_Initialize(); + PySys_SetArgv(argc, argv); - if (!split_last(file, base, ext, '.') || ext != "py") - panic("Config file '%s' must end in '.py'\n", file); + // loadSwigModules(); - pyconfig.load(file); - configfile_found = true; - } - } + // Set Python module path to include current file to find embedded + // zip archive + PyRun_SimpleString("import sys"); + string pathCmd = csprintf("sys.path[1:1] = ['%s']", fileName); + PyRun_SimpleString(pathCmd.c_str()); - if (outdir.empty()) { - char *env = getenv("OUTPUT_DIR"); - outdir = env ? env : "."; - } - - simout.setDirectory(outdir); + // Pass compile timestamp string to Python + extern const char *compileDate; // from date.cc + string setCompileDate = csprintf("compileDate = '%s'", compileDate); + PyRun_SimpleString(setCompileDate.c_str()); - char *env = getenv("CONFIG_OUTPUT"); - if (!env) - env = "config.out"; - configStream = simout.find(env); + // PyRun_InteractiveLoop(stdin, "stdin"); + // m5/__init__.py currently contains main argv parsing loop etc., + // and will write out config.ini file before returning. + PyImport_ImportModule("defines"); + PyImport_ImportModule("m5"); + Py_Finalize(); - if (!configfile_found) - panic("no configuration file specified!"); + configStream = simout.find("config.out"); // The configuration database is now complete; start processing it. IniFile inifile; - if (!pyconfig.output(inifile)) - panic("Error processing python code"); + inifile.load("config.ini"); // Initialize statistics database Stats::InitSimStats(); @@ -346,11 +205,6 @@ main(int argc, char **argv) ParamContext::parseAllContexts(inifile); ParamContext::checkAllContexts(); - // Print hello message to stats file if it's actually a file. If - // it's not (i.e. it's cout or cerr) then we already did it above. - if (simout.isFile(*outputStream)) - sayHello(*outputStream); - // Echo command line and all parameter settings to stats file as well. echoCommandLine(argc, argv, *outputStream); ParamContext::showAllContexts(*configStream); -- cgit v1.2.3