summaryrefslogtreecommitdiff
path: root/src/mem/ruby/system/RubyPort.cc
diff options
context:
space:
mode:
authorNilay Vaish <nilay@cs.wisc.edu>2012-01-11 13:48:48 -0600
committerNilay Vaish <nilay@cs.wisc.edu>2012-01-11 13:48:48 -0600
commitbf59a9298f6154cb85ebebabd4f45738caf29b35 (patch)
treec1fb403509108916dcb36e4d432a877d733085ab /src/mem/ruby/system/RubyPort.cc
parent3f8065290a4740baea8b9a8ebcd361b161636d56 (diff)
downloadgem5-bf59a9298f6154cb85ebebabd4f45738caf29b35.tar.xz
Ruby: Resurrect Cache Warmup Capability
This patch resurrects ruby's cache warmup capability. It essentially makes use of all the infrastructure that was added to the controllers, memories and the cache recorder.
Diffstat (limited to 'src/mem/ruby/system/RubyPort.cc')
-rw-r--r--src/mem/ruby/system/RubyPort.cc80
1 files changed, 79 insertions, 1 deletions
diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc
index d5f21c312..64faf6aed 100644
--- a/src/mem/ruby/system/RubyPort.cc
+++ b/src/mem/ruby/system/RubyPort.cc
@@ -27,11 +27,11 @@
*/
#include "cpu/testers/rubytest/RubyTester.hh"
+#include "debug/Config.hh"
#include "debug/Ruby.hh"
#include "mem/protocol/AccessPermission.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/system/RubyPort.hh"
-#include "mem/physical.hh"
RubyPort::RubyPort(const Params *p)
: MemObject(p)
@@ -51,6 +51,8 @@ RubyPort::RubyPort(const Params *p)
m_usingRubyTester = p->using_ruby_tester;
access_phys_mem = p->access_phys_mem;
+ drainEvent = NULL;
+
ruby_system = p->ruby_system;
waitingOnSequencer = false;
}
@@ -510,6 +512,82 @@ RubyPort::ruby_hit_callback(PacketPtr pkt)
(*i)->sendRetry();
}
}
+
+ testDrainComplete();
+}
+
+void
+RubyPort::testDrainComplete()
+{
+ //If we weren't able to drain before, we might be able to now.
+ if (drainEvent != NULL) {
+ unsigned int drainCount = getDrainCount(drainEvent);
+ DPRINTF(Config, "Drain count: %u\n", drainCount);
+ if (drainCount == 0) {
+ drainEvent->process();
+ // Clear the drain event once we're done with it.
+ drainEvent = NULL;
+ }
+ }
+}
+
+unsigned int
+RubyPort::getDrainCount(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 != NULL) {
+ count += pio_port->drain(de);
+ DPRINTF(Config, "count after pio check %d\n", count);
+ }
+ if (physMemPort != NULL) {
+ count += physMemPort->drain(de);
+ DPRINTF(Config, "count after physmem check %d\n", count);
+ }
+
+ for (CpuPortIter p_iter = cpu_ports.begin(); p_iter != cpu_ports.end();
+ p_iter++) {
+ M5Port* cpu_port = *p_iter;
+ count += cpu_port->drain(de);
+ DPRINTF(Config, "count after cpu port check %d\n", count);
+ }
+
+ DPRINTF(Config, "final count %d\n", count);
+
+ return count;
+}
+
+unsigned int
+RubyPort::drain(Event *de)
+{
+ if (isDeadlockEventScheduled()) {
+ descheduleDeadlockEvent();
+ }
+
+ int count = getDrainCount(de);
+
+ // Set status
+ if (count != 0) {
+ drainEvent = de;
+
+ changeState(SimObject::Draining);
+ return count;
+ }
+
+ changeState(SimObject::Drained);
+ return 0;
}
void