Factor code out of main.cc and main.i into a bunch of files
authorNathan Binkert <binkertn@umich.edu>
Sat, 3 Mar 2007 06:24:00 +0000 (22:24 -0800)
committerNathan Binkert <binkertn@umich.edu>
Sat, 3 Mar 2007 06:24:00 +0000 (22:24 -0800)
so things are organized in a more sensible manner.  Take apart
finalInit and expose the individual functions which are now
called from python.  Make checkpointing a bit easier to use.

--HG--
extra : convert_revision : f470ddabbb47103e7b4734ef753c40089f2dcd9d

20 files changed:
src/SConscript
src/python/SConscript
src/python/m5/SimObject.py
src/python/m5/__init__.py
src/python/m5/main.py
src/python/m5/params.py
src/python/swig/core.i [new file with mode: 0644]
src/python/swig/event.i
src/python/swig/pyevent.hh
src/python/swig/pyobject.cc [new file with mode: 0644]
src/python/swig/pyobject.hh [new file with mode: 0644]
src/python/swig/sim_object.i [new file with mode: 0644]
src/python/swig/stats.i
src/sim/async.cc [new file with mode: 0644]
src/sim/async.hh
src/sim/core.cc [new file with mode: 0644]
src/sim/core.hh [new file with mode: 0644]
src/sim/main.cc
src/sim/simulate.cc [new file with mode: 0644]
src/sim/simulate.hh [new file with mode: 0644]

index c93605ff7d735062fc52e482d9ad9c728b770c8e..9d7248213c18a7255115c88ef7513c6dd357589f 100644 (file)
@@ -131,15 +131,19 @@ base_sources = Split('''
         mem/cache/cache_builder.cc
 
         python/swig/init.cc
+        python/swig/core_wrap.cc
         python/swig/debug_wrap.cc
-        python/swig/main_wrap.cc
         python/swig/event_wrap.cc
         python/swig/random_wrap.cc
+        python/swig/sim_object_wrap.cc
         python/swig/stats_wrap.cc
         python/swig/trace_wrap.cc
         python/swig/pyevent.cc
+        python/swig/pyobject.cc
 
+        sim/async.cc
        sim/builder.cc
+        sim/core.cc
        sim/debug.cc
        sim/eventq.cc
        sim/faults.cc
@@ -149,6 +153,7 @@ base_sources = Split('''
        sim/serialize.cc
        sim/sim_events.cc
        sim/sim_object.cc
+        sim/simulate.cc
        sim/startup.cc
        sim/stat_control.cc
        sim/system.cc
index 8c7e479097c011de89b96d5ed737e81c2a65f724..94db1a747c527af104d2d4c147c8a4f6d0891ea0 100644 (file)
@@ -107,10 +107,11 @@ def swig_it(module):
                 '-o ${TARGETS[0]} $SOURCES')
     swig_modules.append(module)
 
-swig_it('main')
+swig_it('core')
 swig_it('debug')
 swig_it('event')
 swig_it('random')
+swig_it('sim_object')
 swig_it('stats')
 swig_it('trace')
 
index ba79d3729c727060a22f1fa2e63aebacb4d8ca8b..42266a80e3546ebc0b32cd89b8c1dd83c5cbe8e0 100644 (file)
@@ -693,7 +693,7 @@ class SimObject(object):
     def getCCObject(self):
         if not self._ccObject:
             self._ccObject = -1 # flag to catch cycles in recursion
-            self._ccObject = internal.main.createSimObject(self.path())
+            self._ccObject = internal.sim_object.createSimObject(self.path())
         elif self._ccObject == -1:
             raise RuntimeError, "%s: recursive call to getCCObject()" \
                   % self.path()
@@ -727,13 +727,13 @@ class SimObject(object):
             # i don't know if there's a better way to do this - calling
             # setMemoryMode directly from self._ccObject results in calling
             # SimObject::setMemoryMode, not the System::setMemoryMode
-            system_ptr = internal.main.convertToSystemPtr(self._ccObject)
+            system_ptr = internal.sim_object.convertToSystemPtr(self._ccObject)
             system_ptr.setMemoryMode(mode)
         for child in self._children.itervalues():
             child.changeTiming(mode)
 
     def takeOverFrom(self, old_cpu):
