main.cc revision 2797
12SN/A/* 21762SN/A * Copyright (c) 2000-2005 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Steve Raasch 292665Ssaidi@eecs.umich.edu * Nathan Binkert 302665Ssaidi@eecs.umich.edu * Steve Reinhardt 312SN/A */ 322SN/A 332SN/A/// 342SN/A/// @file sim/main.cc 352SN/A/// 362655Sstever@eecs.umich.edu#include <Python.h> // must be before system headers... see Python docs 372655Sstever@eecs.umich.edu 382SN/A#include <sys/types.h> 392SN/A#include <sys/stat.h> 401399SN/A#include <errno.h> 411396SN/A#include <libgen.h> 422SN/A#include <stdlib.h> 432SN/A#include <signal.h> 442729Ssaidi@eecs.umich.edu#include <getopt.h> 452SN/A 461310SN/A#include <list> 472SN/A#include <string> 482SN/A#include <vector> 492SN/A 502667Sstever@eecs.umich.edu#include "base/callback.hh" 5156SN/A#include "base/inifile.hh" 52146SN/A#include "base/misc.hh" 531388SN/A#include "base/output.hh" 5456SN/A#include "base/pollevent.hh" 5556SN/A#include "base/statistics.hh" 561311SN/A#include "base/str.hh" 57400SN/A#include "base/time.hh" 581717SN/A#include "cpu/base.hh" 591717SN/A#include "cpu/smt.hh" 602738Sstever@eecs.umich.edu#include "mem/mem_object.hh" 612738Sstever@eecs.umich.edu#include "mem/port.hh" 62146SN/A#include "sim/async.hh" 63146SN/A#include "sim/builder.hh" 64146SN/A#include "sim/host.hh" 652797Sktlim@umich.edu#include "sim/serialize.hh" 6656SN/A#include "sim/sim_events.hh" 6756SN/A#include "sim/sim_exit.hh" 6856SN/A#include "sim/sim_object.hh" 69695SN/A#include "sim/stat_control.hh" 70695SN/A#include "sim/stats.hh" 711696SN/A#include "sim/root.hh" 722SN/A 732SN/Ausing namespace std; 742SN/A 752SN/A// See async.h. 762SN/Avolatile bool async_event = false; 772SN/Avolatile bool async_dump = false; 78329SN/Avolatile bool async_dumpreset = false; 792SN/Avolatile bool async_exit = false; 802SN/Avolatile bool async_io = false; 812SN/Avolatile bool async_alarm = false; 822SN/A 832SN/A/// Stats signal handler. 842SN/Avoid 852SN/AdumpStatsHandler(int sigtype) 862SN/A{ 872SN/A async_event = true; 882SN/A async_dump = true; 892SN/A} 902SN/A 91329SN/Avoid 92329SN/AdumprstStatsHandler(int sigtype) 93329SN/A{ 94329SN/A async_event = true; 95329SN/A async_dumpreset = true; 96329SN/A} 97329SN/A 982SN/A/// Exit signal handler. 992SN/Avoid 1002SN/AexitNowHandler(int sigtype) 1012SN/A{ 1022SN/A async_event = true; 1032SN/A async_exit = true; 1042SN/A} 1052SN/A 106764SN/A/// Abort signal handler. 107764SN/Avoid 108764SN/AabortHandler(int sigtype) 109764SN/A{ 110764SN/A cerr << "Program aborted at cycle " << curTick << endl; 111764SN/A 112764SN/A#if TRACING_ON 113764SN/A // dump trace buffer, if there is one 114764SN/A Trace::theLog.dump(cerr); 115764SN/A#endif 116764SN/A} 117764SN/A 1182729Ssaidi@eecs.umich.edu/// Simulator executable name 1192729Ssaidi@eecs.umich.educhar *myProgName = ""; 1202729Ssaidi@eecs.umich.edu 1212729Ssaidi@eecs.umich.edu/// Show brief help message. 1222729Ssaidi@eecs.umich.eduvoid 1232729Ssaidi@eecs.umich.edushowBriefHelp(ostream &out) 1242729Ssaidi@eecs.umich.edu{ 1252729Ssaidi@eecs.umich.edu char *prog = basename(myProgName); 1262729Ssaidi@eecs.umich.edu 1272729Ssaidi@eecs.umich.edu ccprintf(out, "Usage:\n"); 1282729Ssaidi@eecs.umich.edu ccprintf(out, 1292729Ssaidi@eecs.umich.edu"%s [-p <path>] [-i ] [-h] <config file>\n" 1302729Ssaidi@eecs.umich.edu"\n" 1312729Ssaidi@eecs.umich.edu" -p, --path <path> prepends <path> to PYTHONPATH instead of using\n" 1322729Ssaidi@eecs.umich.edu" built-in zip archive. Useful when developing/debugging\n" 1332729Ssaidi@eecs.umich.edu" changes to built-in Python libraries, as the new Python\n" 1342729Ssaidi@eecs.umich.edu" can be tested without building a new m5 binary.\n\n" 1352729Ssaidi@eecs.umich.edu" -i, --interactive forces entry into interactive mode after the supplied\n" 1362729Ssaidi@eecs.umich.edu" script is executed (just like the -i option to the\n" 1372729Ssaidi@eecs.umich.edu" Python interpreter).\n\n" 1382729Ssaidi@eecs.umich.edu" -h Prints this help\n\n" 1392737Ssaidi@eecs.umich.edu" <configfile> config file name which ends in .py. (Normally you can\n" 1402737Ssaidi@eecs.umich.edu" run <configfile> --help to get help on that config files\n" 1412737Ssaidi@eecs.umich.edu" parameters.\n\n", 1422729Ssaidi@eecs.umich.edu prog); 1432729Ssaidi@eecs.umich.edu 1442729Ssaidi@eecs.umich.edu} 1452SN/A 1462667Sstever@eecs.umich.educonst char *briefCopyright = 1472667Sstever@eecs.umich.edu"Copyright (c) 2001-2006\n" 1482667Sstever@eecs.umich.edu"The Regents of The University of Michigan\n" 1492667Sstever@eecs.umich.edu"All Rights Reserved\n"; 1502667Sstever@eecs.umich.edu 1512667Sstever@eecs.umich.edu/// Print welcome message. 1521388SN/Avoid 1532667Sstever@eecs.umich.edusayHello(ostream &out) 1542SN/A{ 1552667Sstever@eecs.umich.edu extern const char *compileDate; // from date.cc 1562SN/A 1572667Sstever@eecs.umich.edu ccprintf(out, "M5 Simulator System\n"); 1582667Sstever@eecs.umich.edu // display copyright 1592667Sstever@eecs.umich.edu ccprintf(out, "%s\n", briefCopyright); 1602667Sstever@eecs.umich.edu ccprintf(out, "M5 compiled %d\n", compileDate); 1612667Sstever@eecs.umich.edu ccprintf(out, "M5 started %s\n", Time::start); 1622SN/A 1632667Sstever@eecs.umich.edu char *host = getenv("HOSTNAME"); 1642667Sstever@eecs.umich.edu if (!host) 1652667Sstever@eecs.umich.edu host = getenv("HOST"); 1662SN/A 1672667Sstever@eecs.umich.edu if (host) 1682667Sstever@eecs.umich.edu ccprintf(out, "M5 executing on %s\n", host); 1692667Sstever@eecs.umich.edu} 1702SN/A 1712SN/A 1722763Sstever@eecs.umich.eduextern "C" { void init_cc_main(); } 1732SN/A 1742SN/Aint 1752SN/Amain(int argc, char **argv) 1762SN/A{ 1772729Ssaidi@eecs.umich.edu // Saze off program name 1782729Ssaidi@eecs.umich.edu myProgName = argv[0]; 1792729Ssaidi@eecs.umich.edu 1802667Sstever@eecs.umich.edu sayHello(cerr); 1812SN/A 1822SN/A signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths 1832SN/A signal(SIGTRAP, SIG_IGN); 184329SN/A signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats 185329SN/A signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats 186329SN/A signal(SIGINT, exitNowHandler); // dump final stats and exit 187764SN/A signal(SIGABRT, abortHandler); 1882SN/A 1892655Sstever@eecs.umich.edu Py_SetProgramName(argv[0]); 1902667Sstever@eecs.umich.edu 1912667Sstever@eecs.umich.edu // default path to m5 python code is the currently executing 1922667Sstever@eecs.umich.edu // file... Python ZipImporter will find embedded zip archive 1932667Sstever@eecs.umich.edu char *pythonpath = argv[0]; 1942667Sstever@eecs.umich.edu 1952667Sstever@eecs.umich.edu bool interactive = false; 1962729Ssaidi@eecs.umich.edu bool show_help = false; 1972667Sstever@eecs.umich.edu bool getopt_done = false; 1982729Ssaidi@eecs.umich.edu int opt_index = 0; 1992729Ssaidi@eecs.umich.edu 2002729Ssaidi@eecs.umich.edu static struct option long_options[] = { 2012729Ssaidi@eecs.umich.edu {"python", 1, 0, 'p'}, 2022729Ssaidi@eecs.umich.edu {"interactive", 0, 0, 'i'}, 2032729Ssaidi@eecs.umich.edu {"help", 0, 0, 'h'}, 2042729Ssaidi@eecs.umich.edu {0,0,0,0} 2052729Ssaidi@eecs.umich.edu }; 2062729Ssaidi@eecs.umich.edu 2072667Sstever@eecs.umich.edu do { 2082729Ssaidi@eecs.umich.edu switch (getopt_long(argc, argv, "+p:ih", long_options, &opt_index)) { 2092667Sstever@eecs.umich.edu // -p <path> prepends <path> to PYTHONPATH instead of 2102667Sstever@eecs.umich.edu // using built-in zip archive. Useful when 2112667Sstever@eecs.umich.edu // developing/debugging changes to built-in Python 2122667Sstever@eecs.umich.edu // libraries, as the new Python can be tested without 2132667Sstever@eecs.umich.edu // building a new m5 binary. 2142667Sstever@eecs.umich.edu case 'p': 2152667Sstever@eecs.umich.edu pythonpath = optarg; 2162667Sstever@eecs.umich.edu break; 2172667Sstever@eecs.umich.edu 2182667Sstever@eecs.umich.edu // -i forces entry into interactive mode after the 2192667Sstever@eecs.umich.edu // supplied script is executed (just like the -i option to 2202667Sstever@eecs.umich.edu // the Python interpreter). 2212667Sstever@eecs.umich.edu case 'i': 2222667Sstever@eecs.umich.edu interactive = true; 2232667Sstever@eecs.umich.edu break; 2242667Sstever@eecs.umich.edu 2252729Ssaidi@eecs.umich.edu case 'h': 2262729Ssaidi@eecs.umich.edu show_help = true; 2272729Ssaidi@eecs.umich.edu break; 2282667Sstever@eecs.umich.edu case -1: 2292667Sstever@eecs.umich.edu getopt_done = true; 2302667Sstever@eecs.umich.edu break; 2312667Sstever@eecs.umich.edu 2322667Sstever@eecs.umich.edu default: 2332667Sstever@eecs.umich.edu fatal("Unrecognized option %c\n", optopt); 2342667Sstever@eecs.umich.edu } 2352667Sstever@eecs.umich.edu } while (!getopt_done); 2362667Sstever@eecs.umich.edu 2372729Ssaidi@eecs.umich.edu if (show_help) { 2382729Ssaidi@eecs.umich.edu showBriefHelp(cerr); 2392729Ssaidi@eecs.umich.edu exit(1); 2402729Ssaidi@eecs.umich.edu } 2412729Ssaidi@eecs.umich.edu 2422667Sstever@eecs.umich.edu // Fix up argc & argv to hide arguments we just processed. 2432667Sstever@eecs.umich.edu // getopt() sets optind to the index of the first non-processed 2442667Sstever@eecs.umich.edu // argv element. 2452667Sstever@eecs.umich.edu argc -= optind; 2462667Sstever@eecs.umich.edu argv += optind; 2472667Sstever@eecs.umich.edu 2482667Sstever@eecs.umich.edu // Set up PYTHONPATH to make sure the m5 module is found 2492667Sstever@eecs.umich.edu string newpath(pythonpath); 2502667Sstever@eecs.umich.edu 2512667Sstever@eecs.umich.edu char *oldpath = getenv("PYTHONPATH"); 2522667Sstever@eecs.umich.edu if (oldpath != NULL) { 2532667Sstever@eecs.umich.edu newpath += ":"; 2542667Sstever@eecs.umich.edu newpath += oldpath; 2552667Sstever@eecs.umich.edu } 2562667Sstever@eecs.umich.edu 2572667Sstever@eecs.umich.edu if (setenv("PYTHONPATH", newpath.c_str(), true) == -1) 2582667Sstever@eecs.umich.edu fatal("setenv: %s\n", strerror(errno)); 2592667Sstever@eecs.umich.edu 2602667Sstever@eecs.umich.edu // initialize embedded Python interpreter 2612655Sstever@eecs.umich.edu Py_Initialize(); 2622655Sstever@eecs.umich.edu PySys_SetArgv(argc, argv); 2631311SN/A 2642763Sstever@eecs.umich.edu // initialize SWIG 'cc_main' module 2652763Sstever@eecs.umich.edu init_cc_main(); 2661703SN/A 2672667Sstever@eecs.umich.edu if (argc > 0) { 2682667Sstever@eecs.umich.edu // extra arg(s): first is script file, remaining ones are args 2692667Sstever@eecs.umich.edu // to script file 2702667Sstever@eecs.umich.edu char *filename = argv[0]; 2712667Sstever@eecs.umich.edu FILE *fp = fopen(filename, "r"); 2722667Sstever@eecs.umich.edu if (!fp) { 2732667Sstever@eecs.umich.edu fatal("cannot open file '%s'\n", filename); 2742667Sstever@eecs.umich.edu } 2751703SN/A 2762667Sstever@eecs.umich.edu PyRun_AnyFile(fp, filename); 2772667Sstever@eecs.umich.edu } else { 2782667Sstever@eecs.umich.edu // no script file argument... force interactive prompt 2792667Sstever@eecs.umich.edu interactive = true; 2802667Sstever@eecs.umich.edu } 2812SN/A 2822667Sstever@eecs.umich.edu if (interactive) { 2832667Sstever@eecs.umich.edu // The following code to import readline was copied from Python 2842667Sstever@eecs.umich.edu // 2.4.3's Modules/main.c. 2852667Sstever@eecs.umich.edu // Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 2862667Sstever@eecs.umich.edu // Python Software Foundation; All Rights Reserved 2872667Sstever@eecs.umich.edu // We should only enable this if we're actually using an 2882667Sstever@eecs.umich.edu // interactive prompt. 2892667Sstever@eecs.umich.edu PyObject *v; 2902667Sstever@eecs.umich.edu v = PyImport_ImportModule("readline"); 2912667Sstever@eecs.umich.edu if (v == NULL) 2922667Sstever@eecs.umich.edu PyErr_Clear(); 2932667Sstever@eecs.umich.edu else 2942667Sstever@eecs.umich.edu Py_DECREF(v); 2952667Sstever@eecs.umich.edu 2962667Sstever@eecs.umich.edu PyRun_InteractiveLoop(stdin, "stdin"); 2972667Sstever@eecs.umich.edu } 2982667Sstever@eecs.umich.edu 2992667Sstever@eecs.umich.edu // clean up Python intepreter. 3002655Sstever@eecs.umich.edu Py_Finalize(); 3012667Sstever@eecs.umich.edu} 3021388SN/A 3032762Sstever@eecs.umich.edu 3042762Sstever@eecs.umich.eduvoid 3052762Sstever@eecs.umich.edusetOutputDir(const string &dir) 3062762Sstever@eecs.umich.edu{ 3072762Sstever@eecs.umich.edu simout.setDirectory(dir); 3082762Sstever@eecs.umich.edu} 3092762Sstever@eecs.umich.edu 3102762Sstever@eecs.umich.edu 3112738Sstever@eecs.umich.eduIniFile inifile; 3122667Sstever@eecs.umich.edu 3132738Sstever@eecs.umich.eduSimObject * 3142738Sstever@eecs.umich.educreateSimObject(const string &name) 3152738Sstever@eecs.umich.edu{ 3162738Sstever@eecs.umich.edu return SimObjectClass::createObject(inifile, name); 3172738Sstever@eecs.umich.edu} 3182738Sstever@eecs.umich.edu 3192738Sstever@eecs.umich.edu 3202738Sstever@eecs.umich.edu/** 3212738Sstever@eecs.umich.edu * Pointer to the Python function that maps names to SimObjects. 3222738Sstever@eecs.umich.edu */ 3232738Sstever@eecs.umich.eduPyObject *resolveFunc = NULL; 3242738Sstever@eecs.umich.edu 3252738Sstever@eecs.umich.edu/** 3262738Sstever@eecs.umich.edu * Convert a pointer to the Python object that SWIG wraps around a C++ 3272738Sstever@eecs.umich.edu * SimObject pointer back to the actual C++ pointer. See main.i. 3282738Sstever@eecs.umich.edu */ 3292738Sstever@eecs.umich.eduextern "C" SimObject *convertSwigSimObjectPtr(PyObject *); 3302738Sstever@eecs.umich.edu 3312738Sstever@eecs.umich.edu 3322738Sstever@eecs.umich.eduSimObject * 3332738Sstever@eecs.umich.eduresolveSimObject(const string &name) 3342738Sstever@eecs.umich.edu{ 3352738Sstever@eecs.umich.edu PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str()); 3362738Sstever@eecs.umich.edu if (pyPtr == NULL) { 3372738Sstever@eecs.umich.edu PyErr_Print(); 3382738Sstever@eecs.umich.edu panic("resolveSimObject: failure on call to Python for %s", name); 3392738Sstever@eecs.umich.edu } 3402738Sstever@eecs.umich.edu 3412738Sstever@eecs.umich.edu SimObject *simObj = convertSwigSimObjectPtr(pyPtr); 3422738Sstever@eecs.umich.edu if (simObj == NULL) 3432738Sstever@eecs.umich.edu panic("resolveSimObject: failure on pointer conversion for %s", name); 3442738Sstever@eecs.umich.edu 3452738Sstever@eecs.umich.edu return simObj; 3462738Sstever@eecs.umich.edu} 3472738Sstever@eecs.umich.edu 3482738Sstever@eecs.umich.edu 3492738Sstever@eecs.umich.edu/** 3502738Sstever@eecs.umich.edu * Load config.ini into C++ database. Exported to Python via SWIG; 3512738Sstever@eecs.umich.edu * invoked from m5.instantiate(). 3522738Sstever@eecs.umich.edu */ 3532667Sstever@eecs.umich.eduvoid 3542738Sstever@eecs.umich.eduloadIniFile(PyObject *_resolveFunc) 3552667Sstever@eecs.umich.edu{ 3562738Sstever@eecs.umich.edu resolveFunc = _resolveFunc; 3572655Sstever@eecs.umich.edu configStream = simout.find("config.out"); 3581388SN/A 3592SN/A // The configuration database is now complete; start processing it. 3602655Sstever@eecs.umich.edu inifile.load("config.ini"); 3612SN/A 3621388SN/A // Initialize statistics database 3631388SN/A Stats::InitSimStats(); 3642738Sstever@eecs.umich.edu} 3652SN/A 3661310SN/A 3672738Sstever@eecs.umich.edu/** 3682738Sstever@eecs.umich.edu * Look up a MemObject port. Helper function for connectPorts(). 3692738Sstever@eecs.umich.edu */ 3702738Sstever@eecs.umich.eduPort * 3712738Sstever@eecs.umich.edulookupPort(SimObject *so, const std::string &name, int i) 3722738Sstever@eecs.umich.edu{ 3732738Sstever@eecs.umich.edu MemObject *mo = dynamic_cast<MemObject *>(so); 3742738Sstever@eecs.umich.edu if (mo == NULL) { 3752738Sstever@eecs.umich.edu warn("error casting SimObject %s to MemObject", so->name()); 3762738Sstever@eecs.umich.edu return NULL; 3772738Sstever@eecs.umich.edu } 3782738Sstever@eecs.umich.edu 3792738Sstever@eecs.umich.edu Port *p = mo->getPort(name, i); 3802738Sstever@eecs.umich.edu if (p == NULL) 3812738Sstever@eecs.umich.edu warn("error looking up port %s on object %s", name, so->name()); 3822738Sstever@eecs.umich.edu return p; 3832738Sstever@eecs.umich.edu} 3842738Sstever@eecs.umich.edu 3852738Sstever@eecs.umich.edu 3862738Sstever@eecs.umich.edu/** 3872738Sstever@eecs.umich.edu * Connect the described MemObject ports. Called from Python via SWIG. 3882738Sstever@eecs.umich.edu */ 3892738Sstever@eecs.umich.eduint 3902738Sstever@eecs.umich.educonnectPorts(SimObject *o1, const std::string &name1, int i1, 3912738Sstever@eecs.umich.edu SimObject *o2, const std::string &name2, int i2) 3922738Sstever@eecs.umich.edu{ 3932738Sstever@eecs.umich.edu Port *p1 = lookupPort(o1, name1, i1); 3942738Sstever@eecs.umich.edu Port *p2 = lookupPort(o2, name2, i2); 3952738Sstever@eecs.umich.edu 3962738Sstever@eecs.umich.edu if (p1 == NULL || p2 == NULL) { 3972738Sstever@eecs.umich.edu warn("connectPorts: port lookup error"); 3982738Sstever@eecs.umich.edu return 0; 3992738Sstever@eecs.umich.edu } 4002738Sstever@eecs.umich.edu 4012738Sstever@eecs.umich.edu p1->setPeer(p2); 4022738Sstever@eecs.umich.edu p2->setPeer(p1); 4032738Sstever@eecs.umich.edu 4042738Sstever@eecs.umich.edu return 1; 4052738Sstever@eecs.umich.edu} 4062738Sstever@eecs.umich.edu 4072738Sstever@eecs.umich.edu/** 4082738Sstever@eecs.umich.edu * Do final initialization steps after object construction but before 4092738Sstever@eecs.umich.edu * start of simulation. 4102738Sstever@eecs.umich.edu */ 4112738Sstever@eecs.umich.eduvoid 4122738Sstever@eecs.umich.edufinalInit() 4132738Sstever@eecs.umich.edu{ 4141388SN/A // Parse and check all non-config-hierarchy parameters. 4151388SN/A ParamContext::parseAllContexts(inifile); 4161388SN/A ParamContext::checkAllContexts(); 4171388SN/A 4182667Sstever@eecs.umich.edu // Echo all parameter settings to stats file as well. 4191104SN/A ParamContext::showAllContexts(*configStream); 4202SN/A 4211127SN/A // Do a second pass to finish initializing the sim objects 4221127SN/A SimObject::initAll(); 4231127SN/A 4242SN/A // Restore checkpointed state, if any. 4252738Sstever@eecs.umich.edu#if 0 4262SN/A configHierarchy.unserializeSimObjects(); 4272738Sstever@eecs.umich.edu#endif 4282SN/A 4292SN/A SimObject::regAllStats(); 4302SN/A 4312SN/A // Check to make sure that the stats package is properly initialized 432729SN/A Stats::check(); 4332SN/A 434395SN/A // Reset to put the stats in a consistent state. 435729SN/A Stats::reset(); 436395SN/A 4371127SN/A SimStartup(); 4382667Sstever@eecs.umich.edu} 4392667Sstever@eecs.umich.edu 4402667Sstever@eecs.umich.edu 4412667Sstever@eecs.umich.edu/** Simulate for num_cycles additional cycles. If num_cycles is -1 4422667Sstever@eecs.umich.edu * (the default), do not limit simulation; some other event must 4432667Sstever@eecs.umich.edu * terminate the loop. Exported to Python via SWIG. 4442667Sstever@eecs.umich.edu * @return The SimLoopExitEvent that caused the loop to exit. 4452667Sstever@eecs.umich.edu */ 4462667Sstever@eecs.umich.eduSimLoopExitEvent * 4472667Sstever@eecs.umich.edusimulate(Tick num_cycles = -1) 4482667Sstever@eecs.umich.edu{ 4492667Sstever@eecs.umich.edu warn("Entering event queue @ %d. Starting simulation...\n", curTick); 4502667Sstever@eecs.umich.edu 4512667Sstever@eecs.umich.edu // Fix up num_cycles. Special default value -1 means simulate 4522667Sstever@eecs.umich.edu // "forever"... schedule event at MaxTick just to be safe. 4532667Sstever@eecs.umich.edu // Otherwise it's a delta for additional cycles to simulate past 4542667Sstever@eecs.umich.edu // curTick, and thus must be non-negative. 4552667Sstever@eecs.umich.edu if (num_cycles == -1) 4562667Sstever@eecs.umich.edu num_cycles = MaxTick; 4572667Sstever@eecs.umich.edu else if (num_cycles < 0) 4582667Sstever@eecs.umich.edu fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); 4592667Sstever@eecs.umich.edu else 4602667Sstever@eecs.umich.edu num_cycles = curTick + num_cycles; 4612667Sstever@eecs.umich.edu 4622667Sstever@eecs.umich.edu Event *limit_event = new SimLoopExitEvent(num_cycles, 4632667Sstever@eecs.umich.edu "simulate() limit reached"); 4642667Sstever@eecs.umich.edu 4652667Sstever@eecs.umich.edu while (1) { 4662667Sstever@eecs.umich.edu // there should always be at least one event (the SimLoopExitEvent 4672667Sstever@eecs.umich.edu // we just scheduled) in the queue 4682667Sstever@eecs.umich.edu assert(!mainEventQueue.empty()); 4692SN/A assert(curTick <= mainEventQueue.nextTick() && 4702SN/A "event scheduled in the past"); 4712SN/A 4722SN/A // forward current cycle to the time of the first event on the 4732SN/A // queue 4742SN/A curTick = mainEventQueue.nextTick(); 4752667Sstever@eecs.umich.edu Event *exit_event = mainEventQueue.serviceOne(); 4762667Sstever@eecs.umich.edu if (exit_event != NULL) { 4772667Sstever@eecs.umich.edu // hit some kind of exit event; return to Python 4782667Sstever@eecs.umich.edu // event must be subclass of SimLoopExitEvent... 4792667Sstever@eecs.umich.edu SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); 4802667Sstever@eecs.umich.edu if (se_event == NULL) 4812667Sstever@eecs.umich.edu panic("Bogus exit event class!"); 4822667Sstever@eecs.umich.edu 4832667Sstever@eecs.umich.edu // if we didn't hit limit_event, delete it 4842667Sstever@eecs.umich.edu if (se_event != limit_event) { 4852667Sstever@eecs.umich.edu assert(limit_event->scheduled()); 4862667Sstever@eecs.umich.edu limit_event->deschedule(); 4872667Sstever@eecs.umich.edu delete limit_event; 4882667Sstever@eecs.umich.edu } 4892667Sstever@eecs.umich.edu 4902667Sstever@eecs.umich.edu return se_event; 4912667Sstever@eecs.umich.edu } 4922SN/A 4932SN/A if (async_event) { 4942SN/A async_event = false; 4952SN/A if (async_dump) { 4962SN/A async_dump = false; 497294SN/A 498729SN/A using namespace Stats; 499294SN/A SetupEvent(Dump, curTick); 5002SN/A } 5012SN/A 502329SN/A if (async_dumpreset) { 503329SN/A async_dumpreset = false; 504329SN/A 505729SN/A using namespace Stats; 506329SN/A SetupEvent(Dump | Reset, curTick); 507329SN/A } 508329SN/A 5092SN/A if (async_exit) { 5102SN/A async_exit = false; 5112667Sstever@eecs.umich.edu exitSimLoop("user interrupt received"); 5122SN/A } 5132SN/A 5142SN/A if (async_io || async_alarm) { 5152SN/A async_io = false; 5162SN/A async_alarm = false; 5172SN/A pollQueue.service(); 5182SN/A } 5192SN/A } 5202SN/A } 5212SN/A 5222667Sstever@eecs.umich.edu // not reached... only exit is return on SimLoopExitEvent 5232667Sstever@eecs.umich.edu} 5242SN/A 5252797Sktlim@umich.eduEvent * 5262797Sktlim@umich.educreateCountedQuiesce() 5272797Sktlim@umich.edu{ 5282797Sktlim@umich.edu return new CountedQuiesceEvent(); 5292797Sktlim@umich.edu} 5302797Sktlim@umich.edu 5312797Sktlim@umich.eduvoid 5322797Sktlim@umich.educleanupCountedQuiesce(Event *counted_quiesce) 5332797Sktlim@umich.edu{ 5342797Sktlim@umich.edu CountedQuiesceEvent *event = 5352797Sktlim@umich.edu dynamic_cast<CountedQuiesceEvent *>(counted_quiesce); 5362797Sktlim@umich.edu if (event == NULL) { 5372797Sktlim@umich.edu fatal("Called cleanupCountedQuiesce() on an event that was not " 5382797Sktlim@umich.edu "a CountedQuiesceEvent."); 5392797Sktlim@umich.edu } 5402797Sktlim@umich.edu assert(event->getCount() == 0); 5412797Sktlim@umich.edu delete event; 5422797Sktlim@umich.edu} 5432797Sktlim@umich.edu 5442797Sktlim@umich.eduvoid 5452797Sktlim@umich.eduserializeAll() 5462797Sktlim@umich.edu{ 5472797Sktlim@umich.edu Serializable::serializeAll(); 5482797Sktlim@umich.edu} 5492797Sktlim@umich.edu 5502797Sktlim@umich.eduvoid 5512797Sktlim@umich.eduunserializeAll() 5522797Sktlim@umich.edu{ 5532797Sktlim@umich.edu Serializable::unserializeAll(); 5542797Sktlim@umich.edu} 5552797Sktlim@umich.edu 5562667Sstever@eecs.umich.edu/** 5572667Sstever@eecs.umich.edu * Queue of C++ callbacks to invoke on simulator exit. 5582667Sstever@eecs.umich.edu */ 5592667Sstever@eecs.umich.eduCallbackQueue exitCallbacks; 5602667Sstever@eecs.umich.edu 5612667Sstever@eecs.umich.edu/** 5622667Sstever@eecs.umich.edu * Register an exit callback. 5632667Sstever@eecs.umich.edu */ 5642667Sstever@eecs.umich.eduvoid 5652667Sstever@eecs.umich.eduregisterExitCallback(Callback *callback) 5662667Sstever@eecs.umich.edu{ 5672667Sstever@eecs.umich.edu exitCallbacks.add(callback); 5682SN/A} 5692667Sstever@eecs.umich.edu 5702797Sktlim@umich.eduBaseCPU * 5712797Sktlim@umich.educonvertToBaseCPUPtr(SimObject *obj) 5722797Sktlim@umich.edu{ 5732797Sktlim@umich.edu BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj); 5742797Sktlim@umich.edu 5752797Sktlim@umich.edu if (ptr == NULL) 5762797Sktlim@umich.edu warn("Casting to BaseCPU pointer failed"); 5772797Sktlim@umich.edu return ptr; 5782797Sktlim@umich.edu} 5792797Sktlim@umich.edu 5802667Sstever@eecs.umich.edu/** 5812667Sstever@eecs.umich.edu * Do C++ simulator exit processing. Exported to SWIG to be invoked 5822667Sstever@eecs.umich.edu * when simulator terminates via Python's atexit mechanism. 5832667Sstever@eecs.umich.edu */ 5842667Sstever@eecs.umich.eduvoid 5852667Sstever@eecs.umich.edudoExitCleanup() 5862667Sstever@eecs.umich.edu{ 5872667Sstever@eecs.umich.edu exitCallbacks.process(); 5882667Sstever@eecs.umich.edu exitCallbacks.clear(); 5892667Sstever@eecs.umich.edu 5902667Sstever@eecs.umich.edu cout.flush(); 5912667Sstever@eecs.umich.edu 5922667Sstever@eecs.umich.edu ParamContext::cleanupAllContexts(); 5932667Sstever@eecs.umich.edu 5942667Sstever@eecs.umich.edu // print simulation stats 5952667Sstever@eecs.umich.edu Stats::DumpNow(); 5962667Sstever@eecs.umich.edu} 597