diff options
Diffstat (limited to 'src/mem/cache/prefetch/queued.cc')
-rw-r--r-- | src/mem/cache/prefetch/queued.cc | 213 |
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"); +} |