arch,x86,mem: Dynamically determine the ISA for Ruby store check
[gem5.git] / src / mem / bridge.hh
index 7342f4a9f5d4396dde117d49227049227ca16bfc..a79d6748489cbea4010b74baebca61cb32f6d906 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012 ARM Limited
+ * Copyright (c) 2011-2013 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
 
 /**
  * @file
- * Declaration of a memory-mapped bus bridge that connects a master
+ * Declaration of a memory-mapped bridge that connects a master
  * and a slave through a request and response queue.
  */
 
 #ifndef __MEM_BRIDGE_HH__
 #define __MEM_BRIDGE_HH__
 
-#include <list>
-#include <queue>
-#include <string>
+#include <deque>
 
-#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
+ * A bridge is used to interface two different crossbars (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.
@@ -72,9 +66,9 @@
  * 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. An incoming request is always
- * accepted (recvTiming returns true), but is potentially NACKed if
- * there is no request space or 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
 {
@@ -85,62 +79,31 @@ class Bridge : public MemObject
      * 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 FastAlloc
+    class RequestState : public Packet::SenderState
     {
 
       public:
 
-        Packet::SenderState *origSenderState;
-        PortID origSrc;
+        const PortID origSrc;
 
-        RequestState(PacketPtr _pkt)
-            : origSenderState(_pkt->senderState),
-              origSrc(_pkt->getSrc())
+        RequestState(PortID orig_src) : origSrc(orig_src)
         { }
 
-        void fixResponse(PacketPtr pkt)
-        {
-            assert(pkt->senderState == this);
-            pkt->setDest(origSrc);
-            pkt->senderState = origSenderState;
-        }
     };
 
     /**
-     * A deferred request stores a packet along with its scheduled
-     * transmission time, and whether we can expect to see a response
-     * or not.
+     * A deferred packet stores a packet along with its scheduled
+     * transmission time
      */
-    class DeferredRequest
+    class DeferredPacket
     {
 
       public:
 
-        Tick ready;
-        PacketPtr pkt;
-        bool expectResponse;
+        const Tick tick;
+        const PacketPtr pkt;
 
-        DeferredRequest(PacketPtr _pkt, Tick t)
-            : ready(t), pkt(_pkt), expectResponse(_pkt->needsResponse())
-        { }
-    };
-
-    /**
-     * A deferred response stores a packet along with its scheduled
-     * transmission time. It also contains information of whether the
-     * bridge NACKed the packet to be able to correctly maintain
-     * counters of outstanding responses.
-     */
-    class DeferredResponse {
-
-      public:
-
-        Tick ready;
-        PacketPtr pkt;
-        bool nackedHere;
-
-        DeferredResponse(PacketPtr _pkt, Tick t, bool nack = false)
-            : ready(t), pkt(_pkt), nackedHere(nack)
+        DeferredPacket(PacketPtr _pkt, Tick _tick) : tick(_tick), pkt(_pkt)
         { }
     };
 
@@ -158,36 +121,33 @@ class Bridge : public MemObject
 
       private:
 
-        /** A pointer to the bridge to which this port belongs. */
-        Bridge *bridge;
+        /** The bridge to which this port belongs. */
+        Bridgebridge;
 
         /**
-         * Master port on the other side of the bridge
-         * (connected to the other bus).
+         * Master port on the other side of the bridge.
          */
         BridgeMasterPort& masterPort;
 
         /** Minimum request delay though this bridge. */
-        Tick delay;
-
-        /** Min delay to respond with a nack. */
-        Tick nackDelay;
+        const Cycles delay;
 
         /** Address ranges to pass through the bridge */
-        AddrRangeList ranges;
+        const AddrRangeList ranges;
 
         /**
          * Response packet queue. Response packets are held in this
          * queue for a specified delay to model the processing delay
-         * of the bridge.
+         * of the bridge. We use a deque as we need to iterate over
+         * the items for functional accesses.
          */
-        std::list<DeferredResponse> responseQueue;
+        std::deque<DeferredPacket> transmitList;
 
         /** Counter to track the outstanding responses. */
         unsigned int outstandingResponses;
 
-        /** If we're waiting for a retry to happen. */
-        bool inRetry;
+        /** If we should send a retry when space becomes available. */
+        bool retryReq;
 
         /** Max queue size for reserved responses. */
         unsigned int respQueueLimit;
@@ -197,39 +157,18 @@ class Bridge : public MemObject
          *
          * @return true if the reserved space has reached the set limit
          */
-        bool respQueueFull();
-
-        /**
-         * Turn the request packet into a NACK response and put it in
-         * the response queue and schedule its transmission.
-         *
-         * @param pkt the request packet to NACK
-         */
-        void nackRequest(PacketPtr pkt);
+        bool respQueueFull() const;
 
         /**
          * Handle send event, scheduled when the packet at the head of
          * the response queue is ready to transmit (for timing
          * accesses only).
          */
-        void trySend();
-
-        /**
-         * Private class for scheduling sending of responses from the
-         * response queue.
-         */
-        class SendEvent : public Event
-        {
-            BridgeSlavePort& port;
-
-          public:
-            SendEvent(BridgeSlavePort& p) : port(p) {}
-            virtual void process() { port.trySend(); }
-            virtual const char *description() const { return "bridge send"; }
-        };
+        void trySendTiming();
 
         /** Send event for the response queue. */
-        SendEvent sendEvent;
+        EventWrapper<BridgeSlavePort,
+                     &BridgeSlavePort::trySendTiming> sendEvent;
 
       public:
 
@@ -239,45 +178,51 @@ class Bridge : public MemObject
          * @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 from seeing a response to sending it
-         * @param _nack_delay the delay from a NACK to sending the response
+         * @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, int _delay,
-                        int _nack_delay, int _resp_limit,
-                        std::vector<Range<Addr> > _ranges);
+        BridgeSlavePort(const std::string& _name, Bridge& _bridge,
+                        BridgeMasterPort& _masterPort, Cycles _delay,
+                        int _resp_limit, std::vector<AddrRange> _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 queueForSendTiming(PacketPtr pkt);
+        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 recvTimingReq(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);
+        void recvFunctional(PacketPtr pkt);
 
         /** When receiving a address range request the peer port,
             pass it to the bridge. */
-        virtual AddrRangeList getAddrRanges();
+        AddrRangeList getAddrRanges() const;
     };
 
 
@@ -291,54 +236,38 @@ class Bridge : public MemObject
 
       private:
 
-        /** A pointer to the bridge to which this port belongs. */
-        Bridge* bridge;
+        /** The bridge to which this port belongs. */
+        Bridge& bridge;
 
         /**
-         * Pointer to the slave port on the other side of the bridge
-         * (connected to the other bus).
+         * The slave port on the other side of the bridge.
          */
         BridgeSlavePort& slavePort;
 
         /** Minimum delay though this bridge. */
-        Tick delay;
+        const Cycles delay;
 
         /**
          * Request packet queue. Request packets are held in this
          * queue for a specified delay to model the processing delay
-         * of the bridge.
+         * of the bridge.  We use a deque as we need to iterate over
+         * the items for functional accesses.
          */
-        std::list<DeferredRequest> requestQueue;
-
-        /** If we're waiting for a retry to happen. */
-        bool inRetry;
+        std::deque<DeferredPacket> transmitList;
 
         /** Max queue size for request packets */
-        unsigned int reqQueueLimit;
+        const 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 trySend();
-
-        /**
-         * Private class for scheduling sending of requests from the
-         * request queue.
-         */
-        class SendEvent : public Event
-        {
-            BridgeMasterPort& port;
-
-          public:
-            SendEvent(BridgeMasterPort& p) : port(p) {}
-            virtual void process() { port.trySend(); }
-            virtual const char *description() const { return "bridge send"; }
-        };
+        void trySendTiming();
 
         /** Send event for the request queue. */
-        SendEvent sendEvent;
+        EventWrapper<BridgeMasterPort,
+                     &BridgeMasterPort::trySendTiming> sendEvent;
 
       public:
 
@@ -348,11 +277,11 @@ class Bridge : public MemObject
          * @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 from seeing a request to sending it
+         * @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, int _delay,
+        BridgeMasterPort(const std::string& _name, Bridge& _bridge,
+                         BridgeSlavePort& _slavePort, Cycles _delay,
                          int _req_limit);
 
         /**
@@ -360,15 +289,16 @@ class Bridge : public MemObject
          *
          * @return true if the occupied space has reached the set limit
          */
-        bool reqQueueFull();
+        bool reqQueueFull() const;
 
         /**
          * 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 queueForSendTiming(PacketPtr pkt);
+        void schedTimingReq(PacketPtr pkt, Tick when);
 
         /**
          * Check a functional request against the packets in our
@@ -384,11 +314,11 @@ class Bridge : public MemObject
 
         /** When receiving a timing request from the peer port,
             pass it to the bridge. */
-        virtual bool recvTimingResp(PacketPtr pkt);
+        bool recvTimingResp(PacketPtr pkt);
 
         /** When receiving a retry request from the peer port,
             pass it to the bridge. */
-        virtual void recvRetry();
+        void recvRetry();
     };
 
     /** Slave port of the bridge. */
@@ -397,25 +327,18 @@ class Bridge : public MemObject
     /** Master port of the bridge. */
     BridgeMasterPort masterPort;
 
-    /** If this bridge should acknowledge writes. */
-    bool ackWrites;
-
-  public:
-    typedef BridgeParams Params;
-
-  protected:
-    Params *_params;
-
   public:
-    const Params *params() const { return _params; }
 
-    virtual MasterPort& getMasterPort(const std::string& if_name,
-                                      int idx = -1);
-    virtual SlavePort& getSlavePort(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);
 };
 
-#endif //__MEM_BUS_HH__
+#endif //__MEM_BRIDGE_HH__