writeBuffer("write buffer", p->write_buffers, p->mshrs), // see below
tags(p->tags),
prefetcher(p->prefetcher),
- prefetchOnAccess(p->prefetch_on_access),
writeAllocator(p->write_allocator),
writebackClean(p->writeback_clean),
tempBlockWriteback(nullptr),
Tick request_time = clockEdge(lat) + pkt->headerDelay;
// Here we reset the timing of the packet.
pkt->headerDelay = pkt->payloadDelay = 0;
- // track time of availability of next prefetch, if any
- Tick next_pf_time = MaxTick;
if (satisfied) {
- // if need to notify the prefetcher we have to do it before
- // anything else as later handleTimingReqHit might turn the
- // packet in a response
- if (prefetcher &&
- (prefetchOnAccess || (blk && blk->wasPrefetched()))) {
- if (blk)
- blk->status &= ~BlkHWPrefetched;
-
- // Don't notify on SWPrefetch
- if (!pkt->cmd.isSWPrefetch()) {
- assert(!pkt->req->isCacheMaintenance());
- next_pf_time = prefetcher->notify(pkt);
- }
+ // notify before anything else as later handleTimingReqHit might turn
+ // the packet in a response
+ ppHit->notify(pkt);
+
+ if (prefetcher && blk && blk->wasPrefetched()) {
+ blk->status &= ~BlkHWPrefetched;
}
handleTimingReqHit(pkt, blk, request_time);
} else {
handleTimingReqMiss(pkt, blk, forward_time, request_time);
- // We should call the prefetcher reguardless if the request is
- // satisfied or not, reguardless if the request is in the MSHR
- // or not. The request could be a ReadReq hit, but still not
- // satisfied (potentially because of a prior write to the same
- // cache line. So, even when not satisfied, there is an MSHR
- // already allocated for this, we need to let the prefetcher
- // know about the request
-
- // Don't notify prefetcher on SWPrefetch, cache maintenance
- // operations or for writes that we are coaslescing.
- if (prefetcher && pkt &&
- !pkt->cmd.isSWPrefetch() &&
- !pkt->req->isCacheMaintenance() &&
- !(writeAllocator && writeAllocator->coalesce() &&
- pkt->isWrite())) {
- next_pf_time = prefetcher->notify(pkt);
- }
+ ppMiss->notify(pkt);
}
- if (next_pf_time != MaxTick) {
- schedMemSideSendEvent(next_pf_time);
+ 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);
+ }
}
}
return tags->anyBlk([](CacheBlk &blk) { return blk.isDirty(); });
}
+bool
+BaseCache::coalesce() const
+{
+ return writeAllocator && writeAllocator->coalesce();
+}
+
void
BaseCache::writebackVisitor(CacheBlk &blk)
{
;
}
+void
+BaseCache::regProbePoints()
+{
+ ppHit = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Hit");
+ ppMiss = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Miss");
+}
+
///////////////
//
// CpuSidePort
#include "mem/request.hh"
#include "params/WriteAllocator.hh"
#include "sim/eventq.hh"
+#include "sim/probe/probe.hh"
#include "sim/serialize.hh"
#include "sim/sim_exit.hh"
#include "sim/system.hh"
/** Prefetcher */
BasePrefetcher *prefetcher;
- /**
- * Notify the prefetcher on every access, not just misses.
- */
- const bool prefetchOnAccess;
+ /** To probe when a cache hit occurs */
+ ProbePointArg<PacketPtr> *ppHit;
+
+ /** To probe when a cache miss occurs */
+ ProbePointArg<PacketPtr> *ppMiss;
/**
* The writeAllocator drive optimizations for streaming writes.
*/
void regStats() override;
+ /** Registers probes. */
+ void regProbePoints() override;
+
public:
BaseCache(const BaseCacheParams *p, unsigned blk_size);
~BaseCache();
}
+ /**
+ * Checks if the cache is coalescing writes
+ *
+ * @return True if the cache is coalescing writes
+ */
+ bool coalesce() const;
+
+
/**
* Cache block visitor that writes back dirty cache blocks using
* functional writes.
*/
void serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override;
-
};
/**
# Mitch Hayenga
from ClockedObject import ClockedObject
+from m5.SimObject import *
from m5.params import *
from m5.proxy import *
+class HWPProbeEvent(object):
+ def __init__(self, prefetcher, obj, *listOfNames):
+ self.obj = obj
+ self.prefetcher = prefetcher
+ self.names = listOfNames
+
+ def register(self):
+ if self.obj:
+ for name in self.names:
+ self.prefetcher.getCCObject().addEventProbe(
+ self.obj.getCCObject(), name)
+
class BasePrefetcher(ClockedObject):
type = 'BasePrefetcher'
abstract = True
cxx_header = "mem/cache/prefetch/base.hh"
+ cxx_exports = [
+ PyBindMethod("addEventProbe"),
+ ]
sys = Param.System(Parent.any, "System this prefetcher belongs to")
on_miss = Param.Bool(False, "Only notify prefetcher on misses")
on_write = Param.Bool(True, "Notify prefetcher on writes")
on_data = Param.Bool(True, "Notify prefetcher on data accesses")
on_inst = Param.Bool(True, "Notify prefetcher on instruction accesses")
+ prefetch_on_access = Param.Bool(Parent.prefetch_on_access,
+ "Notify the hardware prefetcher on every access (not just misses)")
+
+ _events = []
+ def addEvent(self, newObject):
+ self._events.append(newObject)
+
+ # Override the normal SimObject::regProbeListeners method and
+ # register deferred event handlers.
+ def regProbeListeners(self):
+ for event in self._events:
+ event.register()
+ self.getCCObject().regProbeListeners()
+
+ def listenFromProbe(self, simObj, *probeNames):
+ if not isinstance(simObj, SimObject):
+ raise TypeError("argument must be of SimObject type")
+ if len(probeNames) <= 0:
+ raise TypeError("probeNames must have at least one element")
+ self.addEvent(HWPProbeEvent(self, simObj, *probeNames))
class QueuedPrefetcher(BasePrefetcher):
type = "QueuedPrefetcher"
#include <cassert>
#include "base/intmath.hh"
+#include "cpu/base.hh"
#include "mem/cache/base.hh"
#include "params/BasePrefetcher.hh"
#include "sim/system.hh"
+void
+BasePrefetcher::PrefetchListener::notify(const PacketPtr &pkt)
+{
+ parent.probeNotify(pkt);
+}
+
BasePrefetcher::BasePrefetcher(const BasePrefetcherParams *p)
- : ClockedObject(p), cache(nullptr), blkSize(0), lBlkSize(0),
+ : ClockedObject(p), listeners(), cache(nullptr), blkSize(0), lBlkSize(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(this)),
- pageBytes(system->getPageBytes())
+ pageBytes(system->getPageBytes()),
+ prefetchOnAccess(p->prefetch_on_access)
{
}
{
return page + (blockIndex << lBlkSize);
}
+
+void
+BasePrefetcher::probeNotify(const PacketPtr &pkt)
+{
+ // 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;
+ notify(pkt);
+}
+
+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"));
+ if (prefetchOnAccess) {
+ listeners.push_back(new PrefetchListener(*this, pm, "Hit"));
+ }
+ }
+}
+
+void
+BasePrefetcher::addEventProbe(SimObject *obj, const char *name)
+{
+ ProbeManager *pm(obj->getProbeManager());
+ listeners.push_back(new PrefetchListener(*this, pm, name));
+}
#include "mem/packet.hh"
#include "mem/request.hh"
#include "sim/clocked_object.hh"
+#include "sim/probe/probe.hh"
class BaseCache;
struct BasePrefetcherParams;
class BasePrefetcher : public ClockedObject
{
+ class PrefetchListener : public ProbeListenerArgBase<PacketPtr>
+ {
+ public:
+ PrefetchListener(BasePrefetcher &_parent, ProbeManager *pm,
+ const std::string &name)
+ : ProbeListenerArgBase(pm, name),
+ parent(_parent) {}
+ void notify(const PacketPtr &pkt) override;
+ protected:
+ BasePrefetcher &parent;
+ };
+
+ std::vector<PrefetchListener *> listeners;
protected:
// PARAMETERS
const Addr pageBytes;
+ /** Prefetch on every access, not just misses */
+ const bool prefetchOnAccess;
+
/** Determine if this access should be observed */
bool observeAccess(const PacketPtr &pkt) const;
/**
* Notify prefetcher of cache access (may be any access or just
* misses, depending on cache parameters.)
- * @retval Time of next prefetch availability, or MaxTick if none.
*/
- virtual Tick notify(const PacketPtr &pkt) = 0;
+ virtual void notify(const PacketPtr &pkt) = 0;
virtual PacketPtr getPacket() = 0;
virtual Tick nextPrefetchReadyTime() const = 0;
virtual void regStats();
+
+ /**
+ * Register probe points for this object.
+ */
+ void regProbeListeners() override;
+
+ /**
+ * Process a notification event from the ProbeListener.
+ * @param pkt The memory request causing the event
+ */
+ void probeNotify(const PacketPtr &pkt);
+
+ /**
+ * Add a SimObject and a probe name to listen events from
+ * @param obj The SimObject pointer to listen from
+ * @param name The probe name
+ */
+ void addEventProbe(SimObject *obj, const char *name);
};
#endif //__MEM_CACHE_PREFETCH_BASE_HH__
}
}
-Tick
+void
QueuedPrefetcher::notify(const PacketPtr &pkt)
{
// Verify this access type is observed by prefetcher
}
}
}
-
- return pfq.empty() ? MaxTick : pfq.front().tick;
}
PacketPtr
QueuedPrefetcher(const QueuedPrefetcherParams *p);
virtual ~QueuedPrefetcher();
- Tick notify(const PacketPtr &pkt);
+ void notify(const PacketPtr &pkt) override;
PacketPtr insert(AddrPriority& info, bool is_secure);
// Note: This should really be pure virtual, but doesnt go well with params