mem: Tidy up bus addr range debug messages
[gem5.git] / src / mem / bridge.hh
index 40f033811277e5ac453b4807680045d1d2be0d94..6855d27222374b0544c239f9eb71baacd096c8cc 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2011-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.
  *
  *
  * Authors: Ali Saidi
  *          Steve Reinhardt
+ *          Andreas Hansson
  */
 
 /**
  * @file
- * Declaration of a simple bus bridge object with no buffering
+ * Declaration of a memory-mapped bus bridge that connects a master
+ * and a slave through a request and response queue.
  */
 
 #ifndef __MEM_BRIDGE_HH__
 #define __MEM_BRIDGE_HH__
 
-#include <string>
 #include <list>
-#include <inttypes.h>
-#include <queue>
 
-#include "base/fast_alloc.hh"
+#include "base/types.hh"
 #include "mem/mem_object.hh"
-#include "mem/packet.hh"
-#include "mem/port.hh"
 #include "params/Bridge.hh"
-#include "sim/eventq.hh"
 
+/**
+ * A bridge is used to interface two different busses (or in general a
+ * memory-mapped master and slave), with buffering for requests and
+ * responses. The bridge has a fixed delay for packets passing through
+ * it and responds to a fixed set of address ranges.
+ *
+ * The bridge comprises a slave port and a master port, that buffer
+ * outgoing responses and requests respectively. Buffer space is
+ * reserved when a request arrives, also reserving response space
+ * before forwarding the request. If there is no space present, then
+ * the bridge will delay accepting the packet until space becomes
+ * available.
+ */
 class Bridge : public MemObject
 {
   protected:
-    /** Declaration of the buses port type, one will be instantiated for each
-        of the interfaces connecting to the bus. */
-    class BridgePort : public Port
+
+    /**
+     * A bridge request state stores packets along with their sender
+     * state and original source. It has enough information to also
+     * restore the response once it comes back to the bridge.
+     */
+    class RequestState : public Packet::SenderState
+    {
+
+      public:
+
+        Packet::SenderState *origSenderState;
+        PortID origSrc;
+
+        RequestState(PacketPtr _pkt)
+            : origSenderState(_pkt->senderState),
+              origSrc(_pkt->getSrc())
+        { }
+
+        void fixResponse(PacketPtr pkt)
+        {
+            assert(pkt->senderState == this);
+            pkt->setDest(origSrc);
+            pkt->senderState = origSenderState;
+        }
+    };
+
+    /**
+     * A deferred packet stores a packet along with its scheduled
+     * transmission time
+     */
+    class DeferredPacket
+    {
+
+      public:
+
+        Tick tick;
+        PacketPtr pkt;
+
+        DeferredPacket(PacketPtr _pkt, Tick _tick) : tick(_tick), pkt(_pkt)
+        { }
+    };
+
+    // Forward declaration to allow the slave port to have a pointer
+    class BridgeMasterPort;
+
+    /**
+     * The port on the side that receives requests and sends
+     * responses. The slave port has a set of address ranges that it
+     * is responsible for. The slave port also has a buffer for the
+     * responses not yet sent.
+     */
+    class BridgeSlavePort : public SlavePort
     {
-        /** A pointer to the bridge to which this port belongs. */
-        Bridge *bridge;
+
+      private:
+
+        /** The bridge to which this port belongs. */
+        Bridge& bridge;
 
         /**
-         * Pointer to the port on the other side of the bridge
-         * (connected to the other bus).
+         * Master port on the other side of the bridge (connected to
+         * the other bus).
          */
-        BridgePort *otherPort;
+        BridgeMasterPort& masterPort;
 
-        /** Minimum delay though this bridge. */
-        Tick delay;
-
-        /** Min delay to respond to a nack. */
-        Tick nackDelay;
-
-        /** Pass ranges from one side of the bridge to the other? */
-        std::vector<Range<Addr> > filterRanges;
-
-        class PacketBuffer : public Packet::SenderState, public FastAlloc {
-
-          public:
-            Tick ready;
-            PacketPtr pkt;
-            bool nackedHere;
-            Packet::SenderState *origSenderState;
-            short origSrc;
-            bool expectResponse;
-
-            PacketBuffer(PacketPtr _pkt, Tick t, bool nack = false)
-                : ready(t), pkt(_pkt), nackedHere(nack),
-                  origSenderState(_pkt->senderState),
-                  origSrc(nack ? _pkt->getDest() : _pkt->getSrc() ),
-                  expectResponse(_pkt->needsResponse() && !nack)
-
-            {
-                if (!pkt->isResponse() && !nack)
-                    pkt->senderState = this;
-            }
-
-            void fixResponse(PacketPtr pkt)
-            {
-                assert(pkt->senderState == this);
-                pkt->setDest(origSrc);
-                pkt->senderState = origSenderState;
-            }
-        };
+        /** Minimum request delay though this bridge. */
+        Cycles delay;
+
+        /** Address ranges to pass through the bridge */
+        AddrRangeList ranges;
 
         /**
-         * Outbound packet queue.  Packets are held in this queue for a
-         * specified delay to model the processing delay of the
-         * bridge.
+         * Response packet queue. Response packets are held in this
+         * queue for a specified delay to model the processing delay
+         * of the bridge.
          */
-        std::list<PacketBuffer*> sendQueue;
+        std::list<DeferredPacket> transmitList;
 
-        int outstandingResponses;
-        int queuedRequests;
+        /** Counter to track the outstanding responses. */
+        unsigned int outstandingResponses;
 
-        /** If we're waiting for a retry to happen.*/
-        bool inRetry;
-
-        /** Max queue size for outbound packets */
-        int reqQueueLimit;
+        /** If we should send a retry when space becomes available. */
+        bool retryReq;
 
         /** Max queue size for reserved responses. */
-        int respQueueLimit;
+        unsigned int respQueueLimit;
 
         /**
-         * Is this side blocked from accepting outbound packets?
+         * Is this side blocked from accepting new response packets.
+         *
+         * @return true if the reserved space has reached the set limit
          */
         bool respQueueFull();
-        bool reqQueueFull();
-
-        void queueForSendTiming(PacketPtr pkt);
-
-        void finishSend(PacketBuffer *buf);
-
-        void nackRequest(PacketPtr pkt);
 
         /**
          * Handle send event, scheduled when the packet at the head of
-         * the outbound queue is ready to transmit (for timing
+         * the response queue is ready to transmit (for timing
          * accesses only).
          */
-        void trySend();
+        void trySendTiming();
 
-        class SendEvent : public Event
-        {
-            BridgePort *port;
+        /** Send event for the response queue. */
+        EventWrapper<BridgeSlavePort,
+                     &BridgeSlavePort::trySendTiming> sendEvent;
 
-          public:
-            SendEvent(BridgePort *p) : port(p) {}
-            virtual void process() { port->trySend(); }
-            virtual const char *description() const { return "bridge send"; }
-        };
+      public:
 
-        SendEvent sendEvent;
+        /**
+         * Constructor for the BridgeSlavePort.
+         *
+         * @param _name the port name including the owner
+         * @param _bridge the structural owner
+         * @param _masterPort the master port on the other side of the bridge
+         * @param _delay the delay in cycles from receiving to sending
+         * @param _resp_limit the size of the response queue
+         * @param _ranges a number of address ranges to forward
+         */
+        BridgeSlavePort(const std::string& _name, Bridge& _bridge,
+                        BridgeMasterPort& _masterPort, Cycles _delay,
+                        int _resp_limit, std::vector<AddrRange> _ranges);
 
-      public:
-        /** Constructor for the BusPort.*/
-        BridgePort(const std::string &_name, Bridge *_bridge,
-                BridgePort *_otherPort, int _delay, int _nack_delay,
-                int _req_limit, int _resp_limit,
-                std::vector<Range<Addr> > filter_ranges);
+        /**
+         * Queue a response packet to be sent out later and also schedule
+         * a send if necessary.
+         *
+         * @param pkt a response to send out after a delay
+         * @param when tick when response packet should be sent
+         */
+        void schedTimingResp(PacketPtr pkt, Tick when);
+
+        /**
+         * Retry any stalled request that we have failed to accept at
+         * an earlier point in time. This call will do nothing if no
+         * request is waiting.
+         */
+        void retryStalledReq();
 
       protected:
 
         /** When receiving a timing request from the peer port,
             pass it to the bridge. */
-        virtual bool recvTiming(PacketPtr pkt);
+        bool recvTimingReq(PacketPtr pkt);
 
         /** When receiving a retry request from the peer port,
             pass it to the bridge. */
-        virtual void recvRetry();
+        void recvRetry();
 
         /** When receiving a Atomic requestfrom the peer port,
             pass it to the bridge. */
-        virtual Tick recvAtomic(PacketPtr pkt);
+        Tick recvAtomic(PacketPtr pkt);
 
         /** When receiving a Functional request from the peer port,
             pass it to the bridge. */
-        virtual void recvFunctional(PacketPtr pkt);
-
-        /** When receiving a status changefrom the peer port,
-            pass it to the bridge. */
-        virtual void recvStatusChange(Status status);
+        void recvFunctional(PacketPtr pkt);
 
         /** When receiving a address range request the peer port,
             pass it to the bridge. */
-        virtual void getDeviceAddressRanges(AddrRangeList &resp,
-                                            bool &snoop);
+        AddrRangeList getAddrRanges() const;
     };
 
-    BridgePort portA, portB;
 
-    /** If this bridge should acknowledge writes. */
-    bool ackWrites;
+    /**
+     * Port on the side that forwards requests and receives
+     * responses. The master port has a buffer for the requests not
+     * yet sent.
+     */
+    class BridgeMasterPort : public MasterPort
+    {
 
-  public:
-    typedef BridgeParams Params;
+      private:
 
-  protected:
-    Params *_params;
+        /** The bridge to which this port belongs. */
+        Bridge& bridge;
+
+        /**
+         * The slave port on the other side of the bridge (connected
+         * to the other bus).
+         */
+        BridgeSlavePort& slavePort;
+
+        /** Minimum delay though this bridge. */
+        Cycles delay;
+
+        /**
+         * Request packet queue. Request packets are held in this
+         * queue for a specified delay to model the processing delay
+         * of the bridge.
+         */
+        std::list<DeferredPacket> transmitList;
+
+        /** Max queue size for request packets */
+        unsigned int reqQueueLimit;
+
+        /**
+         * Handle send event, scheduled when the packet at the head of
+         * the outbound queue is ready to transmit (for timing
+         * accesses only).
+         */
+        void trySendTiming();
+
+        /** Send event for the request queue. */
+        EventWrapper<BridgeMasterPort,
+                     &BridgeMasterPort::trySendTiming> sendEvent;
+
+      public:
+
+        /**
+         * Constructor for the BridgeMasterPort.
+         *
+         * @param _name the port name including the owner
+         * @param _bridge the structural owner
+         * @param _slavePort the slave port on the other side of the bridge
+         * @param _delay the delay in cycles from receiving to sending
+         * @param _req_limit the size of the request queue
+         */
+        BridgeMasterPort(const std::string& _name, Bridge& _bridge,
+                         BridgeSlavePort& _slavePort, Cycles _delay,
+                         int _req_limit);
+
+        /**
+         * Is this side blocked from accepting new request packets.
+         *
+         * @return true if the occupied space has reached the set limit
+         */
+        bool reqQueueFull();
+
+        /**
+         * Queue a request packet to be sent out later and also schedule
+         * a send if necessary.
+         *
+         * @param pkt a request to send out after a delay
+         * @param when tick when response packet should be sent
+         */
+        void schedTimingReq(PacketPtr pkt, Tick when);
+
+        /**
+         * Check a functional request against the packets in our
+         * request queue.
+         *
+         * @param pkt packet to check against
+         *
+         * @return true if we find a match
+         */
+        bool checkFunctional(PacketPtr pkt);
+
+      protected:
+
+        /** When receiving a timing request from the peer port,
+            pass it to the bridge. */
+        bool recvTimingResp(PacketPtr pkt);
+
+        /** When receiving a retry request from the peer port,
+            pass it to the bridge. */
+        void recvRetry();
+    };
+
+    /** Slave port of the bridge. */
+    BridgeSlavePort slavePort;
+
+    /** Master port of the bridge. */
+    BridgeMasterPort masterPort;
 
   public:
-    const Params *params() const { return _params; }
 
-    /** A function used to return the port associated with this bus object. */
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual BaseMasterPort& getMasterPort(const std::string& if_name,
+                                          PortID idx = InvalidPortID);
+    virtual BaseSlavePort& getSlavePort(const std::string& if_name,
+                                        PortID idx = InvalidPortID);
 
     virtual void init();
 
+    typedef BridgeParams Params;
+
     Bridge(Params *p);
 };