main.cc revision 3868
1955SN/A/* 2955SN/A * Copyright (c) 2000-2005 The Regents of The University of Michigan 31762SN/A * All rights reserved. 4955SN/A * 5955SN/A * Redistribution and use in source and binary forms, with or without 6955SN/A * modification, are permitted provided that the following conditions are 7955SN/A * met: redistributions of source code must retain the above copyright 8955SN/A * notice, this list of conditions and the following disclaimer; 9955SN/A * redistributions in binary form must reproduce the above copyright 10955SN/A * notice, this list of conditions and the following disclaimer in the 11955SN/A * documentation and/or other materials provided with the distribution; 12955SN/A * neither the name of the copyright holders nor the names of its 13955SN/A * contributors may be used to endorse or promote products derived from 14955SN/A * this software without specific prior written permission. 15955SN/A * 16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27955SN/A * 282665Ssaidi@eecs.umich.edu * Authors: Steve Raasch 294762Snate@binkert.org * Nathan Binkert 30955SN/A * Steve Reinhardt 315522Snate@binkert.org */ 326143Snate@binkert.org 334762Snate@binkert.org/// 345522Snate@binkert.org/// @file sim/main.cc 35955SN/A/// 365522Snate@binkert.org#include <Python.h> // must be before system headers... see Python docs 37955SN/A 385522Snate@binkert.org#include <sys/types.h> 394202Sbinkertn@umich.edu#include <sys/stat.h> 405742Snate@binkert.org#include <errno.h> 41955SN/A#include <libgen.h> 424381Sbinkertn@umich.edu#include <stdlib.h> 434381Sbinkertn@umich.edu#include <signal.h> 448334Snate@binkert.org#include <getopt.h> 45955SN/A 46955SN/A#include <list> 474202Sbinkertn@umich.edu#include <string> 48955SN/A#include <vector> 494382Sbinkertn@umich.edu 504382Sbinkertn@umich.edu#include "base/callback.hh" 514382Sbinkertn@umich.edu#include "base/inifile.hh" 526654Snate@binkert.org#include "base/misc.hh" 535517Snate@binkert.org#include "base/output.hh" 548614Sgblack@eecs.umich.edu#include "base/pollevent.hh" 557674Snate@binkert.org#include "base/statistics.hh" 566143Snate@binkert.org#include "base/str.hh" 576143Snate@binkert.org#include "base/time.hh" 586143Snate@binkert.org#include "config/pythonhome.hh" 598233Snate@binkert.org#include "cpu/base.hh" 608233Snate@binkert.org#include "cpu/smt.hh" 618233Snate@binkert.org#include "mem/mem_object.hh" 628233Snate@binkert.org#include "mem/port.hh" 638233Snate@binkert.org#include "python/swig/init.hh" 648334Snate@binkert.org#include "sim/async.hh" 658334Snate@binkert.org#include "sim/builder.hh" 668233Snate@binkert.org#include "sim/host.hh" 678233Snate@binkert.org#include "sim/serialize.hh" 688233Snate@binkert.org#include "sim/sim_events.hh" 698233Snate@binkert.org#include "sim/sim_exit.hh" 708233Snate@binkert.org#include "sim/sim_object.hh" 718233Snate@binkert.org#include "sim/system.hh" 726143Snate@binkert.org#include "sim/stat_control.hh" 738233Snate@binkert.org#include "sim/stats.hh" 748233Snate@binkert.org#include "sim/root.hh" 758233Snate@binkert.org 766143Snate@binkert.orgusing namespace std; 776143Snate@binkert.org 786143Snate@binkert.org// See async.h. 796143Snate@binkert.orgvolatile bool async_event = false; 808233Snate@binkert.orgvolatile bool async_dump = false; 818233Snate@binkert.orgvolatile bool async_dumpreset = false; 828233Snate@binkert.orgvolatile bool async_exit = false; 836143Snate@binkert.orgvolatile bool async_io = false; 848233Snate@binkert.orgvolatile bool async_alarm = false; 858233Snate@binkert.org 868233Snate@binkert.org/// Stats signal handler. 878233Snate@binkert.orgvoid 886143Snate@binkert.orgdumpStatsHandler(int sigtype) 896143Snate@binkert.org{ 906143Snate@binkert.org async_event = true; 914762Snate@binkert.org async_dump = true; 926143Snate@binkert.org} 938233Snate@binkert.org 948233Snate@binkert.orgvoid 958233Snate@binkert.orgdumprstStatsHandler(int sigtype) 968233Snate@binkert.org{ 978233Snate@binkert.org async_event = true; 986143Snate@binkert.org async_dumpreset = true; 998233Snate@binkert.org} 1008233Snate@binkert.org 1018233Snate@binkert.org/// Exit signal handler. 1028233Snate@binkert.orgvoid 1036143Snate@binkert.orgexitNowHandler(int sigtype) 1046143Snate@binkert.org{ 1056143Snate@binkert.org async_event = true; 1066143Snate@binkert.org async_exit = true; 1076143Snate@binkert.org} 1086143Snate@binkert.org 1096143Snate@binkert.org/// Abort signal handler. 1106143Snate@binkert.orgvoid 1116143Snate@binkert.orgabortHandler(int sigtype) 1127065Snate@binkert.org{ 1136143Snate@binkert.org cerr << "Program aborted at cycle " << curTick << endl; 1148233Snate@binkert.org 1158233Snate@binkert.org#if TRACING_ON 1168233Snate@binkert.org // dump trace buffer, if there is one 1178233Snate@binkert.org Trace::theLog.dump(cerr); 1188233Snate@binkert.org#endif 1198233Snate@binkert.org} 1208233Snate@binkert.org 1218233Snate@binkert.orgint 1228233Snate@binkert.orgmain(int argc, char **argv) 1238233Snate@binkert.org{ 1248233Snate@binkert.org signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths 1258233Snate@binkert.org signal(SIGTRAP, SIG_IGN); 1268233Snate@binkert.org signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats 1278233Snate@binkert.org signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats 1288233Snate@binkert.org signal(SIGINT, exitNowHandler); // dump final stats and exit 1298233Snate@binkert.org signal(SIGABRT, abortHandler); 1308233Snate@binkert.org 1318233Snate@binkert.org Py_SetProgramName(argv[0]); 1328233Snate@binkert.org 1338233Snate@binkert.org // default path to m5 python code is the currently executing 1348233Snate@binkert.org // file... Python ZipImporter will find embedded zip archive. 1358233Snate@binkert.org // The M5_ARCHIVE environment variable can be used to override this. 1368233Snate@binkert.org char *m5_archive = getenv("M5_ARCHIVE"); 1378233Snate@binkert.org string pythonpath = m5_archive ? m5_archive : argv[0]; 1388233Snate@binkert.org 1398233Snate@binkert.org char *oldpath = getenv("PYTHONPATH"); 1408233Snate@binkert.org if (oldpath != NULL) { 1418233Snate@binkert.org pythonpath += ":"; 1428233Snate@binkert.org pythonpath += oldpath; 1438233Snate@binkert.org } 1448233Snate@binkert.org 1456143Snate@binkert.org if (setenv("PYTHONPATH", pythonpath.c_str(), true) == -1) 1466143Snate@binkert.org fatal("setenv: %s\n", strerror(errno)); 1476143Snate@binkert.org 1486143Snate@binkert.org char *python_home = getenv("PYTHONHOME"); 1496143Snate@binkert.org if (!python_home) 1506143Snate@binkert.org python_home = PYTHONHOME; 1516143Snate@binkert.org Py_SetPythonHome(python_home); 1526143Snate@binkert.org 1536143Snate@binkert.org // initialize embedded Python interpreter 1548945Ssteve.reinhardt@amd.com Py_Initialize(); 1558233Snate@binkert.org PySys_SetArgv(argc, argv); 1568233Snate@binkert.org 1576143Snate@binkert.org // initialize SWIG modules 1588945Ssteve.reinhardt@amd.com init_swig(); 1596143Snate@binkert.org 1606143Snate@binkert.org PyRun_SimpleString("import m5.main"); 1616143Snate@binkert.org PyRun_SimpleString("m5.main.main()"); 1626143Snate@binkert.org 1635522Snate@binkert.org // clean up Python intepreter. 1646143Snate@binkert.org Py_Finalize(); 1656143Snate@binkert.org} 1666143Snate@binkert.org 1676143Snate@binkert.org 1688233Snate@binkert.orgvoid 1698233Snate@binkert.orgsetOutputDir(const string &dir) 1708233Snate@binkert.org{ 1716143Snate@binkert.org simout.setDirectory(dir); 1726143Snate@binkert.org} 1736143Snate@binkert.org 1746143Snate@binkert.org 1755522Snate@binkert.orgIniFile inifile; 1765522Snate@binkert.org 1775522Snate@binkert.orgSimObject * 1785522Snate@binkert.orgcreateSimObject(const string &name) 1795604Snate@binkert.org{ 1805604Snate@binkert.org return SimObjectClass::createObject(inifile, name); 1816143Snate@binkert.org} 1826143Snate@binkert.org 1834762Snate@binkert.org 1844762Snate@binkert.org/** 1856143Snate@binkert.org * Pointer to the Python function that maps names to SimObjects. 1866727Ssteve.reinhardt@amd.com */ 1876727Ssteve.reinhardt@amd.comPyObject *resolveFunc = NULL; 1886727Ssteve.reinhardt@amd.com 1894762Snate@binkert.org/** 1906143Snate@binkert.org * Convert a pointer to the Python object that SWIG wraps around a C++ 1916143Snate@binkert.org * SimObject pointer back to the actual C++ pointer. See main.i. 1926143Snate@binkert.org */ 1936143Snate@binkert.orgextern "C" SimObject *convertSwigSimObjectPtr(PyObject *); 1946727Ssteve.reinhardt@amd.com 1956143Snate@binkert.org 1967674Snate@binkert.orgSimObject * 1977674Snate@binkert.orgresolveSimObject(const string &name) 1985604Snate@binkert.org{ 1996143Snate@binkert.org PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str()); 2006143Snate@binkert.org if (pyPtr == NULL) { 2016143Snate@binkert.org PyErr_Print(); 2024762Snate@binkert.org panic("resolveSimObject: failure on call to Python for %s", name); 2036143Snate@binkert.org } 2044762Snate@binkert.org 2054762Snate@binkert.org SimObject *simObj = convertSwigSimObjectPtr(pyPtr); 2064762Snate@binkert.org if (simObj == NULL) 2076143Snate@binkert.org panic("resolveSimObject: failure on pointer conversion for %s", name); 2086143Snate@binkert.org 2094762Snate@binkert.org return simObj; 2108233Snate@binkert.org} 2118233Snate@binkert.org 2128233Snate@binkert.org 2138233Snate@binkert.org/** 2146143Snate@binkert.org * Load config.ini into C++ database. Exported to Python via SWIG; 2156143Snate@binkert.org * invoked from m5.instantiate(). 2164762Snate@binkert.org */ 2176143Snate@binkert.orgvoid 2184762Snate@binkert.orgloadIniFile(PyObject *_resolveFunc) 2196143Snate@binkert.org{ 2204762Snate@binkert.org resolveFunc = _resolveFunc; 2216143Snate@binkert.org configStream = simout.find("config.out"); 2228233Snate@binkert.org 2238233Snate@binkert.org // The configuration database is now complete; start processing it. 2248233Snate@binkert.org inifile.load(simout.resolve("config.ini")); 2256143Snate@binkert.org 2266143Snate@binkert.org // Initialize statistics database 2276143Snate@binkert.org Stats::InitSimStats(); 2286143Snate@binkert.org} 2296143Snate@binkert.org 2306143Snate@binkert.org 2316143Snate@binkert.org/** 2326143Snate@binkert.org * Look up a MemObject port. Helper function for connectPorts(). 2338233Snate@binkert.org */ 2348233Snate@binkert.orgPort * 235955SN/AlookupPort(SimObject *so, const std::string &name, int i) 2369396Sandreas.hansson@arm.com{ 2379396Sandreas.hansson@arm.com MemObject *mo = dynamic_cast<MemObject *>(so); 2389396Sandreas.hansson@arm.com if (mo == NULL) { 2399396Sandreas.hansson@arm.com warn("error casting SimObject %s to MemObject", so->name()); 2409396Sandreas.hansson@arm.com return NULL; 2419396Sandreas.hansson@arm.com } 2429396Sandreas.hansson@arm.com 2439396Sandreas.hansson@arm.com Port *p = mo->getPort(name, i); 2449396Sandreas.hansson@arm.com if (p == NULL) 2459396Sandreas.hansson@arm.com warn("error looking up port %s on object %s", name, so->name()); 2469396Sandreas.hansson@arm.com return p; 2479396Sandreas.hansson@arm.com} 2489396Sandreas.hansson@arm.com 2499396Sandreas.hansson@arm.com 2509396Sandreas.hansson@arm.com/** 2519396Sandreas.hansson@arm.com * Connect the described MemObject ports. Called from Python via SWIG. 2528235Snate@binkert.org */ 2538235Snate@binkert.orgint 2546143Snate@binkert.orgconnectPorts(SimObject *o1, const std::string &name1, int i1, 2558235Snate@binkert.org SimObject *o2, const std::string &name2, int i2) 2569003SAli.Saidi@ARM.com{ 2578235Snate@binkert.org Port *p1 = lookupPort(o1, name1, i1); 2588235Snate@binkert.org Port *p2 = lookupPort(o2, name2, i2); 2598235Snate@binkert.org 2608235Snate@binkert.org if (p1 == NULL || p2 == NULL) { 2618235Snate@binkert.org warn("connectPorts: port lookup error"); 2628235Snate@binkert.org return 0; 2638235Snate@binkert.org } 2648235Snate@binkert.org 2658235Snate@binkert.org p1->setPeer(p2); 2668235Snate@binkert.org p2->setPeer(p1); 2678235Snate@binkert.org 2688235Snate@binkert.org return 1; 2698235Snate@binkert.org} 2708235Snate@binkert.org 2719003SAli.Saidi@ARM.com/** 2728235Snate@binkert.org * Do final initialization steps after object construction but before 2735584Snate@binkert.org * start of simulation. 2744382Sbinkertn@umich.edu */ 2754202Sbinkertn@umich.eduvoid 2764382Sbinkertn@umich.edufinalInit() 2774382Sbinkertn@umich.edu{ 2784382Sbinkertn@umich.edu // Parse and check all non-config-hierarchy parameters. 2799396Sandreas.hansson@arm.com ParamContext::parseAllContexts(inifile); 2805584Snate@binkert.org ParamContext::checkAllContexts(); 2814382Sbinkertn@umich.edu 2824382Sbinkertn@umich.edu // Echo all parameter settings to stats file as well. 2834382Sbinkertn@umich.edu ParamContext::showAllContexts(*configStream); 2848232Snate@binkert.org 2855192Ssaidi@eecs.umich.edu // Do a second pass to finish initializing the sim objects 2868232Snate@binkert.org SimObject::initAll(); 2878232Snate@binkert.org 2888232Snate@binkert.org // Restore checkpointed state, if any. 2895192Ssaidi@eecs.umich.edu#if 0 2908232Snate@binkert.org configHierarchy.unserializeSimObjects(); 2915192Ssaidi@eecs.umich.edu#endif 2925799Snate@binkert.org 2938232Snate@binkert.org SimObject::regAllStats(); 2945192Ssaidi@eecs.umich.edu 2955192Ssaidi@eecs.umich.edu // Check to make sure that the stats package is properly initialized 2965192Ssaidi@eecs.umich.edu Stats::check(); 2978232Snate@binkert.org 2985192Ssaidi@eecs.umich.edu // Reset to put the stats in a consistent state. 2998232Snate@binkert.org Stats::reset(); 3005192Ssaidi@eecs.umich.edu 3015192Ssaidi@eecs.umich.edu SimStartup(); 3025192Ssaidi@eecs.umich.edu} 3035192Ssaidi@eecs.umich.edu 3044382Sbinkertn@umich.edu 3054382Sbinkertn@umich.edu/** Simulate for num_cycles additional cycles. If num_cycles is -1 3064382Sbinkertn@umich.edu * (the default), do not limit simulation; some other event must 3072667Sstever@eecs.umich.edu * terminate the loop. Exported to Python via SWIG. 3082667Sstever@eecs.umich.edu * @return The SimLoopExitEvent that caused the loop to exit. 3092667Sstever@eecs.umich.edu */ 3102667Sstever@eecs.umich.eduSimLoopExitEvent * 3112667Sstever@eecs.umich.edusimulate(Tick num_cycles = MaxTick) 3122667Sstever@eecs.umich.edu{ 3135742Snate@binkert.org warn("Entering event queue @ %d. Starting simulation...\n", curTick); 3145742Snate@binkert.org 3155742Snate@binkert.org if (num_cycles < 0) 3165793Snate@binkert.org fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); 3178334Snate@binkert.org else if (curTick + num_cycles < 0) //Overflow 3185793Snate@binkert.org num_cycles = MaxTick; 3195793Snate@binkert.org else 3205793Snate@binkert.org num_cycles = curTick + num_cycles; 3214382Sbinkertn@umich.edu 3224762Snate@binkert.org Event *limit_event = schedExitSimLoop("simulate() limit reached", 3235344Sstever@gmail.com num_cycles); 3244382Sbinkertn@umich.edu 3255341Sstever@gmail.com while (1) { 3265742Snate@binkert.org // there should always be at least one event (the SimLoopExitEvent 3275742Snate@binkert.org // we just scheduled) in the queue 3285742Snate@binkert.org assert(!mainEventQueue.empty()); 3295742Snate@binkert.org assert(curTick <= mainEventQueue.nextTick() && 3305742Snate@binkert.org "event scheduled in the past"); 3314762Snate@binkert.org 3325742Snate@binkert.org // forward current cycle to the time of the first event on the 3335742Snate@binkert.org // queue 3347722Sgblack@eecs.umich.edu curTick = mainEventQueue.nextTick(); 3355742Snate@binkert.org Event *exit_event = mainEventQueue.serviceOne(); 3365742Snate@binkert.org if (exit_event != NULL) { 3375742Snate@binkert.org // hit some kind of exit event; return to Python 3385742Snate@binkert.org // event must be subclass of SimLoopExitEvent... 3398242Sbradley.danofsky@amd.com SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); 3408242Sbradley.danofsky@amd.com if (se_event == NULL) 3418242Sbradley.danofsky@amd.com panic("Bogus exit event class!"); 3428242Sbradley.danofsky@amd.com 3435341Sstever@gmail.com // if we didn't hit limit_event, delete it 3445742Snate@binkert.org if (se_event != limit_event) { 3457722Sgblack@eecs.umich.edu assert(limit_event->scheduled()); 3464773Snate@binkert.org limit_event->deschedule(); 3476108Snate@binkert.org delete limit_event; 3481858SN/A } 3491085SN/A 3506658Snate@binkert.org return se_event; 3516658Snate@binkert.org } 3527673Snate@binkert.org 3536658Snate@binkert.org if (async_event) { 3546658Snate@binkert.org async_event = false; 3556658Snate@binkert.org if (async_dump) { 3566658Snate@binkert.org async_dump = false; 3576658Snate@binkert.org 3586658Snate@binkert.org using namespace Stats; 3596658Snate@binkert.org SetupEvent(Dump, curTick); 3607673Snate@binkert.org } 3617673Snate@binkert.org 3627673Snate@binkert.org if (async_dumpreset) { 3637673Snate@binkert.org async_dumpreset = false; 3647673Snate@binkert.org 3657673Snate@binkert.org using namespace Stats; 3667673Snate@binkert.org SetupEvent(Dump | Reset, curTick); 3676658Snate@binkert.org } 3687673Snate@binkert.org 3697673Snate@binkert.org if (async_exit) { 3707673Snate@binkert.org async_exit = false; 3717673Snate@binkert.org exitSimLoop("user interrupt received"); 3727673Snate@binkert.org } 3737673Snate@binkert.org 3749048SAli.Saidi@ARM.com if (async_io || async_alarm) { 3757673Snate@binkert.org async_io = false; 3767673Snate@binkert.org async_alarm = false; 3777673Snate@binkert.org pollQueue.service(); 3787673Snate@binkert.org } 3796658Snate@binkert.org } 3807756SAli.Saidi@ARM.com } 3817816Ssteve.reinhardt@amd.com 3826658Snate@binkert.org // not reached... only exit is return on SimLoopExitEvent 3834382Sbinkertn@umich.edu} 3844382Sbinkertn@umich.edu 3854762Snate@binkert.orgEvent * 3864762Snate@binkert.orgcreateCountedDrain() 3874762Snate@binkert.org{ 3886654Snate@binkert.org return new CountedDrainEvent(); 3896654Snate@binkert.org} 3905517Snate@binkert.org 3915517Snate@binkert.orgvoid 3925517Snate@binkert.orgcleanupCountedDrain(Event *counted_drain) 3935517Snate@binkert.org{ 3945517Snate@binkert.org CountedDrainEvent *event = 3955517Snate@binkert.org dynamic_cast<CountedDrainEvent *>(counted_drain); 3965517Snate@binkert.org if (event == NULL) { 3975517Snate@binkert.org fatal("Called cleanupCountedDrain() on an event that was not " 3985517Snate@binkert.org "a CountedDrainEvent."); 3995517Snate@binkert.org } 4005517Snate@binkert.org assert(event->getCount() == 0); 4015517Snate@binkert.org delete event; 4025517Snate@binkert.org} 4035517Snate@binkert.org 4045517Snate@binkert.orgvoid 4055517Snate@binkert.orgserializeAll(const std::string &cpt_dir) 4065517Snate@binkert.org{ 4076654Snate@binkert.org Serializable::serializeAll(cpt_dir); 4085517Snate@binkert.org} 4095517Snate@binkert.org 4105517Snate@binkert.orgvoid 4115517Snate@binkert.orgunserializeAll(const std::string &cpt_dir) 4125517Snate@binkert.org{ 4135517Snate@binkert.org Serializable::unserializeAll(cpt_dir); 4145517Snate@binkert.org} 4155517Snate@binkert.org 4166143Snate@binkert.org/** 4176654Snate@binkert.org * Queue of C++ callbacks to invoke on simulator exit. 4185517Snate@binkert.org */ 4195517Snate@binkert.orgCallbackQueue& 4205517Snate@binkert.orgexitCallbacks() 4215517Snate@binkert.org{ 4225517Snate@binkert.org static CallbackQueue theQueue; 4235517Snate@binkert.org return theQueue; 4245517Snate@binkert.org} 4255517Snate@binkert.org 4265517Snate@binkert.org/** 4275517Snate@binkert.org * Register an exit callback. 4285517Snate@binkert.org */ 4295517Snate@binkert.orgvoid 4305517Snate@binkert.orgregisterExitCallback(Callback *callback) 4315517Snate@binkert.org{ 4326654Snate@binkert.org exitCallbacks().add(callback); 4336654Snate@binkert.org} 4345517Snate@binkert.org 4355517Snate@binkert.orgBaseCPU * 4366143Snate@binkert.orgconvertToBaseCPUPtr(SimObject *obj) 4376143Snate@binkert.org{ 4386143Snate@binkert.org BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj); 4396727Ssteve.reinhardt@amd.com 4405517Snate@binkert.org if (ptr == NULL) 4416727Ssteve.reinhardt@amd.com warn("Casting to BaseCPU pointer failed"); 4425517Snate@binkert.org return ptr; 4435517Snate@binkert.org} 4445517Snate@binkert.org 4456654Snate@binkert.orgSystem * 4466654Snate@binkert.orgconvertToSystemPtr(SimObject *obj) 4477673Snate@binkert.org{ 4486654Snate@binkert.org System *ptr = dynamic_cast<System *>(obj); 4496654Snate@binkert.org 4506654Snate@binkert.org if (ptr == NULL) 4516654Snate@binkert.org warn("Casting to System pointer failed"); 4525517Snate@binkert.org return ptr; 4535517Snate@binkert.org} 4545517Snate@binkert.org 4556143Snate@binkert.org 4565517Snate@binkert.org/** 4574762Snate@binkert.org * Do C++ simulator exit processing. Exported to SWIG to be invoked 4585517Snate@binkert.org * when simulator terminates via Python's atexit mechanism. 4595517Snate@binkert.org */ 4606143Snate@binkert.orgvoid 4616143Snate@binkert.orgdoExitCleanup() 4625517Snate@binkert.org{ 4635517Snate@binkert.org exitCallbacks().process(); 4645517Snate@binkert.org exitCallbacks().clear(); 4655517Snate@binkert.org 4665517Snate@binkert.org cout.flush(); 4675517Snate@binkert.org 4685517Snate@binkert.org ParamContext::cleanupAllContexts(); 4695517Snate@binkert.org 4705517Snate@binkert.org // print simulation stats 4719338SAndreas.Sandberg@arm.com Stats::DumpNow(); 4729338SAndreas.Sandberg@arm.com} 4739338SAndreas.Sandberg@arm.com