mem-cache: decoupled prefetchers from cache
This patches decouples the prefetchers from the cache implementation as the first step to allow using the classic prefetchers with ruby caches. The prefetchers that need do cache lookups can do so using the accessor object provided when the probes are notified. This may also facilitate connecting the same prefetcher to multiple caches. Related JIRA: https://gem5.atlassian.net/browse/GEM5-457 https://gem5.atlassian.net/browse/GEM5-1112 Change-Id: I4fee1a3613ae009fabf45d7b747e4582cad315ef Signed-off-by: Tiago Mück <tiago.muck@arm.com>
This commit is contained in:
32
src/mem/cache/base.cc
vendored
32
src/mem/cache/base.cc
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013, 2018-2019 ARM Limited
|
||||
* Copyright (c) 2012-2013, 2018-2019, 2023 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -81,6 +81,7 @@ BaseCache::BaseCache(const BaseCacheParams &p, unsigned blk_size)
|
||||
: ClockedObject(p),
|
||||
cpuSidePort (p.name + ".cpu_side_port", *this, "CpuSidePort"),
|
||||
memSidePort(p.name + ".mem_side_port", this, "MemSidePort"),
|
||||
accessor(*this),
|
||||
mshrQueue("MSHRs", p.mshrs, 0, p.demand_mshr_reserve, p.name),
|
||||
writeBuffer("write buffer", p.write_buffers, p.mshrs, p.name),
|
||||
tags(p.tags),
|
||||
@@ -126,7 +127,7 @@ BaseCache::BaseCache(const BaseCacheParams &p, unsigned blk_size)
|
||||
|
||||
tags->tagsInit();
|
||||
if (prefetcher)
|
||||
prefetcher->setCache(this);
|
||||
prefetcher->setParentInfo(system, getProbeManager(), getBlockSize());
|
||||
|
||||
fatal_if(compressor && !dynamic_cast<CompressedTags*>(tags),
|
||||
"The tags of compressed cache %s must derive from CompressedTags",
|
||||
@@ -448,7 +449,7 @@ BaseCache::recvTimingReq(PacketPtr pkt)
|
||||
if (satisfied) {
|
||||
// notify before anything else as later handleTimingReqHit might turn
|
||||
// the packet in a response
|
||||
ppHit->notify(pkt);
|
||||
ppHit->notify(CacheAccessProbeArg(pkt,accessor));
|
||||
|
||||
if (prefetcher && blk && blk->wasPrefetched()) {
|
||||
DPRINTF(Cache, "Hit on prefetch for addr %#x (%s)\n",
|
||||
@@ -460,7 +461,7 @@ BaseCache::recvTimingReq(PacketPtr pkt)
|
||||
} else {
|
||||
handleTimingReqMiss(pkt, blk, forward_time, request_time);
|
||||
|
||||
ppMiss->notify(pkt);
|
||||
ppMiss->notify(CacheAccessProbeArg(pkt,accessor));
|
||||
}
|
||||
|
||||
if (prefetcher) {
|
||||
@@ -557,7 +558,7 @@ BaseCache::recvTimingResp(PacketPtr pkt)
|
||||
writeAllocator->allocate() : mshr->allocOnFill();
|
||||
blk = handleFill(pkt, blk, writebacks, allocate);
|
||||
assert(blk != nullptr);
|
||||
ppFill->notify(pkt);
|
||||
ppFill->notify(CacheAccessProbeArg(pkt, accessor));
|
||||
}
|
||||
|
||||
// Don't want to promote the Locked RMW Read until
|
||||
@@ -771,7 +772,8 @@ void
|
||||
BaseCache::updateBlockData(CacheBlk *blk, const PacketPtr cpkt,
|
||||
bool has_old_data)
|
||||
{
|
||||
DataUpdate data_update(regenerateBlkAddr(blk), blk->isSecure());
|
||||
CacheDataUpdateProbeArg data_update(
|
||||
regenerateBlkAddr(blk), blk->isSecure(), accessor);
|
||||
if (ppDataUpdate->hasListeners()) {
|
||||
if (has_old_data) {
|
||||
data_update.oldData = std::vector<uint64_t>(blk->data,
|
||||
@@ -809,7 +811,8 @@ BaseCache::cmpAndSwap(CacheBlk *blk, PacketPtr pkt)
|
||||
assert(sizeof(uint64_t) >= pkt->getSize());
|
||||
|
||||
// Get a copy of the old block's contents for the probe before the update
|
||||
DataUpdate data_update(regenerateBlkAddr(blk), blk->isSecure());
|
||||
CacheDataUpdateProbeArg data_update(
|
||||
regenerateBlkAddr(blk), blk->isSecure(), accessor);
|
||||
if (ppDataUpdate->hasListeners()) {
|
||||
data_update.oldData = std::vector<uint64_t>(blk->data,
|
||||
blk->data + (blkSize / sizeof(uint64_t)));
|
||||
@@ -1106,7 +1109,8 @@ BaseCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool, bool)
|
||||
if (pkt->isAtomicOp()) {
|
||||
// Get a copy of the old block's contents for the probe before
|
||||
// the update
|
||||
DataUpdate data_update(regenerateBlkAddr(blk), blk->isSecure());
|
||||
CacheDataUpdateProbeArg data_update(
|
||||
regenerateBlkAddr(blk), blk->isSecure(), accessor);
|
||||
if (ppDataUpdate->hasListeners()) {
|
||||
data_update.oldData = std::vector<uint64_t>(blk->data,
|
||||
blk->data + (blkSize / sizeof(uint64_t)));
|
||||
@@ -2507,11 +2511,15 @@ BaseCache::CacheStats::regStats()
|
||||
void
|
||||
BaseCache::regProbePoints()
|
||||
{
|
||||
ppHit = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Hit");
|
||||
ppMiss = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Miss");
|
||||
ppFill = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Fill");
|
||||
ppHit = new ProbePointArg<CacheAccessProbeArg>(
|
||||
this->getProbeManager(), "Hit");
|
||||
ppMiss = new ProbePointArg<CacheAccessProbeArg>(
|
||||
this->getProbeManager(), "Miss");
|
||||
ppFill = new ProbePointArg<CacheAccessProbeArg>(
|
||||
this->getProbeManager(), "Fill");
|
||||
ppDataUpdate =
|
||||
new ProbePointArg<DataUpdate>(this->getProbeManager(), "Data Update");
|
||||
new ProbePointArg<CacheDataUpdateProbeArg>(
|
||||
this->getProbeManager(), "Data Update");
|
||||
}
|
||||
|
||||
///////////////
|
||||
|
||||
53
src/mem/cache/base.hh
vendored
53
src/mem/cache/base.hh
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013, 2015-2016, 2018-2019 ARM Limited
|
||||
* Copyright (c) 2012-2013, 2015-2016, 2018-2019, 2023 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "debug/CachePort.hh"
|
||||
#include "enums/Clusivity.hh"
|
||||
#include "mem/cache/cache_blk.hh"
|
||||
#include "mem/cache/cache_probe_arg.hh"
|
||||
#include "mem/cache/compressors/base.hh"
|
||||
#include "mem/cache/mshr_queue.hh"
|
||||
#include "mem/cache/tags/base.hh"
|
||||
@@ -115,28 +116,6 @@ class BaseCache : public ClockedObject
|
||||
NUM_BLOCKED_CAUSES
|
||||
};
|
||||
|
||||
/**
|
||||
* A data contents update is composed of the updated block's address,
|
||||
* the old contents, and the new contents.
|
||||
* @sa ppDataUpdate
|
||||
*/
|
||||
struct DataUpdate
|
||||
{
|
||||
/** The updated block's address. */
|
||||
Addr addr;
|
||||
/** Whether the block belongs to the secure address space. */
|
||||
bool isSecure;
|
||||
/** The stale data contents. If zero-sized this update is a fill. */
|
||||
std::vector<uint64_t> oldData;
|
||||
/** The new data contents. If zero-sized this is an invalidation. */
|
||||
std::vector<uint64_t> newData;
|
||||
|
||||
DataUpdate(Addr _addr, bool is_secure)
|
||||
: addr(_addr), isSecure(is_secure), oldData(), newData()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
@@ -336,6 +315,26 @@ class BaseCache : public ClockedObject
|
||||
|
||||
protected:
|
||||
|
||||
struct CacheAccessorImpl : CacheAccessor
|
||||
{
|
||||
BaseCache &cache;
|
||||
|
||||
CacheAccessorImpl(BaseCache &_cache) :cache(_cache) {}
|
||||
|
||||
bool inCache(Addr addr, bool is_secure) const override
|
||||
{ return cache.inCache(addr, is_secure); }
|
||||
|
||||
bool hasBeenPrefetched(Addr addr, bool is_secure) const override
|
||||
{ return cache.hasBeenPrefetched(addr, is_secure); }
|
||||
|
||||
bool inMissQueue(Addr addr, bool is_secure) const override
|
||||
{ return cache.inMissQueue(addr, is_secure); }
|
||||
|
||||
bool coalesce() const override
|
||||
{ return cache.coalesce(); }
|
||||
|
||||
} accessor;
|
||||
|
||||
/** Miss status registers */
|
||||
MSHRQueue mshrQueue;
|
||||
|
||||
@@ -352,20 +351,20 @@ class BaseCache : public ClockedObject
|
||||
prefetch::Base *prefetcher;
|
||||
|
||||
/** To probe when a cache hit occurs */
|
||||
ProbePointArg<PacketPtr> *ppHit;
|
||||
ProbePointArg<CacheAccessProbeArg> *ppHit;
|
||||
|
||||
/** To probe when a cache miss occurs */
|
||||
ProbePointArg<PacketPtr> *ppMiss;
|
||||
ProbePointArg<CacheAccessProbeArg> *ppMiss;
|
||||
|
||||
/** To probe when a cache fill occurs */
|
||||
ProbePointArg<PacketPtr> *ppFill;
|
||||
ProbePointArg<CacheAccessProbeArg> *ppFill;
|
||||
|
||||
/**
|
||||
* To probe when the contents of a block are updated. Content updates
|
||||
* include data fills, overwrites, and invalidations, which means that
|
||||
* this probe partially overlaps with other probes.
|
||||
*/
|
||||
ProbePointArg<DataUpdate> *ppDataUpdate;
|
||||
ProbePointArg<CacheDataUpdateProbeArg> *ppDataUpdate;
|
||||
|
||||
/**
|
||||
* The writeAllocator drive optimizations for streaming writes.
|
||||
|
||||
115
src/mem/cache/cache_probe_arg.hh
vendored
Normal file
115
src/mem/cache/cache_probe_arg.hh
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2023 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __MEM_CACHE_PROBE_ARG_HH__
|
||||
#define __MEM_CACHE_PROBE_ARG_HH__
|
||||
|
||||
#include "mem/packet.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
/**
|
||||
* Provides generic cache lookup functions. A cache may provide
|
||||
* a CacheAccessor object to other components that need to perform
|
||||
* a lookup outside the normal cache control flow. Currently this
|
||||
* is used by prefetchers that perform lookups when notified by
|
||||
* cache events.
|
||||
*/
|
||||
struct CacheAccessor
|
||||
{
|
||||
/** Determine if address is in cache */
|
||||
virtual bool inCache(Addr addr, bool is_secure) const = 0;
|
||||
|
||||
/** Determine if address has been prefetched */
|
||||
virtual bool hasBeenPrefetched(Addr addr, bool is_secure) const = 0;
|
||||
|
||||
/** Determine if address is in cache miss queue */
|
||||
virtual bool inMissQueue(Addr addr, bool is_secure) const = 0;
|
||||
|
||||
/** Determine if cache is coalescing writes */
|
||||
virtual bool coalesce() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Information provided to probes on a cache event.
|
||||
* @sa ppHit, ppMiss, ppFill in gem5::BaseCache (src/mem/cache/base.hh)
|
||||
*/
|
||||
class CacheAccessProbeArg
|
||||
{
|
||||
public:
|
||||
/** Packet that triggered the cache access*/
|
||||
PacketPtr pkt;
|
||||
/** Accessor for the cache */
|
||||
CacheAccessor &cache;
|
||||
|
||||
CacheAccessProbeArg(PacketPtr _pkt, CacheAccessor &_cache)
|
||||
:pkt(_pkt), cache(_cache)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A data contents update is composed of the updated block's address,
|
||||
* the old contents, and the new contents.
|
||||
* @sa ppDataUpdate in gem5::BaseCache (src/mem/cache/base.hh)
|
||||
*/
|
||||
struct CacheDataUpdateProbeArg
|
||||
{
|
||||
/** The updated block's address. */
|
||||
Addr addr;
|
||||
/** Whether the block belongs to the secure address space. */
|
||||
bool isSecure;
|
||||
/** The stale data contents. If zero-sized this update is a fill. */
|
||||
std::vector<uint64_t> oldData;
|
||||
/** The new data contents. If zero-sized this is an invalidation. */
|
||||
std::vector<uint64_t> newData;
|
||||
/** Accessor for the cache */
|
||||
CacheAccessor &accessor;
|
||||
|
||||
CacheDataUpdateProbeArg(Addr _addr, bool is_secure,
|
||||
CacheAccessor &_accessor)
|
||||
: addr(_addr), isSecure(is_secure), oldData(), newData(),
|
||||
accessor(_accessor)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gem5
|
||||
|
||||
#endif //__MEM_CACHE_PROBE_ARG_HH__
|
||||
3
src/mem/cache/compressors/frequent_values.hh
vendored
3
src/mem/cache/compressors/frequent_values.hh
vendored
@@ -37,6 +37,7 @@
|
||||
#include "base/sat_counter.hh"
|
||||
#include "base/types.hh"
|
||||
#include "mem/cache/base.hh"
|
||||
#include "mem/cache/cache_probe_arg.hh"
|
||||
#include "mem/cache/compressors/base.hh"
|
||||
#include "mem/cache/compressors/encoders/huffman.hh"
|
||||
#include "mem/cache/prefetch/associative_set.hh"
|
||||
@@ -63,7 +64,7 @@ class FrequentValues : public Base
|
||||
private:
|
||||
class CompData;
|
||||
|
||||
using DataUpdate = BaseCache::DataUpdate;
|
||||
using DataUpdate = CacheDataUpdateProbeArg;
|
||||
|
||||
class FrequentValuesListener : public ProbeListenerArgBase<DataUpdate>
|
||||
{
|
||||
|
||||
@@ -156,7 +156,8 @@ AccessMapPatternMatching::setEntryState(AccessMapEntry &entry,
|
||||
|
||||
void
|
||||
AccessMapPatternMatching::calculatePrefetch(const Base::PrefetchInfo &pfi,
|
||||
std::vector<Queued::AddrPriority> &addresses)
|
||||
std::vector<Queued::AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
assert(addresses.empty());
|
||||
|
||||
@@ -262,9 +263,10 @@ AMPM::AMPM(const AMPMPrefetcherParams &p)
|
||||
|
||||
void
|
||||
AMPM::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
ampm.calculatePrefetch(pfi, addresses);
|
||||
ampm.calculatePrefetch(pfi, addresses, cache);
|
||||
}
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
@@ -190,7 +190,8 @@ class AccessMapPatternMatching : public ClockedObject
|
||||
|
||||
void startup() override;
|
||||
void calculatePrefetch(const Base::PrefetchInfo &pfi,
|
||||
std::vector<Queued::AddrPriority> &addresses);
|
||||
std::vector<Queued::AddrPriority> &addresses,
|
||||
const CacheAccessor &cache);
|
||||
};
|
||||
|
||||
class AMPM : public Queued
|
||||
@@ -201,7 +202,8 @@ class AMPM : public Queued
|
||||
~AMPM() = default;
|
||||
|
||||
void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses) override;
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache) override;
|
||||
};
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
77
src/mem/cache/prefetch/base.cc
vendored
77
src/mem/cache/prefetch/base.cc
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 ARM Limited
|
||||
* Copyright (c) 2013-2014, 2023 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -83,18 +83,19 @@ Base::PrefetchInfo::PrefetchInfo(PrefetchInfo const &pfi, Addr addr)
|
||||
}
|
||||
|
||||
void
|
||||
Base::PrefetchListener::notify(const PacketPtr &pkt)
|
||||
Base::PrefetchListener::notify(const CacheAccessProbeArg &arg)
|
||||
{
|
||||
if (isFill) {
|
||||
parent.notifyFill(pkt);
|
||||
parent.notifyFill(arg);
|
||||
} else {
|
||||
parent.probeNotify(pkt, miss);
|
||||
parent.probeNotify(arg, miss);
|
||||
}
|
||||
}
|
||||
|
||||
Base::Base(const BasePrefetcherParams &p)
|
||||
: ClockedObject(p), listeners(), cache(nullptr), blkSize(p.block_size),
|
||||
lBlkSize(floorLog2(blkSize)), onMiss(p.on_miss), onRead(p.on_read),
|
||||
: ClockedObject(p), listeners(), system(nullptr), probeManager(nullptr),
|
||||
blkSize(p.block_size), lBlkSize(floorLog2(blkSize)),
|
||||
onMiss(p.on_miss), onRead(p.on_read),
|
||||
onWrite(p.on_write), onData(p.on_data), onInst(p.on_inst),
|
||||
requestorId(p.sys->getRequestorId(this)),
|
||||
pageBytes(p.page_bytes),
|
||||
@@ -107,13 +108,13 @@ Base::Base(const BasePrefetcherParams &p)
|
||||
}
|
||||
|
||||
void
|
||||
Base::setCache(BaseCache *_cache)
|
||||
Base::setParentInfo(System *sys, ProbeManager *pm, unsigned blk_size)
|
||||
{
|
||||
assert(!cache);
|
||||
cache = _cache;
|
||||
|
||||
assert(!system && !probeManager);
|
||||
system = sys;
|
||||
probeManager = pm;
|
||||
// If the cache has a different block size from the system's, save it
|
||||
blkSize = cache->getBlockSize();
|
||||
blkSize = blk_size;
|
||||
lBlkSize = floorLog2(blkSize);
|
||||
}
|
||||
|
||||
@@ -157,7 +158,7 @@ Base::StatGroup::StatGroup(statistics::Group *parent)
|
||||
}
|
||||
|
||||
bool
|
||||
Base::observeAccess(const PacketPtr &pkt, bool miss) const
|
||||
Base::observeAccess(const PacketPtr &pkt, bool miss, bool prefetched) const
|
||||
{
|
||||
bool fetch = pkt->req->isInstFetch();
|
||||
bool read = pkt->isRead();
|
||||
@@ -165,7 +166,7 @@ Base::observeAccess(const PacketPtr &pkt, bool miss) const
|
||||
|
||||
if (!miss) {
|
||||
if (prefetchOnPfHit)
|
||||
return hasBeenPrefetched(pkt->getAddr(), pkt->isSecure());
|
||||
return prefetched;
|
||||
if (!prefetchOnAccess)
|
||||
return false;
|
||||
}
|
||||
@@ -184,24 +185,6 @@ Base::observeAccess(const PacketPtr &pkt, bool miss) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Base::inCache(Addr addr, bool is_secure) const
|
||||
{
|
||||
return cache->inCache(addr, is_secure);
|
||||
}
|
||||
|
||||
bool
|
||||
Base::inMissQueue(Addr addr, bool is_secure) const
|
||||
{
|
||||
return cache->inMissQueue(addr, is_secure);
|
||||
}
|
||||
|
||||
bool
|
||||
Base::hasBeenPrefetched(Addr addr, bool is_secure) const
|
||||
{
|
||||
return cache->hasBeenPrefetched(addr, is_secure);
|
||||
}
|
||||
|
||||
bool
|
||||
Base::samePage(Addr a, Addr b) const
|
||||
{
|
||||
@@ -239,18 +222,23 @@ Base::pageIthBlockAddress(Addr page, uint32_t blockIndex) const
|
||||
}
|
||||
|
||||
void
|
||||
Base::probeNotify(const PacketPtr &pkt, bool miss)
|
||||
Base::probeNotify(const CacheAccessProbeArg &acc, bool miss)
|
||||
{
|
||||
const PacketPtr pkt = acc.pkt;
|
||||
const CacheAccessor &cache = acc.cache;
|
||||
|
||||
// Don't notify prefetcher on SWPrefetch, cache maintenance
|
||||
// operations or for writes that we are coaslescing.
|
||||
if (pkt->cmd.isSWPrefetch()) return;
|
||||
if (pkt->req->isCacheMaintenance()) return;
|
||||
if (pkt->isWrite() && cache != nullptr && cache->coalesce()) return;
|
||||
if (pkt->isWrite() && cache.coalesce()) return;
|
||||
if (!pkt->req->hasPaddr()) {
|
||||
panic("Request must have a physical address");
|
||||
}
|
||||
|
||||
if (hasBeenPrefetched(pkt->getAddr(), pkt->isSecure())) {
|
||||
bool has_been_prefetched =
|
||||
acc.cache.hasBeenPrefetched(pkt->getAddr(), pkt->isSecure());
|
||||
if (has_been_prefetched) {
|
||||
usefulPrefetches += 1;
|
||||
prefetchStats.pfUseful++;
|
||||
if (miss)
|
||||
@@ -260,13 +248,13 @@ Base::probeNotify(const PacketPtr &pkt, bool miss)
|
||||
}
|
||||
|
||||
// Verify this access type is observed by prefetcher
|
||||
if (observeAccess(pkt, miss)) {
|
||||
if (observeAccess(pkt, miss, has_been_prefetched)) {
|
||||
if (useVirtualAddresses && pkt->req->hasVaddr()) {
|
||||
PrefetchInfo pfi(pkt, pkt->req->getVaddr(), miss);
|
||||
notify(pkt, pfi);
|
||||
notify(acc, pfi);
|
||||
} else if (!useVirtualAddresses) {
|
||||
PrefetchInfo pfi(pkt, pkt->req->getPaddr(), miss);
|
||||
notify(pkt, pfi);
|
||||
notify(acc, pfi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,14 +267,13 @@ Base::regProbeListeners()
|
||||
* parent cache using the probe "Miss". Also connect to "Hit", if the
|
||||
* cache is configured to prefetch on accesses.
|
||||
*/
|
||||
if (listeners.empty() && cache != nullptr) {
|
||||
ProbeManager *pm(cache->getProbeManager());
|
||||
listeners.push_back(new PrefetchListener(*this, pm, "Miss", false,
|
||||
true));
|
||||
listeners.push_back(new PrefetchListener(*this, pm, "Fill", true,
|
||||
false));
|
||||
listeners.push_back(new PrefetchListener(*this, pm, "Hit", false,
|
||||
false));
|
||||
if (listeners.empty() && probeManager != nullptr) {
|
||||
listeners.push_back(new PrefetchListener(*this, probeManager,
|
||||
"Miss", false, true));
|
||||
listeners.push_back(new PrefetchListener(*this, probeManager,
|
||||
"Fill", true, false));
|
||||
listeners.push_back(new PrefetchListener(*this, probeManager,
|
||||
"Hit", false, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
41
src/mem/cache/prefetch/base.hh
vendored
41
src/mem/cache/prefetch/base.hh
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 ARM Limited
|
||||
* Copyright (c) 2013-2014, 2023 ARM Limited
|
||||
* All rights reserved.
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -52,7 +52,7 @@
|
||||
#include "base/compiler.hh"
|
||||
#include "base/statistics.hh"
|
||||
#include "base/types.hh"
|
||||
#include "mem/cache/cache_blk.hh"
|
||||
#include "mem/cache/cache_probe_arg.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/request.hh"
|
||||
#include "sim/byteswap.hh"
|
||||
@@ -62,15 +62,16 @@
|
||||
namespace gem5
|
||||
{
|
||||
|
||||
class BaseCache;
|
||||
struct BasePrefetcherParams;
|
||||
class ProbeManager;
|
||||
class System;
|
||||
|
||||
namespace prefetch
|
||||
{
|
||||
|
||||
class Base : public ClockedObject
|
||||
{
|
||||
class PrefetchListener : public ProbeListenerArgBase<PacketPtr>
|
||||
class PrefetchListener : public ProbeListenerArgBase<CacheAccessProbeArg>
|
||||
{
|
||||
public:
|
||||
PrefetchListener(Base &_parent, ProbeManager *pm,
|
||||
@@ -78,7 +79,7 @@ class Base : public ClockedObject
|
||||
bool _miss = false)
|
||||
: ProbeListenerArgBase(pm, name),
|
||||
parent(_parent), isFill(_isFill), miss(_miss) {}
|
||||
void notify(const PacketPtr &pkt) override;
|
||||
void notify(const CacheAccessProbeArg &arg) override;
|
||||
protected:
|
||||
Base &parent;
|
||||
const bool isFill;
|
||||
@@ -262,8 +263,11 @@ class Base : public ClockedObject
|
||||
|
||||
// PARAMETERS
|
||||
|
||||
/** Pointr to the parent cache. */
|
||||
BaseCache* cache;
|
||||
/** Pointer to the parent system. */
|
||||
System* system;
|
||||
|
||||
/** Pointer to the parent cache's probe manager. */
|
||||
ProbeManager *probeManager;
|
||||
|
||||
/** The block size of the parent cache. */
|
||||
unsigned blkSize;
|
||||
@@ -304,16 +308,9 @@ class Base : public ClockedObject
|
||||
* Determine if this access should be observed
|
||||
* @param pkt The memory request causing the event
|
||||
* @param miss whether this event comes from a cache miss
|
||||
* @param prefetched on a hit, this indicates the block was prefetched
|
||||
*/
|
||||
bool observeAccess(const PacketPtr &pkt, bool miss) const;
|
||||
|
||||
/** Determine if address is in cache */
|
||||
bool inCache(Addr addr, bool is_secure) const;
|
||||
|
||||
/** Determine if address is in cache miss queue */
|
||||
bool inMissQueue(Addr addr, bool is_secure) const;
|
||||
|
||||
bool hasBeenPrefetched(Addr addr, bool is_secure) const;
|
||||
bool observeAccess(const PacketPtr &pkt, bool miss, bool prefetched) const;
|
||||
|
||||
/** Determine if addresses are on the same page */
|
||||
bool samePage(Addr a, Addr b) const;
|
||||
@@ -370,16 +367,18 @@ class Base : public ClockedObject
|
||||
Base(const BasePrefetcherParams &p);
|
||||
virtual ~Base() = default;
|
||||
|
||||
virtual void setCache(BaseCache *_cache);
|
||||
virtual void
|
||||
setParentInfo(System *sys, ProbeManager *pm, unsigned blk_size);
|
||||
|
||||
/**
|
||||
* Notify prefetcher of cache access (may be any access or just
|
||||
* misses, depending on cache parameters.)
|
||||
*/
|
||||
virtual void notify(const PacketPtr &pkt, const PrefetchInfo &pfi) = 0;
|
||||
virtual void
|
||||
notify(const CacheAccessProbeArg &acc, const PrefetchInfo &pfi) = 0;
|
||||
|
||||
/** Notify prefetcher of cache fill */
|
||||
virtual void notifyFill(const PacketPtr &pkt)
|
||||
virtual void notifyFill(const CacheAccessProbeArg &acc)
|
||||
{}
|
||||
|
||||
virtual PacketPtr getPacket() = 0;
|
||||
@@ -423,10 +422,10 @@ class Base : public ClockedObject
|
||||
|
||||
/**
|
||||
* Process a notification event from the ProbeListener.
|
||||
* @param pkt The memory request causing the event
|
||||
* @param acc probe arg encapsulating the memory request causing the event
|
||||
* @param miss whether this event comes from a cache miss
|
||||
*/
|
||||
void probeNotify(const PacketPtr &pkt, bool miss);
|
||||
void probeNotify(const CacheAccessProbeArg &acc, bool miss);
|
||||
|
||||
/**
|
||||
* Add a SimObject and a probe name to listen events from
|
||||
|
||||
7
src/mem/cache/prefetch/bop.cc
vendored
7
src/mem/cache/prefetch/bop.cc
vendored
@@ -227,7 +227,8 @@ BOP::bestOffsetLearning(Addr x)
|
||||
|
||||
void
|
||||
BOP::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
Addr addr = pfi.getAddr();
|
||||
Addr tag_x = tag(addr);
|
||||
@@ -252,8 +253,10 @@ BOP::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
}
|
||||
|
||||
void
|
||||
BOP::notifyFill(const PacketPtr& pkt)
|
||||
BOP::notifyFill(const CacheAccessProbeArg &arg)
|
||||
{
|
||||
const PacketPtr& pkt = arg.pkt;
|
||||
|
||||
// Only insert into the RR right way if it's the pkt is a HWP
|
||||
if (!pkt->cmd.isHWPrefetch()) return;
|
||||
|
||||
|
||||
5
src/mem/cache/prefetch/bop.hh
vendored
5
src/mem/cache/prefetch/bop.hh
vendored
@@ -148,7 +148,7 @@ class BOP : public Queued
|
||||
void bestOffsetLearning(Addr);
|
||||
|
||||
/** Update the RR right table after a prefetch fill */
|
||||
void notifyFill(const PacketPtr& pkt) override;
|
||||
void notifyFill(const CacheAccessProbeArg &arg) override;
|
||||
|
||||
public:
|
||||
|
||||
@@ -156,7 +156,8 @@ class BOP : public Queued
|
||||
~BOP() = default;
|
||||
|
||||
void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses) override;
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache) override;
|
||||
};
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
@@ -125,7 +125,8 @@ DeltaCorrelatingPredictionTables::DCPTEntry::getCandidates(
|
||||
void
|
||||
DeltaCorrelatingPredictionTables::calculatePrefetch(
|
||||
const Base::PrefetchInfo &pfi,
|
||||
std::vector<Queued::AddrPriority> &addresses)
|
||||
std::vector<Queued::AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
if (!pfi.hasPC()) {
|
||||
DPRINTF(HWPrefetch, "Ignoring request with no PC.\n");
|
||||
@@ -156,9 +157,10 @@ DCPT::DCPT(const DCPTPrefetcherParams &p)
|
||||
|
||||
void
|
||||
DCPT::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
dcpt.calculatePrefetch(pfi, addresses);
|
||||
dcpt.calculatePrefetch(pfi, addresses, cache);
|
||||
}
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
@@ -114,9 +114,11 @@ class DeltaCorrelatingPredictionTables : public SimObject
|
||||
* Computes the prefetch candidates given a prefetch event.
|
||||
* @param pfi The prefetch event information
|
||||
* @param addresses prefetch candidates generated
|
||||
* @param cache accessor for cache lookups
|
||||
*/
|
||||
void calculatePrefetch(const Base::PrefetchInfo &pfi,
|
||||
std::vector<Queued::AddrPriority> &addresses);
|
||||
std::vector<Queued::AddrPriority> &addresses,
|
||||
const CacheAccessor &cache);
|
||||
|
||||
};
|
||||
|
||||
@@ -130,7 +132,8 @@ class DCPT : public Queued
|
||||
~DCPT() = default;
|
||||
|
||||
void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses) override;
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache) override;
|
||||
};
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
3
src/mem/cache/prefetch/indirect_memory.cc
vendored
3
src/mem/cache/prefetch/indirect_memory.cc
vendored
@@ -56,7 +56,8 @@ IndirectMemory::IndirectMemory(const IndirectMemoryPrefetcherParams &p)
|
||||
|
||||
void
|
||||
IndirectMemory::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
// This prefetcher requires a PC
|
||||
if (!pfi.hasPC()) {
|
||||
|
||||
3
src/mem/cache/prefetch/indirect_memory.hh
vendored
3
src/mem/cache/prefetch/indirect_memory.hh
vendored
@@ -201,7 +201,8 @@ class IndirectMemory : public Queued
|
||||
~IndirectMemory() = default;
|
||||
|
||||
void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses) override;
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache) override;
|
||||
};
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
@@ -66,7 +66,8 @@ IrregularStreamBuffer::IrregularStreamBuffer(
|
||||
|
||||
void
|
||||
IrregularStreamBuffer::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
// This prefetcher requires a PC
|
||||
if (!pfi.hasPC()) {
|
||||
|
||||
@@ -137,7 +137,8 @@ class IrregularStreamBuffer : public Queued
|
||||
~IrregularStreamBuffer() = default;
|
||||
|
||||
void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses) override;
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache) override;
|
||||
};
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
6
src/mem/cache/prefetch/multi.cc
vendored
6
src/mem/cache/prefetch/multi.cc
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019 ARM Limited
|
||||
* Copyright (c) 2014, 2019, 2023 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -53,10 +53,10 @@ Multi::Multi(const MultiPrefetcherParams &p)
|
||||
}
|
||||
|
||||
void
|
||||
Multi::setCache(BaseCache *_cache)
|
||||
Multi::setParentInfo(System *sys, ProbeManager *pm, unsigned blk_size)
|
||||
{
|
||||
for (auto pf : prefetchers)
|
||||
pf->setCache(_cache);
|
||||
pf->setParentInfo(sys, pm, blk_size);
|
||||
}
|
||||
|
||||
Tick
|
||||
|
||||
12
src/mem/cache/prefetch/multi.hh
vendored
12
src/mem/cache/prefetch/multi.hh
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019 ARM Limited
|
||||
* Copyright (c) 2014, 2019, 2023 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -56,7 +56,8 @@ class Multi : public Base
|
||||
Multi(const MultiPrefetcherParams &p);
|
||||
|
||||
public:
|
||||
void setCache(BaseCache *_cache) override;
|
||||
void
|
||||
setParentInfo(System *sys, ProbeManager *pm, unsigned blk_size) override;
|
||||
PacketPtr getPacket() override;
|
||||
Tick nextPrefetchReadyTime() const override;
|
||||
|
||||
@@ -65,8 +66,11 @@ class Multi : public Base
|
||||
* Ignore notifications since each sub-prefetcher already gets a
|
||||
* notification through their probes-based interface.
|
||||
*/
|
||||
void notify(const PacketPtr &pkt, const PrefetchInfo &pfi) override {};
|
||||
void notifyFill(const PacketPtr &pkt) override {};
|
||||
void
|
||||
notify(const CacheAccessProbeArg &arg, const PrefetchInfo &pfi) override
|
||||
{};
|
||||
|
||||
void notifyFill(const CacheAccessProbeArg &arg) override {};
|
||||
/** @} */
|
||||
|
||||
protected:
|
||||
|
||||
3
src/mem/cache/prefetch/pif.cc
vendored
3
src/mem/cache/prefetch/pif.cc
vendored
@@ -198,7 +198,8 @@ PIF::notifyRetiredInst(const Addr pc)
|
||||
|
||||
void
|
||||
PIF::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
if (!pfi.hasPC()) {
|
||||
return;
|
||||
|
||||
3
src/mem/cache/prefetch/pif.hh
vendored
3
src/mem/cache/prefetch/pif.hh
vendored
@@ -182,7 +182,8 @@ class PIF : public Queued
|
||||
~PIF() = default;
|
||||
|
||||
void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses);
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache);
|
||||
|
||||
/**
|
||||
* Add a SimObject and a probe name to monitor the retired instructions
|
||||
|
||||
32
src/mem/cache/prefetch/queued.cc
vendored
32
src/mem/cache/prefetch/queued.cc
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2015 ARM Limited
|
||||
* Copyright (c) 2014-2015, 2023 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -94,7 +94,7 @@ Queued::DeferredPacket::finish(const Fault &fault,
|
||||
assert(ongoingTranslation);
|
||||
ongoingTranslation = false;
|
||||
bool failed = (fault != NoFault);
|
||||
owner->translationComplete(this, failed);
|
||||
owner->translationComplete(this, failed, *cache);
|
||||
}
|
||||
|
||||
Queued::Queued(const QueuedPrefetcherParams &p)
|
||||
@@ -169,10 +169,12 @@ Queued::getMaxPermittedPrefetches(size_t total) const
|
||||
}
|
||||
|
||||
void
|
||||
Queued::notify(const PacketPtr &pkt, const PrefetchInfo &pfi)
|
||||
Queued::notify(const CacheAccessProbeArg &acc, const PrefetchInfo &pfi)
|
||||
{
|
||||
Addr blk_addr = blockAddress(pfi.getAddr());
|
||||
bool is_secure = pfi.isSecure();
|
||||
const PacketPtr pkt = acc.pkt;
|
||||
const CacheAccessor &cache = acc.cache;
|
||||
|
||||
// Squash queued prefetches if demand miss to same line
|
||||
if (queueSquash) {
|
||||
@@ -195,7 +197,7 @@ Queued::notify(const PacketPtr &pkt, const PrefetchInfo &pfi)
|
||||
|
||||
// Calculate prefetches given this access
|
||||
std::vector<AddrPriority> addresses;
|
||||
calculatePrefetch(pfi, addresses);
|
||||
calculatePrefetch(pfi, addresses, cache);
|
||||
|
||||
// Get the maximu number of prefetches that we are allowed to generate
|
||||
size_t max_pfs = getMaxPermittedPrefetches(addresses.size());
|
||||
@@ -210,7 +212,7 @@ Queued::notify(const PacketPtr &pkt, const PrefetchInfo &pfi)
|
||||
if (!samePage(addr_prio.first, pfi.getAddr())) {
|
||||
statsQueued.pfSpanPage += 1;
|
||||
|
||||
if (hasBeenPrefetched(pkt->getAddr(), pkt->isSecure())) {
|
||||
if (cache.hasBeenPrefetched(pkt->getAddr(), pkt->isSecure())) {
|
||||
statsQueued.pfUsefulSpanPage += 1;
|
||||
}
|
||||
}
|
||||
@@ -222,7 +224,7 @@ Queued::notify(const PacketPtr &pkt, const PrefetchInfo &pfi)
|
||||
DPRINTF(HWPrefetch, "Found a pf candidate addr: %#x, "
|
||||
"inserting into prefetch queue.\n", new_pfi.getAddr());
|
||||
// Create and insert the request
|
||||
insert(pkt, new_pfi, addr_prio.second);
|
||||
insert(pkt, new_pfi, addr_prio.second, cache);
|
||||
num_pfs += 1;
|
||||
if (num_pfs == max_pfs) {
|
||||
break;
|
||||
@@ -298,7 +300,8 @@ Queued::processMissingTranslations(unsigned max)
|
||||
}
|
||||
|
||||
void
|
||||
Queued::translationComplete(DeferredPacket *dp, bool failed)
|
||||
Queued::translationComplete(DeferredPacket *dp, bool failed,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
auto it = pfqMissingTranslation.begin();
|
||||
while (it != pfqMissingTranslation.end()) {
|
||||
@@ -315,8 +318,9 @@ Queued::translationComplete(DeferredPacket *dp, bool failed)
|
||||
it->translationRequest->getPaddr());
|
||||
Addr target_paddr = it->translationRequest->getPaddr();
|
||||
// check if this prefetch is already redundant
|
||||
if (cacheSnoop && (inCache(target_paddr, it->pfInfo.isSecure()) ||
|
||||
inMissQueue(target_paddr, it->pfInfo.isSecure()))) {
|
||||
if (cacheSnoop &&
|
||||
(cache.inCache(target_paddr, it->pfInfo.isSecure()) ||
|
||||
cache.inMissQueue(target_paddr, it->pfInfo.isSecure()))) {
|
||||
statsQueued.pfInCache++;
|
||||
DPRINTF(HWPrefetch, "Dropping redundant in "
|
||||
"cache/MSHR prefetch addr:%#x\n", target_paddr);
|
||||
@@ -382,7 +386,7 @@ Queued::createPrefetchRequest(Addr addr, PrefetchInfo const &pfi,
|
||||
|
||||
void
|
||||
Queued::insert(const PacketPtr &pkt, PrefetchInfo &new_pfi,
|
||||
int32_t priority)
|
||||
int32_t priority, const CacheAccessor &cache)
|
||||
{
|
||||
if (queueFilter) {
|
||||
if (alreadyInQueue(pfq, new_pfi, priority)) {
|
||||
@@ -451,8 +455,8 @@ Queued::insert(const PacketPtr &pkt, PrefetchInfo &new_pfi,
|
||||
}
|
||||
}
|
||||
if (has_target_pa && cacheSnoop &&
|
||||
(inCache(target_paddr, new_pfi.isSecure()) ||
|
||||
inMissQueue(target_paddr, new_pfi.isSecure()))) {
|
||||
(cache.inCache(target_paddr, new_pfi.isSecure()) ||
|
||||
cache.inMissQueue(target_paddr, new_pfi.isSecure()))) {
|
||||
statsQueued.pfInCache++;
|
||||
DPRINTF(HWPrefetch, "Dropping redundant in "
|
||||
"cache/MSHR prefetch addr:%#x\n", target_paddr);
|
||||
@@ -460,7 +464,7 @@ Queued::insert(const PacketPtr &pkt, PrefetchInfo &new_pfi,
|
||||
}
|
||||
|
||||
/* Create the packet and find the spot to insert it */
|
||||
DeferredPacket dpp(this, new_pfi, 0, priority);
|
||||
DeferredPacket dpp(this, new_pfi, 0, priority, cache);
|
||||
if (has_target_pa) {
|
||||
Tick pf_time = curTick() + clockPeriod() * latency;
|
||||
dpp.createPkt(target_paddr, blkSize, requestorId, tagPrefetch,
|
||||
@@ -472,7 +476,7 @@ Queued::insert(const PacketPtr &pkt, PrefetchInfo &new_pfi,
|
||||
} else {
|
||||
// Add the translation request and try to resolve it later
|
||||
dpp.setTranslationRequest(translation_req);
|
||||
dpp.tc = cache->system->threads[translation_req->contextId()];
|
||||
dpp.tc = system->threads[translation_req->contextId()];
|
||||
DPRINTF(HWPrefetch, "Prefetch queued with no translation. "
|
||||
"addr:%#x priority: %3d\n", new_pfi.getAddr(), priority);
|
||||
addToQueue(pfqMissingTranslation, dpp);
|
||||
|
||||
21
src/mem/cache/prefetch/queued.hh
vendored
21
src/mem/cache/prefetch/queued.hh
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2015 ARM Limited
|
||||
* Copyright (c) 2014-2015, 2023 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -75,6 +75,7 @@ class Queued : public Base
|
||||
RequestPtr translationRequest;
|
||||
ThreadContext *tc;
|
||||
bool ongoingTranslation;
|
||||
const CacheAccessor *cache;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -85,9 +86,10 @@ class Queued : public Base
|
||||
* @param prio This prefetch priority
|
||||
*/
|
||||
DeferredPacket(Queued *o, PrefetchInfo const &pfi, Tick t,
|
||||
int32_t prio) : owner(o), pfInfo(pfi), tick(t), pkt(nullptr),
|
||||
int32_t prio, const CacheAccessor &_cache)
|
||||
: owner(o), pfInfo(pfi), tick(t), pkt(nullptr),
|
||||
priority(prio), translationRequest(), tc(nullptr),
|
||||
ongoingTranslation(false) {
|
||||
ongoingTranslation(false), cache(&_cache) {
|
||||
}
|
||||
|
||||
bool operator>(const DeferredPacket& that) const
|
||||
@@ -192,12 +194,15 @@ class Queued : public Base
|
||||
Queued(const QueuedPrefetcherParams &p);
|
||||
virtual ~Queued();
|
||||
|
||||
void notify(const PacketPtr &pkt, const PrefetchInfo &pfi) override;
|
||||
void
|
||||
notify(const CacheAccessProbeArg &acc, const PrefetchInfo &pfi) override;
|
||||
|
||||
void insert(const PacketPtr &pkt, PrefetchInfo &new_pfi, int32_t priority);
|
||||
void insert(const PacketPtr &pkt, PrefetchInfo &new_pfi, int32_t priority,
|
||||
const CacheAccessor &cache);
|
||||
|
||||
virtual void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses) = 0;
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache) = 0;
|
||||
PacketPtr getPacket() override;
|
||||
|
||||
Tick nextPrefetchReadyTime() const override
|
||||
@@ -231,8 +236,10 @@ class Queued : public Base
|
||||
* new prefetch request.
|
||||
* @param dp the deferred packet that has completed the translation request
|
||||
* @param failed whether the translation was successful
|
||||
* @param cache accessor for lookups on the cache that originated this pkt
|
||||
*/
|
||||
void translationComplete(DeferredPacket *dp, bool failed);
|
||||
void translationComplete(DeferredPacket *dp, bool failed,
|
||||
const CacheAccessor &cache);
|
||||
|
||||
/**
|
||||
* Checks whether the specified prefetch request is already in the
|
||||
|
||||
7
src/mem/cache/prefetch/sbooe.cc
vendored
7
src/mem/cache/prefetch/sbooe.cc
vendored
@@ -91,8 +91,10 @@ SBOOE::access(Addr access_line)
|
||||
}
|
||||
|
||||
void
|
||||
SBOOE::notifyFill(const PacketPtr& pkt)
|
||||
SBOOE::notifyFill(const CacheAccessProbeArg &arg)
|
||||
{
|
||||
const PacketPtr& pkt = arg.pkt;
|
||||
|
||||
// (1) Look for the address in the demands list
|
||||
// (2) Calculate the elapsed cycles until it was filled (curTick)
|
||||
// (3) Insert the latency into the latency buffer (FIFO)
|
||||
@@ -117,7 +119,8 @@ SBOOE::notifyFill(const PacketPtr& pkt)
|
||||
|
||||
void
|
||||
SBOOE::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
const Addr pfi_addr = pfi.getAddr();
|
||||
const Addr pfi_line = pfi_addr >> lBlkSize;
|
||||
|
||||
5
src/mem/cache/prefetch/sbooe.hh
vendored
5
src/mem/cache/prefetch/sbooe.hh
vendored
@@ -153,13 +153,14 @@ class SBOOE : public Queued
|
||||
bool access(Addr line);
|
||||
|
||||
/** Update the latency buffer after a prefetch fill */
|
||||
void notifyFill(const PacketPtr& pkt) override;
|
||||
void notifyFill(const CacheAccessProbeArg &arg) override;
|
||||
|
||||
public:
|
||||
SBOOE(const SBOOEPrefetcherParams &p);
|
||||
|
||||
void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses) override;
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache) override;
|
||||
};
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
3
src/mem/cache/prefetch/signature_path.cc
vendored
3
src/mem/cache/prefetch/signature_path.cc
vendored
@@ -227,7 +227,8 @@ SignaturePath::calculateLookaheadConfidence(PatternEntry const &sig,
|
||||
|
||||
void
|
||||
SignaturePath::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
Addr request_addr = pfi.getAddr();
|
||||
Addr ppn = request_addr / pageBytes;
|
||||
|
||||
3
src/mem/cache/prefetch/signature_path.hh
vendored
3
src/mem/cache/prefetch/signature_path.hh
vendored
@@ -287,7 +287,8 @@ class SignaturePath : public Queued
|
||||
~SignaturePath() = default;
|
||||
|
||||
void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses) override;
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache) override;
|
||||
};
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
7
src/mem/cache/prefetch/slim_ampm.cc
vendored
7
src/mem/cache/prefetch/slim_ampm.cc
vendored
@@ -43,11 +43,12 @@ SlimAMPM::SlimAMPM(const SlimAMPMPrefetcherParams &p)
|
||||
|
||||
void
|
||||
SlimAMPM::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
dcpt.calculatePrefetch(pfi, addresses);
|
||||
dcpt.calculatePrefetch(pfi, addresses, cache);
|
||||
if (addresses.empty()) {
|
||||
ampm.calculatePrefetch(pfi, addresses);
|
||||
ampm.calculatePrefetch(pfi, addresses, cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
3
src/mem/cache/prefetch/slim_ampm.hh
vendored
3
src/mem/cache/prefetch/slim_ampm.hh
vendored
@@ -62,7 +62,8 @@ class SlimAMPM : public Queued
|
||||
~SlimAMPM() = default;
|
||||
|
||||
void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses) override;
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache) override;
|
||||
};
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
@@ -63,7 +63,7 @@ STeMS::STeMS(const STeMSPrefetcherParams &p)
|
||||
}
|
||||
|
||||
void
|
||||
STeMS::checkForActiveGenerationsEnd()
|
||||
STeMS::checkForActiveGenerationsEnd(const CacheAccessor &cache)
|
||||
{
|
||||
// This prefetcher operates attached to the L1 and it observes all
|
||||
// accesses, this guarantees that no evictions are missed
|
||||
@@ -79,8 +79,8 @@ STeMS::checkForActiveGenerationsEnd()
|
||||
if (seq_entry.counter > 0) {
|
||||
Addr cache_addr =
|
||||
agt_entry.paddress + seq_entry.offset * blkSize;
|
||||
if (!inCache(cache_addr, sr_is_secure) &&
|
||||
!inMissQueue(cache_addr, sr_is_secure)) {
|
||||
if (!cache.inCache(cache_addr, sr_is_secure) &&
|
||||
!cache.inMissQueue(cache_addr, sr_is_secure)) {
|
||||
generation_ended = true;
|
||||
pst_addr = (agt_entry.pc << spatialRegionSizeBits)
|
||||
+ seq_entry.offset;
|
||||
@@ -135,7 +135,8 @@ STeMS::addToRMOB(Addr sr_addr, Addr pst_addr, unsigned int delta)
|
||||
|
||||
void
|
||||
STeMS::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
if (!pfi.hasPC()) {
|
||||
DPRINTF(HWPrefetch, "Ignoring request with no PC.\n");
|
||||
@@ -152,7 +153,7 @@ STeMS::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
Addr sr_offset = (pfi.getAddr() % spatialRegionSize) / blkSize;
|
||||
|
||||
// Check if any active generation has ended
|
||||
checkForActiveGenerationsEnd();
|
||||
checkForActiveGenerationsEnd(cache);
|
||||
|
||||
ActiveGenerationTableEntry *agt_entry =
|
||||
activeGenerationTable.findEntry(sr_addr, is_secure);
|
||||
|
||||
@@ -181,7 +181,7 @@ class STeMS : public Queued
|
||||
unsigned int lastTriggerCounter;
|
||||
|
||||
/** Checks if the active generations have ended */
|
||||
void checkForActiveGenerationsEnd();
|
||||
void checkForActiveGenerationsEnd(const CacheAccessor &cache);
|
||||
/**
|
||||
* Adds an entry to the RMOB
|
||||
* @param sr_addr Spatial region address
|
||||
@@ -206,7 +206,8 @@ class STeMS : public Queued
|
||||
~STeMS() = default;
|
||||
|
||||
void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses) override;
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache) override;
|
||||
};
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
3
src/mem/cache/prefetch/stride.cc
vendored
3
src/mem/cache/prefetch/stride.cc
vendored
@@ -118,7 +118,8 @@ Stride::allocateNewContext(int context)
|
||||
|
||||
void
|
||||
Stride::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
if (!pfi.hasPC()) {
|
||||
DPRINTF(HWPrefetch, "Ignoring request with no PC.\n");
|
||||
|
||||
3
src/mem/cache/prefetch/stride.hh
vendored
3
src/mem/cache/prefetch/stride.hh
vendored
@@ -160,7 +160,8 @@ class Stride : public Queued
|
||||
Stride(const StridePrefetcherParams &p);
|
||||
|
||||
void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses) override;
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache) override;
|
||||
};
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
3
src/mem/cache/prefetch/tagged.cc
vendored
3
src/mem/cache/prefetch/tagged.cc
vendored
@@ -49,7 +49,8 @@ Tagged::Tagged(const TaggedPrefetcherParams &p)
|
||||
|
||||
void
|
||||
Tagged::calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses)
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache)
|
||||
{
|
||||
Addr blkAddr = blockAddress(pfi.getAddr());
|
||||
|
||||
|
||||
3
src/mem/cache/prefetch/tagged.hh
vendored
3
src/mem/cache/prefetch/tagged.hh
vendored
@@ -55,7 +55,8 @@ class Tagged : public Queued
|
||||
~Tagged() = default;
|
||||
|
||||
void calculatePrefetch(const PrefetchInfo &pfi,
|
||||
std::vector<AddrPriority> &addresses) override;
|
||||
std::vector<AddrPriority> &addresses,
|
||||
const CacheAccessor &cache) override;
|
||||
};
|
||||
|
||||
} // namespace prefetch
|
||||
|
||||
Reference in New Issue
Block a user