-        cpu_ptr = internal.main.convertToBaseCPUPtr(old_cpu._ccObject)
+        cpu_ptr = internal.sim_object.convertToBaseCPUPtr(old_cpu._ccObject)
         self._ccObject.takeOverFrom(cpu_ptr)
 
     # generate output file for 'dot' to display as a pretty graph.
index f39cc670a21c339a1905691637d0731f5a25f600..1c4a790206a6875d6e5290d54db96056723f3276 100644 (file)
 # Authors: Nathan Binkert
 #          Steve Reinhardt
 
-import atexit, os, sys
+import atexit
+import os
+import sys
 
 # import the SWIG-wrapped main C++ functions
 import internal
 # import a few SWIG-wrapped items (those that are likely to be used
 # directly by user scripts) completely into this module for
 # convenience
-from internal.main import simulate, SimLoopExitEvent
+from internal.event import SimLoopExitEvent
 
 # import the m5 compile options
 import defines
@@ -85,27 +87,60 @@ def instantiate(root):
     root.print_ini()
     sys.stdout.close() # close config.ini
     sys.stdout = sys.__stdout__ # restore to original
-    internal.main.loadIniFile(resolveSimObject)  # load config.ini into C++
+
+    # load config.ini into C++
+    internal.core.loadIniFile(resolveSimObject)
+
+    # Initialize the global statistics
+    internal.stats.initSimStats()
+
     root.createCCObject()
     root.connectPorts()
-    internal.main.finalInit()
-    noDot = True # temporary until we fix dot
-    if not noDot:
-       dot = pydot.Dot()
-       instance.outputDot(dot)
-       dot.orientation = "portrait"
-       dot.size = "8.5,11"
-       dot.ranksep="equally"
-       dot.rank="samerank"
-       dot.write("config.dot")
-       dot.write_ps("config.ps")
+
+    # Do a second pass to finish initializing the sim objects
+    internal.sim_object.initAll()
+
+    # Do a third pass to initialize statistics
+    internal.sim_object.regAllStats()
+
+    # Check to make sure that the stats package is properly initialized
+    internal.stats.check()
+
+    # Reset to put the stats in a consistent state.
+    internal.stats.reset()
+
+def doDot(root):
+    dot = pydot.Dot()
+    instance.outputDot(dot)
+    dot.orientation = "portrait"
+    dot.size = "8.5,11"
+    dot.ranksep="equally"
+    dot.rank="samerank"
+    dot.write("config.dot")
+    dot.write_ps("config.ps")
+
+need_resume = []
+need_startup = True
+def simulate(*args, **kwargs):
+    global need_resume, need_startup
+
+    if need_startup:
+        internal.core.SimStartup()
+        need_startup = False
+
+    for root in need_resume:
+        resume(root)
+    need_resume = []
+
+    return internal.event.simulate(*args, **kwargs)
 
 # Export curTick to user script.
 def curTick():
-    return internal.main.cvar.curTick
+    return internal.event.cvar.curTick
 
 # register our C++ exit callback function with Python
-atexit.register(internal.main.doExitCleanup)
+atexit.register(internal.core.doExitCleanup)
+atexit.register(internal.stats.dump)
 
 # This loops until all objects have been fully drained.
 def doDrain(root):
@@ -119,7 +154,7 @@ def doDrain(root):
 # be drained.
 def drain(root):
     all_drained = False
-    drain_event = internal.main.createCountedDrain()
+    drain_event = internal.event.createCountedDrain()
     unready_objects = root.startDrain(drain_event, True)
     # If we've got some objects that can't drain immediately, then simulate
     if unready_objects > 0:
@@ -127,7 +162,7 @@ def drain(root):
         simulate()
     else:
         all_drained = True
-    internal.main.cleanupCountedDrain(drain_event)
+    internal.event.cleanupCountedDrain(drain_event)
     return all_drained
 
 def resume(root):
@@ -135,16 +170,16 @@ def resume(root):
 
 def checkpoint(root, dir):
     if not isinstance(root, objects.Root):
-        raise TypeError, "Object is not a root object. Checkpoint must be called on a root object."
+        raise TypeError, "Checkpoint must be called on a root object."
     doDrain(root)
     print "Writing checkpoint"
-    internal.main.serializeAll(dir)
+    internal.sim_object.serializeAll(dir)
     resume(root)
 
 def restoreCheckpoint(root, dir):
     print "Restoring from checkpoint"
