main.cc revision 3511
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" 583356Sbinkertn@umich.edu#include "config/pythonhome.hh" 591717SN/A#include "cpu/base.hh" 601717SN/A#include "cpu/smt.hh" 612738Sstever@eecs.umich.edu#include "mem/mem_object.hh" 622738Sstever@eecs.umich.edu#include "mem/port.hh" 63146SN/A#include "sim/async.hh" 64146SN/A#include "sim/builder.hh" 65146SN/A#include "sim/host.hh" 662797Sktlim@umich.edu#include "sim/serialize.hh" 6756SN/A#include "sim/sim_events.hh" 6856SN/A#include "sim/sim_exit.hh" 6956SN/A#include "sim/sim_object.hh" 703202Shsul@eecs.umich.edu#include "sim/system.hh" 71695SN/A#include "sim/stat_control.hh" 72695SN/A#include "sim/stats.hh" 731696SN/A#include "sim/root.hh" 742SN/A 752SN/Ausing namespace std; 762SN/A 772SN/A// See async.h. 782SN/Avolatile bool async_event = false; 792SN/Avolatile bool async_dump = false; 80329SN/Avolatile bool async_dumpreset = false; 812SN/Avolatile bool async_exit = false; 822SN/Avolatile bool async_io = false; 832SN/Avolatile bool async_alarm = false; 842SN/A 852SN/A/// Stats signal handler. 862SN/Avoid 872SN/AdumpStatsHandler(int sigtype) 882SN/A{ 892SN/A async_event = true; 902SN/A async_dump = true; 912SN/A} 922SN/A 93329SN/Avoid 94329SN/AdumprstStatsHandler(int sigtype) 95329SN/A{ 96329SN/A async_event = true; 97329SN/A async_dumpreset = true; 98329SN/A} 99329SN/A 1002SN/A/// Exit signal handler. 1012SN/Avoid 1022SN/AexitNowHandler(int sigtype) 1032SN/A{ 1042SN/A async_event = true; 1052SN/A async_exit = true; 1062SN/A} 1072SN/A 108764SN/A/// Abort signal handler. 109764SN/Avoid 110764SN/AabortHandler(int sigtype) 111764SN/A{ 112764SN/A cerr << "Program aborted at cycle " << curTick << endl; 113764SN/A 114764SN/A#if TRACING_ON 115764SN/A // dump trace buffer, if there is one 116764SN/A Trace::theLog.dump(cerr); 117764SN/A#endif 118764SN/A} 119764SN/A 1202763Sstever@eecs.umich.eduextern "C" { void init_cc_main(); } 1212SN/A 1222SN/Aint 1232SN/Amain(int argc, char **argv) 1242SN/A{ 1252SN/A signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths 1262SN/A signal(SIGTRAP, SIG_IGN); 127329SN/A signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats 128329SN/A signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats 129329SN/A signal(SIGINT, exitNowHandler); // dump final stats and exit 130764SN/A signal(SIGABRT, abortHandler); 1312SN/A 1322655Sstever@eecs.umich.edu Py_SetProgramName(argv[0]); 1332667Sstever@eecs.umich.edu 1342667Sstever@eecs.umich.edu // default path to m5 python code is the currently executing 1352889Sbinkertn@umich.edu // file... Python ZipImporter will find embedded zip archive. 1362889Sbinkertn@umich.edu // The M5_ARCHIVE environment variable can be used to override this. 1372889Sbinkertn@umich.edu char *m5_archive = getenv("M5_ARCHIVE"); 1382889Sbinkertn@umich.edu string pythonpath = m5_archive ? m5_archive : argv[0]; 1392667Sstever@eecs.umich.edu 1402667Sstever@eecs.umich.edu char *oldpath = getenv("PYTHONPATH"); 1412667Sstever@eecs.umich.edu if (oldpath != NULL) { 1422889Sbinkertn@umich.edu pythonpath += ":"; 1432889Sbinkertn@umich.edu pythonpath += oldpath; 1442667Sstever@eecs.umich.edu } 1452667Sstever@eecs.umich.edu 1462889Sbinkertn@umich.edu if (setenv("PYTHONPATH", pythonpath.c_str(), true) == -1) 1472667Sstever@eecs.umich.edu fatal("setenv: %s\n", strerror(errno)); 1482667Sstever@eecs.umich.edu 1493356Sbinkertn@umich.edu char *python_home = getenv("PYTHONHOME"); 1503356Sbinkertn@umich.edu if (!python_home) 1513356Sbinkertn@umich.edu python_home = PYTHONHOME; 1523356Sbinkertn@umich.edu Py_SetPythonHome(python_home); 1533356Sbinkertn@umich.edu 1542667Sstever@eecs.umich.edu // initialize embedded Python interpreter 1552655Sstever@eecs.umich.edu Py_Initialize(); 1562655Sstever@eecs.umich.edu PySys_SetArgv(argc, argv); 1571311SN/A 1582763Sstever@eecs.umich.edu // initialize SWIG 'cc_main' module 1592763Sstever@eecs.umich.edu init_cc_main(); 1601703SN/A 1613102Sstever@eecs.umich.edu PyRun_SimpleString("import m5.main"); 1623102Sstever@eecs.umich.edu PyRun_SimpleString("m5.main.main()"); 1632667Sstever@eecs.umich.edu 1642667Sstever@eecs.umich.edu // clean up Python intepreter. 1652655Sstever@eecs.umich.edu Py_Finalize(); 1662667Sstever@eecs.umich.edu} 1671388SN/A 1682762Sstever@eecs.umich.edu 1692762Sstever@eecs.umich.eduvoid 1702762Sstever@eecs.umich.edusetOutputDir(const string &dir) 1712762Sstever@eecs.umich.edu{ 1722762Sstever@eecs.umich.edu simout.setDirectory(dir); 1732762Sstever@eecs.umich.edu} 1742762Sstever@eecs.umich.edu 1752762Sstever@eecs.umich.edu 1762738Sstever@eecs.umich.eduIniFile inifile; 1772667Sstever@eecs.umich.edu 1782738Sstever@eecs.umich.eduSimObject * 1792738Sstever@eecs.umich.educreateSimObject(const string &name) 1802738Sstever@eecs.umich.edu{ 1812738Sstever@eecs.umich.edu return SimObjectClass::createObject(inifile, name); 1822738Sstever@eecs.umich.edu} 1832738Sstever@eecs.umich.edu 1842738Sstever@eecs.umich.edu 1852738Sstever@eecs.umich.edu/** 1862738Sstever@eecs.umich.edu * Pointer to the Python function that maps names to SimObjects. 1872738Sstever@eecs.umich.edu */ 1882738Sstever@eecs.umich.eduPyObject *resolveFunc = NULL; 1892738Sstever@eecs.umich.edu 1902738Sstever@eecs.umich.edu/** 1912738Sstever@eecs.umich.edu * Convert a pointer to the Python object that SWIG wraps around a C++ 1922738Sstever@eecs.umich.edu * SimObject pointer back to the actual C++ pointer. See main.i. 1932738Sstever@eecs.umich.edu */ 1942738Sstever@eecs.umich.eduextern "C" SimObject *convertSwigSimObjectPtr(PyObject *); 1952738Sstever@eecs.umich.edu 1962738Sstever@eecs.umich.edu 1972738Sstever@eecs.umich.eduSimObject * 1982738Sstever@eecs.umich.eduresolveSimObject(const string &name) 1992738Sstever@eecs.umich.edu{ 2002738Sstever@eecs.umich.edu PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str()); 2012738Sstever@eecs.umich.edu if (pyPtr == NULL) { 2022738Sstever@eecs.umich.edu PyErr_Print(); 2032738Sstever@eecs.umich.edu panic("resolveSimObject: failure on call to Python for %s", name); 2042738Sstever@eecs.umich.edu } 2052738Sstever@eecs.umich.edu 2062738Sstever@eecs.umich.edu SimObject *simObj = convertSwigSimObjectPtr(pyPtr); 2072738Sstever@eecs.umich.edu if (simObj == NULL) 2082738Sstever@eecs.umich.edu panic("resolveSimObject: failure on pointer conversion for %s", name); 2092738Sstever@eecs.umich.edu 2102738Sstever@eecs.umich.edu return simObj; 2112738Sstever@eecs.umich.edu} 2122738Sstever@eecs.umich.edu 2132738Sstever@eecs.umich.edu 2142738Sstever@eecs.umich.edu/** 2152738Sstever@eecs.umich.edu * Load config.ini into C++ database. Exported to Python via SWIG; 2162738Sstever@eecs.umich.edu * invoked from m5.instantiate(). 2172738Sstever@eecs.umich.edu */ 2182667Sstever@eecs.umich.eduvoid 2192738Sstever@eecs.umich.eduloadIniFile(PyObject *_resolveFunc) 2202667Sstever@eecs.umich.edu{ 2212738Sstever@eecs.umich.edu resolveFunc = _resolveFunc; 2222655Sstever@eecs.umich.edu configStream = simout.find("config.out"); 2231388SN/A 2242SN/A // The configuration database is now complete; start processing it. 2252928Sktlim@umich.edu inifile.load(simout.resolve("config.ini")); 2262SN/A 2271388SN/A // Initialize statistics database 2281388SN/A Stats::InitSimStats(); 2292738Sstever@eecs.umich.edu} 2302SN/A 2311310SN/A 2322738Sstever@eecs.umich.edu/** 2332738Sstever@eecs.umich.edu * Look up a MemObject port. Helper function for connectPorts(). 2342738Sstever@eecs.umich.edu */ 2352738Sstever@eecs.umich.eduPort * 2362738Sstever@eecs.umich.edulookupPort(SimObject *so, const std::string &name, int i) 2372738Sstever@eecs.umich.edu{ 2382738Sstever@eecs.umich.edu MemObject *mo = dynamic_cast<MemObject *>(so); 2392738Sstever@eecs.umich.edu if (mo == NULL) { 2402738Sstever@eecs.umich.edu warn("error casting SimObject %s to MemObject", so->name()); 2412738Sstever@eecs.umich.edu return NULL; 2422738Sstever@eecs.umich.edu } 2432738Sstever@eecs.umich.edu 2442738Sstever@eecs.umich.edu Port *p = mo->getPort(name, i); 2452738Sstever@eecs.umich.edu if (p == NULL) 2462738Sstever@eecs.umich.edu warn("error looking up port %s on object %s", name, so->name()); 2472738Sstever@eecs.umich.edu return p; 2482738Sstever@eecs.umich.edu} 2492738Sstever@eecs.umich.edu 2502738Sstever@eecs.umich.edu 2512738Sstever@eecs.umich.edu/** 2522738Sstever@eecs.umich.edu * Connect the described MemObject ports. Called from Python via SWIG. 2532738Sstever@eecs.umich.edu */ 2542738Sstever@eecs.umich.eduint 2552738Sstever@eecs.umich.educonnectPorts(SimObject *o1, const std::string &name1, int i1, 2562738Sstever@eecs.umich.edu SimObject *o2, const std::string &name2, int i2) 2572738Sstever@eecs.umich.edu{ 2582738Sstever@eecs.umich.edu Port *p1 = lookupPort(o1, name1, i1); 2592738Sstever@eecs.umich.edu Port *p2 = lookupPort(o2, name2, i2); 2602738Sstever@eecs.umich.edu 2612738Sstever@eecs.umich.edu if (p1 == NULL || p2 == NULL) { 2622738Sstever@eecs.umich.edu warn("connectPorts: port lookup error"); 2632738Sstever@eecs.umich.edu return 0; 2642738Sstever@eecs.umich.edu } 2652738Sstever@eecs.umich.edu 2662738Sstever@eecs.umich.edu p1->setPeer(p2); 2672738Sstever@eecs.umich.edu p2->setPeer(p1); 2682738Sstever@eecs.umich.edu 2692738Sstever@eecs.umich.edu return 1; 2702738Sstever@eecs.umich.edu} 2712738Sstever@eecs.umich.edu 2722738Sstever@eecs.umich.edu/** 2732738Sstever@eecs.umich.edu * Do final initialization steps after object construction but before 2742738Sstever@eecs.umich.edu * start of simulation. 2752738Sstever@eecs.umich.edu */ 2762738Sstever@eecs.umich.eduvoid 2772738Sstever@eecs.umich.edufinalInit() 2782738Sstever@eecs.umich.edu{ 2791388SN/A // Parse and check all non-config-hierarchy parameters. 2801388SN/A ParamContext::parseAllContexts(inifile); 2811388SN/A ParamContext::checkAllContexts(); 2821388SN/A 2832667Sstever@eecs.umich.edu // Echo all parameter settings to stats file as well. 2841104SN/A ParamContext::showAllContexts(*configStream); 2852SN/A 2861127SN/A // Do a second pass to finish initializing the sim objects 2871127SN/A SimObject::initAll(); 2881127SN/A 2892SN/A // Restore checkpointed state, if any. 2902738Sstever@eecs.umich.edu#if 0 2912SN/A configHierarchy.unserializeSimObjects(); 2922738Sstever@eecs.umich.edu#endif 2932SN/A 2942SN/A SimObject::regAllStats(); 2952SN/A 2962SN/A // Check to make sure that the stats package is properly initialized 297729SN/A Stats::check(); 2982SN/A 299395SN/A // Reset to put the stats in a consistent state. 300729SN/A Stats::reset(); 301395SN/A 3021127SN/A SimStartup(); 3032667Sstever@eecs.umich.edu} 3042667Sstever@eecs.umich.edu 3052667Sstever@eecs.umich.edu 3062667Sstever@eecs.umich.edu/** Simulate for num_cycles additional cycles. If num_cycles is -1 3072667Sstever@eecs.umich.edu * (the default), do not limit simulation; some other event must 3082667Sstever@eecs.umich.edu * terminate the loop. Exported to Python via SWIG. 3092667Sstever@eecs.umich.edu * @return The SimLoopExitEvent that caused the loop to exit. 3102667Sstever@eecs.umich.edu */ 3112667Sstever@eecs.umich.eduSimLoopExitEvent * 3123511Shsul@eecs.umich.edusimulate(Tick num_cycles = MaxTick) 3132667Sstever@eecs.umich.edu{ 3142667Sstever@eecs.umich.edu warn("Entering event queue @ %d. Starting simulation...\n", curTick); 3152667Sstever@eecs.umich.edu 3163511Shsul@eecs.umich.edu if (num_cycles < 0) 3173511Shsul@eecs.umich.edu fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); 3183511Shsul@eecs.umich.edu else if (curTick + num_cycles < 0) //Overflow 3192667Sstever@eecs.umich.edu num_cycles = MaxTick; 3202667Sstever@eecs.umich.edu else 3212667Sstever@eecs.umich.edu num_cycles = curTick + num_cycles; 3222667Sstever@eecs.umich.edu 3233144Shsul@eecs.umich.edu Event *limit_event = schedExitSimLoop("simulate() limit reached", 3243144Shsul@eecs.umich.edu num_cycles); 3252667Sstever@eecs.umich.edu 3262667Sstever@eecs.umich.edu while (1) { 3272667Sstever@eecs.umich.edu // there should always be at least one event (the SimLoopExitEvent 3282667Sstever@eecs.umich.edu // we just scheduled) in the queue 3292667Sstever@eecs.umich.edu assert(!mainEventQueue.empty()); 3302SN/A assert(curTick <= mainEventQueue.nextTick() && 3312SN/A "event scheduled in the past"); 3322SN/A 3332SN/A // forward current cycle to the time of the first event on the 3342SN/A // queue 3352SN/A curTick = mainEventQueue.nextTick(); 3362667Sstever@eecs.umich.edu Event *exit_event = mainEventQueue.serviceOne(); 3372667Sstever@eecs.umich.edu if (exit_event != NULL) { 3382667Sstever@eecs.umich.edu // hit some kind of exit event; return to Python 3392667Sstever@eecs.umich.edu // event must be subclass of SimLoopExitEvent... 3402667Sstever@eecs.umich.edu SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); 3412667Sstever@eecs.umich.edu if (se_event == NULL) 3422667Sstever@eecs.umich.edu panic("Bogus exit event class!"); 3432667Sstever@eecs.umich.edu 3442667Sstever@eecs.umich.edu // if we didn't hit limit_event, delete it 3452667Sstever@eecs.umich.edu if (se_event != limit_event) { 3462667Sstever@eecs.umich.edu assert(limit_event->scheduled()); 3472667Sstever@eecs.umich.edu limit_event->deschedule(); 3482667Sstever@eecs.umich.edu delete limit_event; 3492667Sstever@eecs.umich.edu } 3502667Sstever@eecs.umich.edu 3512667Sstever@eecs.umich.edu return se_event; 3522667Sstever@eecs.umich.edu } 3532SN/A 3542SN/A if (async_event) { 3552SN/A async_event = false; 3562SN/A if (async_dump) { 3572SN/A async_dump = false; 358294SN/A 359729SN/A using namespace Stats; 360294SN/A SetupEvent(Dump, curTick); 3612SN/A } 3622SN/A 363329SN/A if (async_dumpreset) { 364329SN/A async_dumpreset = false; 365329SN/A 366729SN/A using namespace Stats; 367329SN/A SetupEvent(Dump | Reset, curTick); 368329SN/A } 369329SN/A 3702SN/A if (async_exit) { 3712SN/A async_exit = false; 3722667Sstever@eecs.umich.edu exitSimLoop("user interrupt received"); 3732SN/A } 3742SN/A 3752SN/A if (async_io || async_alarm) { 3762SN/A async_io = false; 3772SN/A async_alarm = false; 3782SN/A pollQueue.service(); 3792SN/A } 3802SN/A } 3812SN/A } 3822SN/A 3832667Sstever@eecs.umich.edu // not reached... only exit is return on SimLoopExitEvent 3842667Sstever@eecs.umich.edu} 3852SN/A 3862797Sktlim@umich.eduEvent * 3872839Sktlim@umich.educreateCountedDrain() 3882797Sktlim@umich.edu{ 3892839Sktlim@umich.edu return new CountedDrainEvent(); 3902797Sktlim@umich.edu} 3912797Sktlim@umich.edu 3922797Sktlim@umich.eduvoid 3932839Sktlim@umich.educleanupCountedDrain(Event *counted_drain) 3942797Sktlim@umich.edu{ 3952839Sktlim@umich.edu CountedDrainEvent *event = 3962839Sktlim@umich.edu dynamic_cast<CountedDrainEvent *>(counted_drain); 3972797Sktlim@umich.edu if (event == NULL) { 3982839Sktlim@umich.edu fatal("Called cleanupCountedDrain() on an event that was not " 3992839Sktlim@umich.edu "a CountedDrainEvent."); 4002797Sktlim@umich.edu } 4012797Sktlim@umich.edu assert(event->getCount() == 0); 4022797Sktlim@umich.edu delete event; 4032797Sktlim@umich.edu} 4042797Sktlim@umich.edu 4052797Sktlim@umich.eduvoid 4062868Sktlim@umich.eduserializeAll(const std::string &cpt_dir) 4072797Sktlim@umich.edu{ 4082868Sktlim@umich.edu Serializable::serializeAll(cpt_dir); 4092797Sktlim@umich.edu} 4102797Sktlim@umich.edu 4112797Sktlim@umich.eduvoid 4122868Sktlim@umich.eduunserializeAll(const std::string &cpt_dir) 4132797Sktlim@umich.edu{ 4142868Sktlim@umich.edu Serializable::unserializeAll(cpt_dir); 4152797Sktlim@umich.edu} 4162797Sktlim@umich.edu 4172667Sstever@eecs.umich.edu/** 4182667Sstever@eecs.umich.edu * Queue of C++ callbacks to invoke on simulator exit. 4192667Sstever@eecs.umich.edu */ 4203132Sbinkertn@umich.eduCallbackQueue& 4213132Sbinkertn@umich.eduexitCallbacks() 4223132Sbinkertn@umich.edu{ 4233132Sbinkertn@umich.edu static CallbackQueue theQueue; 4243132Sbinkertn@umich.edu return theQueue; 4253132Sbinkertn@umich.edu} 4262667Sstever@eecs.umich.edu 4272667Sstever@eecs.umich.edu/** 4282667Sstever@eecs.umich.edu * Register an exit callback. 4292667Sstever@eecs.umich.edu */ 4302667Sstever@eecs.umich.eduvoid 4312667Sstever@eecs.umich.eduregisterExitCallback(Callback *callback) 4322667Sstever@eecs.umich.edu{ 4333132Sbinkertn@umich.edu exitCallbacks().add(callback); 4342SN/A} 4352667Sstever@eecs.umich.edu 4362797Sktlim@umich.eduBaseCPU * 4372797Sktlim@umich.educonvertToBaseCPUPtr(SimObject *obj) 4382797Sktlim@umich.edu{ 4392797Sktlim@umich.edu BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj); 4402797Sktlim@umich.edu 4412797Sktlim@umich.edu if (ptr == NULL) 4422797Sktlim@umich.edu warn("Casting to BaseCPU pointer failed"); 4432797Sktlim@umich.edu return ptr; 4442797Sktlim@umich.edu} 4452797Sktlim@umich.edu 4463202Shsul@eecs.umich.eduSystem * 4473202Shsul@eecs.umich.educonvertToSystemPtr(SimObject *obj) 4483202Shsul@eecs.umich.edu{ 4493202Shsul@eecs.umich.edu System *ptr = dynamic_cast<System *>(obj); 4503202Shsul@eecs.umich.edu 4513202Shsul@eecs.umich.edu if (ptr == NULL) 4523202Shsul@eecs.umich.edu warn("Casting to System pointer failed"); 4533202Shsul@eecs.umich.edu return ptr; 4543202Shsul@eecs.umich.edu} 4553202Shsul@eecs.umich.edu 4563202Shsul@eecs.umich.edu 4572667Sstever@eecs.umich.edu/** 4582667Sstever@eecs.umich.edu * Do C++ simulator exit processing. Exported to SWIG to be invoked 4592667Sstever@eecs.umich.edu * when simulator terminates via Python's atexit mechanism. 4602667Sstever@eecs.umich.edu */ 4612667Sstever@eecs.umich.eduvoid 4622667Sstever@eecs.umich.edudoExitCleanup() 4632667Sstever@eecs.umich.edu{ 4643132Sbinkertn@umich.edu exitCallbacks().process(); 4653132Sbinkertn@umich.edu exitCallbacks().clear(); 4662667Sstever@eecs.umich.edu 4672667Sstever@eecs.umich.edu cout.flush(); 4682667Sstever@eecs.umich.edu 4692667Sstever@eecs.umich.edu ParamContext::cleanupAllContexts(); 4702667Sstever@eecs.umich.edu 4712667Sstever@eecs.umich.edu // print simulation stats 4722667Sstever@eecs.umich.edu Stats::DumpNow(); 4732667Sstever@eecs.umich.edu} 474