main.cc revision 2667
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> 442667Sstever@eecs.umich.edu#include <unistd.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" 60146SN/A#include "sim/async.hh" 61146SN/A#include "sim/builder.hh" 62146SN/A#include "sim/configfile.hh" 63146SN/A#include "sim/host.hh" 6456SN/A#include "sim/sim_events.hh" 6556SN/A#include "sim/sim_exit.hh" 6656SN/A#include "sim/sim_object.hh" 67695SN/A#include "sim/stat_control.hh" 68695SN/A#include "sim/stats.hh" 691696SN/A#include "sim/root.hh" 702SN/A 712SN/Ausing namespace std; 722SN/A 732SN/A// See async.h. 742SN/Avolatile bool async_event = false; 752SN/Avolatile bool async_dump = false; 76329SN/Avolatile bool async_dumpreset = false; 772SN/Avolatile bool async_exit = false; 782SN/Avolatile bool async_io = false; 792SN/Avolatile bool async_alarm = false; 802SN/A 812SN/A/// Stats signal handler. 822SN/Avoid 832SN/AdumpStatsHandler(int sigtype) 842SN/A{ 852SN/A async_event = true; 862SN/A async_dump = true; 872SN/A} 882SN/A 89329SN/Avoid 90329SN/AdumprstStatsHandler(int sigtype) 91329SN/A{ 92329SN/A async_event = true; 93329SN/A async_dumpreset = true; 94329SN/A} 95329SN/A 962SN/A/// Exit signal handler. 972SN/Avoid 982SN/AexitNowHandler(int sigtype) 992SN/A{ 1002SN/A async_event = true; 1012SN/A async_exit = true; 1022SN/A} 1032SN/A 104764SN/A/// Abort signal handler. 105764SN/Avoid 106764SN/AabortHandler(int sigtype) 107764SN/A{ 108764SN/A cerr << "Program aborted at cycle " << curTick << endl; 109764SN/A 110764SN/A#if TRACING_ON 111764SN/A // dump trace buffer, if there is one 112764SN/A Trace::theLog.dump(cerr); 113764SN/A#endif 114764SN/A} 115764SN/A 1162SN/A 1172667Sstever@eecs.umich.educonst char *briefCopyright = 1182667Sstever@eecs.umich.edu"Copyright (c) 2001-2006\n" 1192667Sstever@eecs.umich.edu"The Regents of The University of Michigan\n" 1202667Sstever@eecs.umich.edu"All Rights Reserved\n"; 1212667Sstever@eecs.umich.edu 1222667Sstever@eecs.umich.edu/// Print welcome message. 1231388SN/Avoid 1242667Sstever@eecs.umich.edusayHello(ostream &out) 1252SN/A{ 1262667Sstever@eecs.umich.edu extern const char *compileDate; // from date.cc 1272SN/A 1282667Sstever@eecs.umich.edu ccprintf(out, "M5 Simulator System\n"); 1292667Sstever@eecs.umich.edu // display copyright 1302667Sstever@eecs.umich.edu ccprintf(out, "%s\n", briefCopyright); 1312667Sstever@eecs.umich.edu ccprintf(out, "M5 compiled %d\n", compileDate); 1322667Sstever@eecs.umich.edu ccprintf(out, "M5 started %s\n", Time::start); 1332SN/A 1342667Sstever@eecs.umich.edu char *host = getenv("HOSTNAME"); 1352667Sstever@eecs.umich.edu if (!host) 1362667Sstever@eecs.umich.edu host = getenv("HOST"); 1372SN/A 1382667Sstever@eecs.umich.edu if (host) 1392667Sstever@eecs.umich.edu ccprintf(out, "M5 executing on %s\n", host); 1402667Sstever@eecs.umich.edu} 1412SN/A 1422SN/A 1432667Sstever@eecs.umich.eduextern "C" { void init_main(); } 1442SN/A 1452SN/Aint 1462SN/Amain(int argc, char **argv) 1472SN/A{ 1482667Sstever@eecs.umich.edu sayHello(cerr); 1492SN/A 1502SN/A signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths 1512SN/A signal(SIGTRAP, SIG_IGN); 152329SN/A signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats 153329SN/A signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats 154329SN/A signal(SIGINT, exitNowHandler); // dump final stats and exit 155764SN/A signal(SIGABRT, abortHandler); 1562SN/A 1572655Sstever@eecs.umich.edu Py_SetProgramName(argv[0]); 1582667Sstever@eecs.umich.edu 1592667Sstever@eecs.umich.edu // default path to m5 python code is the currently executing 1602667Sstever@eecs.umich.edu // file... Python ZipImporter will find embedded zip archive 1612667Sstever@eecs.umich.edu char *pythonpath = argv[0]; 1622667Sstever@eecs.umich.edu 1632667Sstever@eecs.umich.edu bool interactive = false; 1642667Sstever@eecs.umich.edu bool getopt_done = false; 1652667Sstever@eecs.umich.edu do { 1662667Sstever@eecs.umich.edu switch (getopt(argc, argv, "+p:i")) { 1672667Sstever@eecs.umich.edu // -p <path> prepends <path> to PYTHONPATH instead of 1682667Sstever@eecs.umich.edu // using built-in zip archive. Useful when 1692667Sstever@eecs.umich.edu // developing/debugging changes to built-in Python 1702667Sstever@eecs.umich.edu // libraries, as the new Python can be tested without 1712667Sstever@eecs.umich.edu // building a new m5 binary. 1722667Sstever@eecs.umich.edu case 'p': 1732667Sstever@eecs.umich.edu pythonpath = optarg; 1742667Sstever@eecs.umich.edu break; 1752667Sstever@eecs.umich.edu 1762667Sstever@eecs.umich.edu // -i forces entry into interactive mode after the 1772667Sstever@eecs.umich.edu // supplied script is executed (just like the -i option to 1782667Sstever@eecs.umich.edu // the Python interpreter). 1792667Sstever@eecs.umich.edu case 'i': 1802667Sstever@eecs.umich.edu interactive = true; 1812667Sstever@eecs.umich.edu break; 1822667Sstever@eecs.umich.edu 1832667Sstever@eecs.umich.edu case -1: 1842667Sstever@eecs.umich.edu getopt_done = true; 1852667Sstever@eecs.umich.edu break; 1862667Sstever@eecs.umich.edu 1872667Sstever@eecs.umich.edu default: 1882667Sstever@eecs.umich.edu fatal("Unrecognized option %c\n", optopt); 1892667Sstever@eecs.umich.edu } 1902667Sstever@eecs.umich.edu } while (!getopt_done); 1912667Sstever@eecs.umich.edu 1922667Sstever@eecs.umich.edu // Fix up argc & argv to hide arguments we just processed. 1932667Sstever@eecs.umich.edu // getopt() sets optind to the index of the first non-processed 1942667Sstever@eecs.umich.edu // argv element. 1952667Sstever@eecs.umich.edu argc -= optind; 1962667Sstever@eecs.umich.edu argv += optind; 1972667Sstever@eecs.umich.edu 1982667Sstever@eecs.umich.edu // Set up PYTHONPATH to make sure the m5 module is found 1992667Sstever@eecs.umich.edu string newpath(pythonpath); 2002667Sstever@eecs.umich.edu 2012667Sstever@eecs.umich.edu char *oldpath = getenv("PYTHONPATH"); 2022667Sstever@eecs.umich.edu if (oldpath != NULL) { 2032667Sstever@eecs.umich.edu newpath += ":"; 2042667Sstever@eecs.umich.edu newpath += oldpath; 2052667Sstever@eecs.umich.edu } 2062667Sstever@eecs.umich.edu 2072667Sstever@eecs.umich.edu if (setenv("PYTHONPATH", newpath.c_str(), true) == -1) 2082667Sstever@eecs.umich.edu fatal("setenv: %s\n", strerror(errno)); 2092667Sstever@eecs.umich.edu 2102667Sstever@eecs.umich.edu // initialize embedded Python interpreter 2112655Sstever@eecs.umich.edu Py_Initialize(); 2122655Sstever@eecs.umich.edu PySys_SetArgv(argc, argv); 2131311SN/A 2142667Sstever@eecs.umich.edu // initialize SWIG 'main' module 2152667Sstever@eecs.umich.edu init_main(); 2161703SN/A 2172667Sstever@eecs.umich.edu if (argc > 0) { 2182667Sstever@eecs.umich.edu // extra arg(s): first is script file, remaining ones are args 2192667Sstever@eecs.umich.edu // to script file 2202667Sstever@eecs.umich.edu char *filename = argv[0]; 2212667Sstever@eecs.umich.edu FILE *fp = fopen(filename, "r"); 2222667Sstever@eecs.umich.edu if (!fp) { 2232667Sstever@eecs.umich.edu fatal("cannot open file '%s'\n", filename); 2242667Sstever@eecs.umich.edu } 2251703SN/A 2262667Sstever@eecs.umich.edu PyRun_AnyFile(fp, filename); 2272667Sstever@eecs.umich.edu } else { 2282667Sstever@eecs.umich.edu // no script file argument... force interactive prompt 2292667Sstever@eecs.umich.edu interactive = true; 2302667Sstever@eecs.umich.edu } 2312SN/A 2322667Sstever@eecs.umich.edu if (interactive) { 2332667Sstever@eecs.umich.edu // The following code to import readline was copied from Python 2342667Sstever@eecs.umich.edu // 2.4.3's Modules/main.c. 2352667Sstever@eecs.umich.edu // Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 2362667Sstever@eecs.umich.edu // Python Software Foundation; All Rights Reserved 2372667Sstever@eecs.umich.edu // We should only enable this if we're actually using an 2382667Sstever@eecs.umich.edu // interactive prompt. 2392667Sstever@eecs.umich.edu PyObject *v; 2402667Sstever@eecs.umich.edu v = PyImport_ImportModule("readline"); 2412667Sstever@eecs.umich.edu if (v == NULL) 2422667Sstever@eecs.umich.edu PyErr_Clear(); 2432667Sstever@eecs.umich.edu else 2442667Sstever@eecs.umich.edu Py_DECREF(v); 2452667Sstever@eecs.umich.edu 2462667Sstever@eecs.umich.edu PyRun_InteractiveLoop(stdin, "stdin"); 2472667Sstever@eecs.umich.edu } 2482667Sstever@eecs.umich.edu 2492667Sstever@eecs.umich.edu // clean up Python intepreter. 2502655Sstever@eecs.umich.edu Py_Finalize(); 2512667Sstever@eecs.umich.edu} 2521388SN/A 2532667Sstever@eecs.umich.edu 2542667Sstever@eecs.umich.edu/// Initialize C++ configuration. Exported to Python via SWIG; invoked 2552667Sstever@eecs.umich.edu/// from m5.instantiate(). 2562667Sstever@eecs.umich.eduvoid 2572667Sstever@eecs.umich.eduinitialize() 2582667Sstever@eecs.umich.edu{ 2592655Sstever@eecs.umich.edu configStream = simout.find("config.out"); 2601388SN/A 2612SN/A // The configuration database is now complete; start processing it. 2621388SN/A IniFile inifile; 2632655Sstever@eecs.umich.edu inifile.load("config.ini"); 2642SN/A 2651388SN/A // Initialize statistics database 2661388SN/A Stats::InitSimStats(); 2672SN/A 2681310SN/A // Now process the configuration hierarchy and create the SimObjects. 2691388SN/A ConfigHierarchy configHierarchy(inifile); 2701310SN/A configHierarchy.build(); 2711310SN/A configHierarchy.createSimObjects(); 2721310SN/A 2731388SN/A // Parse and check all non-config-hierarchy parameters. 2741388SN/A ParamContext::parseAllContexts(inifile); 2751388SN/A ParamContext::checkAllContexts(); 2761388SN/A 2772667Sstever@eecs.umich.edu // Echo all parameter settings to stats file as well. 2781104SN/A ParamContext::showAllContexts(*configStream); 2792SN/A 2802499SN/A // Any objects that can't connect themselves until after construction should 2812499SN/A // do so now 2822499SN/A SimObject::connectAll(); 2832499SN/A 2841127SN/A // Do a second pass to finish initializing the sim objects 2851127SN/A SimObject::initAll(); 2861127SN/A 2872SN/A // Restore checkpointed state, if any. 2882SN/A configHierarchy.unserializeSimObjects(); 2892SN/A 2902SN/A // Done processing the configuration database. 2912SN/A // Check for unreferenced entries. 2921388SN/A if (inifile.printUnreferenced()) 2931388SN/A panic("unreferenced sections/entries in the intermediate ini file"); 2942SN/A 2952SN/A SimObject::regAllStats(); 2962SN/A 2972SN/A // uncomment the following to get PC-based execution-time profile 2982SN/A#ifdef DO_PROFILE 2992SN/A init_profile((char *)&_init, (char *)&_fini); 3002SN/A#endif 3012SN/A 3022SN/A // Check to make sure that the stats package is properly initialized 303729SN/A Stats::check(); 3042SN/A 305395SN/A // Reset to put the stats in a consistent state. 306729SN/A Stats::reset(); 307395SN/A 3081127SN/A SimStartup(); 3092667Sstever@eecs.umich.edu} 3102667Sstever@eecs.umich.edu 3112667Sstever@eecs.umich.edu 3122667Sstever@eecs.umich.edu/** Simulate for num_cycles additional cycles. If num_cycles is -1 3132667Sstever@eecs.umich.edu * (the default), do not limit simulation; some other event must 3142667Sstever@eecs.umich.edu * terminate the loop. Exported to Python via SWIG. 3152667Sstever@eecs.umich.edu * @return The SimLoopExitEvent that caused the loop to exit. 3162667Sstever@eecs.umich.edu */ 3172667Sstever@eecs.umich.eduSimLoopExitEvent * 3182667Sstever@eecs.umich.edusimulate(Tick num_cycles = -1) 3192667Sstever@eecs.umich.edu{ 3202667Sstever@eecs.umich.edu warn("Entering event queue @ %d. Starting simulation...\n", curTick); 3212667Sstever@eecs.umich.edu 3222667Sstever@eecs.umich.edu // Fix up num_cycles. Special default value -1 means simulate 3232667Sstever@eecs.umich.edu // "forever"... schedule event at MaxTick just to be safe. 3242667Sstever@eecs.umich.edu // Otherwise it's a delta for additional cycles to simulate past 3252667Sstever@eecs.umich.edu // curTick, and thus must be non-negative. 3262667Sstever@eecs.umich.edu if (num_cycles == -1) 3272667Sstever@eecs.umich.edu num_cycles = MaxTick; 3282667Sstever@eecs.umich.edu else if (num_cycles < 0) 3292667Sstever@eecs.umich.edu fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); 3302667Sstever@eecs.umich.edu else 3312667Sstever@eecs.umich.edu num_cycles = curTick + num_cycles; 3322667Sstever@eecs.umich.edu 3332667Sstever@eecs.umich.edu Event *limit_event = new SimLoopExitEvent(num_cycles, 3342667Sstever@eecs.umich.edu "simulate() limit reached"); 3352667Sstever@eecs.umich.edu 3362667Sstever@eecs.umich.edu while (1) { 3372667Sstever@eecs.umich.edu // there should always be at least one event (the SimLoopExitEvent 3382667Sstever@eecs.umich.edu // we just scheduled) in the queue 3392667Sstever@eecs.umich.edu assert(!mainEventQueue.empty()); 3402SN/A assert(curTick <= mainEventQueue.nextTick() && 3412SN/A "event scheduled in the past"); 3422SN/A 3432SN/A // forward current cycle to the time of the first event on the 3442SN/A // queue 3452SN/A curTick = mainEventQueue.nextTick(); 3462667Sstever@eecs.umich.edu Event *exit_event = mainEventQueue.serviceOne(); 3472667Sstever@eecs.umich.edu if (exit_event != NULL) { 3482667Sstever@eecs.umich.edu // hit some kind of exit event; return to Python 3492667Sstever@eecs.umich.edu // event must be subclass of SimLoopExitEvent... 3502667Sstever@eecs.umich.edu SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); 3512667Sstever@eecs.umich.edu if (se_event == NULL) 3522667Sstever@eecs.umich.edu panic("Bogus exit event class!"); 3532667Sstever@eecs.umich.edu 3542667Sstever@eecs.umich.edu // if we didn't hit limit_event, delete it 3552667Sstever@eecs.umich.edu if (se_event != limit_event) { 3562667Sstever@eecs.umich.edu assert(limit_event->scheduled()); 3572667Sstever@eecs.umich.edu limit_event->deschedule(); 3582667Sstever@eecs.umich.edu delete limit_event; 3592667Sstever@eecs.umich.edu } 3602667Sstever@eecs.umich.edu 3612667Sstever@eecs.umich.edu return se_event; 3622667Sstever@eecs.umich.edu } 3632SN/A 3642SN/A if (async_event) { 3652SN/A async_event = false; 3662SN/A if (async_dump) { 3672SN/A async_dump = false; 368294SN/A 369729SN/A using namespace Stats; 370294SN/A SetupEvent(Dump, curTick); 3712SN/A } 3722SN/A 373329SN/A if (async_dumpreset) { 374329SN/A async_dumpreset = false; 375329SN/A 376729SN/A using namespace Stats; 377329SN/A SetupEvent(Dump | Reset, curTick); 378329SN/A } 379329SN/A 3802SN/A if (async_exit) { 3812SN/A async_exit = false; 3822667Sstever@eecs.umich.edu exitSimLoop("user interrupt received"); 3832SN/A } 3842SN/A 3852SN/A if (async_io || async_alarm) { 3862SN/A async_io = false; 3872SN/A async_alarm = false; 3882SN/A pollQueue.service(); 3892SN/A } 3902SN/A } 3912SN/A } 3922SN/A 3932667Sstever@eecs.umich.edu // not reached... only exit is return on SimLoopExitEvent 3942667Sstever@eecs.umich.edu} 3952SN/A 3962667Sstever@eecs.umich.edu/** 3972667Sstever@eecs.umich.edu * Queue of C++ callbacks to invoke on simulator exit. 3982667Sstever@eecs.umich.edu */ 3992667Sstever@eecs.umich.eduCallbackQueue exitCallbacks; 4002667Sstever@eecs.umich.edu 4012667Sstever@eecs.umich.edu/** 4022667Sstever@eecs.umich.edu * Register an exit callback. 4032667Sstever@eecs.umich.edu */ 4042667Sstever@eecs.umich.eduvoid 4052667Sstever@eecs.umich.eduregisterExitCallback(Callback *callback) 4062667Sstever@eecs.umich.edu{ 4072667Sstever@eecs.umich.edu exitCallbacks.add(callback); 4082SN/A} 4092667Sstever@eecs.umich.edu 4102667Sstever@eecs.umich.edu/** 4112667Sstever@eecs.umich.edu * Do C++ simulator exit processing. Exported to SWIG to be invoked 4122667Sstever@eecs.umich.edu * when simulator terminates via Python's atexit mechanism. 4132667Sstever@eecs.umich.edu */ 4142667Sstever@eecs.umich.eduvoid 4152667Sstever@eecs.umich.edudoExitCleanup() 4162667Sstever@eecs.umich.edu{ 4172667Sstever@eecs.umich.edu exitCallbacks.process(); 4182667Sstever@eecs.umich.edu exitCallbacks.clear(); 4192667Sstever@eecs.umich.edu 4202667Sstever@eecs.umich.edu cout.flush(); 4212667Sstever@eecs.umich.edu 4222667Sstever@eecs.umich.edu ParamContext::cleanupAllContexts(); 4232667Sstever@eecs.umich.edu 4242667Sstever@eecs.umich.edu // print simulation stats 4252667Sstever@eecs.umich.edu Stats::DumpNow(); 4262667Sstever@eecs.umich.edu} 427