mem-cache: Move access latency calculation to Cache
authorDaniel R. Carvalho <odanrc@yahoo.com.br>
Thu, 18 Oct 2018 13:31:51 +0000 (15:31 +0200)
committerDaniel Carvalho <odanrc@yahoo.com.br>
Wed, 14 Nov 2018 21:02:08 +0000 (21:02 +0000)
Access latency was not being calculated properly, as it was
always assuming that for hits reads take as long as writes,
and that parallel accesses would produce the same latency
for read and write misses.

By moving the calculation to the Cache we can use the write/
read information, reduce latency variables duplication and
remove Cache dependency from Tags.

The tag lookup latency is still calculated by the Tags.

Change-Id: I71bc68fb5c3515b372c3bf002d61b6f048a45540
Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/13697
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>

src/mem/cache/base.cc
src/mem/cache/base.hh
src/mem/cache/tags/Tags.py
src/mem/cache/tags/base.cc
src/mem/cache/tags/base.hh
src/mem/cache/tags/base_set_assoc.hh
src/mem/cache/tags/fa_lru.cc
src/mem/cache/tags/fa_lru.hh
src/mem/cache/tags/sector_tags.cc
src/mem/cache/tags/sector_tags.hh

index 4ca8152e978bd1a2a0e45639e40b0ec308dad61c..980aa91f8de5e7ff84bb165d8009ef6105bdf70f 100644 (file)
@@ -95,6 +95,7 @@ BaseCache::BaseCache(const BaseCacheParams *p, unsigned blk_size)
       forwardLatency(p->tag_latency),
       fillLatency(p->data_latency),
       responseLatency(p->response_latency),
+      sequentialAccess(p->sequential_access),
       numTarget(p->tgts_per_mshr),
       forwardSnoops(true),
       clusivity(p->clusivity),
@@ -225,8 +226,8 @@ BaseCache::handleTimingReqHit(PacketPtr pkt, CacheBlk *blk, Tick request_time)
         // In this case we are considering request_time that takes
         // into account the delay of the xbar, if any, and just
         // lat, neglecting responseLatency, modelling hit latency
