summaryrefslogtreecommitdiff
path: root/src/mem/cache/prefetch/queued.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/cache/prefetch/queued.cc')
-rw-r--r--src/mem/cache/prefetch/queued.cc213
1 files changed, 213 insertions, 0 deletions
diff --git a/src/mem/cache/prefetch/queued.cc b/src/mem/cache/prefetch/queued.cc
new file mode 100644
index 000000000..318d565dc
--- /dev/null
+++ b/src/mem/cache/prefetch/queued.cc
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2014 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.
+ *
+ * Authors: Mitch Hayenga
+ */
+
+#include "debug/HWPrefetch.hh"
+#include "mem/cache/prefetch/queued.hh"
+#include "mem/cache/base.hh"
+
+QueuedPrefetcher::QueuedPrefetcher(const QueuedPrefetcherParams *p)
+ : BasePrefetcher(p), queueSize(p->queue_size), latency(p->latency),
+ queueSquash(p->queue_squash), queueFilter(p->queue_filter),
+ cacheSnoop(p->cache_snoop), tagPrefetch(p->tag_prefetch)
+{
+
+}
+
+QueuedPrefetcher::~QueuedPrefetcher()
+{
+ // Delete the queued prefetch packets
+ for (DeferredPacket &p : pfq) {
+ delete p.pkt->req;
+ delete p.pkt;
+ }
+}
+
+Tick
+QueuedPrefetcher::notify(const PacketPtr &pkt)
+{
+ // Verify this access type is observed by prefetcher
+ if (observeAccess(pkt)) {
+ Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize - 1);
+ bool is_secure = pkt->isSecure();
+
+ // Squash queued prefetches if demand miss to same line
+ if (queueSquash) {
+ auto itr = pfq.begin();
+ while (itr != pfq.end()) {
+ if (itr->pkt->getAddr() == blk_addr &&
+ itr->pkt->isSecure() == is_secure) {
+ delete itr->pkt->req;
+ delete itr->pkt;
+ itr = pfq.erase(itr);
+ } else {
+ ++itr;
+ }
+ }
+
+ if (pfq.empty())
+ cache->deassertMemSideBusRequest(BaseCache::Request_PF);
+ }
+
+ // Calculate prefetches given this access
+ std::vector<Addr> addresses;
+ calculatePrefetch(pkt, addresses);
+
+ // Queue up generated prefetches
+ for (Addr pf_addr : addresses) {
+
+ // Block align prefetch address
+ pf_addr = pf_addr & ~(Addr)(blkSize - 1);
+
+ pfIdentified++;
+ DPRINTF(HWPrefetch, "Found a pf candidate addr: %#x, "
+ "inserting into prefetch queue.\n", pf_addr);
+
+ if (queueFilter && inPrefetch(pf_addr, is_secure)) {
+ pfBufferHit++;
+ DPRINTF(HWPrefetch, "Prefetch addr already in "
+ "prefetch queue\n");
+ continue;
+ }
+
+ if (cacheSnoop && (inCache(pf_addr, is_secure) ||
+ inMissQueue(pf_addr, is_secure))) {
+ pfInCache++;
+ DPRINTF(HWPrefetch, "Dropping redundant in "
+ "cache/MSHR prefetch addr:%#x\n", pf_addr);
+ continue;
+ }
+
+ // Create a prefetch memory request
+ Request *pf_req =
+ new Request(pf_addr, blkSize, 0, masterId);
+
+ if (is_secure) {
+ pf_req->setFlags(Request::SECURE);
+ }
+ pf_req->taskId(ContextSwitchTaskId::Prefetcher);
+ PacketPtr pf_pkt = new Packet(pf_req, MemCmd::HardPFReq);
+ pf_pkt->allocate();
+
+ if (pkt->req->hasContextId()) {
+ pf_req->setThreadContext(pkt->req->contextId(),
+ pkt->req->threadId());
+ }
+
+ if (tagPrefetch && pkt->req->hasPC()) {
+ // Tag prefetch packet with accessing pc
+ pf_pkt->req->setPC(pkt->req->getPC());
+ }
+
+ // Verify prefetch buffer space for request
+ if (pfq.size() == queueSize) {
+ pfRemovedFull++;
+ PacketPtr old_pkt = pfq.begin()->pkt;
+ DPRINTF(HWPrefetch, "Prefetch queue full, removing "
+ "oldest packet addr: %#x", old_pkt->getAddr());
+ delete old_pkt->req;
+ delete old_pkt;
+ pfq.pop_front();
+ }
+
+ Tick pf_time = curTick() + clockPeriod() * latency;
+ DPRINTF(HWPrefetch, "Prefetch queued. "
+ "addr:%#x tick:%lld.\n", pf_addr, pf_time);
+
+ pfq.push_back(DeferredPacket(pf_time, pf_pkt));
+ }
+ }
+
+ return pfq.empty() ? MaxTick : pfq.front().tick;
+}
+
+PacketPtr
+QueuedPrefetcher::getPacket()
+{
+ DPRINTF(HWPrefetch, "Requesting a prefetch to issue.\n");
+
+ if (pfq.empty()) {
+ DPRINTF(HWPrefetch, "No hardware prefetches available.\n");
+ return NULL;
+ }
+
+ PacketPtr pkt = pfq.begin()->pkt;
+ pfq.pop_front();
+
+ pfIssued++;
+ assert(pkt != NULL);
+ DPRINTF(HWPrefetch, "Generating prefetch for %#x.\n", pkt->getAddr());
+ return pkt;
+}
+
+bool
+QueuedPrefetcher::inPrefetch(Addr address, bool is_secure) const
+{
+ for (const DeferredPacket &dp : pfq) {
+ if (dp.pkt->getAddr() == address &&
+ dp.pkt->isSecure() == is_secure) return true;
+ }
+
+ return false;
+}
+
+void
+QueuedPrefetcher::regStats()
+{
+ BasePrefetcher::regStats();
+
+ pfIdentified
+ .name(name() + ".pfIdentified")
+ .desc("number of prefetch candidates identified");
+
+ pfBufferHit
+ .name(name() + ".pfBufferHit")
+ .desc("number of redundant prefetches already in prefetch queue");
+
+ pfInCache
+ .name(name() + ".pfInCache")
+ .desc("number of redundant prefetches already in cache/mshr dropped");
+
+ pfRemovedFull
+ .name(name() + ".pfRemovedFull")
+ .desc("number of prefetches dropped due to prefetch queue size");
+
+ pfSpanPage
+ .name(name() + ".pfSpanPage")
+ .desc("number of prefetches not generated due to page crossing");
+}