base.cc revision 4022
1360SN/A/* 21458SN/A * Copyright (c) 2005 The Regents of The University of Michigan 3360SN/A * All rights reserved. 4360SN/A * 5360SN/A * Redistribution and use in source and binary forms, with or without 6360SN/A * modification, are permitted provided that the following conditions are 7360SN/A * met: redistributions of source code must retain the above copyright 8360SN/A * notice, this list of conditions and the following disclaimer; 9360SN/A * redistributions in binary form must reproduce the above copyright 10360SN/A * notice, this list of conditions and the following disclaimer in the 11360SN/A * documentation and/or other materials provided with the distribution; 12360SN/A * neither the name of the copyright holders nor the names of its 13360SN/A * contributors may be used to endorse or promote products derived from 14360SN/A * this software without specific prior written permission. 15360SN/A * 16360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 292665Ssaidi@eecs.umich.edu */ 30360SN/A 31360SN/A/** 321354SN/A * @file 331354SN/A * Hardware Prefetcher Definition. 34360SN/A */ 352764Sstever@eecs.umich.edu 362764Sstever@eecs.umich.edu#include "base/trace.hh" 372064SN/A#include "mem/cache/base_cache.hh" 38360SN/A#include "mem/cache/prefetch/base_prefetcher.hh" 39360SN/A#include "mem/request.hh" 40360SN/A#include <list> 41360SN/A 42360SN/ABasePrefetcher::BasePrefetcher(int size, bool pageStop, bool serialSquash, 43360SN/A bool cacheCheckPush, bool onlyData) 441809SN/A :size(size), pageStop(pageStop), serialSquash(serialSquash), 455543Ssaidi@eecs.umich.edu cacheCheckPush(cacheCheckPush), only_data(onlyData) 461809SN/A{ 473113Sgblack@eecs.umich.edu} 488229Snate@binkert.org 498229Snate@binkert.orgvoid 503113Sgblack@eecs.umich.eduBasePrefetcher::setCache(BaseCache *_cache) 517075Snate@binkert.org{ 528229Snate@binkert.org cache = _cache; 537075Snate@binkert.org blkSize = cache->getBlockSize(); 54360SN/A} 552474SN/A 565543Ssaidi@eecs.umich.eduvoid 572462SN/ABasePrefetcher::regStats(const std::string &name) 581354SN/A{ 596216Snate@binkert.org pfIdentified 606658Snate@binkert.org .name(name + ".prefetcher.num_hwpf_identified") 612474SN/A .desc("number of hwpf identified") 622680Sktlim@umich.edu ; 638229Snate@binkert.org 642474SN/A pfMSHRHit 657678Sgblack@eecs.umich.edu .name(name + ".prefetcher.num_hwpf_already_in_mshr") 668229Snate@binkert.org .desc("number of hwpf that were already in mshr") 676640Svince@csl.cornell.edu ; 68360SN/A 69360SN/A pfCacheHit 70360SN/A .name(name + ".prefetcher.num_hwpf_already_in_cache") 71360SN/A .desc("number of hwpf that were already in the cache") 72360SN/A ; 73360SN/A 74360SN/A pfBufferHit 75360SN/A .name(name + ".prefetcher.num_hwpf_already_in_prefetcher") 76378SN/A .desc("number of hwpf that were already in the prefetch queue") 771450SN/A ; 783114Sgblack@eecs.umich.edu 79360SN/A pfRemovedFull 805543Ssaidi@eecs.umich.edu .name(name + ".prefetcher.num_hwpf_evicted") 815543Ssaidi@eecs.umich.edu .desc("number of hwpf removed due to no buffer left") 825543Ssaidi@eecs.umich.edu ; 83360SN/A 84360SN/A pfRemovedMSHR 85360SN/A .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit") 86360SN/A .desc("number of hwpf removed because MSHR allocated") 87360SN/A ; 882680Sktlim@umich.edu 89360SN/A pfIssued 90360SN/A .name(name + ".prefetcher.num_hwpf_issued") 91360SN/A .desc("number of hwpf issued") 92360SN/A ; 93360SN/A 94360SN/A pfSpanPage 95360SN/A .name(name + ".prefetcher.num_hwpf_span_page") 96360SN/A .desc("number of hwpf spanning a virtual page") 97360SN/A ; 98360SN/A 99360SN/A pfSquashed 1003114Sgblack@eecs.umich.edu .name(name + ".prefetcher.num_hwpf_squashed_from_miss") 101360SN/A .desc("number of hwpf that got squashed due to a miss aborting calculation time") 102360SN/A ; 103360SN/A} 104360SN/A 105360SN/Ainline bool 106360SN/ABasePrefetcher::inCache(Addr addr) 107360SN/A{ 108360SN/A if (cache->inCache(addr)) { 109360SN/A pfCacheHit++; 110360SN/A return true; 111360SN/A } 112360SN/A return false; 113360SN/A} 114360SN/A 115360SN/Ainline bool 116360SN/ABasePrefetcher::inMissQueue(Addr addr) 117360SN/A{ 118360SN/A if (cache->inMissQueue(addr)) { 119360SN/A pfMSHRHit++; 120360SN/A return true; 121360SN/A } 1222400SN/A return false; 123360SN/A} 1242461SN/A 1255543Ssaidi@eecs.umich.eduPacketPtr 126360SN/ABasePrefetcher::getPacket() 127360SN/A{ 128360SN/A DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name()); 129360SN/A 130360SN/A if (pf.empty()) { 1312400SN/A DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name()); 132360SN/A return NULL; 1332461SN/A } 1345543Ssaidi@eecs.umich.edu 135360SN/A PacketPtr pkt; 136360SN/A bool keepTrying = false; 137360SN/A do { 138360SN/A pkt = *pf.begin(); 139360SN/A pf.pop_front(); 140360SN/A if (!cacheCheckPush) { 141360SN/A keepTrying = cache->inCache(pkt->getAddr()); 142360SN/A } 143360SN/A if (pf.empty()) { 144360SN/A cache->clearMasterRequest(Request_PF); 145360SN/A if (keepTrying) return NULL; //None left, all were in cache 146360SN/A } 147360SN/A } while (keepTrying); 1485543Ssaidi@eecs.umich.edu 149360SN/A pfIssued++; 150360SN/A return pkt; 151360SN/A} 152360SN/A 153360SN/Avoid 154360SN/ABasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) 155360SN/A{ 156360SN/A if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && only_data)) 157360SN/A { 158360SN/A //Calculate the blk address 159360SN/A Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1); 160360SN/A 161360SN/A //Check if miss is in pfq, if so remove it 162360SN/A std::list<PacketPtr>::iterator iter = inPrefetch(blkAddr); 163360SN/A if (iter != pf.end()) { 164360SN/A DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name()); 165360SN/A pfRemovedMSHR++; 1665543Ssaidi@eecs.umich.edu pf.erase(iter); 1675543Ssaidi@eecs.umich.edu if (pf.empty()) 168502SN/A cache->clearMasterRequest(Request_PF); 169360SN/A } 170360SN/A 171360SN/A //Remove anything in queue with delay older than time 172360SN/A //since everything is inserted in time order, start from end 173360SN/A //and work until pf.empty() or time is earlier 174360SN/A //This is done to emulate Aborting the previous work on a new miss 175360SN/A //Needed for serial calculators like GHB 176360SN/A if (serialSquash) { 177360SN/A iter = pf.end(); 178360SN/A iter--; 179360SN/A while (!pf.empty() && ((*iter)->time >= time)) { 180378SN/A pfSquashed++; 1811706SN/A pf.pop_back(); 1823114Sgblack@eecs.umich.edu iter--; 183378SN/A } 184378SN/A if (pf.empty()) 185378SN/A cache->clearMasterRequest(Request_PF); 186378SN/A } 187378SN/A 1881706SN/A 1893114Sgblack@eecs.umich.edu std::list<Addr> addresses; 1908149SChris.Emmons@ARM.com std::list<Tick> delays; 1918149SChris.Emmons@ARM.com calculatePrefetch(pkt, addresses, delays); 192360SN/A 1936109Ssanchezd@stanford.edu std::list<Addr>::iterator addr = addresses.begin(); 1941706SN/A std::list<Tick>::iterator delay = delays.begin(); 1953114Sgblack@eecs.umich.edu while (addr != addresses.end()) 196378SN/A { 1976109Ssanchezd@stanford.edu DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name()); 1986109Ssanchezd@stanford.edu //temp calc this here... 1996109Ssanchezd@stanford.edu pfIdentified++; 2006109Ssanchezd@stanford.edu //create a prefetch memreq 201378SN/A Request * prefetchReq = new Request(*addr, blkSize, 0); 2021706SN/A PacketPtr prefetch; 2033114Sgblack@eecs.umich.edu prefetch = new Packet(prefetchReq, MemCmd::HardPFReq, -1); 204378SN/A prefetch->allocate(); 2055748SSteve.Reinhardt@amd.com prefetch->req->setThreadContext(pkt->req->getCpuNum(), 2065748SSteve.Reinhardt@amd.com pkt->req->getThreadNum()); 2075748SSteve.Reinhardt@amd.com 208378SN/A prefetch->time = time + (*delay); //@todo ADD LATENCY HERE 209378SN/A //... initialize 2101706SN/A 2113114Sgblack@eecs.umich.edu //Check if it is already in the cache 212378SN/A if (cacheCheckPush) { 213378SN/A if (cache->inCache(prefetch->getAddr())) { 2141706SN/A addr++; 2153114Sgblack@eecs.umich.edu delay++; 216378SN/A continue; 217378SN/A } 2181706SN/A } 2193114Sgblack@eecs.umich.edu 220378SN/A //Check if it is already in the miss_queue 221378SN/A if (cache->inMissQueue(prefetch->getAddr())) { 2221706SN/A addr++; 2233114Sgblack@eecs.umich.edu delay++; 224378SN/A continue; 2254118Sgblack@eecs.umich.edu } 2264118Sgblack@eecs.umich.edu 2274118Sgblack@eecs.umich.edu //Check if it is already in the pf buffer 2284118Sgblack@eecs.umich.edu if (inPrefetch(prefetch->getAddr()) != pf.end()) { 229378SN/A pfBufferHit++; 2301706SN/A addr++; 2313114Sgblack@eecs.umich.edu delay++; 232378SN/A continue; 233378SN/A } 2341706SN/A 2353114Sgblack@eecs.umich.edu //We just remove the head if we are full 236360SN/A if (pf.size() == size) 2375513SMichael.Adler@intel.com { 2385513SMichael.Adler@intel.com DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name()); 2395513SMichael.Adler@intel.com pfRemovedFull++; 2405513SMichael.Adler@intel.com pf.pop_front(); 2415513SMichael.Adler@intel.com } 2425513SMichael.Adler@intel.com 2435513SMichael.Adler@intel.com pf.push_back(prefetch); 2445513SMichael.Adler@intel.com prefetch->flags |= CACHE_LINE_FILL; 245511SN/A 2461706SN/A //Make sure to request the bus, with proper delay 2473114Sgblack@eecs.umich.edu cache->setMasterRequest(Request_PF, prefetch->time); 248511SN/A 2495513SMichael.Adler@intel.com //Increment through the list 2505513SMichael.Adler@intel.com addr++; 2515513SMichael.Adler@intel.com delay++; 2525513SMichael.Adler@intel.com } 253511SN/A } 2541706SN/A} 2553114Sgblack@eecs.umich.edu 2561706SN/Astd::list<PacketPtr>::iterator 2571706SN/ABasePrefetcher::inPrefetch(Addr address) 2581706SN/A{ 2591706SN/A //Guaranteed to only be one match, we always check before inserting 2603114Sgblack@eecs.umich.edu std::list<PacketPtr>::iterator iter; 2611706SN/A for (iter=pf.begin(); iter != pf.end(); iter++) { 2621706SN/A if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { 2631706SN/A return iter; 2641706SN/A } 2653114Sgblack@eecs.umich.edu } 2661706SN/A return pf.end(); 267511SN/A} 2686703Svince@csl.cornell.edu 2696703Svince@csl.cornell.edu 2706703Svince@csl.cornell.edu