From 89a7fb03934b3e38c7d8b2c4818794b3ec874fdf Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 16 Feb 2009 08:56:40 -0800 Subject: Fixes to get prefetching working again. Apparently we broke it with the cache rewrite and never noticed. Thanks to Bao Yungang for a significant part of these changes (and for inspiring me to work on the rest). Some other overdue cleanup on the prefetch code too. --- src/mem/cache/prefetch/base.cc | 156 +++++++++++++++++++++++------------------ 1 file changed, 89 insertions(+), 67 deletions(-) (limited to 'src/mem/cache/prefetch/base.cc') diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index a7e6cfdfc..365ce6727 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -33,6 +33,7 @@ * Hardware Prefetcher Definition. */ +#include "arch/isa_traits.hh" #include "base/trace.hh" #include "mem/cache/base.hh" #include "mem/cache/prefetch/base.hh" @@ -43,7 +44,7 @@ BasePrefetcher::BasePrefetcher(const BaseCacheParams *p) : size(p->prefetcher_size), pageStop(!p->prefetch_past_page), serialSquash(p->prefetch_serial_squash), cacheCheckPush(p->prefetch_cache_check_push), - only_data(p->prefetch_data_accesses_only) + onlyData(p->prefetch_data_accesses_only) { } @@ -52,6 +53,7 @@ BasePrefetcher::setCache(BaseCache *_cache) { cache = _cache; blkSize = cache->getBlockSize(); + _name = cache->name() + "-pf"; } void @@ -99,7 +101,8 @@ BasePrefetcher::regStats(const std::string &name) pfSquashed .name(name + ".prefetcher.num_hwpf_squashed_from_miss") - .desc("number of hwpf that got squashed due to a miss aborting calculation time") + .desc("number of hwpf that got squashed due to a miss " + "aborting calculation time") ; } @@ -126,60 +129,79 @@ BasePrefetcher::inMissQueue(Addr addr) PacketPtr BasePrefetcher::getPacket() { - DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name()); + DPRINTF(HWPrefetch, "Requesting a hw_pf to issue\n"); if (pf.empty()) { - DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name()); + DPRINTF(HWPrefetch, "No HW_PF found\n"); return NULL; } PacketPtr pkt; - bool keepTrying = false; + bool keep_trying = false; do { pkt = *pf.begin(); pf.pop_front(); if (!cacheCheckPush) { - keepTrying = cache->inCache(pkt->getAddr()); + keep_trying = cache->inCache(pkt->getAddr()); } + + if (keep_trying) { + DPRINTF(HWPrefetch, "addr 0x%x in cache, skipping\n", + pkt->getAddr()); + delete pkt->req; + delete pkt; + } + if (pf.empty()) { cache->deassertMemSideBusRequest(BaseCache::Request_PF); - if (keepTrying) return NULL; //None left, all were in cache + if (keep_trying) { + return NULL; // None left, all were in cache + } } - } while (keepTrying); + } while (keep_trying); pfIssued++; + assert(pkt != NULL); + DPRINTF(HWPrefetch, "returning 0x%x\n", pkt->getAddr()); return pkt; } -void -BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) + +Tick +BasePrefetcher::notify(PacketPtr &pkt, Tick time) { - if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && only_data)) - { - //Calculate the blk address - Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1); + if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && onlyData)) { + // Calculate the blk address + Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); - //Check if miss is in pfq, if so remove it - std::list::iterator iter = inPrefetch(blkAddr); + // Check if miss is in pfq, if so remove it + std::list::iterator iter = inPrefetch(blk_addr); if (iter != pf.end()) { - DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name()); + DPRINTF(HWPrefetch, "Saw a miss to a queued prefetch addr: " + "0x%x, removing it\n", blk_addr); pfRemovedMSHR++; + delete (*iter)->req; + delete (*iter); pf.erase(iter); if (pf.empty()) cache->deassertMemSideBusRequest(BaseCache::Request_PF); } - //Remove anything in queue with delay older than time - //since everything is inserted in time order, start from end - //and work until pf.empty() or time is earlier - //This is done to emulate Aborting the previous work on a new miss - //Needed for serial calculators like GHB + // Remove anything in queue with delay older than time + // since everything is inserted in time order, start from end + // and work until pf.empty() or time is earlier + // This is done to emulate Aborting the previous work on a new miss + // Needed for serial calculators like GHB if (serialSquash) { iter = pf.end(); iter--; while (!pf.empty() && ((*iter)->time >= time)) { pfSquashed++; - pf.pop_back(); + DPRINTF(HWPrefetch, "Squashing old prefetch addr: 0x%x\n", + (*iter)->getAddr()); + delete (*iter)->req; + delete (*iter); + pf.erase(iter); iter--; } if (pf.empty()) @@ -191,74 +213,70 @@ BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) std::list delays; calculatePrefetch(pkt, addresses, delays); - std::list::iterator addr = addresses.begin(); - std::list::iterator delay = delays.begin(); - while (addr != addresses.end()) - { - DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name()); - //temp calc this here... + std::list::iterator addrIter = addresses.begin(); + std::list::iterator delayIter = delays.begin(); + for (; addrIter != addresses.end(); ++addrIter, ++delayIter) { + Addr addr = *addrIter; + pfIdentified++; - //create a prefetch memreq - Request * prefetchReq = new Request(*addr, blkSize, 0); - PacketPtr prefetch; - prefetch = new Packet(prefetchReq, MemCmd::HardPFReq, -1); - prefetch->allocate(); - prefetch->req->setThreadContext(pkt->req->contextId(), - pkt->req->threadId()); - prefetch->time = time + (*delay); //@todo ADD LATENCY HERE - //... initialize + DPRINTF(HWPrefetch, "Found a pf candidate addr: 0x%x, " + "inserting into prefetch queue with delay %d time %d\n", + addr, *delayIter, time); - //Check if it is already in the cache - if (cacheCheckPush) { - if (cache->inCache(prefetch->getAddr())) { - addr++; - delay++; - continue; - } + // Check if it is already in the cache + if (cacheCheckPush && cache->inCache(addr)) { + DPRINTF(HWPrefetch, "Prefetch addr already in cache\n"); + continue; } - //Check if it is already in the miss_queue - if (cache->inMissQueue(prefetch->getAddr())) { - addr++; - delay++; + // Check if it is already in the miss_queue + if (cache->inMissQueue(addr)) { + DPRINTF(HWPrefetch, "Prefetch addr already in miss queue\n"); continue; } - //Check if it is already in the pf buffer - if (inPrefetch(prefetch->getAddr()) != pf.end()) { + // Check if it is already in the pf buffer + if (inPrefetch(addr) != pf.end()) { pfBufferHit++; - addr++; - delay++; + DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n"); continue; } - //We just remove the head if we are full - if (pf.size() == size) - { - DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name()); + // create a prefetch memreq + Request *prefetchReq = new Request(*addrIter, blkSize, 0); + PacketPtr prefetch = + new Packet(prefetchReq, MemCmd::HardPFReq, Packet::Broadcast); + prefetch->allocate(); + prefetch->req->setThreadContext(pkt->req->contextId(), + pkt->req->threadId()); + + prefetch->time = time + (*delayIter); // @todo ADD LATENCY HERE + + // We just remove the head if we are full + if (pf.size() == size) { pfRemovedFull++; + PacketPtr old_pkt = *pf.begin(); + DPRINTF(HWPrefetch, "Prefetch queue full, " + "removing oldest 0x%x\n", old_pkt->getAddr()); + delete old_pkt->req; + delete old_pkt; pf.pop_front(); } pf.push_back(prefetch); - - //Make sure to request the bus, with proper delay - cache->requestMemSideBus(BaseCache::Request_PF, prefetch->time); - - //Increment through the list - addr++; - delay++; } } + + return pf.empty() ? 0 : pf.front()->time; } std::list::iterator BasePrefetcher::inPrefetch(Addr address) { - //Guaranteed to only be one match, we always check before inserting + // Guaranteed to only be one match, we always check before inserting std::list::iterator iter; - for (iter=pf.begin(); iter != pf.end(); iter++) { + for (iter = pf.begin(); iter != pf.end(); iter++) { if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { return iter; } @@ -266,4 +284,8 @@ BasePrefetcher::inPrefetch(Addr address) return pf.end(); } - +bool +BasePrefetcher::samePage(Addr a, Addr b) +{ + return roundDown(a, TheISA::VMPageSize) == roundDown(b, TheISA::VMPageSize); +} -- cgit v1.2.3