-        // just as lookupLatency or or the value of lat overriden
-        // by access(), that calls accessBlock() function.
+        // just as the value of lat overriden by access(), which calls
+        // the calculateAccessLatency() function.
         cpuSidePort.schedTimingResp(pkt, request_time, true);
     } else {
         DPRINTF(Cache, "%s satisfied %s, no response needed\n", __func__,
@@ -342,15 +343,13 @@ BaseCache::recvTimingReq(PacketPtr pkt)
     // the delay provided by the crossbar
     Tick forward_time = clockEdge(forwardLatency) + pkt->headerDelay;
 
-    // We use lookupLatency here because it is used to specify the latency
-    // to access.
-    Cycles lat = lookupLatency;
+    Cycles lat;
     CacheBlk *blk = nullptr;
     bool satisfied = false;
     {
         PacketList writebacks;
         // Note that lat is passed by reference here. The function
-        // access() calls accessBlock() which can modify lat value.
+        // access() will set the lat value.
         satisfied = access(pkt, blk, lat, writebacks);
 
         // copy writebacks to write buffer here to ensure they logically
@@ -360,8 +359,7 @@ BaseCache::recvTimingReq(PacketPtr pkt)
 
     // Here we charge the headerDelay that takes into account the latencies
     // of the bus, if the packet comes from it.
-    // The latency charged it is just lat that is the value of lookupLatency
-    // modified by access() function, or if not just lookupLatency.
+    // The latency charged is just the value set by the access() function.
     // In case of a hit we are neglecting response latency.
     // In case of a miss we are neglecting forward latency.
     Tick request_time = clockEdge(lat) + pkt->headerDelay;
@@ -886,6 +884,31 @@ BaseCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool, bool)
 // Access path: requests coming in from the CPU side
 //
 /////////////////////////////////////////////////////
+Cycles
+BaseCache::calculateAccessLatency(const CacheBlk* blk,
+                                  const Cycles lookup_lat) const
+{
+    Cycles lat(lookup_lat);
+
+    if (blk != nullptr) {
+        // First access tags, then data
+        if (sequentialAccess) {
+            lat += dataLatency;
+        // Latency is dictated by the slowest of tag and data latencies
+        } else {
+            lat = std::max(lookup_lat, dataLatency);
+        }
+
+        // Check if the block to be accessed is available. If not, apply the
+        // access latency on top of block->whenReady.
+        if (blk->whenReady > curTick() &&
+            ticksToCycles(blk->whenReady - curTick()) > lat) {
+            lat += ticksToCycles(blk->whenReady - curTick());
+        }
+    }
+
+    return lat;
+}
 
 bool
 BaseCache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat,
@@ -898,9 +921,12 @@ BaseCache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat,
                   "Should never see a write in a read-only cache %s\n",
                   name());
 
-    // Here lat is the value passed as parameter to accessBlock() function
-    // that can modify its value.
-    blk = tags->accessBlock(pkt->getAddr(), pkt->isSecure(), lat);
+    // Access block in the tags
+    Cycles tag_latency(0);
+    blk = tags->accessBlock(pkt->getAddr(), pkt->isSecure(), tag_latency);
+
+    // Calculate access latency
+    lat = calculateAccessLatency(blk, tag_latency);
 
     DPRINTF(Cache, "%s for %s %s\n", __func__, pkt->print(),
             blk ? "hit " + blk->print() : "miss");
index ad5ff3bc4a5154b4acc19dd40f688d14368f6d36..240bf216f317296a4914cf4d6750063bfeb9bb6f 100644 (file)
@@ -418,6 +418,17 @@ class BaseCache : public MemObject
      */
     Addr regenerateBlkAddr(CacheBlk* blk);
 
+    /**
+     * Calculate access latency in ticks given a tag lookup latency, and
+     * whether access was a hit or miss.
+     *
+     * @param blk The cache block that was accessed.
+     * @param lookup_lat Latency of the respective tag lookup.
+     * @return The number of ticks that pass due to a block access.
+     */
+    Cycles calculateAccessLatency(const CacheBlk* blk,
+                                  const Cycles lookup_lat) const;
+
     /**
      * Does all the processing necessary to perform the provided request.
      * @param pkt The memory request to perform.
@@ -805,6 +816,11 @@ class BaseCache : public MemObject
      */
     const Cycles responseLatency;
 
+    /**
+     * Whether tags and data are accessed sequentially.
+     */
+    const bool sequentialAccess;
+
     /** The number of targets for each MSHR. */
     const int numTarget;
 
index 8e302898c68f4ef86eacdb8253f8be1cafef4236..b34779eeff8f6e17b16bf96c4b2ca49ee4be48e7 100644 (file)
@@ -54,10 +54,6 @@ class BaseTags(ClockedObject):
     tag_latency = Param.Cycles(Parent.tag_latency,
                                "The tag lookup latency for this cache")
 
-    # Get the RAM access latency from the parent (cache)
-    data_latency = Param.Cycles(Parent.data_latency,
-                               "The data access latency for this cache")
-
     # Get the warmup percentage from the parent (cache)
     warmup_percentage = Param.Percent(Parent.warmup_percentage,
         "Percentage of tags to be touched to warm up the cache")
index c6a9a8295ba048eb47603c5735101b50ab75a72b..5fbbdc1940290b6d0bc281f6d432b87088d2cfa5 100644 (file)
 
 BaseTags::BaseTags(const Params *p)
     : ClockedObject(p), blkSize(p->block_size), blkMask(blkSize - 1),
-      size(p->size),
-      lookupLatency(p->tag_latency),
-      accessLatency(p->sequential_access ?
-                    p->tag_latency + p->data_latency :
-                    std::max(p->tag_latency, p->data_latency)),
+      size(p->size), lookupLatency(p->tag_latency),
       cache(nullptr), indexingPolicy(p->indexing_policy),
       warmupBound((p->warmup_percentage/100.0) * (p->size / p->block_size)),
       warmedUp(false), numBlocks(p->size / p->block_size),
index a7a35ffbbaba2465f1b5da2220b5a3b6cf2c3a99..273abf5dcf3d195781fcea5be7d84356a5f19a73 100644 (file)
@@ -79,12 +79,7 @@ class BaseTags : public ClockedObject
     const unsigned size;
     /** The tag lookup latency of the cache. */
     const Cycles lookupLatency;
-    /**
-     * The total access latency of the cache. This latency
-     * is different depending on the cache access mode
-     * (parallel or sequential)
-     */
-    const Cycles accessLatency;
+
     /** Pointer to the parent cache. */
     BaseCache *cache;
 
@@ -293,6 +288,17 @@ class BaseTags : public ClockedObject
     virtual CacheBlk* findVictim(Addr addr, const bool is_secure,
                                  std::vector<CacheBlk*>& evict_blks) const = 0;
 
+    /**
+     * Access block and update replacement data. May not succeed, in which case
+     * nullptr is returned. This has all the implications of a cache access and
+     * should only be used as such. Returns the tag lookup latency as a side
+     * effect.
+     *
+     * @param addr The address to find.
+     * @param is_secure True if the target memory space is secure.
+     * @param lat The latency of the tag lookup.
+     * @return Pointer to the cache block if found.
+     */
     virtual CacheBlk* accessBlock(Addr addr, bool is_secure, Cycles &lat) = 0;
 
     /**
index 58aceb0878cc882ec9c932fcce1a180fd0af44e8..bc98afa5e53c54a5bd8af71af1d8325188bb02c7 100644 (file)
@@ -115,12 +115,13 @@ class BaseSetAssoc : public BaseTags
 
     /**
      * Access block and update replacement data. May not succeed, in which case
-     * nullptr is returned. This has all the implications of a cache
-     * access and should only be used as such. Returns the access latency as a
-     * side effect.
+     * nullptr is returned. This has all the implications of a cache access and
+     * should only be used as such. Returns the tag lookup latency as a side
+     * effect.
+     *
      * @param addr The address to find.
      * @param is_secure True if the target memory space is secure.
-     * @param lat The access latency.
+     * @param lat The latency of the tag lookup.
      * @return Pointer to the cache block if found.
      */
     CacheBlk* accessBlock(Addr addr, bool is_secure, Cycles &lat) override
@@ -139,28 +140,18 @@ class BaseSetAssoc : public BaseTags
             dataAccesses += allocAssoc;
         }
 
