mem: write streaming support via WriteInvalidate promotion
[gem5.git] / src / mem / cache / base.hh
index e522bc0c960b4d6ec1f85bfedb86c733c429d96c..297b80180f7fd21352866ff933cb669573adab14 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012-2013 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -64,8 +64,8 @@
 #include "mem/cache/mshr_queue.hh"
 #include "mem/mem_object.hh"
 #include "mem/packet.hh"
+#include "mem/qport.hh"
 #include "mem/request.hh"
-#include "mem/tport.hh"
 #include "params/BaseCache.hh"
 #include "sim/eventq.hh"
 #include "sim/full_system.hh"
@@ -94,6 +94,7 @@ class BaseCache : public MemObject
         Blocked_NoMSHRs = MSHRQueue_MSHRs,
         Blocked_NoWBBuffers = MSHRQueue_WriteBuffer,
         Blocked_NoTargets,
+        Blocked_PendingWriteInvalidate,
         NUM_BLOCKED_CAUSES
     };
 
@@ -118,7 +119,7 @@ class BaseCache : public MemObject
      * and the sendDeferredPacket of the timing port is modified to
      * consider both the transmit list and the requests from the MSHR.
      */
-    class CacheMasterPort : public SimpleTimingPort
+    class CacheMasterPort : public QueuedMasterPort
     {
 
       public:
@@ -131,24 +132,22 @@ class BaseCache : public MemObject
         void requestBus(RequestCause cause, Tick time)
         {
             DPRINTF(CachePort, "Asserting bus request for cause %d\n", cause);
-            schedSendEvent(time);
-        }
-
-        void respond(PacketPtr pkt, Tick time) {
-            schedSendTiming(pkt, time);
+            queue.schedSendEvent(time);
         }
 
       protected:
 
         CacheMasterPort(const std::string &_name, BaseCache *_cache,
-                        const std::string &_label);
+                        MasterPacketQueue &_queue) :
+            QueuedMasterPort(_name, _cache, _queue)
+        { }
 
         /**
          * Memory-side port always snoops.
          *
-         * return always true
+         * @return always true
          */
-        virtual bool isSnooping() { return true; }
+        virtual bool isSnooping() const { return true; }
     };
 
     /**
@@ -159,7 +158,7 @@ class BaseCache : public MemObject
      * incoming requests. If blocked, the port will issue a retry once
      * unblocked.
      */
-    class CacheSlavePort : public SimpleTimingPort
+    class CacheSlavePort : public QueuedSlavePort
     {
 
       public:
@@ -170,22 +169,26 @@ class BaseCache : public MemObject
         /** Return to normal operation and accept new requests. */
         void clearBlocked();
 
-        void respond(PacketPtr pkt, Tick time) {
-            schedSendTiming(pkt, time);
-        }
+        bool isBlocked() const { return blocked; }
 
       protected:
 
         CacheSlavePort(const std::string &_name, BaseCache *_cache,
                        const std::string &_label);
 
+        /** A normal packet queue used to store responses. */
+        SlavePacketQueue queue;
+
         bool blocked;
 
         bool mustSendRetry;
 
       private:
 
-        EventWrapper<Port, &Port::sendRetry> sendRetryEvent;
+        void processSendRetry();
+
+        EventWrapper<CacheSlavePort,
+                     &CacheSlavePort::processSendRetry> sendRetryEvent;
 
     };
 
@@ -226,24 +229,51 @@ class BaseCache : public MemObject
         }
     }
 
+    /**
+     * Write back dirty blocks in the cache using functional accesses.
+     */
+    virtual void memWriteback() = 0;
+    /**
+     * Invalidates all blocks in the cache.
+     *
+     * @warn Dirty cache lines will not be written back to
+     * memory. Make sure to call functionalWriteback() first if you
+     * want the to write them to memory.
+     */
+    virtual void memInvalidate() = 0;
+    /**
+     * Determine if there are any dirty blocks in the cache.
+     *
+     * \return true if at least one block is dirty, false otherwise.
+     */
+    virtual bool isDirty() const = 0;
+
     /** Block size of this cache */
     const unsigned blkSize;
 
     /**
      * The latency of a hit in this device.
      */
