/*
+ * Copyright (c) 2012 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) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* 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: Ali Saidi
*/
+#ifndef __MEM_TPORT_HH__
+#define __MEM_TPORT_HH__
+
/**
* @file
- * Implement a port which adds simple support of a sendTiming() function that
- * takes a delay. In this way the * device can immediatly call
- * sendTiming(pkt, time) after processing a request and the request will be
- * handled by the port even if the port bus the device connects to is blocked.
+ *
+ * Declaration of SimpleTimingPort.
*/
-/** recvTiming and drain should be implemented something like this when this
- * class is used.
+#include "mem/qport.hh"
-bool
-PioPort::recvTiming(Packet *pkt)
-{
- if (pkt->result == Packet::Nacked) {
- resendNacked(pkt);
- } else {
- Tick latency = device->recvAtomic(pkt);
- // turn packet around to go back to requester
- pkt->makeTimingResponse();
- sendTiming(pkt, latency);
- }
- return true;
-}
-
-PioDevice::drain(Event *de)
-{
- unsigned int count;
- count = SimpleTimingPort->drain(de);
- if (count)
- changeState(Draining);
- else
- changeState(Drained);
- return count;
-}
-*/
+class SimObject;
-#ifndef __MEM_TPORT_HH__
-#define __MEM_TPORT_HH__
+/**
+ * The simple timing port uses a queued port to implement
+ * recvFunctional and recvTimingReq through recvAtomic. It is always a
+ * response port.
+ */
+class SimpleTimingPort : public QueuedResponsePort
+{
-#include "mem/port.hh"
-#include "sim/eventq.hh"
-#include <list>
-#include <string>
+ private:
-class SimpleTimingPort : public Port
-{
- protected:
- /** A list of outgoing timing response packets that haven't been
- * serviced yet. */
- std::list<Packet*> transmitList;
/**
- * This class is used to implemented sendTiming() with a delay. When
- * a delay is requested a new event is created. When the event time
- * expires it attempts to send the packet. If it cannot, the packet
- * is pushed onto the transmit list to be sent when recvRetry() is
- * called. */
- class SendEvent : public Event
- {
- SimpleTimingPort *port;
- Packet *packet;
-
- public:
- SendEvent(SimpleTimingPort *p, Packet *pkt, Tick t)
- : Event(&mainEventQueue), port(p), packet(pkt)
- { setFlags(AutoDelete); schedule(curTick + t); }
-
- virtual void process();
-
- virtual const char *description()
- { return "Future scheduled sendTiming event"; }
- };
-
-
- /** Number of timing requests that are emulating the device timing before
- * attempting to end up on the bus.
+ * The packet queue used to store outgoing responses. Note that
+ * the queue is made private and that we avoid overloading the
+ * name used in the QueuedResponsePort. Access is provided through
+ * the queue reference in the base class.
*/
- int outTiming;
+ RespPacketQueue queueImpl;
+
+ protected:
- /** If we need to drain, keep the drain event around until we're done
- * here.*/
- Event *drainEvent;
+ /** Implemented using recvAtomic(). */
+ void recvFunctional(PacketPtr pkt);
- /** Schedule a sendTiming() event to be called in the future. */
- void sendTiming(Packet *pkt, Tick time)
- { outTiming++; new SimpleTimingPort::SendEvent(this, pkt, time); }
+ /** Implemented using recvAtomic(). */
+ bool recvTimingReq(PacketPtr pkt);
- /** This function is notification that the device should attempt to send a
- * packet again. */
- virtual void recvRetry();
+ virtual Tick recvAtomic(PacketPtr pkt) = 0;
+
+ /**
+ * Upstream caches need this packet until true is returned, so
+ * hold it for deletion until a subsequent call
+ */
+ std::unique_ptr<Packet> pendingDelete;
- void resendNacked(Packet *pkt);
public:
- SimpleTimingPort(std::string pname)
- : Port(pname), outTiming(0), drainEvent(NULL)
- {}
+ /**
+ * Create a new SimpleTimingPort that relies on a packet queue to
+ * hold responses, and implements recvTimingReq and recvFunctional
+ * through calls to recvAtomic. Once a request arrives, it is
+ * passed to recvAtomic, and in the case of a timing access any
+ * response is scheduled to be sent after the delay of the atomic
+ * operation.
+ *
+ * @param name port name
+ * @param owner structural owner
+ */
+ SimpleTimingPort(const std::string& name, SimObject* owner);
+
+ virtual ~SimpleTimingPort() { }
- unsigned int drain(Event *de);
};
#endif // __MEM_TPORT_HH__