Hello Sudhanshu Jha, Nikos Nikoleris,

I'd like you to do a code review. Please visit

    https://gem5-review.googlesource.com/c/public/gem5/+/18809

to review the following change.


Change subject: mem-cache: Add support for more than one prefetcher
......................................................................

mem-cache: Add support for more than one prefetcher

The cache currently only supports a single hardware
prefetcher. However, there are cases where it is desirable to have
multiple prefetchers active at any given moment.

This patch changes the prefetcher parameter into a vector. The cache
then uses the prefetch packet from the first prefetcher that is able
to generate a prefetch. That is, the prefetch vector is sorted in
priority order.

Change-Id: I64b4d8fd424012cb05f5754e6a5956b6ebd9cd0d
Signed-off-by: Andreas Sandberg <[email protected]>
Reviewed-by: Nikos Nikoleris <[email protected]>
Reviewed-by: Sudhanshu Jha <[email protected]>
---
M src/mem/cache/Cache.py
M src/mem/cache/base.cc
M src/mem/cache/base.hh
3 files changed, 54 insertions(+), 24 deletions(-)



diff --git a/src/mem/cache/Cache.py b/src/mem/cache/Cache.py
index 7a28136..dabb016 100644
--- a/src/mem/cache/Cache.py
+++ b/src/mem/cache/Cache.py
@@ -97,7 +97,7 @@

     is_read_only = Param.Bool(False, "Is this cache read only (e.g. inst)")

-    prefetcher = Param.BasePrefetcher(NULL,"Prefetcher attached to cache")
+ prefetcher = VectorParam.BasePrefetcher([], "Prefetcher attached to cache")
     prefetch_on_access = Param.Bool(False,
"Notify the hardware prefetcher on every access (not just misses)")

diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc
index 8929343..ca8d280 100644
--- a/src/mem/cache/base.cc
+++ b/src/mem/cache/base.cc
@@ -87,7 +87,7 @@
       writeBuffer("write buffer", p->write_buffers, p->mshrs), // see below
       tags(p->tags),
       compressor(p->compressor),
-      prefetcher(p->prefetcher),
+      prefetchers(p->prefetcher.begin(), p->prefetcher.end()),
       writeAllocator(p->write_allocator),
       writebackClean(p->writeback_clean),
       tempBlockWriteback(nullptr),
@@ -124,7 +124,7 @@
     tempBlock = new TempCacheBlk(blkSize);

     tags->tagsInit();
-    if (prefetcher)
+    for (auto prefetcher : prefetchers)
         prefetcher->setCache(this);
 }

@@ -212,6 +212,31 @@
     return false;
 }

+Tick
+BaseCache::nextPrefetchReadyTick() const
+{
+    Tick next_ready = MaxTick;
+
+    for (auto prefetcher : prefetchers) {
+        Tick cur_ready = prefetcher->nextPrefetchReadyTime();
+        next_ready = std::min(next_ready, cur_ready);
+    }
+
+    return std::max(next_ready, clockEdge());
+}
+
+PacketPtr
+BaseCache::getPrefetchPacket()
+{
+    for (auto prefetcher : prefetchers) {
+        PacketPtr p = prefetcher->getPacket();
+        if (p)
+            return p;
+    }
+
+    return nullptr;
+}
+
 void
BaseCache::handleTimingReqHit(PacketPtr pkt, CacheBlk *blk, Tick request_time)
 {
@@ -362,7 +387,7 @@
         // the packet in a response
         ppHit->notify(pkt);

-        if (prefetcher && blk && blk->wasPrefetched()) {
+        if (!prefetchers.empty() && blk && blk->wasPrefetched()) {
             blk->status &= ~BlkHWPrefetched;
         }

@@ -373,13 +398,10 @@
         ppMiss->notify(pkt);
     }

-    if (prefetcher) {
-        // track time of availability of next prefetch, if any
-        Tick next_pf_time = prefetcher->nextPrefetchReadyTime();
-        if (next_pf_time != MaxTick) {
-            schedMemSideSendEvent(next_pf_time);
-        }
-    }
+    // track time of availability of next prefetch, if any
+    Tick next_pf_time = nextPrefetchReadyTick();
+    if (next_pf_time != MaxTick)
+        schedMemSideSendEvent(next_pf_time);
 }

 void
@@ -510,9 +532,8 @@

         // Request the bus for a prefetch if this deallocation freed enough
         // MSHRs for a prefetch to take place
-        if (prefetcher && mshrQueue.canPrefetch()) {
- Tick next_pf_time = std::max(prefetcher->nextPrefetchReadyTime(),
-                                         clockEdge());
+        if (mshrQueue.canPrefetch()) {
+            Tick next_pf_time = nextPrefetchReadyTick();
             if (next_pf_time != MaxTick)
                 schedMemSideSendEvent(next_pf_time);
         }
@@ -747,9 +768,9 @@

     // fall through... no pending requests.  Try a prefetch.
     assert(!miss_mshr && !wq_entry);
-    if (prefetcher && mshrQueue.canPrefetch()) {
+    if (mshrQueue.canPrefetch()) {
         // If we have a miss queue slot, we can try a prefetch
-        PacketPtr pkt = prefetcher->getPacket();
+        PacketPtr pkt = getPrefetchPacket();
         if (pkt) {
             Addr pf_addr = pkt->getBlockAddr(blkSize);
             if (!tags->findBlock(pf_addr, pkt->isSecure()) &&
@@ -1715,11 +1736,9 @@
                               writeBuffer.nextReadyTime());

     // Don't signal prefetch ready time if no MSHRs available
-    // Will signal once enoguh MSHRs are deallocated
-    if (prefetcher && mshrQueue.canPrefetch()) {
-        nextReady = std::min(nextReady,
-                             prefetcher->nextPrefetchReadyTime());
-    }
+    // Will signal once enough MSHRs are deallocated
+    if (mshrQueue.canPrefetch())
+        nextReady = std::min(nextReady, nextPrefetchReadyTick());

     return nextReady;
 }
diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh
index bf190a5..93c34e6 100644
--- a/src/mem/cache/base.hh
+++ b/src/mem/cache/base.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, 2015-2016, 2018 ARM Limited
+ * Copyright (c) 2012-2013, 2015-2016, 2018-2019 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -328,8 +328,8 @@
     /** Compression method being used. */
     BaseCacheCompressor* compressor;

-    /** Prefetcher */
-    BasePrefetcher *prefetcher;
+    /** Prefetchers */
+    std::list<BasePrefetcher *> prefetchers;

     /** To probe when a cache hit occurs */
     ProbePointArg<PacketPtr> *ppHit;
@@ -824,6 +824,17 @@
      */
     Tick nextQueueReadyTime() const;

+    /**
+     * Determine when the next prefetch packet will be ready.
+     */
+    Tick nextPrefetchReadyTick() const;
+
+    /**
+     * Get a packet from a prefetch packet from one of the configured
+     * hardware prefetchers.
+     */
+    PacketPtr getPrefetchPacket();
+
     /** Block size of this cache */
     const unsigned blkSize;


--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/18809
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I64b4d8fd424012cb05f5754e6a5956b6ebd9cd0d
Gerrit-Change-Number: 18809
Gerrit-PatchSet: 1
Gerrit-Owner: Andreas Sandberg <[email protected]>
Gerrit-Reviewer: Nikos Nikoleris <[email protected]>
Gerrit-Reviewer: Sudhanshu Jha <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to