-    internal.main.unserializeAll(dir)
-    resume(root)
+    internal.sim_object.unserializeAll(dir)
+    need_resume.append(root)
 
 def changeToAtomic(system):
     if not isinstance(system, objects.Root) and not isinstance(system, objects.System):
@@ -152,7 +187,7 @@ def changeToAtomic(system):
         "called on a root object."
     doDrain(system)
     print "Changing memory mode to atomic"
-    system.changeTiming(internal.main.SimObject.Atomic)
+    system.changeTiming(internal.sim_object.SimObject.Atomic)
 
 def changeToTiming(system):
     if not isinstance(system, objects.Root) and not isinstance(system, objects.System):
@@ -160,7 +195,7 @@ def changeToTiming(system):
         "called on a root object."
     doDrain(system)
     print "Changing memory mode to timing"
-    system.changeTiming(internal.main.SimObject.Timing)
+    system.changeTiming(internal.sim_object.SimObject.Timing)
 
 def switchCpus(cpuList):
     print "switching cpus"
@@ -180,7 +215,7 @@ def switchCpus(cpuList):
             raise TypeError, "%s is not of type BaseCPU" % cpu
 
     # Drain all of the individual CPUs
-    drain_event = internal.main.createCountedDrain()
+    drain_event = internal.event.createCountedDrain()
     unready_cpus = 0
     for old_cpu in old_cpus:
         unready_cpus += old_cpu.startDrain(drain_event, False)
@@ -188,7 +223,7 @@ def switchCpus(cpuList):
     if unready_cpus > 0:
         drain_event.setCount(unready_cpus)
         simulate()
-    internal.main.cleanupCountedDrain(drain_event)
+    internal.event.cleanupCountedDrain(drain_event)
     # Now all of the CPUs are ready to be switched out
     for old_cpu in old_cpus:
         old_cpu._ccObject.switchOut()
@@ -198,6 +233,14 @@ def switchCpus(cpuList):
         new_cpu._ccObject.resume()
         index += 1
 
+def dumpStats():
+    print 'Dumping stats'
+    internal.stats.dump()
+
+def resetStats():
+    print 'Resetting stats'
+    internal.stats.reset()
+
 # Since we have so many mutual imports in this package, we should:
 # 1. Put all intra-package imports at the *bottom* of the file, unless
 #    they're absolutely needed before that (for top-level statements
index 37df884d0515eec8eda5ce2d802e464d93005f40..54368b91ef13f50863606215dc60137658203326 100644 (file)
@@ -240,7 +240,7 @@ def main():
         print "M5 Simulator System"
         print brief_copyright
         print
-        print "M5 compiled %s" % internal.main.cvar.compileDate;
+        print "M5 compiled %s" % internal.core.cvar.compileDate;
         print "M5 started %s" % datetime.now().ctime()
         print "M5 executing on %s" % socket.gethostname()
         print "command line:",
@@ -256,7 +256,7 @@ def main():
         usage(2)
 
     # tell C++ about output directory
-    internal.main.setOutputDir(options.outdir)
+    internal.core.setOutputDir(options.outdir)
 
     # update the system path with elements from the -p option
     sys.path[0:0] = options.path
index f8a9f9ddd1371201adca0019ffb07138d684883c..e71e1c3c52a88e06160419ed6df2702a9bf5b8ae 100644 (file)
@@ -894,9 +894,8 @@ class PortRef(object):
         if self.ccConnected: # already done this
             return
         peer = self.peer
-        internal.main.connectPorts(self.simobj.getCCObject(), self.name,
-                                   self.index, peer.simobj.getCCObject(),
-                                   peer.name, peer.index)
+        internal.sim_object.connectPorts(self.simobj.getCCObject(), self.name,
+            self.index, peer.simobj.getCCObject(), peer.name, peer.index)
         self.ccConnected = True
         peer.ccConnected = True
 
