ARM: Implement WFE/WFI/SEV semantics.
[gem5.git] / src / sim / sim_events.cc
index c2bdca9dfc488d86bd474ed935ac959d1aba7c3c..aac844429767ccc18e30e102baf3350cd6ad96a4 100644 (file)
@@ -24,6 +24,8 @@
  * 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 <string>
 #include "base/callback.hh"
 #include "base/hostinfo.hh"
 #include "sim/eventq.hh"
-#include "sim/param.hh"
 #include "sim/sim_events.hh"
 #include "sim/sim_exit.hh"
-#include "sim/startup.hh"
 #include "sim/stats.hh"
 
 using namespace std;
 
+SimLoopExitEvent::SimLoopExitEvent(const std::string &_cause, int c, Tick r)
+    : Event(Sim_Exit_Pri), cause(_cause), code(c), repeat(r)
+{
+    setFlags(IsExitEvent);
+}
+
+
 //
 // handle termination event
 //
 void
-SimExitEvent::process()
+SimLoopExitEvent::process()
 {
-    // This event does not autodelete because exitNow may be called,
-    // and the function will never be allowed to finish.
-    if (theQueue() == &mainEventQueue) {
-        string _cause = cause;
-        int _code = code;
-        delete this;
-        exitNow(_cause, _code);
-    } else {
-        new SimExitEvent(cause, code);
+    // if this got scheduled on a different queue (e.g. the committed
+    // instruction queue) then make a corresponding event on the main
+    // queue.
+    if (!getFlags(IsMainQueue)) {
+        exitSimLoop(cause, code);
         delete this;
     }
+
+    // otherwise do nothing... the IsExitEvent flag takes care of
+    // exiting the simulation loop and returning this object to Python
+
+    // but if you are doing this on intervals, don't forget to make another
+    if (repeat) {
+        assert(getFlags(IsMainQueue));
+        mainEventQueue.schedule(this, curTick() + repeat);
+    }
 }
 
 
 const char *
-SimExitEvent::description()
+SimLoopExitEvent::description() const
+{
+    return "simulation loop exit";
+}
+
+void
+exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat)
 {
-    return "simulation termination";
+    Event *event = new SimLoopExitEvent(message, exit_code, repeat);
+    mainEventQueue.schedule(event, when);
+}
+
+CountedDrainEvent::CountedDrainEvent()
+    : count(0)
+{ }
+
+void
+CountedDrainEvent::process()
+{
+    if (--count == 0)
+        exitSimLoop("Finished drain", 0);
 }
 
 //
 // constructor: automatically schedules at specified time
 //
-CountedExitEvent::CountedExitEvent(EventQueue *q, const std::string &_cause,
-                                   Tick _when, int &_downCounter)
-    : Event(q, Sim_Exit_Pri),
-      cause(_cause),
-      downCounter(_downCounter)
+CountedExitEvent::CountedExitEvent(const std::string &_cause, int &counter)
+    : Event(Sim_Exit_Pri), cause(_cause), downCounter(counter)
 {
     // catch stupid mistakes
     assert(downCounter > 0);
-
-    schedule(_when);
 }
 
 
@@ -88,61 +113,13 @@ void
 CountedExitEvent::process()
 {
     if (--downCounter == 0) {
-        new SimExitEvent(cause, 0);
+        exitSimLoop(cause, 0);
     }
 }
 
 
 const char *
-CountedExitEvent::description()
+CountedExitEvent::description() const
 {
     return "counted exit";
 }
-
-#ifdef CHECK_SWAP_CYCLES
-new CheckSwapEvent(&mainEventQueue, CHECK_SWAP_CYCLES);
-#endif
-
-void
-CheckSwapEvent::process()
-{
-    /*  Check the amount of free swap space  */
-    long swap;
-
-    /*  returns free swap in KBytes  */
-    swap = procInfo("/proc/meminfo", "SwapFree:");
-
-    if (swap < 1000)
-        ccprintf(cerr, "\a\a\aWarning! Swap space is low (%d)\n", swap);
-
-    if (swap < 100) {
-        cerr << "\a\aAborting Simulation! Inadequate swap space!\n\n";
-        new SimExitEvent("Lack of swap space");
-    }
-
-    schedule(curTick + interval);
-}
-
-const char *
-CheckSwapEvent::description()
-{
-    return "check swap";
-}
-
-//
-// handle progress event: print message and reschedule
-//
-void
-ProgressEvent::process()
-{
-    DPRINTFN("ProgressEvent\n");
-    // reschedule for next interval
-    schedule(curTick + interval);
-}
-
-
-const char *
-ProgressEvent::description()
-{
-    return "progress message";
-}