From d97e4e1dd01a943a2c40ead90099d3e085059715 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 15 Aug 2019 16:41:51 -0700 Subject: mem: Split the various protocols out of the gem5 master/slave ports. This makes the protocols easier to see in their entirity, and makes it easier to add a new type of port which only supports the functional protocol. Change-Id: If5d639bef45062f0a23af2ac46f50933e6a8f144 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20228 Maintainer: Gabe Black Tested-by: kokoro Reviewed-by: Andreas Sandberg --- src/mem/port.hh | 343 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 188 insertions(+), 155 deletions(-) (limited to 'src/mem/port.hh') diff --git a/src/mem/port.hh b/src/mem/port.hh index 76ad3bd63..16257ed4f 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -51,8 +51,10 @@ #define __MEM_PORT_HH__ #include "base/addr_range.hh" -#include "mem/backdoor.hh" +#include "mem/atomic_protocol.hh" +#include "mem/functional_protocol.hh" #include "mem/packet.hh" +#include "mem/timing_protocol.hh" #include "sim/port.hh" class SimObject; @@ -68,18 +70,14 @@ class BaseSlavePort; */ class BaseMasterPort : public Port { - protected: + BaseSlavePort *_baseSlavePort; - BaseSlavePort* _baseSlavePort; - - BaseMasterPort(const std::string& name, PortID id=InvalidPortID); + BaseMasterPort(const std::string &name, PortID id=InvalidPortID); virtual ~BaseMasterPort(); public: - BaseSlavePort& getSlavePort() const; - }; /** @@ -88,18 +86,14 @@ class BaseMasterPort : public Port */ class BaseSlavePort : public Port { - protected: + BaseMasterPort *_baseMasterPort; - BaseMasterPort* _baseMasterPort; - - BaseSlavePort(const std::string& name, PortID id=InvalidPortID); + BaseSlavePort(const std::string &name, PortID id=InvalidPortID); virtual ~BaseSlavePort(); public: - BaseMasterPort& getMasterPort() const; - }; /** Forward declaration */ @@ -111,22 +105,22 @@ class SlavePort; * transport functions. In addition to the basic functionality of * sending packets, it also has functions to receive range changes or * determine if the port is snooping or not. + * + * The three protocols are atomic, timing, and functional, each with its own + * header file. */ -class MasterPort : public BaseMasterPort +class MasterPort : public BaseMasterPort, public AtomicRequestProtocol, + public TimingRequestProtocol, public FunctionalRequestProtocol { - friend class SlavePort; private: - - SlavePort* _slavePort; + SlavePort *_slavePort; protected: - - SimObject& owner; + SimObject &owner; public: - MasterPort(const std::string& name, SimObject* _owner, PortID id=InvalidPortID); virtual ~MasterPort(); @@ -142,6 +136,31 @@ class MasterPort : public BaseMasterPort */ void unbind() override; + /** + * Determine if this master port is snooping or not. The default + * implementation returns false and thus tells the neighbour we + * are not snooping. Any master port that wants to receive snoop + * requests (e.g. a cache connected to a bus) has to override this + * function. + * + * @return true if the port should be considered a snooper + */ + virtual bool isSnooping() const { return false; } + + /** + * Get the address ranges of the connected slave port. + */ + AddrRangeList getAddrRanges() const; + + /** + * Inject a PrintReq for the given address to print the state of + * that address throughout the memory system. For debugging. + */ + void printAddr(Addr a); + + public: + /* The atomic protocol. */ + /** * Send an atomic request packet, where the data is moved and the * state is updated in zero time, without interleaving with other @@ -165,6 +184,9 @@ class MasterPort : public BaseMasterPort */ Tick sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor); + public: + /* The functional protocol. */ + /** * Send a functional request packet, where the data is instantly * updated everywhere in the memory system, without affecting the @@ -172,7 +194,10 @@ class MasterPort : public BaseMasterPort * * @param pkt Packet to send. */ - void sendFunctional(PacketPtr pkt); + void sendFunctional(PacketPtr pkt) const; + + public: + /* The timing protocol. */ /** * Attempt to send a timing request to the slave port by calling @@ -219,84 +244,43 @@ class MasterPort : public BaseMasterPort */ virtual void sendRetryResp(); + protected: /** - * Determine if this master port is snooping or not. The default - * implementation returns false and thus tells the neighbour we - * are not snooping. Any master port that wants to receive snoop - * requests (e.g. a cache connected to a bus) has to override this - * function. - * - * @return true if the port should be considered a snooper - */ - virtual bool isSnooping() const { return false; } - - /** - * Get the address ranges of the connected slave port. - */ - AddrRangeList getAddrRanges() const; - - /** Inject a PrintReq for the given address to print the state of - * that address throughout the memory system. For debugging. + * Called to receive an address range change from the peer slave + * port. The default implementation ignores the change and does + * nothing. Override this function in a derived class if the owner + * needs to be aware of the address ranges, e.g. in an + * interconnect component like a bus. */ - void printAddr(Addr a); - - protected: + virtual void recvRangeChange() { } /** - * Receive an atomic snoop request packet from the slave port. + * Default implementations. */ - virtual Tick recvAtomicSnoop(PacketPtr pkt) + Tick + recvAtomicSnoop(PacketPtr pkt) override { panic("%s was not expecting an atomic snoop request\n", name()); return 0; } - /** - * Receive a functional snoop request packet from the slave port. - */ - virtual void recvFunctionalSnoop(PacketPtr pkt) + void + recvFunctionalSnoop(PacketPtr pkt) override { panic("%s was not expecting a functional snoop request\n", name()); } - /** - * Receive a timing response from the slave port. - */ - virtual bool recvTimingResp(PacketPtr pkt) = 0; - - /** - * Receive a timing snoop request from the slave port. - */ - virtual void recvTimingSnoopReq(PacketPtr pkt) + void + recvTimingSnoopReq(PacketPtr pkt) override { - panic("%s was not expecting a timing snoop request\n", name()); + panic("%s was not expecting a timing snoop request.\n", name()); } - /** - * Called by the slave port if sendTimingReq was called on this - * master port (causing recvTimingReq to be called on the slave - * port) and was unsuccesful. - */ - virtual void recvReqRetry() = 0; - - /** - * Called by the slave port if sendTimingSnoopResp was called on this - * master port (causing recvTimingSnoopResp to be called on the slave - * port) and was unsuccesful. - */ - virtual void recvRetrySnoopResp() + void + recvRetrySnoopResp() override { - panic("%s was not expecting a snoop retry\n", name()); + panic("%s was not expecting a snoop retry.\n", name()); } - - /** - * Called to receive an address range change from the peer slave - * port. The default implementation ignores the change and does - * nothing. Override this function in a derived class if the owner - * needs to be aware of the address ranges, e.g. in an - * interconnect component like a bus. - */ - virtual void recvRangeChange() { } }; /** @@ -304,27 +288,63 @@ class MasterPort : public BaseMasterPort * basic functionality of sending packets to its master peer, it also * has functions specific to a slave, e.g. to send range changes * and get the address ranges that the port responds to. + * + * The three protocols are atomic, timing, and functional, each with its own + * header file. */ -class SlavePort : public BaseSlavePort +class SlavePort : public BaseSlavePort, public AtomicResponseProtocol, + public TimingResponseProtocol, public FunctionalResponseProtocol { - friend class MasterPort; private: - MasterPort* _masterPort; bool defaultBackdoorWarned; protected: - SimObject& owner; public: - SlavePort(const std::string& name, SimObject* _owner, PortID id=InvalidPortID); virtual ~SlavePort(); + /** + * Find out if the peer master port is snooping or not. + * + * @return true if the peer master port is snooping + */ + bool isSnooping() const { return _masterPort->isSnooping(); } + + /** + * Called by the owner to send a range change + */ + void + sendRangeChange() const + { + fatal_if(!_masterPort, + "%s cannot sendRangeChange() without master port.", name()); + _masterPort->recvRangeChange(); + } + + /** + * Get a list of the non-overlapping address ranges the owner is + * responsible for. All slave ports must override this function + * and return a populated list with at least one item. + * + * @return a list of ranges responded to + */ + virtual AddrRangeList getAddrRanges() const = 0; + + /** + * We let the master port do the work, so these don't do anything. + */ + void unbind() override {} + void bind(Port &peer) override {} + + public: + /* The atomic protocol. */ + /** * Send an atomic snoop request packet, where the data is moved * and the state is updated in zero time, without interleaving @@ -334,7 +354,14 @@ class SlavePort : public BaseSlavePort * * @return Estimated latency of access. */ - Tick sendAtomicSnoop(PacketPtr pkt); + Tick + sendAtomicSnoop(PacketPtr pkt) + { + return AtomicResponseProtocol::sendSnoop(_masterPort, pkt); + } + + public: + /* The functional protocol. */ /** * Send a functional snoop request packet, where the data is @@ -343,7 +370,14 @@ class SlavePort : public BaseSlavePort * * @param pkt Snoop packet to send. */ - void sendFunctionalSnoop(PacketPtr pkt); + void + sendFunctionalSnoop(PacketPtr pkt) const + { + FunctionalResponseProtocol::sendSnoop(_masterPort, pkt); + } + + public: + /* The timing protocol. */ /** * Attempt to send a timing response to the master port by calling @@ -356,7 +390,11 @@ class SlavePort : public BaseSlavePort * * @return If the send was succesful or not. */ - bool sendTimingResp(PacketPtr pkt); + bool + sendTimingResp(PacketPtr pkt) + { + return TimingResponseProtocol::sendResp(_masterPort, pkt); + } /** * Attempt to send a timing snoop request packet to the master port @@ -365,53 +403,33 @@ class SlavePort : public BaseSlavePort * * @param pkt Packet to send. */ - void sendTimingSnoopReq(PacketPtr pkt); + void + sendTimingSnoopReq(PacketPtr pkt) + { + TimingResponseProtocol::sendSnoopReq(_masterPort, pkt); + } /** * Send a retry to the master port that previously attempted a * sendTimingReq to this slave port and failed. */ - void sendRetryReq(); + void + sendRetryReq() + { + TimingResponseProtocol::sendRetryReq(_masterPort); + } /** * Send a retry to the master port that previously attempted a * sendTimingSnoopResp to this slave port and failed. */ - void sendRetrySnoopResp(); - - /** - * Find out if the peer master port is snooping or not. - * - * @return true if the peer master port is snooping - */ - bool isSnooping() const { return _masterPort->isSnooping(); } - - /** - * Called by the owner to send a range change - */ - void sendRangeChange() const { - if (!_masterPort) - fatal("%s cannot sendRangeChange() without master port", name()); - _masterPort->recvRangeChange(); + void + sendRetrySnoopResp() + { + TimingResponseProtocol::sendRetrySnoopResp(_masterPort); } - /** - * Get a list of the non-overlapping address ranges the owner is - * responsible for. All slave ports must override this function - * and return a populated list with at least one item. - * - * @return a list of ranges responded to - */ - virtual AddrRangeList getAddrRanges() const = 0; - - /** - * We let the master port do the work, so these don't do anything. - */ - void unbind() override {} - void bind(Port &peer) override {} - protected: - /** * Called by the master port to unbind. Should never be called * directly. @@ -425,48 +443,63 @@ class SlavePort : public BaseSlavePort void slaveBind(MasterPort& master_port); /** - * Receive an atomic request packet from the master port. - */ - virtual Tick recvAtomic(PacketPtr pkt) = 0; - - /** - * Receive an atomic request packet from the master port, and optionally - * provide a backdoor to the data being accessed. - */ - virtual Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor); - - /** - * Receive a functional request packet from the master port. + * Default implementations. */ - virtual void recvFunctional(PacketPtr pkt) = 0; + Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor) override; - /** - * Receive a timing request from the master port. - */ - virtual bool recvTimingReq(PacketPtr pkt) = 0; - - /** - * Availability request from the master port. - */ - virtual bool tryTiming(PacketPtr pkt) { + bool + tryTiming(PacketPtr pkt) override + { panic("%s was not expecting a %s\n", name(), __func__); } - /** - * Receive a timing snoop response from the master port. - */ - virtual bool recvTimingSnoopResp(PacketPtr pkt) + bool + recvTimingSnoopResp(PacketPtr pkt) override { panic("%s was not expecting a timing snoop response\n", name()); } +}; - /** - * Called by the master port if sendTimingResp was called on this - * slave port (causing recvTimingResp to be called on the master - * port) and was unsuccesful. - */ - virtual void recvRespRetry() = 0; +inline Tick +MasterPort::sendAtomic(PacketPtr pkt) +{ + return AtomicRequestProtocol::send(_slavePort, pkt); +} -}; +inline Tick +MasterPort::sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor) +{ + return AtomicRequestProtocol::sendBackdoor(_slavePort, pkt, backdoor); +} + +inline void +MasterPort::sendFunctional(PacketPtr pkt) const +{ + return FunctionalRequestProtocol::send(_slavePort, pkt); +} + +inline bool +MasterPort::sendTimingReq(PacketPtr pkt) +{ + return TimingRequestProtocol::sendReq(_slavePort, pkt); +} + +inline bool +MasterPort::tryTiming(PacketPtr pkt) const +{ + return TimingRequestProtocol::trySend(_slavePort, pkt); +} + +inline bool +MasterPort::sendTimingSnoopResp(PacketPtr pkt) +{ + return TimingRequestProtocol::sendSnoopResp(_slavePort, pkt); +} + +inline void +MasterPort::sendRetryResp() +{ + TimingRequestProtocol::sendRetryResp(_slavePort); +} #endif //__MEM_PORT_HH__ -- cgit v1.2.3