diff --git a/src/python/swig/core.i b/src/python/swig/core.i
new file mode 100644 (file)
index 0000000..1168907
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ *          Steve Reinhardt
+ */
+
+%module core
+
+%{
+#include "python/swig/pyobject.hh"
+
+#include "sim/core.hh"
+#include "sim/host.hh"
+#include "sim/startup.hh"
+
+extern const char *compileDate;
+%}
+
+%include "std_string.i"
+
+void setOutputDir(const std::string &dir);
+void loadIniFile(PyObject *);
+void SimStartup();
+void doExitCleanup();
+
+char *compileDate;
+
+%wrapper %{
+// fix up module name to reflect the fact that it's inside the m5 package
+#undef SWIG_name
+#define SWIG_name "m5.internal._core"
+%}
index 554c9fa0e99c6208bdcf6d95965d3e13e18afa75..51d7d89f0f04121c8aeb0304c4655abb39212732 100644 (file)
 %{
 #include "python/swig/pyevent.hh"
 
-inline void
-create(PyObject *object, Tick when)
-{
-    new PythonEvent(object, when);
-}
+#include "sim/sim_events.hh"
+#include "sim/sim_exit.hh"
+#include "sim/simulate.hh"
 %}
 
 %include "stdint.i"
+%include "std_string.i"
 %include "sim/host.hh"
 
-%inline %{
-extern void create(PyObject *object, Tick when);
-%}
+void create(PyObject *object, Tick when);
+
+class Event;
+class CountedDrainEvent : public Event {
+  public:
+    void setCount(int _count);
+};
+
+CountedDrainEvent *createCountedDrain();
+void cleanupCountedDrain(Event *drain_event);
+
+%immutable curTick;
+Tick curTick;
+
+// minimal definition of SimExitEvent interface to wrap
+class SimLoopExitEvent {
+  public:
+    std::string getCause();
+    int getCode();
+    SimLoopExitEvent(EventQueue *q, Tick _when, Tick _repeat,
+                     const std::string &_cause, int c = 0);
+};
+
+%exception simulate {
+    $action
+    if (!result) {
+        return NULL;
+    }
+}
+SimLoopExitEvent *simulate(Tick num_cycles = MaxTick);
+void exitSimLoop(const std::string &message, int exit_code);
+
+Tick curTick;
 
 %wrapper %{
 // fix up module name to reflect the fact that it's inside the m5 package
index 16af85a846cea5f1ea627c4745e395f499b17f2e..65e80e9e49f41d9ad4abfcd229f9798ccde811e7 100644 (file)
@@ -32,6 +32,7 @@
 #define __PYTHON_SWIG_PYEVENT_HH__
 
 #include "sim/eventq.hh"
+#include "sim/sim_events.hh"
 
 class PythonEvent : public Event
 {
@@ -45,4 +46,29 @@ class PythonEvent : public Event
     virtual void process();
 };
 
+inline void
+create(PyObject *object, Tick when)
+{
+    new PythonEvent(object, when);
+}
+
+inline Event *
+createCountedDrain()
+{
+    return new CountedDrainEvent();
+}
+
+inline 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;
+}
+
 #endif // __PYTHON_SWIG_PYEVENT_HH__
