X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmem%2Fcache%2Fprefetch%2Fbase.cc;h=b3a43cc582ecea5744316889241d9381ac3559a2;hb=e0de180ee4eb3316d2dd0d20320f2a1b310101bc;hp=6b4cf05861f270ca72291821425760d29a28b7b0;hpb=7a8dda49a4ec33be17bbd101ebd68e02562b9c3d;p=gem5.git diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index 6b4cf0586..b3a43cc58 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -48,18 +48,55 @@ #include "mem/cache/prefetch/base.hh" -#include +#include #include "base/intmath.hh" +#include "cpu/base.hh" #include "mem/cache/base.hh" +#include "params/BasePrefetcher.hh" #include "sim/system.hh" +BasePrefetcher::PrefetchInfo::PrefetchInfo(PacketPtr pkt, Addr addr, bool miss) + : address(addr), pc(pkt->req->hasPC() ? pkt->req->getPC() : 0), + masterId(pkt->req->masterId()), validPC(pkt->req->hasPC()), + secure(pkt->isSecure()), size(pkt->req->getSize()), write(pkt->isWrite()), + paddress(pkt->req->getPaddr()), cacheMiss(miss) +{ + unsigned int req_size = pkt->req->getSize(); + if (!write && miss) { + data = nullptr; + } else { + data = new uint8_t[req_size]; + Addr offset = pkt->req->getPaddr() - pkt->getAddr(); + std::memcpy(data, &(pkt->getConstPtr()[offset]), req_size); + } +} + +BasePrefetcher::PrefetchInfo::PrefetchInfo(PrefetchInfo const &pfi, Addr addr) + : address(addr), pc(pfi.pc), masterId(pfi.masterId), validPC(pfi.validPC), + secure(pfi.secure), size(pfi.size), write(pfi.write), + paddress(pfi.paddress), cacheMiss(pfi.cacheMiss), data(nullptr) +{ +} + +void +BasePrefetcher::PrefetchListener::notify(const PacketPtr &pkt) +{ + if (isFill) { + parent.notifyFill(pkt); + } else { + parent.probeNotify(pkt, miss); + } +} + BasePrefetcher::BasePrefetcher(const BasePrefetcherParams *p) - : ClockedObject(p), cache(nullptr), blkSize(0), lBlkSize(0), - system(p->sys), onMiss(p->on_miss), onRead(p->on_read), + : ClockedObject(p), listeners(), cache(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), - masterId(system->getMasterId(name())), - pageBytes(system->getPageBytes()) + masterId(p->sys->getMasterId(this)), pageBytes(p->sys->getPageBytes()), + prefetchOnAccess(p->prefetch_on_access), + useVirtualAddresses(p->use_virtual_addresses), issuedPrefetches(0), + usefulPrefetches(0), tlb(nullptr) { } @@ -68,6 +105,8 @@ BasePrefetcher::setCache(BaseCache *_cache) { assert(!cache); cache = _cache; + + // If the cache has a different block size from the system's, save it blkSize = cache->getBlockSize(); lBlkSize = floorLog2(blkSize); } @@ -85,13 +124,11 @@ BasePrefetcher::regStats() } bool -BasePrefetcher::observeAccess(const PacketPtr &pkt) const +BasePrefetcher::observeAccess(const PacketPtr &pkt, bool miss) const { - Addr addr = pkt->getAddr(); bool fetch = pkt->req->isInstFetch(); bool read = pkt->isRead(); bool inv = pkt->isInvalidate(); - bool is_secure = pkt->isSecure(); if (pkt->req->isUncacheable()) return false; if (fetch && !onInst) return false; @@ -102,8 +139,7 @@ BasePrefetcher::observeAccess(const PacketPtr &pkt) const if (pkt->cmd == MemCmd::CleanEvict) return false; if (onMiss) { - return !inCache(addr, is_secure) && - !inMissQueue(addr, is_secure); + return miss; } return true; @@ -112,19 +148,19 @@ BasePrefetcher::observeAccess(const PacketPtr &pkt) const bool BasePrefetcher::inCache(Addr addr, bool is_secure) const { - if (cache->inCache(addr, is_secure)) { - return true; - } - return false; + return cache->inCache(addr, is_secure); } bool BasePrefetcher::inMissQueue(Addr addr, bool is_secure) const { - if (cache->inMissQueue(addr, is_secure)) { - return true; - } - return false; + return cache->inMissQueue(addr, is_secure); +} + +bool +BasePrefetcher::hasBeenPrefetched(Addr addr, bool is_secure) const +{ + return cache->hasBeenPrefetched(addr, is_secure); } bool @@ -136,7 +172,7 @@ BasePrefetcher::samePage(Addr a, Addr b) const Addr BasePrefetcher::blockAddress(Addr a) const { - return a & ~(blkSize-1); + return a & ~((Addr)blkSize-1); } Addr @@ -162,3 +198,66 @@ BasePrefetcher::pageIthBlockAddress(Addr page, uint32_t blockIndex) const { return page + (blockIndex << lBlkSize); } + +void +BasePrefetcher::probeNotify(const PacketPtr &pkt, bool miss) +{ + // 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->req->hasPaddr()) { + panic("Request must have a physical address"); + } + + if (hasBeenPrefetched(pkt->getAddr(), pkt->isSecure())) { + usefulPrefetches += 1; + } + + // Verify this access type is observed by prefetcher + if (observeAccess(pkt, miss)) { + if (useVirtualAddresses && pkt->req->hasVaddr()) { + PrefetchInfo pfi(pkt, pkt->req->getVaddr(), miss); + notify(pkt, pfi); + } else if (!useVirtualAddresses) { + PrefetchInfo pfi(pkt, pkt->req->getPaddr(), miss); + notify(pkt, pfi); + } + } +} + +void +BasePrefetcher::regProbeListeners() +{ + /** + * If no probes were added by the configuration scripts, connect to the + * 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)); + if (prefetchOnAccess) { + listeners.push_back(new PrefetchListener(*this, pm, "Hit", false, + false)); + } + } +} + +void +BasePrefetcher::addEventProbe(SimObject *obj, const char *name) +{ + ProbeManager *pm(obj->getProbeManager()); + listeners.push_back(new PrefetchListener(*this, pm, name)); +} + +void +BasePrefetcher::addTLB(BaseTLB *t) +{ + fatal_if(tlb != nullptr, "Only one TLB can be registered"); + tlb = t; +}