diff options
Diffstat (limited to 'src/mem/ruby/system/DMASequencer.cc')
-rw-r--r-- | src/mem/ruby/system/DMASequencer.cc | 174 |
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 |