diff --git a/src/python/swig/pyobject.cc b/src/python/swig/pyobject.cc
new file mode 100644 (file)
index 0000000..11141fa
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#include <Python.h>
+
+#include <string>
+
+#include "base/inifile.hh"
+#include "base/output.hh"
+#include "mem/mem_object.hh"
+#include "mem/port.hh"
+#include "sim/builder.hh"
+#include "sim/sim_object.hh"
+
+using namespace std;
+
+/**
+ * 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;
+}
+
+inline IniFile &
+inifile()
+{
+    static IniFile inifile;
+    return 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"));
+}
+
diff --git a/src/python/swig/pyobject.hh b/src/python/swig/pyobject.hh
new file mode 100644 (file)
index 0000000..d8efc91
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#include <Python.h>
+
+#include "cpu/base.hh"
+#include "sim/host.hh"
+#include "sim/serialize.hh"
+#include "sim/sim_object.hh"
+#include "sim/system.hh"
+
+SimObject *createSimObject(const std::string &name);
+extern "C" SimObject *convertSwigSimObjectPtr(PyObject *);
+SimObject *resolveSimObject(const std::string &name);
+void loadIniFile(PyObject *_resolveFunc);
+
+
+/**
+ * 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);
+
+inline BaseCPU *
+convertToBaseCPUPtr(SimObject *obj)
+{
+    BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj);
+
+    if (ptr == NULL)
+        warn("Casting to BaseCPU pointer failed");
+    return ptr;
+}
+
+inline System *
+convertToSystemPtr(SimObject *obj)
+{
+    System *ptr = dynamic_cast<System *>(obj);
+
+    if (ptr == NULL)
+        warn("Casting to System pointer failed");
+    return ptr;
+}
+
+inline void
+initAll()
+{
+    SimObject::initAll();
+}
+
+inline void
+regAllStats()
+{
+    SimObject::regAllStats();
+}
+
+inline void
+serializeAll(const std::string &cpt_dir)
+{
+    Serializable::serializeAll(cpt_dir);
+}
+
+inline void
+unserializeAll(const std::string &cpt_dir)
+{
+    Serializable::unserializeAll(cpt_dir);
+}
+
diff --git a/src/python/swig/sim_object.i b/src/python/swig/sim_object.i
new file mode 100644 (file)
index 0000000..b2af72c
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+%module sim_object
+
+%{
+#include "python/swig/pyobject.hh"
+%}
+
+// import these files for SWIG to wrap
+%include "stdint.i"
+%include "std_string.i"
+%include "sim/host.hh"
+
+class BaseCPU;
+
+class SimObject {
+  public:
+    enum State {
+      Running,
+      Draining,
+      Drained
+    };
+
+    enum MemoryMode {
+      Invalid,
+      Atomic,
+      Timing
+    };
+
+    unsigned int drain(Event *drain_event);
+    void resume();
+    void switchOut();
+    void takeOverFrom(BaseCPU *cpu);
+    SimObject(const std::string &_name);
+};
+
+class System {
+    private:
+      System();
+    public:
+      void setMemoryMode(SimObject::MemoryMode mode);
+};
+
+SimObject *createSimObject(const std::string &name);
+
+int connectPorts(SimObject *o1, const std::string &name1, int i1,
+                 SimObject *o2, const std::string &name2, int i2);
+
+BaseCPU *convertToBaseCPUPtr(SimObject *obj);
+System *convertToSystemPtr(SimObject *obj);
+
+void serializeAll(const std::string &cpt_dir);
+void unserializeAll(const std::string &cpt_dir);
+
+void initAll();
+void regAllStats();
+
+%wrapper %{
+// fix up module name to reflect the fact that it's inside the m5 package
+#undef SWIG_name
+#define SWIG_name "m5.internal._sim_object"
+
+// Convert a pointer to the Python object that SWIG wraps around a
+// C++ SimObject pointer back to the actual C++ pointer.
+SimObject *
+convertSwigSimObjectPtr(PyObject *pyObj)
+{
+    SimObject *so;
+    if (SWIG_ConvertPtr(pyObj, (void **) &so, SWIGTYPE_p_SimObject, 0) == -1)
+        return NULL;
+    return so;
+}
+%}
index d6b39c2cb6e9b82237b348b3eaf45a015a478e3f..b7cd4715743da758ee8e7ec1401283e1bbbda6fd 100644 (file)
@@ -48,6 +48,7 @@ void initMySQL(std::string host, std::string database, std::string user = "",
 
 void StatEvent(bool dump, bool reset, Tick when = curTick, Tick repeat = 0);
 
+void check();
 void dump();
 void reset();
 
diff --git a/src/sim/async.cc b/src/sim/async.cc
new file mode 100644 (file)
index 0000000..1a8e499
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2000-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+volatile bool async_event = false;
+volatile bool async_statdump = false;
+volatile bool async_statreset = false;
+volatile bool async_exit = false;
+volatile bool async_io = false;
+volatile bool async_alarm = false;
+volatile bool async_exception = false;
+
index 6ee5eb46a1902174fcbb093c6e4cfe9e0be5d973..932f975d271c00116226ebf0c3972d2ff26e93ab 100644 (file)
@@ -43,7 +43,8 @@
 /// @note See the PollQueue object (in pollevent.hh) for the use of async_io and async_alarm.
 //@{
 extern volatile bool async_event;      ///< Some asynchronous event has happened.
-extern volatile bool async_dump;       ///< Async request to dump stats.
+extern volatile bool async_statdump;   ///< Async request to dump stats.
+extern volatile bool async_statreset;  ///< Async request to reset stats.
 extern volatile bool async_exit;       ///< Async request to exit simulator.
 extern volatile bool async_io;         ///< Async I/O request (SIGIO).
 extern volatile bool async_alarm;      ///< Async alarm event (SIGALRM).
diff --git a/src/sim/core.cc b/src/sim/core.cc
new file mode 100644 (file)
index 0000000..24cc33d
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ *          Steve Reinhardt
+ */
+
+#include <iostream>
+#include <string>
+
+#include "base/callback.hh"
+#include "base/output.hh"
+
+using namespace std;
+
+void
+setOutputDir(const string &dir)
+{
+    simout.setDirectory(dir);
+}
+
+/**
+ * Queue of C++ callbacks to invoke on simulator exit.
+ */
+inline CallbackQueue &
+exitCallbacks()
+{
+    static CallbackQueue theQueue;
+    return theQueue;
+}
+
+/**
+ * Register an exit callback.
+ */
+void
+registerExitCallback(Callback *callback)
+{
+    exitCallbacks().add(callback);
+}
+
+/**
+ * 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();
+}
diff --git a/src/sim/core.hh b/src/sim/core.hh
new file mode 100644 (file)
index 0000000..2ef21c4
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ *          Steve Reinhardt
+ */
+
+#include <Python.h>
+#include <string>
+
+#include "base/callback.hh"
+
+void setOutputDir(const std::string &dir);
+
+void registerExitCallback(Callback *callback);
+void doExitCleanup();
index 8e47ac6a08e401dea70dd42fcd53aeafd83d1bca..e7fb4039eb9a04cd0a3faf9b309938c5e819b05e 100644 (file)
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * Authors: Steve Raasch
- *          Nathan Binkert
- *          Steve Reinhardt
+ * Authors: Nathan Binkert
  */
 
