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 -#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(&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(&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(&owner); - return seq->system->isMemAddr(addr); } RequestStatus diff --git a/src/mem/ruby/system/DMASequencer.hh b/src/mem/ruby/system/DMASequencer.hh index 34f9be34c..9cf187c83 100644 --- a/src/mem/ruby/system/DMASequencer.hh +++ b/src/mem/ruby/system/DMASequencer.hh @@ -32,18 +32,11 @@ #include #include -#include "mem/mem_object.hh" #include "mem/protocol/DMASequencerRequestType.hh" -#include "mem/protocol/RequestStatus.hh" #include "mem/ruby/common/DataBlock.hh" -#include "mem/ruby/network/MessageBuffer.hh" -#include "mem/ruby/system/RubySystem.hh" -#include "mem/simple_mem.hh" -#include "mem/tport.hh" +#include "mem/ruby/system/RubyPort.hh" #include "params/DMASequencer.hh" -class AbstractController; - struct DMARequest { uint64_t start_paddr; @@ -55,47 +48,12 @@ struct DMARequest PacketPtr pkt; }; -class DMASequencer : public MemObject +class DMASequencer : public RubyPort { public: typedef DMASequencerParams Params; DMASequencer(const Params *); void init() override; - RubySystem *m_ruby_system; - - public: - class MemSlavePort : public QueuedSlavePort - { - private: - RespPacketQueue queue; - RubySystem* m_ruby_system; - bool access_backing_store; - - public: - MemSlavePort(const std::string &_name, DMASequencer *_port, - PortID id, RubySystem *_ruby_system, - bool _access_backing_store); - void hitCallback(PacketPtr pkt); - void evictionCallback(Addr address); - - protected: - bool recvTimingReq(PacketPtr pkt); - - Tick recvAtomic(PacketPtr pkt) - { panic("DMASequencer::MemSlavePort::recvAtomic() not implemented!\n"); } - - void recvFunctional(PacketPtr pkt) - { panic("DMASequencer::MemSlavePort::recvFunctional() not implemented!\n"); } - - AddrRangeList getAddrRanges() const - { AddrRangeList ranges; return ranges; } - - private: - bool isPhysMemAddress(Addr addr) const; - }; - - BaseSlavePort &getSlavePort(const std::string &if_name, - PortID idx = InvalidPortID) override; /* external interface */ RequestStatus makeRequest(PacketPtr pkt); @@ -104,12 +62,6 @@ class DMASequencer : public MemObject bool isDeadlockEventScheduled() const { return false; } void descheduleDeadlockEvent() {} - // Called by the controller to give the sequencer a pointer. - // A pointer to the controller is needed for atomic support. - void setController(AbstractController* _cntrl) { m_controller = _cntrl; } - uint32_t getId() { return m_version; } - DrainState drain() override; - /* SLICC callback */ void dataCallback(const DataBlock & dblk); void ackCallback(); @@ -118,31 +70,7 @@ class DMASequencer : public MemObject private: void issueNext(); - void ruby_hit_callback(PacketPtr pkt); - void testDrainComplete(); - /** - * Called by the PIO port when receiving a timing response. - * - * @param pkt Response packet - * @param master_port_id Port id of the PIO port - * - * @return Whether successfully sent - */ - bool recvTimingResp(PacketPtr pkt, PortID master_port_id); - unsigned int getChildDrainCount(); - - private: - uint32_t m_version; - AbstractController* m_controller; - MessageBuffer* m_mandatory_q_ptr; - bool m_usingRubyTester; - - MemSlavePort slave_port; - - System* system; - - bool retry; bool m_is_busy; uint64_t m_data_block_mask; DMARequest active_request; diff --git a/src/mem/ruby/system/Sequencer.py b/src/mem/ruby/system/Sequencer.py index d6ee0aa2f..5b6a673da 100644 --- a/src/mem/ruby/system/Sequencer.py +++ b/src/mem/ruby/system/Sequencer.py @@ -78,12 +78,6 @@ class RubySequencer(RubyPort): # 99 is the dummy default value coreid = Param.Int(99, "CorePair core id") -class DMASequencer(MemObject): +class DMASequencer(RubyPort): type = 'DMASequencer' cxx_header = "mem/ruby/system/DMASequencer.hh" - - version = Param.Int(0, "") - slave = SlavePort("Device slave port") - using_ruby_tester = Param.Bool(False, "") - ruby_system = Param.RubySystem(Parent.any, "") - system = Param.System(Parent.any, "system object")