-    int hitLatency;
+    const Cycles hitLatency;
+
+    /**
+     * The latency of sending reponse to its upper level cache/core on a
+     * linefill. In most contemporary processors, the return path on a cache
+     * miss is much quicker that the hit latency. The responseLatency parameter
+     * tries to capture this latency.
+     */
+    const Cycles responseLatency;
 
     /** The number of targets for each MSHR. */
     const int numTarget;
 
     /** Do we forward snoops from mem side port through to cpu side port? */
-    bool forwardSnoops;
+    const bool forwardSnoops;
 
     /** Is this cache a toplevel cache (e.g. L1, I/O cache). If so we should
      * never try to forward ownership and similar optimizations to the cpu
      * side */
-    bool isTopLevel;
+    const bool isTopLevel;
 
     /**
      * Bit vector of the blocking reasons for the access path.
@@ -255,7 +285,7 @@ class BaseCache : public MemObject
     uint64_t order;
 
     /** Stores time the cache blocked for statistics. */
-    Tick blockedCycle;
+    Cycles blockedCycle;
 
     /** Pointer to the MSHR that has no targets. */
     MSHR *noTargetMSHR;
@@ -263,13 +293,10 @@ class BaseCache : public MemObject
     /** The number of misses to trigger an exit event. */
     Counter missCount;
 
-    /** The drain event. */
-    Event *drainEvent;
-
     /**
      * The address range to which the cache responds on the CPU side.
      * Normally this is all possible memory addresses. */
-    Range<Addr> addrRange;
+    const AddrRangeList addrRanges;
 
   public:
     /** System we are currently operating in. */
@@ -425,6 +452,11 @@ class BaseCache : public MemObject
 
     virtual void init();
 
+    virtual BaseMasterPort &getMasterPort(const std::string &if_name,
+                                          PortID idx = InvalidPortID);
+    virtual BaseSlavePort &getSlavePort(const std::string &if_name,
+                                        PortID idx = InvalidPortID);
+
     /**
      * Query block size of a cache.
      * @return  The block size
@@ -439,7 +471,7 @@ class BaseCache : public MemObject
     Addr blockAlign(Addr addr) const { return (addr & ~(Addr(blkSize - 1))); }
 
 
-    const Range<Addr> &getAddrRange() const { return addrRange; }
+    const AddrRangeList &getAddrRanges() const { return addrRanges; }
 
     MSHR *allocateMissBuffer(PacketPtr pkt, Tick time, bool requestBus)
     {
@@ -469,7 +501,7 @@ class BaseCache : public MemObject
     /**
      * Returns true if the cache is blocked for accesses.
      */
-    bool isBlocked()
+    bool isBlocked() const
     {
         return blocked != 0;
     }
@@ -484,7 +516,7 @@ class BaseCache : public MemObject
         uint8_t flag = 1 << cause;
         if (blocked == 0) {
             blocked_causes[cause]++;
-            blockedCycle = curTick();
+            blockedCycle = curCycle();
             cpuSidePort->setBlocked();
         }
         blocked |= flag;
@@ -504,7 +536,7 @@ class BaseCache : public MemObject
         blocked &= ~flag;
         DPRINTF(Cache,"Unblocking for cause %d, mask=%d\n", cause, blocked);
         if (blocked == 0) {
-            blocked_cycles[cause] += curTick() - blockedCycle;
+            blocked_cycles[cause] += curCycle() - blockedCycle;
             cpuSidePort->clearBlocked();
         }
     }
@@ -532,17 +564,17 @@ class BaseCache : public MemObject
         // interesting again.
     }
 
-    virtual unsigned int drain(Event *de);
+    virtual unsigned int drain(DrainManager *dm);
 
-    virtual bool inCache(Addr addr) = 0;
+    virtual bool inCache(Addr addr, bool is_secure) const = 0;
 
-    virtual bool inMissQueue(Addr addr) = 0;
+    virtual bool inMissQueue(Addr addr, bool is_secure) const = 0;
 
     void incMissCount(PacketPtr pkt)
     {
         assert(pkt->req->masterId() < system->maxMasters());
         misses[pkt->cmdToIndex()][pkt->req->masterId()]++;
-
+        pkt->req->incAccessDepth();
         if (missCount) {
             --missCount;
             if (missCount == 0)