31,32d30
< #include "debug/Config.hh"
< #include "debug/Drain.hh"
35a34
> #include "mem/protocol/SequencerRequestType.hh"
38d36
< #include "sim/system.hh"
41,46c39
< : 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)
48d40
< assert(m_version != -1);
54,56c46
< MemObject::init();
< assert(m_controller != NULL);
< m_mandatory_q_ptr = m_controller->getMandatoryQueue();
---
> RubyPort::init();
59,60d48
<
< slave_port.sendRangeChange();
63,218d50
< 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);
< }
<