28,30c28
< * Authors: Steve Raasch
< * Nathan Binkert
< * Steve Reinhardt
---
> * Authors: Nathan Binkert
33,36c31
< ///
< /// @file sim/main.cc
< ///
< #include <Python.h> // must be before system headers... see Python docs
---
> #include <Python.h>
38,46c33
< #include <sys/types.h>
< #include <sys/stat.h>
< #include <errno.h>
< #include <libgen.h>
< #include <stdlib.h>
< #include <signal.h>
< #include <getopt.h>
<
< #include <list>
---
> #include <iostream>
48d34
< #include <vector>
50,51c36
< #include "base/callback.hh"
< #include "base/inifile.hh"
---
> #include "base/cprintf.hh"
53,58d37
< #include "base/output.hh"
< #include "base/pollevent.hh"
< #include "base/statistics.hh"
< #include "base/stats/output.hh"
< #include "base/str.hh"
< #include "base/time.hh"
60,63d38
< #include "cpu/base.hh"
< #include "cpu/smt.hh"
< #include "mem/mem_object.hh"
< #include "mem/port.hh"
66d40
< #include "sim/builder.hh"
68,74d41
< #include "sim/serialize.hh"
< #include "sim/sim_events.hh"
< #include "sim/sim_exit.hh"
< #include "sim/sim_object.hh"
< #include "sim/system.hh"
< #include "sim/stat_control.hh"
< #include "sim/stats.hh"
79,87d45
< // See async.h.
< volatile bool async_event = false;
< volatile bool async_dump = false;
< volatile bool async_dumpreset = false;
< volatile bool async_exit = false;
< volatile bool async_io = false;
< volatile bool async_alarm = false;
< volatile bool async_exception = false;
<
93c51
< async_dump = true;
---
> async_statdump = true;
100c58,59
< async_dumpreset = true;
---
> async_statdump = true;
> async_statreset = true;
115c74
< cerr << "Program aborted at cycle " << curTick << endl;
---
> ccprintf(cerr, "Program aborted at cycle %d\n", curTick);
163,460d121
<
<
< void
< setOutputDir(const string &dir)
< {
< simout.setDirectory(dir);
< }
<
<
< IniFile inifile;
<
< SimObject *
< createSimObject(const string &name)
< {
< return SimObjectClass::createObject(inifile, name);
< }
<
<
< /**
< * Pointer to the Python function that maps names to SimObjects.
< */
< PyObject *resolveFunc = NULL;
<
< /**
< * Convert a pointer to the Python object that SWIG wraps around a C++
< * SimObject pointer back to the actual C++ pointer. See main.i.
< */
< extern "C" SimObject *convertSwigSimObjectPtr(PyObject *);
<
<
< SimObject *
< resolveSimObject(const string &name)
< {
< PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str());
< if (pyPtr == NULL) {
< PyErr_Print();
< panic("resolveSimObject: failure on call to Python for %s", name);
< }
<
< SimObject *simObj = convertSwigSimObjectPtr(pyPtr);
< if (simObj == NULL)
< panic("resolveSimObject: failure on pointer conversion for %s", name);
<
< return simObj;
< }
<
<
< /**
< * Load config.ini into C++ database. Exported to Python via SWIG;
< * invoked from m5.instantiate().
< */
< void
< loadIniFile(PyObject *_resolveFunc)
< {
< resolveFunc = _resolveFunc;
< configStream = simout.find("config.out");
<
< // The configuration database is now complete; start processing it.
< inifile.load(simout.resolve("config.ini"));
<
< // Initialize statistics database
< Stats::initSimStats();
< }
<
<
< /**
< * Look up a MemObject port. Helper function for connectPorts().
< */
< Port *
< lookupPort(SimObject *so, const std::string &name, int i)
< {
< MemObject *mo = dynamic_cast<MemObject *>(so);
< if (mo == NULL) {
< warn("error casting SimObject %s to MemObject", so->name());
< return NULL;
< }
<
< Port *p = mo->getPort(name, i);
< if (p == NULL)
< warn("error looking up port %s on object %s", name, so->name());
< return p;
< }
<
<
< /**
< * Connect the described MemObject ports. Called from Python via SWIG.
< */
< int
< connectPorts(SimObject *o1, const std::string &name1, int i1,
< SimObject *o2, const std::string &name2, int i2)
< {
< Port *p1 = lookupPort(o1, name1, i1);
< Port *p2 = lookupPort(o2, name2, i2);
<
< if (p1 == NULL || p2 == NULL) {
< warn("connectPorts: port lookup error");
< return 0;
< }
<
< p1->setPeer(p2);
< p2->setPeer(p1);
<
< return 1;
< }
<
< /**
< * Do final initialization steps after object construction but before
< * start of simulation.
< */
< void
< finalInit()
< {
< // Do a second pass to finish initializing the sim objects
< SimObject::initAll();
<
< // Restore checkpointed state, if any.
< #if 0
< configHierarchy.unserializeSimObjects();
< #endif
<
< SimObject::regAllStats();
<
< // Check to make sure that the stats package is properly initialized
< Stats::check();
<
< // Reset to put the stats in a consistent state.
< Stats::reset();
<
< SimStartup();
< }
<
< /** Simulate for num_cycles additional cycles. If num_cycles is -1
< * (the default), do not limit simulation; some other event must
< * terminate the loop. Exported to Python via SWIG.
< * @return The SimLoopExitEvent that caused the loop to exit.
< */
< SimLoopExitEvent *
< simulate(Tick num_cycles = MaxTick)
< {
< warn("Entering event queue @ %d. Starting simulation...\n", curTick);
<
< if (num_cycles < 0)
< fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles);
< else if (curTick + num_cycles < 0) //Overflow
< num_cycles = MaxTick;
< else
< num_cycles = curTick + num_cycles;
<
< Event *limit_event = schedExitSimLoop("simulate() limit reached",
< num_cycles);
<
< while (1) {
< // there should always be at least one event (the SimLoopExitEvent
< // we just scheduled) in the queue
< assert(!mainEventQueue.empty());
< assert(curTick <= mainEventQueue.nextTick() &&
< "event scheduled in the past");
<
< // forward current cycle to the time of the first event on the
< // queue
< curTick = mainEventQueue.nextTick();
< Event *exit_event = mainEventQueue.serviceOne();
< if (exit_event != NULL) {
< // hit some kind of exit event; return to Python
< // event must be subclass of SimLoopExitEvent...
< SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event);
< if (se_event == NULL)
< panic("Bogus exit event class!");
<
< // if we didn't hit limit_event, delete it
< if (se_event != limit_event) {
< assert(limit_event->scheduled());
< limit_event->deschedule();
< delete limit_event;
< }
<
< return se_event;
< }
<
< if (async_event) {
< async_event = false;
< if (async_dump) {
< async_dump = false;
< Stats::StatEvent(true, false);
< }
<
< if (async_dumpreset) {
< async_dumpreset = false;
< Stats::StatEvent(true, true);
< }
<
< if (async_exit) {
< async_exit = false;
< exitSimLoop("user interrupt received");
< }
<
< if (async_io || async_alarm) {
< async_io = false;
< async_alarm = false;
< pollQueue.service();
< }
<
< if (async_exception) {
< async_exception = false;
< return NULL;
< }
< }
< }
<
< // not reached... only exit is return on SimLoopExitEvent
< }
<
< Event *
< createCountedDrain()
< {
< return new CountedDrainEvent();
< }
<
< void
< cleanupCountedDrain(Event *counted_drain)
< {
< CountedDrainEvent *event =
< dynamic_cast<CountedDrainEvent *>(counted_drain);
< if (event == NULL) {
< fatal("Called cleanupCountedDrain() on an event that was not "
< "a CountedDrainEvent.");
< }
< assert(event->getCount() == 0);
< delete event;
< }
<
< void
< serializeAll(const std::string &cpt_dir)
< {
< Serializable::serializeAll(cpt_dir);
< }
<
< void
< unserializeAll(const std::string &cpt_dir)
< {
< Serializable::unserializeAll(cpt_dir);
< }
<
< /**
< * Queue of C++ callbacks to invoke on simulator exit.
< */
< CallbackQueue&
< exitCallbacks()
< {
< static CallbackQueue theQueue;
< return theQueue;
< }
<
< /**
< * Register an exit callback.
< */
< void
< registerExitCallback(Callback *callback)
< {
< exitCallbacks().add(callback);
< }
<
< BaseCPU *
< convertToBaseCPUPtr(SimObject *obj)
< {
< BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj);
<
< if (ptr == NULL)
< warn("Casting to BaseCPU pointer failed");
< return ptr;
< }
<
< System *
< convertToSystemPtr(SimObject *obj)
< {
< System *ptr = dynamic_cast<System *>(obj);
<
< if (ptr == NULL)
< warn("Casting to System pointer failed");
< return ptr;
< }
<
<
< /**
< * Do C++ simulator exit processing. Exported to SWIG to be invoked
< * when simulator terminates via Python's atexit mechanism.
< */
< void
< doExitCleanup()
< {
< exitCallbacks().process();
< exitCallbacks().clear();
<
< cout.flush();
<
< // print simulation stats
< Stats::dump();
< }