+        // If a cache hit
         if (blk != nullptr) {
-            // If a cache hit
-            lat = accessLatency;
-            // Check if the block to be accessed is available. If not,
-            // apply the accessLatency on top of block->whenReady.
-            if (blk->whenReady > curTick() &&
-                cache->ticksToCycles(blk->whenReady - curTick()) >
-                accessLatency) {
-                lat = cache->ticksToCycles(blk->whenReady - curTick()) +
-                accessLatency;
-            }
-
             // Update number of references to accessed block
             blk->refCount++;
 
             // Update replacement data of accessed block
             replacementPolicy->touch(blk->replacementData);
-        } else {
-            // If a cache miss
-            lat = lookupLatency;
         }
 
+        // The tag lookup latency is the same for a hit or a miss
+        lat = lookupLatency;
+
         return blk;
     }
 
index 2c92a940fef205b54f0a42921948a4d0b83da978..9648468716cf997abd3cfec0892a7f67dd3fd213 100644 (file)
@@ -153,30 +153,22 @@ FALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat,
     CachesMask mask = 0;
     FALRUBlk* blk = static_cast<FALRUBlk*>(findBlock(addr, is_secure));
 
+    // If a cache hit
     if (blk && blk->isValid()) {
-        // If a cache hit
-        lat = accessLatency;
-        // Check if the block to be accessed is available. If not,
-        // apply the accessLatency on top of block->whenReady.
-        if (blk->whenReady > curTick() &&
-            cache->ticksToCycles(blk->whenReady - curTick()) >
-            accessLatency) {
-            lat = cache->ticksToCycles(blk->whenReady - curTick()) +
-            accessLatency;
-        }
         mask = blk->inCachesMask;
 
         moveToHead(blk);
-    } else {
-        // If a cache miss
-        lat = lookupLatency;
     }
