From b0d1643ddf849d5e9b68a2e6535fa1ef561eac92 Mon Sep 17 00:00:00 2001 From: Javier Bueno Date: Thu, 21 Feb 2019 22:12:05 +0100 Subject: [PATCH] mem-cache: Added extra information to PrefetchInfo Added additional information to the PrefetchInfo data structure - Whether the event is triggered by a cache miss - Whether the event is a write or a read - Size of the data accessed - Data accessed by the request Change-Id: I070f3ffe837ea960a357388e7f2b8a61d7b2196c Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/16583 Reviewed-by: Daniel Carvalho Reviewed-by: Nikos Nikoleris Maintainer: Nikos Nikoleris --- src/mem/cache/prefetch/base.cc | 47 +++++++++------ src/mem/cache/prefetch/base.hh | 105 ++++++++++++++++++++++++++++++--- 2 files changed, 126 insertions(+), 26 deletions(-) diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index 52f5d1a9a..366489227 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -56,16 +56,26 @@ #include "params/BasePrefetcher.hh" #include "sim/system.hh" -BasePrefetcher::PrefetchInfo::PrefetchInfo(PacketPtr pkt, Addr addr) +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()) + 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) + secure(pfi.secure), size(pfi.size), write(pfi.write), + paddress(pfi.paddress), cacheMiss(pfi.cacheMiss), data(nullptr) { } @@ -75,7 +85,7 @@ BasePrefetcher::PrefetchListener::notify(const PacketPtr &pkt) if (isFill) { parent.notifyFill(pkt); } else { - parent.probeNotify(pkt); + parent.probeNotify(pkt, miss); } } @@ -114,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; @@ -131,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; @@ -193,25 +200,28 @@ BasePrefetcher::pageIthBlockAddress(Addr page, uint32_t blockIndex) const } void -BasePrefetcher::probeNotify(const PacketPtr &pkt) +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)) { + if (observeAccess(pkt, miss)) { if (useVirtualAddresses && pkt->req->hasVaddr()) { - PrefetchInfo pfi(pkt, pkt->req->getVaddr()); + PrefetchInfo pfi(pkt, pkt->req->getVaddr(), miss); notify(pkt, pfi); - } else if (!useVirtualAddresses && pkt->req->hasPaddr()) { - PrefetchInfo pfi(pkt, pkt->req->getPaddr()); + } else if (!useVirtualAddresses) { + PrefetchInfo pfi(pkt, pkt->req->getPaddr(), miss); notify(pkt, pfi); } } @@ -227,10 +237,13 @@ BasePrefetcher::regProbeListeners() */ if (listeners.empty() && cache != nullptr) { ProbeManager *pm(cache->getProbeManager()); - listeners.push_back(new PrefetchListener(*this, pm, "Miss")); - listeners.push_back(new PrefetchListener(*this, pm, "Fill", true)); + 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")); + listeners.push_back(new PrefetchListener(*this, pm, "Hit", false, + false)); } } } diff --git a/src/mem/cache/prefetch/base.hh b/src/mem/cache/prefetch/base.hh index 4df8428c6..05895f223 100644 --- a/src/mem/cache/prefetch/base.hh +++ b/src/mem/cache/prefetch/base.hh @@ -51,10 +51,12 @@ #include +#include "arch/isa_traits.hh" #include "base/statistics.hh" #include "base/types.hh" #include "mem/packet.hh" #include "mem/request.hh" +#include "sim/byteswap.hh" #include "sim/clocked_object.hh" #include "sim/probe/probe.hh" @@ -67,13 +69,15 @@ class BasePrefetcher : public ClockedObject { public: PrefetchListener(BasePrefetcher &_parent, ProbeManager *pm, - const std::string &name, bool _isFill = false) + const std::string &name, bool _isFill = false, + bool _miss = false) : ProbeListenerArgBase(pm, name), - parent(_parent), isFill(_isFill) {} + parent(_parent), isFill(_isFill), miss(_miss) {} void notify(const PacketPtr &pkt) override; protected: BasePrefetcher &parent; - bool isFill; + const bool isFill; + const bool miss; }; std::vector listeners; @@ -85,7 +89,7 @@ class BasePrefetcher : public ClockedObject * generate new prefetch requests. */ class PrefetchInfo { - /** The address. */ + /** The address used to train and generate prefetches */ Addr address; /** The program counter that generated this address. */ Addr pc; @@ -95,6 +99,16 @@ class BasePrefetcher : public ClockedObject bool validPC; /** Whether this address targets the secure memory space. */ bool secure; + /** Size in bytes of the request triggering this event */ + unsigned int size; + /** Whether this event comes from a write request */ + bool write; + /** Physical address, needed because address can be virtual */ + Addr paddress; + /** Whether this event comes from a cache miss */ + bool cacheMiss; + /** Pointer to the associated request data */ + uint8_t *data; public: /** @@ -143,6 +157,67 @@ class BasePrefetcher : public ClockedObject return masterId; } + /** + * Gets the size of the request triggering this event + * @return the size in bytes of the request triggering this event + */ + unsigned int getSize() const + { + return size; + } + + /** + * Checks if the request that caused this prefetch event was a write + * request + * @return true if the request causing this event is a write request + */ + bool isWrite() const + { + return write; + } + + /** + * Gets the physical address of the request + * @return physical address of the request + */ + Addr getPaddr() const + { + return paddress; + } + + /** + * Check if this event comes from a cache miss + * @result true if this event comes from a cache miss + */ + bool isCacheMiss() const + { + return cacheMiss; + } + + /** + * Gets the associated data of the request triggering the event + * @param Byte ordering of the stored data + * @return the data + */ + template + inline T + get(ByteOrder endian = TheISA::GuestByteOrder) const + { + if (data == nullptr) { + panic("PrefetchInfo::get called with a request with no data."); + } + switch (endian) { + case BigEndianByteOrder: + return betoh(*(T*)data); + + case LittleEndianByteOrder: + return letoh(*(T*)data); + + default: + panic("Illegal byte order in PrefetchInfo::get()\n"); + }; + } + /** * Check for equality * @param pfi PrefetchInfo to compare against @@ -157,9 +232,11 @@ class BasePrefetcher : public ClockedObject /** * Constructs a PrefetchInfo using a PacketPtr. * @param pkt PacketPtr used to generate the PrefetchInfo - * @param addr the address value of the new object + * @param addr the address value of the new object, this address is + * used to train the prefetcher + * @param miss whether this event comes from a cache miss */ - PrefetchInfo(PacketPtr pkt, Addr addr); + PrefetchInfo(PacketPtr pkt, Addr addr, bool miss); /** * Constructs a PrefetchInfo using a new address value and @@ -168,6 +245,11 @@ class BasePrefetcher : public ClockedObject * @param addr the address value of the new object */ PrefetchInfo(PrefetchInfo const &pfi, Addr addr); + + ~PrefetchInfo() + { + delete data; + } }; protected: @@ -209,8 +291,12 @@ class BasePrefetcher : public ClockedObject /** Use Virtual Addresses for prefetching */ const bool useVirtualAddresses; - /** Determine if this access should be observed */ - bool observeAccess(const PacketPtr &pkt) const; + /** + * 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 + */ + bool observeAccess(const PacketPtr &pkt, bool miss) const; /** Determine if address is in cache */ bool inCache(Addr addr, bool is_secure) const; @@ -275,8 +361,9 @@ class BasePrefetcher : public ClockedObject /** * Process a notification event from the ProbeListener. * @param pkt The memory request causing the event + * @param miss whether this event comes from a cache miss */ - void probeNotify(const PacketPtr &pkt); + void probeNotify(const PacketPtr &pkt, bool miss); /** * Add a SimObject and a probe name to listen events from -- 2.30.2