summaryrefslogtreecommitdiff
path: root/src/mem/ruby/system/DMASequencer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/ruby/system/DMASequencer.cc')
-rw-r--r--src/mem/ruby/system/DMASequencer.cc174
1 files changed, 3 insertions, 171 deletions
diff --git a/src/mem/ruby/system/DMASequencer.cc b/src/mem/ruby/system/DMASequencer.cc
index 2b65d675a..fc2433a6c 100644
--- a/src/mem/ruby/system/DMASequencer.cc
+++ b/src/mem/ruby/system/DMASequencer.cc
@@ -28,192 +28,24 @@
#include <memory>
-#include "debug/Config.hh"
-#include "debug/Drain.hh"
#include "debug/RubyDma.hh"
#include "debug/RubyStats.hh"
#include "mem/protocol/SequencerMsg.hh"
+#include "mem/protocol/SequencerRequestType.hh"
#include "mem/ruby/system/DMASequencer.hh"
#include "mem/ruby/system/RubySystem.hh"
-#include "sim/system.hh"
DMASequencer::DMASequencer(const Params *p)
- : MemObject(p), m_ruby_system(p->ruby_system), m_version(p->version),
- m_controller(NULL), m_mandatory_q_ptr(NULL),
- m_usingRubyTester(p->using_ruby_tester),
- slave_port(csprintf("%s.slave", name()), this, 0, p->ruby_system,
- p->ruby_system->getAccessBackingStore()),
- system(p->system), retry(false)
+ : RubyPort(p)
{
- assert(m_version != -1);
}
void
DMASequencer::init()
{
- MemObject::init();
- assert(m_controller != NULL);
- m_mandatory_q_ptr = m_controller->getMandatoryQueue();
+ RubyPort::init();
m_is_busy = false;
m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits());
-
- slave_port.sendRangeChange();
-}
-
-BaseSlavePort &
-DMASequencer::getSlavePort(const std::string &if_name, PortID idx)
-{
- // used by the CPUs to connect the caches to the interconnect, and
- // for the x86 case also the interrupt master
- if (if_name != "slave") {
- // pass it along to our super class
- return MemObject::getSlavePort(if_name, idx);
- } else {
- return slave_port;
- }
-}
-
-DMASequencer::MemSlavePort::MemSlavePort(const std::string &_name,
- DMASequencer *_port, PortID id, RubySystem* _ruby_system,
- bool _access_backing_store)
- : QueuedSlavePort(_name, _port, queue, id), queue(*_port, *this),
- m_ruby_system(_ruby_system), access_backing_store(_access_backing_store)
-{
- DPRINTF(RubyDma, "Created slave memport on ruby sequencer %s\n", _name);
-}
-
-bool
-DMASequencer::MemSlavePort::recvTimingReq(PacketPtr pkt)
-{
- DPRINTF(RubyDma, "Timing request for address %#x on port %d\n",
- pkt->getAddr(), id);
- DMASequencer *seq = static_cast<DMASequencer *>(&owner);
-
- if (pkt->cacheResponding())
- panic("DMASequencer should never see a request with the "
- "cacheResponding flag set\n");
-
- assert(isPhysMemAddress(pkt->getAddr()));
- assert(getOffset(pkt->getAddr()) + pkt->getSize() <=
- RubySystem::getBlockSizeBytes());
-
- // Submit the ruby request
- RequestStatus requestStatus = seq->makeRequest(pkt);
-
- // If the request successfully issued then we should return true.
- // Otherwise, we need to tell the port to retry at a later point
- // and return false.
- if (requestStatus == RequestStatus_Issued) {
- DPRINTF(RubyDma, "Request %s 0x%x issued\n", pkt->cmdString(),
- pkt->getAddr());
- return true;
- }
-
- // Unless one is using the ruby tester, record the stalled M5 port for
- // later retry when the sequencer becomes free.
- if (!seq->m_usingRubyTester) {
- seq->retry = true;
- }
-
- DPRINTF(RubyDma, "Request for address %#x did not issued because %s\n",
- pkt->getAddr(), RequestStatus_to_string(requestStatus));
-
- return false;
-}
-
-void
-DMASequencer::ruby_hit_callback(PacketPtr pkt)
-{
- DPRINTF(RubyDma, "Hit callback for %s 0x%x\n", pkt->cmdString(),
- pkt->getAddr());
-
- // The packet was destined for memory and has not yet been turned
- // into a response
- assert(system->isMemAddr(pkt->getAddr()));
- assert(pkt->isRequest());
- slave_port.hitCallback(pkt);
-
- // If we had to stall the slave ports, wake it up because
- // the sequencer likely has free resources now.
- if (retry) {
- retry = false;
- DPRINTF(RubyDma,"Sequencer may now be free. SendRetry to port %s\n",
- slave_port.name());
- slave_port.sendRetryReq();
- }
-
- testDrainComplete();
-}
-
-void
-DMASequencer::testDrainComplete()
-{
- //If we weren't able to drain before, we might be able to now.
- if (drainState() == DrainState::Draining) {
- unsigned int drainCount = outstandingCount();
- DPRINTF(Drain, "Drain count: %u\n", drainCount);
- if (drainCount == 0) {
- DPRINTF(Drain, "DMASequencer done draining, signaling drain done\n");
- signalDrainDone();
- }
- }
-}
-
-DrainState
-DMASequencer::drain()
-{
- if (isDeadlockEventScheduled()) {
- descheduleDeadlockEvent();
- }
-
- // If the DMASequencer is not empty, then it needs to clear all outstanding
- // requests before it should call signalDrainDone()
- DPRINTF(Config, "outstanding count %d\n", outstandingCount());
-
- // Set status
- if (outstandingCount() > 0) {
- DPRINTF(Drain, "DMASequencer not drained\n");
- return DrainState::Draining;
- } else {
- return DrainState::Drained;
- }
-}
-
-void
-DMASequencer::MemSlavePort::hitCallback(PacketPtr pkt)
-{
- bool needsResponse = pkt->needsResponse();
- assert(!pkt->isLLSC());
- assert(!pkt->isFlush());
-
- DPRINTF(RubyDma, "Hit callback needs response %d\n", needsResponse);
-
- // turn packet around to go back to requester if response expected
-
- if (access_backing_store) {
- m_ruby_system->getPhysMem()->access(pkt);
- } else if (needsResponse) {
- pkt->makeResponse();
- }
-
- if (needsResponse) {
- DPRINTF(RubyDma, "Sending packet back over port\n");
- // send next cycle
- DMASequencer *seq = static_cast<DMASequencer *>(&owner);
- RubySystem *rs = seq->m_ruby_system;
- schedTimingResp(pkt, curTick() + rs->clockPeriod());
- } else {
- delete pkt;
- }
-
- DPRINTF(RubyDma, "Hit callback done!\n");
-}
-
-bool
-DMASequencer::MemSlavePort::isPhysMemAddress(Addr addr) const
-{
- DMASequencer *seq = static_cast<DMASequencer *>(&owner);
- return seq->system->isMemAddr(addr);
}
RequestStatus