changeset e215ee9db617 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=e215ee9db617
description:
        RubyPort and Sequencer: Fix draining

        Fix the drain functionality of the RubyPort to only call drain on child 
ports
        during a system-wide drain process, instead of calling each time that a
        ruby_hit_callback is executed.

        This fixes the issue of the RubyPort ports being reawakened during the 
drain
        simulation, possibly with work they didn't previously have to complete. 
If
        they have new work, they may call process on the drain event that they 
had
        not registered work for, causing an assertion failure when completing 
the
        drain event.

        Also, in RubyPort, set the drainEvent to NULL when there are no events
        to be drained. If not set to NULL, the drain loop can result in stale
        drainEvents used.

diffstat:

 src/mem/ruby/system/RubyPort.cc  |  36 ++++++++++++++++++------------------
 src/mem/ruby/system/RubyPort.hh  |   2 +-
 src/mem/ruby/system/Sequencer.cc |   4 +++-
 3 files changed, 22 insertions(+), 20 deletions(-)

diffs (104 lines):

diff -r 4672c12307a7 -r e215ee9db617 src/mem/ruby/system/RubyPort.cc
--- a/src/mem/ruby/system/RubyPort.cc   Fri Sep 21 11:48:14 2012 -0400
+++ b/src/mem/ruby/system/RubyPort.cc   Sun Sep 23 13:57:08 2012 -0500
@@ -527,7 +527,7 @@
 {
     //If we weren't able to drain before, we might be able to now.
     if (drainEvent != NULL) {
-        unsigned int drainCount = getDrainCount(drainEvent);
+        unsigned int drainCount = outstandingCount();
         DPRINTF(Drain, "Drain count: %u\n", drainCount);
         if (drainCount == 0) {
             DPRINTF(Drain, "RubyPort done draining, processing drain event\n");
@@ -539,21 +539,9 @@
 }
 
 unsigned int
-RubyPort::getDrainCount(Event *de)
+RubyPort::getChildDrainCount(Event *de)
 {
     int count = 0;
-    //
-    // If the sequencer is not empty, then requests need to drain.
-    // The outstandingCount is the number of requests outstanding and thus the
-    // number of times M5's timing port will process the drain event.
-    //
-    count += outstandingCount();
-
-    DPRINTF(Config, "outstanding count %d\n", outstandingCount());
-
-    // To simplify the draining process, the sequencer's deadlock detection
-    // event should have been descheduled.
-    assert(isDeadlockEventScheduled() == false);
 
     if (pio_port.isConnected()) {
         count += pio_port.drain(de);
@@ -583,19 +571,31 @@
         descheduleDeadlockEvent();
     }
 
-    int count = getDrainCount(de);
+    //
+    // If the RubyPort is not empty, then it needs to clear all outstanding
+    // requests before it should call drainEvent->process()
+    //
+    DPRINTF(Config, "outstanding count %d\n", outstandingCount());
+    bool need_drain = outstandingCount() > 0;
+
+    //
+    // Also, get the number of child ports that will also need to clear
+    // their buffered requests before they call drainEvent->process()
+    //
+    unsigned int child_drain_count = getChildDrainCount(de);
 
     // Set status
-    if (count != 0) {
+    if (need_drain) {
         drainEvent = de;
 
         DPRINTF(Drain, "RubyPort not drained\n");
         changeState(SimObject::Draining);
-        return count;
+        return child_drain_count + 1;
     }
 
+    drainEvent = NULL;
     changeState(SimObject::Drained);
-    return 0;
+    return child_drain_count;
 }
 
 void
diff -r 4672c12307a7 -r e215ee9db617 src/mem/ruby/system/RubyPort.hh
--- a/src/mem/ruby/system/RubyPort.hh   Fri Sep 21 11:48:14 2012 -0400
+++ b/src/mem/ruby/system/RubyPort.hh   Sun Sep 23 13:57:08 2012 -0500
@@ -166,7 +166,7 @@
         }
     }
 
-    unsigned int getDrainCount(Event *de);
+    unsigned int getChildDrainCount(Event *de);
 
     uint16_t m_port_id;
     uint64_t m_request_cnt;
diff -r 4672c12307a7 -r e215ee9db617 src/mem/ruby/system/Sequencer.cc
--- a/src/mem/ruby/system/Sequencer.cc  Fri Sep 21 11:48:14 2012 -0400
+++ b/src/mem/ruby/system/Sequencer.cc  Sun Sep 23 13:57:08 2012 -0500
@@ -85,6 +85,8 @@
 void
 Sequencer::wakeup()
 {
+    assert(getState() != SimObject::Draining);
+
     // Check for deadlock of any of the requests
     Time current_time = g_system_ptr->getTime();
 
@@ -207,7 +209,7 @@
         (m_writeRequestTable.size() + m_readRequestTable.size()));
 
     // See if we should schedule a deadlock check
-    if (deadlockCheckEvent.scheduled() == false) {
+    if (!deadlockCheckEvent.scheduled() && getState() != SimObject::Draining) {
         schedule(deadlockCheckEvent,
             g_system_ptr->clockPeriod() * m_deadlock_threshold + curTick());
     }
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to