From: Gabe Black Date: Thu, 15 Aug 2019 23:41:51 +0000 (-0700) Subject: mem: Split the various protocols out of the gem5 master/slave ports. X-Git-Tag: v19.0.0.0~636 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d97e4e1dd01a943a2c40ead90099d3e085059715;p=gem5.git 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 --- diff --git a/src/mem/SConscript b/src/mem/SConscript index 95d8654b1..9ebb07436 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -60,12 +60,14 @@ SimObject('MemDelay.py') Source('abstract_mem.cc') Source('addr_mapper.cc') +Source('atomic_protocol.cc') Source('bridge.cc') Source('coherent_xbar.cc') Source('drampower.cc') Source('dram_ctrl.cc') Source('external_master.cc') Source('external_slave.cc') +Source('functional_protocol.cc') Source('mem_object.cc') Source('mport.cc') Source('noncoherent_xbar.cc') @@ -75,6 +77,7 @@ Source('packet_queue.cc') Source('port_proxy.cc') Source('physical.cc') Source('secure_port_proxy.cc') +Source('timing_protocol.cc') Source('simple_mem.cc') Source('snoop_filter.cc') Source('stack_dist_calc.cc') diff --git a/src/mem/atomic_protocol.cc b/src/mem/atomic_protocol.cc new file mode 100644 index 000000000..6aecc4058 --- /dev/null +++ b/src/mem/atomic_protocol.cc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012,2015,2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Andreas Hansson + * William Wang + */ + +#include "mem/atomic_protocol.hh" + +#include "base/trace.hh" + +/* The request protocol. */ + +Tick +AtomicRequestProtocol::send(AtomicResponseProtocol *peer, PacketPtr pkt) +{ + assert(pkt->isRequest()); + return peer->recvAtomic(pkt); +} + +Tick +AtomicRequestProtocol::sendBackdoor(AtomicResponseProtocol *peer, + PacketPtr pkt, MemBackdoorPtr &backdoor) +{ + assert(pkt->isRequest()); + return peer->recvAtomicBackdoor(pkt, backdoor); +} + +/* The response protocol. */ + +Tick +AtomicResponseProtocol::sendSnoop(AtomicRequestProtocol *peer, PacketPtr pkt) +{ + assert(pkt->isRequest()); + return peer->recvAtomicSnoop(pkt); +} diff --git a/src/mem/atomic_protocol.hh b/src/mem/atomic_protocol.hh new file mode 100644 index 000000000..bb2de0a22 --- /dev/null +++ b/src/mem/atomic_protocol.hh @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2011-2012,2015,2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ron Dreslinski + * Andreas Hansson + * William Wang + */ + +#ifndef __MEM_ATOMIC_PROTOCOL_HH__ +#define __MEM_ATOMIC_PROTOCOL_HH__ + +#include "mem/backdoor.hh" +#include "mem/packet.hh" + +class AtomicResponseProtocol; + +class AtomicRequestProtocol +{ + friend class AtomicResponseProtocol; + + protected: + /** + * Send an atomic request packet, where the data is moved and the + * state is updated in zero time, without interleaving with other + * memory accesses. + * + * @param peer Peer to send packet to. + * @param pkt Packet to send. + * + * @return Estimated latency of access. + */ + Tick send(AtomicResponseProtocol *peer, PacketPtr pkt); + + /** + * Send an atomic request packet like above, but also request a backdoor + * to the data being accessed. + * + * @param peer Peer to send packet to. + * @param pkt Packet to send. + * @param backdoor Can be set to a back door pointer by the target to let + * caller have direct access to the requested data. + * + * @return Estimated latency of access. + */ + Tick sendBackdoor(AtomicResponseProtocol *peer, PacketPtr pkt, + MemBackdoorPtr &backdoor); + + /** + * Receive an atomic snoop request packet from our peer. + */ + virtual Tick recvAtomicSnoop(PacketPtr pkt) = 0; +}; + +class AtomicResponseProtocol +{ + friend class AtomicRequestProtocol; + + protected: + /** + * Send an atomic snoop request packet, where the data is moved + * and the state is updated in zero time, without interleaving + * with other memory accesses. + * + * @param peer Peer to send packet to. + * @param pkt Snoop packet to send. + * + * @return Estimated latency of access. + */ + Tick sendSnoop(AtomicRequestProtocol *peer, PacketPtr pkt); + + /** + * Receive an atomic request packet from the peer. + */ + virtual Tick recvAtomic(PacketPtr pkt) = 0; + + /** + * Receive an atomic request packet from the peer, and optionally + * provide a backdoor to the data being accessed. + */ + virtual Tick recvAtomicBackdoor( + PacketPtr pkt, MemBackdoorPtr &backdoor) = 0; +}; + +#endif //__MEM_ATOMIC_PROTOCOL_HH__ diff --git a/src/mem/functional_protocol.cc b/src/mem/functional_protocol.cc new file mode 100644 index 000000000..be129539b --- /dev/null +++ b/src/mem/functional_protocol.cc @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012,2015,2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Andreas Hansson + * William Wang + */ + +#include "mem/functional_protocol.hh" + +/* The request protocol. */ + +void +FunctionalRequestProtocol::send( + FunctionalResponseProtocol *peer, PacketPtr pkt) const +{ + assert(pkt->isRequest()); + return peer->recvFunctional(pkt); +} + +/* The response protocol. */ + +void +FunctionalResponseProtocol::sendSnoop( + FunctionalRequestProtocol *peer, PacketPtr pkt) const +{ + assert(pkt->isRequest()); + return peer->recvFunctionalSnoop(pkt); +} diff --git a/src/mem/functional_protocol.hh b/src/mem/functional_protocol.hh new file mode 100644 index 000000000..443b98032 --- /dev/null +++ b/src/mem/functional_protocol.hh @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2011-2012,2015,2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ron Dreslinski + * Andreas Hansson + * William Wang + */ + +#ifndef __MEM_FUNCTIONAL_PROTOCOL_HH__ +#define __MEM_FUNCTIONAL_PROTOCOL_HH__ + +#include "mem/packet.hh" + +class FunctionalResponseProtocol; + +class FunctionalRequestProtocol +{ + friend class FunctionalResponseProtocol; + + protected: + /** + * Send a functional request packet, where the data is instantly + * updated everywhere in the memory system, without affecting the + * current state of any block or moving the block. + * + * @param pkt Packet to send. + */ + void send(FunctionalResponseProtocol *peer, PacketPtr pkt) const; + + /** + * Receive a functional snoop request packet from the peer. + */ + virtual void recvFunctionalSnoop(PacketPtr pkt) = 0; +}; + +class FunctionalResponseProtocol +{ + friend class FunctionalRequestProtocol; + + protected: + /** + * Send a functional snoop request packet, where the data is + * instantly updated everywhere in the memory system, without + * affecting the current state of any block or moving the block. + * + * @param pkt Snoop packet to send. + */ + void sendSnoop(FunctionalRequestProtocol *peer, PacketPtr pkt) const; + + /** + * Receive a functional request packet from the peer. + */ + virtual void recvFunctional(PacketPtr pkt) = 0; +}; + +#endif //__MEM_FUNCTIONAL_PROTOCOL_HH__ diff --git a/src/mem/port.cc b/src/mem/port.cc index ee312eac7..40481b0bb 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -137,54 +137,6 @@ MasterPort::getAddrRanges() const return _slavePort->getAddrRanges(); } -Tick -MasterPort::sendAtomic(PacketPtr pkt) -{ - assert(pkt->isRequest()); - return _slavePort->recvAtomic(pkt); -} - -Tick -MasterPort::sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor) -{ - assert(pkt->isRequest()); - return _slavePort->recvAtomicBackdoor(pkt, backdoor); -} - -void -MasterPort::sendFunctional(PacketPtr pkt) -{ - assert(pkt->isRequest()); - return _slavePort->recvFunctional(pkt); -} - -bool -MasterPort::sendTimingReq(PacketPtr pkt) -{ - assert(pkt->isRequest()); - return _slavePort->recvTimingReq(pkt); -} - -bool -MasterPort::tryTiming(PacketPtr pkt) const -{ - assert(pkt->isRequest()); - return _slavePort->tryTiming(pkt); -} - -bool -MasterPort::sendTimingSnoopResp(PacketPtr pkt) -{ - assert(pkt->isResponse()); - return _slavePort->recvTimingSnoopResp(pkt); -} - -void -MasterPort::sendRetryResp() -{ - _slavePort->recvRespRetry(); -} - void MasterPort::printAddr(Addr a) { @@ -236,43 +188,3 @@ SlavePort::recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor) } return recvAtomic(pkt); } - -Tick -SlavePort::sendAtomicSnoop(PacketPtr pkt) -{ - assert(pkt->isRequest()); - return _masterPort->recvAtomicSnoop(pkt); -} - -void -SlavePort::sendFunctionalSnoop(PacketPtr pkt) -{ - assert(pkt->isRequest()); - return _masterPort->recvFunctionalSnoop(pkt); -} - -bool -SlavePort::sendTimingResp(PacketPtr pkt) -{ - assert(pkt->isResponse()); - return _masterPort->recvTimingResp(pkt); -} - -void -SlavePort::sendTimingSnoopReq(PacketPtr pkt) -{ - assert(pkt->isRequest()); - _masterPort->recvTimingSnoopReq(pkt); -} - -void -SlavePort::sendRetryReq() -{ - _masterPort->recvReqRetry(); -} - -void -SlavePort::sendRetrySnoopResp() -{ - _masterPort->recvRetrySnoopResp(); -} 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__ diff --git a/src/mem/timing_protocol.cc b/src/mem/timing_protocol.cc new file mode 100644 index 000000000..bc56ce2e3 --- /dev/null +++ b/src/mem/timing_protocol.cc @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2012,2015,2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Andreas Hansson + * William Wang + */ + +#include "mem/timing_protocol.hh" + +/* The request protocol. */ + +bool +TimingRequestProtocol::sendReq(TimingResponseProtocol *peer, PacketPtr pkt) +{ + assert(pkt->isRequest()); + return peer->recvTimingReq(pkt); +} + +bool +TimingRequestProtocol::trySend( + TimingResponseProtocol *peer, PacketPtr pkt) const +{ + assert(pkt->isRequest()); + return peer->tryTiming(pkt); +} + +bool +TimingRequestProtocol::sendSnoopResp( + TimingResponseProtocol *peer, PacketPtr pkt) +{ + assert(pkt->isResponse()); + return peer->recvTimingSnoopResp(pkt); +} + +void +TimingRequestProtocol::sendRetryResp(TimingResponseProtocol *peer) +{ + peer->recvRespRetry(); +} + +/* The response protocol. */ + +bool +TimingResponseProtocol::sendResp(TimingRequestProtocol *peer, PacketPtr pkt) +{ + assert(pkt->isResponse()); + return peer->recvTimingResp(pkt); +} + +void +TimingResponseProtocol::sendSnoopReq( + TimingRequestProtocol *peer, PacketPtr pkt) +{ + assert(pkt->isRequest()); + peer->recvTimingSnoopReq(pkt); +} + +void +TimingResponseProtocol::sendRetryReq(TimingRequestProtocol *peer) +{ + peer->recvReqRetry(); +} + +void +TimingResponseProtocol::sendRetrySnoopResp(TimingRequestProtocol *peer) +{ + peer->recvRetrySnoopResp(); +} diff --git a/src/mem/timing_protocol.hh b/src/mem/timing_protocol.hh new file mode 100644 index 000000000..42235732c --- /dev/null +++ b/src/mem/timing_protocol.hh @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2011-2012,2015,2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ron Dreslinski + * Andreas Hansson + * William Wang + */ + +#ifndef __MEM_TIMING_PROTOCOL_HH__ +#define __MEM_TIMING_PROTOCOL_HH__ + +#include "mem/packet.hh" + +class TimingResponseProtocol; + +class TimingRequestProtocol +{ + friend class TimingResponseProtocol; + + protected: + /** + * Attempt to send a timing request to the peer by calling + * its corresponding receive function. If the send does not + * succeed, as indicated by the return value, then the sender must + * wait for a recvReqRetry at which point it can re-issue a + * sendTimingReq. + * + * @param peer Peer to send packet to. + * @param pkt Packet to send. + * + * @return If the send was succesful or not. + */ + bool sendReq(TimingResponseProtocol *peer, PacketPtr pkt); + + /** + * Check if the peer can handle a timing request. + * + * If the send cannot be handled at the moment, as indicated by + * the return value, then the sender will receive a recvReqRetry + * at which point it can re-issue a sendTimingReq. + * + * @param peer Peer to send packet to. + * @param pkt Packet to send. + * + * @return If the send was succesful or not. + */ + bool trySend(TimingResponseProtocol *peer, PacketPtr pkt) const; + + /** + * Attempt to send a timing snoop response packet to it's peer + * by calling its corresponding receive function. If the send + * does not succeed, as indicated by the return value, then the + * sender must wait for a recvRetrySnoop at which point it can + * re-issue a sendTimingSnoopResp. + * + * @param pkt Packet to send. + */ + bool sendSnoopResp(TimingResponseProtocol *peer, PacketPtr pkt); + + /** + * Send a retry to the peer that previously attempted a + * sendTimingResp to this protocol and failed. + */ + void sendRetryResp(TimingResponseProtocol *peer); + + /** + * Receive a timing response from the peer. + */ + virtual bool recvTimingResp(PacketPtr pkt) = 0; + + /** + * Receive a timing snoop request from the peer. + */ + virtual void recvTimingSnoopReq(PacketPtr pkt) = 0; + + /** + * Called by the peer if sendTimingReq was called on this peer (causing + * recvTimingReq to be called on the peer) and was unsuccessful. + */ + virtual void recvReqRetry() = 0; + + /** + * Called by the peer if sendTimingSnoopResp was called on this + * protocol (causing recvTimingSnoopResp to be called on the peer) + * and was unsuccessful. + */ + virtual void recvRetrySnoopResp() = 0; +}; + +class TimingResponseProtocol +{ + friend class TimingRequestProtocol; + + protected: + /** + * Attempt to send a timing response to the peer by calling + * its corresponding receive function. If the send does not + * succeed, as indicated by the return value, then the sender must + * wait for a recvRespRetry at which point it can re-issue a + * sendTimingResp. + * + * @param peer Peer to send the packet to. + * @param pkt Packet to send. + * + * @return If the send was succesful or not. + */ + bool sendResp(TimingRequestProtocol *peer, PacketPtr pkt); + + /** + * Attempt to send a timing snoop request packet to the peer + * by calling its corresponding receive function. Snoop requests + * always succeed and hence no return value is needed. + * + * @param peer Peer to send the packet to. + * @param pkt Packet to send. + */ + void sendSnoopReq(TimingRequestProtocol *peer, PacketPtr pkt); + + /** + * Send a retry to the peer that previously attempted a + * sendTimingReq to this protocol and failed. + */ + void sendRetryReq(TimingRequestProtocol *peer); + + /** + * Send a retry to the peer that previously attempted a + * sendTimingSnoopResp to this peer and failed. + */ + void sendRetrySnoopResp(TimingRequestProtocol *peer); + + /** + * Receive a timing request from the peer. + */ + virtual bool recvTimingReq(PacketPtr pkt) = 0; + + /** + * Availability request from the peer. + */ + virtual bool tryTiming(PacketPtr pkt) = 0; + + /** + * Receive a timing snoop response from the peer. + */ + virtual bool recvTimingSnoopResp(PacketPtr pkt) = 0; + + /** + * Called by the peer if sendTimingResp was called on this + * protocol (causing recvTimingResp to be called on the peer) + * and was unsuccessful. + */ + virtual void recvRespRetry() = 0; +}; + +#endif //__MEM_TIMING_PROTOCOL_HH__