mem: Introduce a variable for the retrying port
[gem5.git] / src / mem / bus.hh
index a3469a478f22fe7abfb8f6afa013542de19e62f4..2cd21ff85a640c3c6bbfdbe0e3fecd3fde2604ea 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
@@ -51,7 +51,7 @@
 #ifndef __MEM_BUS_HH__
 #define __MEM_BUS_HH__
 
-#include <list>
+#include <deque>
 #include <set>
 
 #include "base/addr_range_map.hh"
@@ -94,7 +94,7 @@ class BaseBus : public MemObject
      * whereas a response layer holds master ports.
      */
     template <typename PortClass>
-    class Layer
+    class Layer : public Drainable
     {
 
       public:
@@ -105,9 +105,8 @@ class BaseBus : public MemObject
          *
          * @param _bus the bus this layer belongs to
          * @param _name the layer's name
-         * @param _clock clock period in ticks
          */
-        Layer(BaseBus& _bus, const std::string& _name, Tick _clock);
+        Layer(BaseBus& _bus, const std::string& _name);
 
         /**
          * Drain according to the normal semantics, so that the bus
@@ -118,7 +117,7 @@ class BaseBus : public MemObject
          *
          * @return 1 if busy or waiting to retry, or 0 if idle
          */
-        unsigned int drain(Event *de);
+        unsigned int drain(DrainManager *dm);
 
         /**
          * Get the bus layer's name
@@ -203,17 +202,22 @@ class BaseBus : public MemObject
         /** track the state of the bus layer */
         State state;
 
-        /** the clock speed for the bus layer */
-        Tick clock;
-
-        /** event for signalling when drained */
-        Event * drainEvent;
+        /** manager to signal when drained */
+        DrainManager *drainManager;
 
         /**
          * An array of ports that retry should be called
          * on because the original send failed for whatever reason.
          */
-        std::list<PortClass*> retryList;
+        std::deque<PortClass*> retryList;
+
+        /**
+         * Port that we are currently in the process of telling to
+         * retry a previously failed attempt to perform a timing
+         * transaction. This is a valid port when in the retry state,
+         * and NULL when in busy or idle.
+         */
+        PortClass* retryingPort;
 
         /**
          * Release the bus layer after being occupied and return to an
@@ -236,7 +240,10 @@ class BaseBus : public MemObject
     typedef AddrRangeMap<PortID>::const_iterator PortMapConstIter;
     AddrRangeMap<PortID> portMap;
 
-    AddrRangeList defaultRange;
+    /** all contigous ranges seen by this bus */
+    AddrRangeList busRanges;
+
+    AddrRange defaultRange;
 
     /**
      * Function called by the port when the bus is recieving a range change.
@@ -256,25 +263,21 @@ class BaseBus : public MemObject
     struct PortCache {
         bool valid;
         PortID id;
-        Addr start;
-        Addr end;
+        AddrRange range;
     };
 
     PortCache portCache[3];
 
     // Checks the cache and returns the id of the port that has the requested
     // address within its range
-    inline PortID checkPortCache(Addr addr) {
-        if (portCache[0].valid && addr >= portCache[0].start &&
-            addr < portCache[0].end) {
+    inline PortID checkPortCache(Addr addr) const {
+        if (portCache[0].valid && portCache[0].range.contains(addr)) {
             return portCache[0].id;
         }
-        if (portCache[1].valid && addr >= portCache[1].start &&
-                   addr < portCache[1].end) {
+        if (portCache[1].valid && portCache[1].range.contains(addr)) {
             return portCache[1].id;
         }
-        if (portCache[2].valid && addr >= portCache[2].start &&
-            addr < portCache[2].end) {
+        if (portCache[2].valid && portCache[2].range.contains(addr)) {
             return portCache[2].id;
         }
 
@@ -282,21 +285,18 @@ class BaseBus : public MemObject
     }
 
     // Clears the earliest entry of the cache and inserts a new port entry
-    inline void updatePortCache(short id, Addr start, Addr end) {
+    inline void updatePortCache(short id, const AddrRange& range) {
         portCache[2].valid = portCache[1].valid;
         portCache[2].id    = portCache[1].id;
-        portCache[2].start = portCache[1].start;
-        portCache[2].end   = portCache[1].end;
+        portCache[2].range = portCache[1].range;
 
         portCache[1].valid = portCache[0].valid;
         portCache[1].id    = portCache[0].id;
-        portCache[1].start = portCache[0].start;
-        portCache[1].end   = portCache[0].end;
+        portCache[1].range = portCache[0].range;
 
         portCache[0].valid = true;
         portCache[0].id    = id;
-        portCache[0].start = start;
-        portCache[0].end   = end;
+        portCache[0].range = range;
     }
 
     // Clears the cache. Needs to be called in constructor.
@@ -313,12 +313,13 @@ class BaseBus : public MemObject
      */
     AddrRangeList getAddrRanges() const;
 
-    /** Calculate the timing parameters for the packet.  Updates the
-     * firstWordTime and finishTime fields of the packet object.
-     * Returns the tick at which the packet header is completed (which
-     * will be all that is sent if the target rejects the packet).
+    /**
+     * Calculate the timing parameters for the packet. Updates the
+     * busFirstWordDelay and busLastWordDelay fields of the packet
+     * object with the relative number of ticks required to transmit
+     * the header and the first word, and the last word, respectively.
      */
-    Tick calcPacketTiming(PacketPtr pkt);
+    void calcPacketTiming(PacketPtr pkt);
 
     /**
      * Ask everyone on the bus what their size is and determine the
@@ -329,7 +330,14 @@ class BaseBus : public MemObject
      */
     unsigned deviceBlockSize() const;
 
-    std::set<PortID> inRecvRangeChange;
+    /**
+     * Remember for each of the master ports of the bus if we got an
+     * address range from the connected slave. For convenience, also
+     * keep track of if we got ranges from all the slave modules or
+     * not.
+     */
+    std::vector<bool> gotAddrRanges;
+    bool gotAllAddrRanges;
 
     /** The master and slave ports of the bus */
     std::vector<SlavePort*> slavePorts;
@@ -361,10 +369,12 @@ class BaseBus : public MemObject
     virtual void init();
 
     /** A function used to return the port associated with this bus object. */
-    virtual MasterPort& getMasterPort(const std::string& if_name, int idx = -1);
-    virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1);
+    BaseMasterPort& getMasterPort(const std::string& if_name,
+                                  PortID idx = InvalidPortID);
+    BaseSlavePort& getSlavePort(const std::string& if_name,
+                                PortID idx = InvalidPortID);
 
-    virtual unsigned int drain(Event *de) = 0;
+    virtual unsigned int drain(DrainManager *dm) = 0;
 
 };