-///
-/// @file sim/main.cc
-///
-#include <Python.h>    // must be before system headers... see Python docs
+#include <Python.h>
 
-#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>
 #include <string>
-#include <vector>
 
-#include "base/callback.hh"
-#include "base/inifile.hh"
+#include "base/cprintf.hh"
 #include "base/misc.hh"
-#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"
 #include "config/pythonhome.hh"
-#include "cpu/base.hh"
-#include "cpu/smt.hh"
-#include "mem/mem_object.hh"
-#include "mem/port.hh"
 #include "python/swig/init.hh"
 #include "sim/async.hh"
-#include "sim/builder.hh"
 #include "sim/host.hh"
-#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"
 #include "sim/root.hh"
 
 using namespace std;
 
-// 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;
-
 /// Stats signal handler.
 void
 dumpStatsHandler(int sigtype)
 {
     async_event = true;
-    async_dump = true;
+    async_statdump = true;
 }
 
 void
 dumprstStatsHandler(int sigtype)
 {
     async_event = true;
-    async_dumpreset = true;
+    async_statdump = true;
+    async_statreset = true;
 }
 
 /// Exit signal handler.
@@ -112,7 +71,7 @@ exitNowHandler(int sigtype)
 void
 abortHandler(int sigtype)
 {
-    cerr << "Program aborted at cycle " << curTick << endl;
+    ccprintf(cerr, "Program aborted at cycle %d\n", curTick);
 }
 
 int
@@ -160,301 +119,3 @@ main(int argc, char **argv)
     // clean up Python intepreter.
     Py_Finalize();
 }
-
-
-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();
-}
diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc
new file mode 100644 (file)
index 0000000..55cbb50
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ *          Steve Reinhardt
+ */
+
+#include "base/misc.hh"
+#include "base/pollevent.hh"
+#include "sim/stat_control.hh"
+#include "sim/async.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
+#include "sim/sim_events.hh"
+#include "sim/sim_exit.hh"
+#include "sim/simulate.hh"
+
+/** 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)
+{
+    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;
+    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;
+            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_statdump || async_statreset) {
+                async_statdump = false;
+                async_statreset = false;
+
+                Stats::StatEvent(async_statdump, async_statreset);
+            }
+
+            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
+}
+
diff --git a/src/sim/simulate.hh b/src/sim/simulate.hh
new file mode 100644 (file)
index 0000000..139bddb
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ *          Steve Reinhardt
+ */
+
+#include "sim/host.hh"
+#include "sim/sim_events.hh"
+
+SimLoopExitEvent *simulate(Tick num_cycles = MaxTick);