summaryrefslogtreecommitdiff
path: root/src/mem
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem')
-rw-r--r--src/mem/ruby/system/RubyPort.cc60
-rw-r--r--src/mem/ruby/system/RubyPort.hh17
-rw-r--r--src/mem/ruby/system/Sequencer.cc1
-rw-r--r--src/mem/ruby/system/Sequencer.py1
4 files changed, 53 insertions, 26 deletions
diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc
index b2fb8d72d..95a83873c 100644
--- a/src/mem/ruby/system/RubyPort.cc
+++ b/src/mem/ruby/system/RubyPort.cc
@@ -11,7 +11,7 @@
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
- * Copyright (c) 2009 Advanced Micro Devices, Inc.
+ * Copyright (c) 2009-2013 Advanced Micro Devices, Inc.
* Copyright (c) 2011 Mark D. Hill and David A. Wood
* All rights reserved.
*
@@ -58,7 +58,8 @@ RubyPort::RubyPort(const Params *p)
pioSlavePort(csprintf("%s.pio-slave-port", name()), this),
memMasterPort(csprintf("%s.mem-master-port", name()), this),
memSlavePort(csprintf("%s-mem-slave-port", name()), this,
- p->ruby_system->getAccessBackingStore(), -1),
+ p->ruby_system->getAccessBackingStore(), -1,
+ p->no_retry_on_stall),
gotAddrRanges(p->port_master_connection_count)
{
assert(m_version != -1);
@@ -66,7 +67,8 @@ RubyPort::RubyPort(const Params *p)
// create the slave ports based on the number of connected ports
for (size_t i = 0; i < p->port_slave_connection_count; ++i) {
slave_ports.push_back(new MemSlavePort(csprintf("%s.slave%d", name(),
- i), this, p->ruby_system->getAccessBackingStore(), i));
+ i), this, p->ruby_system->getAccessBackingStore(),
+ i, p->no_retry_on_stall));
}
// create the master ports based on the number of connected ports
@@ -156,9 +158,11 @@ RubyPort::MemMasterPort::MemMasterPort(const std::string &_name,
}
RubyPort::MemSlavePort::MemSlavePort(const std::string &_name, RubyPort *_port,
- bool _access_backing_store, PortID id)
+ bool _access_backing_store, PortID id,
+ bool _no_retry_on_stall)
: QueuedSlavePort(_name, _port, queue, id), queue(*_port, *this),
- access_backing_store(_access_backing_store)
+ access_backing_store(_access_backing_store),
+ no_retry_on_stall(_no_retry_on_stall)
{
DPRINTF(RubyPort, "Created slave memport on ruby sequencer %s\n", _name);
}
@@ -267,21 +271,31 @@ RubyPort::MemSlavePort::recvTimingReq(PacketPtr pkt)
return true;
}
- //
- // Unless one is using the ruby tester, record the stalled M5 port for
- // later retry when the sequencer becomes free.
- //
- if (!ruby_port->m_usingRubyTester) {
- ruby_port->addToRetryList(this);
- }
DPRINTF(RubyPort, "Request for address %#x did not issued because %s\n",
pkt->getAddr(), RequestStatus_to_string(requestStatus));
+ addToRetryList();
+
return false;
}
void
+RubyPort::MemSlavePort::addToRetryList()
+{
+ RubyPort *ruby_port = static_cast<RubyPort *>(&owner);
+
+ //
+ // Unless the requestor do not want retries (e.g., the Ruby tester),
+ // record the stalled M5 port for later retry when the sequencer
+ // becomes free.
+ //
+ if (!no_retry_on_stall && !ruby_port->onRetryList(this)) {
+ ruby_port->addToRetryList(this);
+ }
+}
+
+void
RubyPort::MemSlavePort::recvFunctional(PacketPtr pkt)
{
DPRINTF(RubyPort, "Functional access for address: %#x\n", pkt->getAddr());
@@ -356,31 +370,33 @@ RubyPort::ruby_hit_callback(PacketPtr pkt)
port->hitCallback(pkt);
+ trySendRetries();
+}
+
+void
+RubyPort::trySendRetries()
+{
//
// If we had to stall the MemSlavePorts, wake them up because the sequencer
// likely has free resources now.
//
if (!retryList.empty()) {
- //
- // Record the current list of ports to retry on a temporary list before
- // calling sendRetry on those ports. sendRetry will cause an
- // immediate retry, which may result in the ports being put back on the
- // list. Therefore we want to clear the retryList before calling
- // sendRetry.
- //
+ // Record the current list of ports to retry on a temporary list
+ // before calling sendRetryReq on those ports. sendRetryReq will cause
+ // an immediate retry, which may result in the ports being put back on
+ // the list. Therefore we want to clear the retryList before calling
+ // sendRetryReq.
std::vector<MemSlavePort *> curRetryList(retryList);
retryList.clear();
for (auto i = curRetryList.begin(); i != curRetryList.end(); ++i) {
DPRINTF(RubyPort,
- "Sequencer may now be free. SendRetry to port %s\n",
+ "Sequencer may now be free. SendRetry to port %s\n",
(*i)->name());
(*i)->sendRetryReq();
}
}
-
- testDrainComplete();
}
void
diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh
index 58d2558dd..07e0fde5a 100644
--- a/src/mem/ruby/system/RubyPort.hh
+++ b/src/mem/ruby/system/RubyPort.hh
@@ -11,7 +11,7 @@
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
- * Copyright (c) 2009 Advanced Micro Devices, Inc.
+ * Copyright (c) 2009-2013 Advanced Micro Devices, Inc.
* Copyright (c) 2011 Mark D. Hill and David A. Wood
* All rights reserved.
*
@@ -76,10 +76,12 @@ class RubyPort : public MemObject
private:
RespPacketQueue queue;
bool access_backing_store;
+ bool no_retry_on_stall;
public:
MemSlavePort(const std::string &_name, RubyPort *_port,
- bool _access_backing_store, PortID id);
+ bool _access_backing_store,
+ PortID id, bool _no_retry_on_stall);
void hitCallback(PacketPtr pkt);
void evictionCallback(Addr address);
@@ -94,6 +96,8 @@ class RubyPort : public MemObject
AddrRangeList getAddrRanges() const
{ AddrRangeList ranges; return ranges; }
+ void addToRetryList();
+
private:
bool isPhysMemAddress(Addr addr) const;
};
@@ -164,6 +168,7 @@ class RubyPort : public MemObject
DrainState drain() override;
protected:
+ void trySendRetries();
void ruby_hit_callback(PacketPtr pkt);
void testDrainComplete();
void ruby_eviction_callback(Addr address);
@@ -186,10 +191,14 @@ class RubyPort : public MemObject
System* system;
private:
+ bool onRetryList(MemSlavePort * port)
+ {
+ return (std::find(retryList.begin(), retryList.end(), port) !=
+ retryList.end());
+ }
void addToRetryList(MemSlavePort * port)
{
- if (std::find(retryList.begin(), retryList.end(), port) !=
- retryList.end()) return;
+ if (onRetryList(port)) return;
retryList.push_back(port);
}
diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc
index 26db6b6f8..50418c700 100644
--- a/src/mem/ruby/system/Sequencer.cc
+++ b/src/mem/ruby/system/Sequencer.cc
@@ -491,6 +491,7 @@ Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data,
rs->m_cache_recorder->enqueueNextFlushRequest();
} else {
ruby_hit_callback(pkt);
+ testDrainComplete();
}
}
diff --git a/src/mem/ruby/system/Sequencer.py b/src/mem/ruby/system/Sequencer.py
index 7494986e9..7c90eb29c 100644
--- a/src/mem/ruby/system/Sequencer.py
+++ b/src/mem/ruby/system/Sequencer.py
@@ -45,6 +45,7 @@ class RubyPort(MemObject):
mem_slave_port = SlavePort("Ruby memory port")
using_ruby_tester = Param.Bool(False, "")
+ no_retry_on_stall = Param.Bool(False, "")
ruby_system = Param.RubySystem(Parent.any, "")
system = Param.System(Parent.any, "system object")
support_data_reqs = Param.Bool(True, "data cache requests supported")