packet_queue.hh revision 9356
11689SN/A/*
27598Sminkyu.jeong@arm.com * Copyright (c) 2012 ARM Limited
37598Sminkyu.jeong@arm.com * All rights reserved.
47598Sminkyu.jeong@arm.com *
57598Sminkyu.jeong@arm.com * The license below extends only to copyright in the software and shall
67598Sminkyu.jeong@arm.com * not be construed as granting a license to any other intellectual
77598Sminkyu.jeong@arm.com * property including but not limited to intellectual property relating
87598Sminkyu.jeong@arm.com * to a hardware implementation of the functionality of the software
97598Sminkyu.jeong@arm.com * licensed hereunder.  You may use the software subject to the license
107598Sminkyu.jeong@arm.com * terms below provided that you ensure that this notice is replicated
117598Sminkyu.jeong@arm.com * unmodified and in its entirety in all distributions of the software,
127598Sminkyu.jeong@arm.com * modified or unmodified, in source code or in binary form.
137598Sminkyu.jeong@arm.com *
142326SN/A * Copyright (c) 2006 The Regents of The University of Michigan
151689SN/A * All rights reserved.
161689SN/A *
171689SN/A * Redistribution and use in source and binary forms, with or without
181689SN/A * modification, are permitted provided that the following conditions are
191689SN/A * met: redistributions of source code must retain the above copyright
201689SN/A * notice, this list of conditions and the following disclaimer;
211689SN/A * redistributions in binary form must reproduce the above copyright
221689SN/A * notice, this list of conditions and the following disclaimer in the
231689SN/A * documentation and/or other materials provided with the distribution;
241689SN/A * neither the name of the copyright holders nor the names of its
251689SN/A * contributors may be used to endorse or promote products derived from
261689SN/A * this software without specific prior written permission.
271689SN/A *
281689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
291689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
301689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
311689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
321689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
331689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
341689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
351689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
361689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
371689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
381689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392665Ssaidi@eecs.umich.edu *
402665Ssaidi@eecs.umich.edu * Authors: Ali Saidi
411689SN/A *          Andreas Hansson
421689SN/A */
431060SN/A
441060SN/A#ifndef __MEM_PACKET_QUEUE_HH__
451689SN/A#define __MEM_PACKET_QUEUE_HH__
461060SN/A
471060SN/A/**
481060SN/A * @file
491060SN/A * Declaration of a simple PacketQueue that is associated with
506658Snate@binkert.org * a port on which it attempts to send packets according to the time
512292SN/A * stamp given to them at insertion. The packet queue is responsible
521717SN/A * for the flow control of the port, but relies on the module
535529Snate@binkert.org * notifying the queue when a transfer ends.
541060SN/A */
556221Snate@binkert.org
566221Snate@binkert.org#include <list>
571681SN/A
585529Snate@binkert.org#include "mem/port.hh"
592873Sktlim@umich.edu#include "sim/drain.hh"
604329Sktlim@umich.edu#include "sim/eventq_impl.hh"
614329Sktlim@umich.edu
624329Sktlim@umich.edu/**
632292SN/A * A packet queue is a class that holds deferred packets and later
642292SN/A * sends them using the associated slave port or master port.
652292SN/A */
662292SN/Aclass PacketQueue : public Drainable
672820Sktlim@umich.edu{
682292SN/A  private:
692820Sktlim@umich.edu    /** A deferred packet, buffered to transmit later. */
702820Sktlim@umich.edu    class DeferredPacket {
715529Snate@binkert.org      public:
722307SN/A        Tick tick;      ///< The tick when the packet is ready to transmit
731060SN/A        PacketPtr pkt;  ///< Pointer to the packet to transmit
742292SN/A        bool sendAsSnoop; ///< Should it be sent as a snoop or not
752292SN/A        DeferredPacket(Tick t, PacketPtr p, bool send_as_snoop)
762292SN/A            : tick(t), pkt(p), sendAsSnoop(send_as_snoop)
771060SN/A        {}
781060SN/A    };
791060SN/A
801060SN/A    typedef std::list<DeferredPacket> DeferredPacketList;
811060SN/A    typedef std::list<DeferredPacket>::iterator DeferredPacketIterator;
821060SN/A
831681SN/A    /** A list of outgoing timing response packets that haven't been
846221Snate@binkert.org     * serviced yet. */
856221Snate@binkert.org    DeferredPacketList transmitList;
866221Snate@binkert.org
876221Snate@binkert.org    /** The manager which is used for the event queue */
882292SN/A    EventManager& em;
892292SN/A
902820Sktlim@umich.edu    /** This function attempts to send deferred packets.  Scheduled to
912820Sktlim@umich.edu     * be called in the future via SendEvent. */
922292SN/A    void processSendEvent();
932292SN/A
942820Sktlim@umich.edu    /**
952820Sktlim@umich.edu     * Event used to call processSendEvent.
962292SN/A     **/
972292SN/A    EventWrapper<PacketQueue, &PacketQueue::processSendEvent> sendEvent;
982292SN/A
992292SN/A    /** If we need to drain, keep the drain manager around until we're done
1002292SN/A     * here.*/
1012292SN/A    DrainManager *drainManager;
1022292SN/A
1032292SN/A  protected:
1041060SN/A
1051060SN/A    /** Label to use for print request packets label stack. */
1061681SN/A    const std::string label;
1071062SN/A
1082292SN/A    /** Remember whether we're awaiting a retry from the bus. */
1091062SN/A    bool waitingOnRetry;
1102301SN/A
1112301SN/A    /** Check whether we have a packet ready to go on the transmit list. */
1121062SN/A    bool deferredPacketReady()
1132727Sktlim@umich.edu    { return !transmitList.empty() && transmitList.front().tick <= curTick(); }
1141062SN/A
1151062SN/A    Tick deferredPacketReadyTime()
1161062SN/A    { return transmitList.empty() ? MaxTick : transmitList.front().tick; }
1171062SN/A
1181062SN/A    /**
1191062SN/A     * Attempt to send the packet at the head of the transmit
1201062SN/A     * list. Caller must guarantee that the list is non-empty and that
1211062SN/A     * the head packet is scheduled for curTick() (or earlier). Note
1221062SN/A     * that a subclass of the PacketQueue can override this method and
1231062SN/A     * thus change the behaviour (as done by the cache).
1241062SN/A     */
1251062SN/A    virtual void sendDeferredPacket();
1261062SN/A
1271062SN/A    /**
1281062SN/A     * Attempt to send the packet at the front of the transmit list,
1291062SN/A     * and set waitingOnRetry accordingly. The packet is temporarily
1301062SN/A     * taken off the list, but put back at the front if not
1311062SN/A     * successfully sent.
1321062SN/A     */
1331062SN/A    void trySendTiming();
1341062SN/A
1351062SN/A    /**
1361062SN/A     *
1371062SN/A     */
1381062SN/A    virtual bool sendTiming(PacketPtr pkt, bool send_as_snoop) = 0;
1391062SN/A
1401062SN/A    /**
1411062SN/A     * Based on the transmit list, or the provided time, schedule a
1421062SN/A     * send event if there are packets to send. If we are idle and
1431062SN/A     * asked to drain then do so.
1441062SN/A     *
1451062SN/A     * @param time an alternative time for the next send event
1461062SN/A     */
1471062SN/A    void scheduleSend(Tick time = MaxTick);
1481062SN/A
1491062SN/A    /**
1501062SN/A     * Simple ports are generally used as slave ports (i.e. the
1511062SN/A     * respond to requests) and thus do not expect to receive any
1521062SN/A     * range changes (as the neighbouring port has a master role and
1531062SN/A     * do not have any address ranges. A subclass can override the
1541062SN/A     * default behaviuor if needed.
1552292SN/A     */
1562292SN/A    virtual void recvRangeChange() { }
1572292SN/A
1582292SN/A    /**
1591062SN/A     * Create a packet queue, linked to an event manager, and a label
1601062SN/A     * that will be used for functional print request packets.
1611062SN/A     *
1621062SN/A     * @param _em Event manager used for scheduling this queue
1631062SN/A     * @param _label Label to push on the label stack for print request packets
1641062SN/A     */
1651062SN/A    PacketQueue(EventManager& _em, const std::string& _label);
1662292SN/A
1672292SN/A    /**
1682292SN/A     * Virtual desctructor since the class may be used as a base class.
1692292SN/A     */
1702292SN/A    virtual ~PacketQueue();
1712292SN/A
1722292SN/A  public:
1732292SN/A
1742292SN/A    /**
1752292SN/A     * Provide a name to simplify debugging.
1762301SN/A     *
1772727Sktlim@umich.edu     * @return A complete name, appended to module and port
1782353SN/A     */
1792727Sktlim@umich.edu    virtual const std::string name() const = 0;
1802727Sktlim@umich.edu
1812727Sktlim@umich.edu    /** Check the list of buffered packets against the supplied
1826221Snate@binkert.org     * functional request. */
1832353SN/A    bool checkFunctional(PacketPtr pkt);
1842727Sktlim@umich.edu
1852727Sktlim@umich.edu    /**
1862727Sktlim@umich.edu     * Schedule a send even if not already waiting for a retry. If the
1872727Sktlim@umich.edu     * requested time is before an already scheduled send event it
1882353SN/A     * will be rescheduled.
1892727Sktlim@umich.edu     *
1902727Sktlim@umich.edu     * @param when
1912727Sktlim@umich.edu     */
1926221Snate@binkert.org    void schedSendEvent(Tick when);
1932301SN/A
1942301SN/A    /**
1952727Sktlim@umich.edu     * Add a packet to the transmit list, and ensure that a
1962301SN/A     * processSendEvent is called in the future.
1972727Sktlim@umich.edu     *
1986221Snate@binkert.org     * @param pkt Packet to send
1992301SN/A     * @param when Absolute time (in ticks) to send packet
2002301SN/A     * @param send_as_snoop Send the packet as a snoop or not
2012727Sktlim@umich.edu     */
2022301SN/A    void schedSendTiming(PacketPtr pkt, Tick when, bool send_as_snoop = false);
2032727Sktlim@umich.edu
2046221Snate@binkert.org    /**
2052301SN/A     * Used by a port to notify the queue that a retry was received
2062301SN/A     * and that the queue can proceed and retry sending the packet
2072727Sktlim@umich.edu     * that caused the wait.
2082301SN/A     */
2092727Sktlim@umich.edu    void retry();
2106221Snate@binkert.org
2112301SN/A    unsigned int drain(DrainManager *dm);
2122301SN/A};
2132727Sktlim@umich.edu
2142301SN/Aclass MasterPacketQueue : public PacketQueue
2152301SN/A{
2162301SN/A
2172301SN/A  protected:
2182727Sktlim@umich.edu
2192727Sktlim@umich.edu    MasterPort& masterPort;
2202727Sktlim@umich.edu
2212727Sktlim@umich.edu  public:
2222727Sktlim@umich.edu
2232727Sktlim@umich.edu    /**
2242727Sktlim@umich.edu     * Create a master packet queue, linked to an event manager, a
2252727Sktlim@umich.edu     * master port, and a label that will be used for functional print
2262727Sktlim@umich.edu     * request packets.
2272301SN/A     *
2282301SN/A     * @param _em Event manager used for scheduling this queue
2296221Snate@binkert.org     * @param _masterPort Master port used to send the packets
2302301SN/A     * @param _label Label to push on the label stack for print request packets
2312301SN/A     */
2322727Sktlim@umich.edu    MasterPacketQueue(EventManager& _em, MasterPort& _masterPort,
2332301SN/A                      const std::string _label = "MasterPacketQueue");
2342326SN/A
2356221Snate@binkert.org    virtual ~MasterPacketQueue() { }
2362301SN/A
2372301SN/A    const std::string name() const
2382727Sktlim@umich.edu    { return masterPort.name() + "-" + label; }
2392301SN/A
2402326SN/A    bool sendTiming(PacketPtr pkt, bool send_as_snoop);
2416221Snate@binkert.org};
2422301SN/A
2432301SN/Aclass SlavePacketQueue : public PacketQueue
2442727Sktlim@umich.edu{
2452301SN/A
2462326SN/A  protected:
2476221Snate@binkert.org
2482301SN/A    SlavePort& slavePort;
2492301SN/A
2502727Sktlim@umich.edu  public:
2512301SN/A
2522326SN/A    /**
2536221Snate@binkert.org     * Create a slave packet queue, linked to an event manager, a
2542301SN/A     * slave port, and a label that will be used for functional print
2552301SN/A     * request packets.
2562727Sktlim@umich.edu     *
2572301SN/A     * @param _em Event manager used for scheduling this queue
2582326SN/A     * @param _slavePort Slave port used to send the packets
2592301SN/A     * @param _label Label to push on the label stack for print request packets
2602301SN/A     */
2612727Sktlim@umich.edu    SlavePacketQueue(EventManager& _em, SlavePort& _slavePort,
2622301SN/A                     const std::string _label = "SlavePacketQueue");
2632326SN/A
2642301SN/A    virtual ~SlavePacketQueue() { }
2652326SN/A
2662301SN/A    const std::string name() const
2672301SN/A    { return slavePort.name() + "-" + label; }
2682727Sktlim@umich.edu
2692301SN/A    bool sendTiming(PacketPtr pkt, bool send_as_snoop);
2702326SN/A
2712301SN/A};
2722326SN/A
2732301SN/A#endif // __MEM_PACKET_QUEUE_HH__
2742301SN/A