summaryrefslogtreecommitdiff
path: root/src/mem/cache/prefetch/base.cc
diff options
context:
space:
mode:
authorMitch Hayenga <mitch.hayenga@arm.com>2014-12-23 09:31:18 -0500
committerMitch Hayenga <mitch.hayenga@arm.com>2014-12-23 09:31:18 -0500
commitdf82a2d00311b96ec7fefc901232ba01bbf26d39 (patch)
treeef7d4ac6cc316d9a67eada5df423d32cef97173d /src/mem/cache/prefetch/base.cc
parent6cb58b2bd2ffd19a667e3b9473ff4a0ccfd14c81 (diff)
downloadgem5-df82a2d00311b96ec7fefc901232ba01bbf26d39.tar.xz
mem: Rework the structuring of the prefetchers
Re-organizes the prefetcher class structure. Previously the BasePrefetcher forced multiple assumptions on the prefetchers that inherited from it. This patch makes the BasePrefetcher class truly representative of base functionality. For example, the base class no longer enforces FIFO order. Instead, prefetchers with FIFO requests (like the existing stride and tagged prefetchers) now inherit from a new QueuedPrefetcher base class. Finally, the stride-based prefetcher now assumes a custimizable lookup table (sets/ways) rather than the previous fully associative structure.
Diffstat (limited to 'src/mem/cache/prefetch/base.cc')
-rw-r--r--src/mem/cache/prefetch/base.cc254
1 files changed, 31 insertions, 223 deletions
diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc
index ab740461d..119397bb5 100644
--- a/src/mem/cache/prefetch/base.cc
+++ b/src/mem/cache/prefetch/base.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 ARM Limited
+ * Copyright (c) 2013-2014 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
@@ -38,6 +38,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ron Dreslinski
+ * Mitch Hayenga
*/
/**
@@ -47,20 +48,14 @@
#include <list>
-#include "base/trace.hh"
-#include "debug/HWPrefetch.hh"
#include "mem/cache/prefetch/base.hh"
#include "mem/cache/base.hh"
-#include "mem/request.hh"
#include "sim/system.hh"
-BasePrefetcher::BasePrefetcher(const Params *p)
- : ClockedObject(p), size(p->size), cache(nullptr), blkSize(0),
- latency(p->latency), degree(p->degree),
- useMasterId(p->use_master_id), pageStop(!p->cross_pages),
- serialSquash(p->serial_squash), onlyData(p->data_accesses_only),
- onMissOnly(p->on_miss_only), onReadOnly(p->on_read_only),
- onPrefetch(p->on_prefetch), system(p->sys),
+BasePrefetcher::BasePrefetcher(const BasePrefetcherParams *p)
+ : ClockedObject(p), cache(nullptr), blkSize(0), system(p->sys),
+ onMiss(p->on_miss), onRead(p->on_read),
+ onWrite(p->on_write), onData(p->on_data), onInst(p->on_inst),
masterId(system->getMasterId(name())),
pageBytes(system->getPageBytes())
{
@@ -77,239 +72,52 @@ BasePrefetcher::setCache(BaseCache *_cache)
void
BasePrefetcher::regStats()
{
- pfIdentified
- .name(name() + ".prefetcher.num_hwpf_identified")
- .desc("number of hwpf identified")
- ;
-
- pfMSHRHit
- .name(name() + ".prefetcher.num_hwpf_already_in_mshr")
- .desc("number of hwpf that were already in mshr")
- ;
-
- pfCacheHit
- .name(name() + ".prefetcher.num_hwpf_already_in_cache")
- .desc("number of hwpf that were already in the cache")
- ;
-
- pfBufferHit
- .name(name() + ".prefetcher.num_hwpf_already_in_prefetcher")
- .desc("number of hwpf that were already in the prefetch queue")
- ;
-
- pfRemovedFull
- .name(name() + ".prefetcher.num_hwpf_evicted")
- .desc("number of hwpf removed due to no buffer left")
- ;
-
- pfRemovedMSHR
- .name(name() + ".prefetcher.num_hwpf_removed_MSHR_hit")
- .desc("number of hwpf removed because MSHR allocated")
- ;
-
pfIssued
- .name(name() + ".prefetcher.num_hwpf_issued")
+ .name(name() + ".num_hwpf_issued")
.desc("number of hwpf issued")
;
+}
- pfSpanPage
- .name(name() + ".prefetcher.num_hwpf_span_page")
- .desc("number of hwpf spanning a virtual page")
- ;
+bool
+BasePrefetcher::observeAccess(const PacketPtr &pkt) const
+{
+ Addr addr = pkt->getAddr();
+ bool fetch = pkt->req->isInstFetch();
+ bool read= pkt->isRead();
+ bool is_secure = pkt->isSecure();
+
+ if (pkt->req->isUncacheable()) return false;
+ if (fetch && !onInst) return false;
+ if (!fetch && !onData) return false;
+ if (!fetch && read && !onRead) return false;
+ if (!fetch && !read && !onWrite) return false;
+
+ if (onMiss) {
+ return !inCache(addr, is_secure) &&
+ !inMissQueue(addr, is_secure);
+ }
- pfSquashed
- .name(name() + ".prefetcher.num_hwpf_squashed_from_miss")
- .desc("number of hwpf that got squashed due to a miss "
- "aborting calculation time")
- ;
+ return true;
}
-inline bool
-BasePrefetcher::inCache(Addr addr, bool is_secure)
+bool
+BasePrefetcher::inCache(Addr addr, bool is_secure) const
{
if (cache->inCache(addr, is_secure)) {
- pfCacheHit++;
return true;
}
return false;
}
-inline bool
-BasePrefetcher::inMissQueue(Addr addr, bool is_secure)
+bool
+BasePrefetcher::inMissQueue(Addr addr, bool is_secure) const
{
if (cache->inMissQueue(addr, is_secure)) {
- pfMSHRHit++;
return true;
}
return false;
}
-PacketPtr
-BasePrefetcher::getPacket()
-{
- DPRINTF(HWPrefetch, "Requesting a hw_pf to issue\n");
-
- if (pf.empty()) {
- DPRINTF(HWPrefetch, "No HW_PF found\n");
- return NULL;
- }
-
- PacketPtr pkt = pf.begin()->pkt;
- while (!pf.empty()) {
- pkt = pf.begin()->pkt;
- pf.pop_front();
-
- Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1);
- bool is_secure = pkt->isSecure();
-
- if (!inCache(blk_addr, is_secure) && !inMissQueue(blk_addr, is_secure))
- // we found a prefetch, return it
- break;
-
- DPRINTF(HWPrefetch, "addr 0x%x (%s) in cache, skipping\n",
- pkt->getAddr(), is_secure ? "s" : "ns");
- delete pkt->req;
- delete pkt;
-
- if (pf.empty()) {
- cache->deassertMemSideBusRequest(BaseCache::Request_PF);
- return NULL; // None left, all were in cache
- }
- }
-
- pfIssued++;
- assert(pkt != NULL);
- DPRINTF(HWPrefetch, "returning 0x%x (%s)\n", pkt->getAddr(),
- pkt->isSecure() ? "s" : "ns");
- return pkt;
-}
-
-
-Tick
-BasePrefetcher::notify(PacketPtr &pkt, Tick tick)
-{
- // Don't consult the prefetcher if any of the following conditons are true
- // 1) The request is uncacheable
- // 2) The request is a fetch, but we are only prefeching data
- // 3) The request is a cache hit, but we are only training on misses
- // 4) THe request is a write, but we are only training on reads
- if (!pkt->req->isUncacheable() && !(pkt->req->isInstFetch() && onlyData) &&
- !(onMissOnly && inCache(pkt->getAddr(), true)) &&
- !(onReadOnly && !pkt->isRead())) {
- // Calculate the blk address
- Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1);
- bool is_secure = pkt->isSecure();
-
- // Check if miss is in pfq, if so remove it
- std::list<DeferredPacket>::iterator iter = inPrefetch(blk_addr,
- is_secure);
- if (iter != pf.end()) {
- DPRINTF(HWPrefetch, "Saw a miss to a queued prefetch addr: "
- "0x%x (%s), removing it\n", blk_addr,
- is_secure ? "s" : "ns");
- pfRemovedMSHR++;
- delete iter->pkt->req;
- delete iter->pkt;
- iter = pf.erase(iter);
- if (pf.empty())
- cache->deassertMemSideBusRequest(BaseCache::Request_PF);
- }
-
- // Remove anything in queue with delay older than time
- // since everything is inserted in time order, start from end
- // and work until pf.empty() or time is earlier
- // This is done to emulate Aborting the previous work on a new miss
- // Needed for serial calculators like GHB
- if (serialSquash) {
- iter = pf.end();
- if (iter != pf.begin())
- iter--;
- while (!pf.empty() && iter->tick >= tick) {
- pfSquashed++;
- DPRINTF(HWPrefetch, "Squashing old prefetch addr: 0x%x\n",
- iter->pkt->getAddr());
- delete iter->pkt->req;
- delete iter->pkt;
- iter = pf.erase(iter);
- if (iter != pf.begin())
- iter--;
- }
- if (pf.empty())
- cache->deassertMemSideBusRequest(BaseCache::Request_PF);
- }
-
-
- std::list<Addr> addresses;
- std::list<Cycles> delays;
- calculatePrefetch(pkt, addresses, delays);
-
- std::list<Addr>::iterator addrIter = addresses.begin();
- std::list<Cycles>::iterator delayIter = delays.begin();
- for (; addrIter != addresses.end(); ++addrIter, ++delayIter) {
- Addr addr = *addrIter;
-
- pfIdentified++;
-
- DPRINTF(HWPrefetch, "Found a pf candidate addr: 0x%x, "
- "inserting into prefetch queue with delay %d time %d\n",
- addr, *delayIter, time);
-
- // Check if it is already in the pf buffer
- if (inPrefetch(addr, is_secure) != pf.end()) {
- pfBufferHit++;
- DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n");
- continue;
- }
-
- // create a prefetch memreq
- Request *prefetchReq = new Request(*addrIter, blkSize, 0, masterId);
- if (is_secure)
- prefetchReq->setFlags(Request::SECURE);
- prefetchReq->taskId(ContextSwitchTaskId::Prefetcher);
- PacketPtr prefetch =
- new Packet(prefetchReq, MemCmd::HardPFReq);
- prefetch->allocate();
- prefetch->req->setThreadContext(pkt->req->contextId(),
- pkt->req->threadId());
-
- // Tag orefetch reqeuests with corresponding PC to train lower
- // cache-level prefetchers
- if (onPrefetch && pkt->req->hasPC())
- prefetch->req->setPC(pkt->req->getPC());
-
- // We just remove the head if we are full
- if (pf.size() == size) {
- pfRemovedFull++;
- PacketPtr old_pkt = pf.begin()->pkt;
- DPRINTF(HWPrefetch, "Prefetch queue full, "
- "removing oldest 0x%x\n", old_pkt->getAddr());
- delete old_pkt->req;
- delete old_pkt;
- pf.pop_front();
- }
-
- pf.push_back(DeferredPacket(tick + clockPeriod() * *delayIter,
- prefetch));
- }
- }
-
- return pf.empty() ? 0 : pf.front().tick;
-}
-
-std::list<BasePrefetcher::DeferredPacket>::iterator
-BasePrefetcher::inPrefetch(Addr address, bool is_secure)
-{
- // Guaranteed to only be one match, we always check before inserting
- std::list<DeferredPacket>::iterator iter;
- for (iter = pf.begin(); iter != pf.end(); iter++) {
- if (((*iter).pkt->getAddr() & ~(Addr)(blkSize-1)) == address &&
- (*iter).pkt->isSecure() == is_secure) {
- return iter;
- }
- }
- return pf.end();
-}
-
bool
BasePrefetcher::samePage(Addr a, Addr b) const
{