+
     if (in_caches_mask) {
         *in_caches_mask = mask;
     }
 
     cacheTracking.recordAccess(blk);
 
+    // The tag lookup latency is the same for a hit or a miss
+    lat = lookupLatency;
+
     return blk;
 }
 
index 6ea4c8d6a3a8e0a071572fd23405876f1493f4aa..1de6de400482b1c36f34a967b67d187f533e3828 100644 (file)
@@ -180,10 +180,11 @@ class FALRU : public BaseTags
      * Access block and update replacement data.  May not succeed, in which
      * case nullptr pointer is returned.  This has all the implications of a
      * cache access and should only be used as such.
-     * Returns the access latency and inCachesMask flags as a side effect.
+     * Returns tag lookup latency and the inCachesMask flags as a side effect.
+     *
      * @param addr The address to look for.
      * @param is_secure True if the target memory space is secure.
-     * @param lat The latency of the access.
+     * @param lat The latency of the tag lookup.
      * @param in_cache_mask Mask indicating the caches in which the blk fits.
      * @return Pointer to the cache block.
      */
index 24751c97dcc07edd38090c8457097cb48654a9c6..02649cc408589f4617d0c72480d6bfff592121b6 100644 (file)
@@ -149,18 +149,8 @@ SectorTags::accessBlock(Addr addr, bool is_secure, Cycles &lat)
         dataAccesses += allocAssoc*numBlocksPerSector;
     }
 
+    // If a cache hit
     if (blk != nullptr) {
-        // If a cache hit
-        lat = accessLatency;
-        // Check if the block to be accessed is available. If not,
-        // apply the accessLatency on top of block->whenReady.
-        if (blk->whenReady > curTick() &&
-            cache->ticksToCycles(blk->whenReady - curTick()) >
-            accessLatency) {
-            lat = cache->ticksToCycles(blk->whenReady - curTick()) +
-            accessLatency;
-        }
-
         // Update number of references to accessed block
         blk->refCount++;
 
@@ -171,11 +161,11 @@ SectorTags::accessBlock(Addr addr, bool is_secure, Cycles &lat)
         // Update replacement data of accessed block, which is shared with
         // the whole sector it belongs to
         replacementPolicy->touch(sector_blk->replacementData);
-    } else {
-        // If a cache miss
-        lat = lookupLatency;
     }
 
+    // The tag lookup latency is the same for a hit or a miss
+    lat = lookupLatency;
+
     return blk;
 }
 
index 1149ba1e074ff50b8a4f8fdea52bbb0d66eacb89..f9d47f3c49c43f134451dd92b68aee523212e097 100644 (file)
@@ -118,12 +118,12 @@ class SectorTags : public BaseTags
     /**
      * Access block and update replacement data. May not succeed, in which
      * case nullptr is returned. This has all the implications of a cache
-     * access and should only be used as such. Returns the access latency
+     * access and should only be used as such. Returns the tag lookup latency
      * as a side effect.
      *
      * @param addr The address to find.
      * @param is_secure True if the target memory space is secure.
-     * @param lat The access latency.
+     * @param lat The latency of the tag lookup.
      * @return Pointer to the cache block if found.
      */
     CacheBlk* accessBlock(Addr addr, bool is_secure, Cycles &lat) override;