packet_queue.hh revision 8856
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Ali Saidi
41 *          Andreas Hansson
42 */
43
44#ifndef __MEM_TPORT_HH__
45#define __MEM_TPORT_HH__
46
47/**
48 * @file
49 *
50 * Declaration of SimpleTimingPort.
51 */
52
53#include <list>
54#include <string>
55
56#include "mem/port.hh"
57#include "sim/eventq.hh"
58
59/**
60 * A simple port for interfacing objects that basically have only
61 * functional memory behavior (e.g. I/O devices) to the memory system.
62 * Both timing and functional accesses are implemented in terms of
63 * atomic accesses.  A derived port class thus only needs to provide
64 * recvAtomic() to support all memory access modes.
65 *
66 * The tricky part is handling recvTiming(), where the response must
67 * be scheduled separately via a later call to sendTiming().  This
68 * feature is handled by scheduling an internal event that calls
69 * sendTiming() after a delay, and optionally rescheduling the
70 * response if it is nacked.
71 */
72class SimpleTimingPort : public Port
73{
74  protected:
75    /** A deferred packet, buffered to transmit later. */
76    class DeferredPacket {
77      public:
78        Tick tick;      ///< The tick when the packet is ready to transmit
79        PacketPtr pkt;  ///< Pointer to the packet to transmit
80        DeferredPacket(Tick t, PacketPtr p)
81            : tick(t), pkt(p)
82        {}
83    };
84
85    typedef std::list<DeferredPacket> DeferredPacketList;
86    typedef std::list<DeferredPacket>::iterator DeferredPacketIterator;
87
88    /** A list of outgoing timing response packets that haven't been
89     * serviced yet. */
90    DeferredPacketList transmitList;
91
92    /** Label to use for print request packets label stack. */
93    const std::string label;
94
95    /** This function attempts to send deferred packets.  Scheduled to
96     * be called in the future via SendEvent. */
97    void processSendEvent();
98
99    /**
100     * This class is used to implemented sendTiming() with a delay. When
101     * a delay is requested a the event is scheduled if it isn't already.
102     * When the event time expires it attempts to send the packet.
103     * If it cannot, the packet sent when recvRetry() is called.
104     **/
105    EventWrapper<SimpleTimingPort,
106                 &SimpleTimingPort::processSendEvent> sendEvent;
107
108    /** If we need to drain, keep the drain event around until we're done
109     * here.*/
110    Event *drainEvent;
111
112    /** Remember whether we're awaiting a retry from the bus. */
113    bool waitingOnRetry;
114
115    /** Check whether we have a packet ready to go on the transmit list. */
116    bool deferredPacketReady()
117    { return !transmitList.empty() && transmitList.front().tick <= curTick(); }
118
119    Tick deferredPacketReadyTime()
120    { return transmitList.empty() ? MaxTick : transmitList.front().tick; }
121
122    /**
123     * Schedule a send even if not already waiting for a retry. If the
124     * requested time is before an already scheduled send event it
125     * will be rescheduled.
126     *
127     * @param when
128     */
129    void schedSendEvent(Tick when);
130
131    /** Schedule a sendTiming() event to be called in the future.
132     * @param pkt packet to send
133     * @param absolute time (in ticks) to send packet
134     */
135    void schedSendTiming(PacketPtr pkt, Tick when);
136
137    /** Attempt to send the packet at the head of the deferred packet
138     * list.  Caller must guarantee that the deferred packet list is
139     * non-empty and that the head packet is scheduled for curTick() (or
140     * earlier).
141     */
142    virtual void sendDeferredPacket();
143
144    /**
145     * Attempt to send the packet at the front of the transmit list,
146     * and set waitingOnRetry accordingly. The packet is temporarily
147     * taken off the list, but put back at the front if not
148     * successfully sent.
149     */
150    void trySendTiming();
151
152    /**
153     * Based on the transmit list, or the provided time, schedule a
154     * send event if there are packets to send. If we are idle and
155     * asked to drain then do so.
156     *
157     * @param time an alternative time for the next send event
158     */
159    void scheduleSend(Tick time = MaxTick);
160
161    /** This function is notification that the device should attempt to send a
162     * packet again. */
163    virtual void recvRetry();
164
165    /** Implemented using recvAtomic(). */
166    void recvFunctional(PacketPtr pkt);
167
168    /** Implemented using recvAtomic(). */
169    bool recvTiming(PacketPtr pkt);
170
171    /**
172     * Simple ports are generally used as slave ports (i.e. the
173     * respond to requests) and thus do not expect to receive any
174     * range changes (as the neighbouring port has a master role and
175     * do not have any address ranges. A subclass can override the
176     * default behaviuor if needed.
177     */
178    virtual void recvRangeChange() { }
179
180
181  public:
182    SimpleTimingPort(const std::string &_name, MemObject *_owner,
183                     const std::string _label = "SimpleTimingPort");
184    ~SimpleTimingPort();
185
186    /** Check the list of buffered packets against the supplied
187     * functional request. */
188    bool checkFunctional(PacketPtr pkt);
189
190    /** Hook for draining timing accesses from the system.  The
191     * associated SimObject's drain() functions should be implemented
192     * something like this when this class is used:
193     \code
194          PioDevice::drain(Event *de)
195          {
196              unsigned int count;
197              count = SimpleTimingPort->drain(de);
198              if (count)
199                  changeState(Draining);
200              else
201                  changeState(Drained);
202              return count;
203          }
204     \endcode
205    */
206    unsigned int drain(Event *de);
207};
208
209#endif // __MEM_TPORT_HH__
210