base.cc revision 3013
12810SN/A/* 210623Smitch.hayenga@arm.com * Copyright (c) 2005 The Regents of The University of Michigan 39546Sandreas.hansson@arm.com * All rights reserved. 49546Sandreas.hansson@arm.com * 59546Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 69546Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 79546Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 89546Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 99546Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 109546Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 119546Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 129546Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 139546Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 142810SN/A * this software without specific prior written permission. 152810SN/A * 162810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272810SN/A * 282810SN/A * Authors: Ron Dreslinski 292810SN/A */ 302810SN/A 312810SN/A/** 322810SN/A * @file 332810SN/A * Hardware Prefetcher Definition. 342810SN/A */ 352810SN/A 362810SN/A#include "base/trace.hh" 372810SN/A#include "mem/cache/base_cache.hh" 382810SN/A#include "mem/cache/prefetch/base_prefetcher.hh" 392810SN/A#include "mem/request.hh" 402810SN/A#include <list> 4110623Smitch.hayenga@arm.com 422810SN/ABasePrefetcher::BasePrefetcher(int size, bool pageStop, bool serialSquash, 432810SN/A bool cacheCheckPush, bool onlyData) 442810SN/A :size(size), pageStop(pageStop), serialSquash(serialSquash), 452810SN/A cacheCheckPush(cacheCheckPush), only_data(onlyData) 462810SN/A{ 472810SN/A} 482810SN/A 4911793Sbrandon.potter@amd.comvoid 5011793Sbrandon.potter@amd.comBasePrefetcher::setCache(BaseCache *_cache) 5112727Snikos.nikoleris@arm.com{ 526658Snate@binkert.org cache = _cache; 5311438SRekai.GonzalezAlberquilla@arm.com blkSize = cache->getBlockSize(); 5413416Sjavier.bueno@metempsy.com} 555338Sstever@gmail.com 5612727Snikos.nikoleris@arm.comvoid 578832SAli.Saidi@ARM.comBasePrefetcher::regStats(const std::string &name) 582810SN/A{ 5913416Sjavier.bueno@metempsy.com pfIdentified 6013416Sjavier.bueno@metempsy.com .name(name + ".prefetcher.num_hwpf_identified") 6113416Sjavier.bueno@metempsy.com .desc("number of hwpf identified") 6213416Sjavier.bueno@metempsy.com ; 6313416Sjavier.bueno@metempsy.com 6413416Sjavier.bueno@metempsy.com pfMSHRHit 6510623Smitch.hayenga@arm.com .name(name + ".prefetcher.num_hwpf_already_in_mshr") 6613416Sjavier.bueno@metempsy.com .desc("number of hwpf that were already in mshr") 6711438SRekai.GonzalezAlberquilla@arm.com ; 6810623Smitch.hayenga@arm.com 6912680Sgiacomo.travaglini@arm.com pfCacheHit 7013416Sjavier.bueno@metempsy.com .name(name + ".prefetcher.num_hwpf_already_in_cache") 7113416Sjavier.bueno@metempsy.com .desc("number of hwpf that were already in the cache") 722810SN/A ; 732810SN/A 742810SN/A pfBufferHit 752810SN/A .name(name + ".prefetcher.num_hwpf_already_in_prefetcher") 762810SN/A .desc("number of hwpf that were already in the prefetch queue") 772810SN/A ; 7810360Sandreas.hansson@arm.com 792810SN/A pfRemovedFull 802810SN/A .name(name + ".prefetcher.num_hwpf_evicted") 8111438SRekai.GonzalezAlberquilla@arm.com .desc("number of hwpf removed due to no buffer left") 822810SN/A ; 832810SN/A 842810SN/A pfRemovedMSHR 858831Smrinmoy.ghosh@arm.com .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit") 862810SN/A .desc("number of hwpf removed because MSHR allocated") 8711522Sstephan.diestelhorst@arm.com ; 8811522Sstephan.diestelhorst@arm.com 892810SN/A pfIssued 9010623Smitch.hayenga@arm.com .name(name + ".prefetcher.num_hwpf_issued") 912810SN/A .desc("number of hwpf issued") 922810SN/A ; 9311438SRekai.GonzalezAlberquilla@arm.com 942810SN/A pfSpanPage 952810SN/A .name(name + ".prefetcher.num_hwpf_span_page") 9610623Smitch.hayenga@arm.com .desc("number of hwpf spanning a virtual page") 9710623Smitch.hayenga@arm.com ; 9810623Smitch.hayenga@arm.com 9910623Smitch.hayenga@arm.com pfSquashed 10010623Smitch.hayenga@arm.com .name(name + ".prefetcher.num_hwpf_squashed_from_miss") 10110626SCurtis.Dunham@arm.com .desc("number of hwpf that got squashed due to a miss aborting calculation time") 10210626SCurtis.Dunham@arm.com ; 10310623Smitch.hayenga@arm.com} 10410623Smitch.hayenga@arm.com 10510623Smitch.hayenga@arm.comPacket * 10610623Smitch.hayenga@arm.comBasePrefetcher::getPacket() 10710623Smitch.hayenga@arm.com{ 10810623Smitch.hayenga@arm.com DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name()); 10910623Smitch.hayenga@arm.com 11010626SCurtis.Dunham@arm.com if (pf.empty()) { 11110883Sali.jafri@arm.com DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name()); 11210623Smitch.hayenga@arm.com return NULL; 11310623Smitch.hayenga@arm.com } 11410623Smitch.hayenga@arm.com 11510623Smitch.hayenga@arm.com Packet * pkt; 11610623Smitch.hayenga@arm.com bool keepTrying = false; 11710623Smitch.hayenga@arm.com do { 11810623Smitch.hayenga@arm.com pkt = *pf.begin(); 11910623Smitch.hayenga@arm.com pf.pop_front(); 12010623Smitch.hayenga@arm.com if (!cacheCheckPush) { 12110623Smitch.hayenga@arm.com keepTrying = inCache(pkt); 12210623Smitch.hayenga@arm.com } 1233861SN/A if (pf.empty()) { 12410028SGiacomo.Gabrielli@arm.com cache->clearMasterRequest(Request_PF); 1253861SN/A if (keepTrying) return NULL; //None left, all were in cache 1263861SN/A } 1273861SN/A } while (keepTrying); 1283861SN/A 1293861SN/A pfIssued++; 13010623Smitch.hayenga@arm.com return pkt; 13110623Smitch.hayenga@arm.com} 1323861SN/A 13310028SGiacomo.Gabrielli@arm.comvoid 1343861SN/ABasePrefetcher::handleMiss(Packet * &pkt, Tick time) 1353861SN/A{ 1363861SN/A if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && only_data)) 1373861SN/A { 1383861SN/A //Calculate the blk address 1395875Ssteve.reinhardt@amd.com Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1); 14010466Sandreas.hansson@arm.com 1415875Ssteve.reinhardt@amd.com //Check if miss is in pfq, if so remove it 14210466Sandreas.hansson@arm.com std::list<Packet *>::iterator iter = inPrefetch(blkAddr); 1435875Ssteve.reinhardt@amd.com if (iter != pf.end()) { 1448831Smrinmoy.ghosh@arm.com DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name()); 14511438SRekai.GonzalezAlberquilla@arm.com pfRemovedMSHR++; 14611438SRekai.GonzalezAlberquilla@arm.com pf.erase(iter); 14711438SRekai.GonzalezAlberquilla@arm.com if (pf.empty()) 14811438SRekai.GonzalezAlberquilla@arm.com cache->clearMasterRequest(Request_PF); 14911438SRekai.GonzalezAlberquilla@arm.com } 1508831Smrinmoy.ghosh@arm.com 15111438SRekai.GonzalezAlberquilla@arm.com //Remove anything in queue with delay older than time 15211438SRekai.GonzalezAlberquilla@arm.com //since everything is inserted in time order, start from end 15311438SRekai.GonzalezAlberquilla@arm.com //and work until pf.empty() or time is earlier 15411438SRekai.GonzalezAlberquilla@arm.com //This is done to emulate Aborting the previous work on a new miss 15511438SRekai.GonzalezAlberquilla@arm.com //Needed for serial calculators like GHB 15611438SRekai.GonzalezAlberquilla@arm.com if (serialSquash) { 15711438SRekai.GonzalezAlberquilla@arm.com iter = pf.end(); 15811438SRekai.GonzalezAlberquilla@arm.com iter--; 15911438SRekai.GonzalezAlberquilla@arm.com while (!pf.empty() && ((*iter)->time >= time)) { 16011438SRekai.GonzalezAlberquilla@arm.com pfSquashed++; 16111438SRekai.GonzalezAlberquilla@arm.com pf.pop_back(); 16211438SRekai.GonzalezAlberquilla@arm.com iter--; 16311438SRekai.GonzalezAlberquilla@arm.com } 16411438SRekai.GonzalezAlberquilla@arm.com if (pf.empty()) 16511438SRekai.GonzalezAlberquilla@arm.com cache->clearMasterRequest(Request_PF); 16611438SRekai.GonzalezAlberquilla@arm.com } 16711438SRekai.GonzalezAlberquilla@arm.com 16811438SRekai.GonzalezAlberquilla@arm.com 16911438SRekai.GonzalezAlberquilla@arm.com std::list<Addr> addresses; 17011438SRekai.GonzalezAlberquilla@arm.com std::list<Tick> delays; 17111438SRekai.GonzalezAlberquilla@arm.com calculatePrefetch(pkt, addresses, delays); 17211438SRekai.GonzalezAlberquilla@arm.com 17311438SRekai.GonzalezAlberquilla@arm.com std::list<Addr>::iterator addr = addresses.begin(); 17413416Sjavier.bueno@metempsy.com std::list<Tick>::iterator delay = delays.begin(); 17513416Sjavier.bueno@metempsy.com while (addr != addresses.end()) 17613416Sjavier.bueno@metempsy.com { 17713416Sjavier.bueno@metempsy.com DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name()); 17813416Sjavier.bueno@metempsy.com //temp calc this here... 17913416Sjavier.bueno@metempsy.com pfIdentified++; 18013416Sjavier.bueno@metempsy.com //create a prefetch memreq 18113416Sjavier.bueno@metempsy.com Request * prefetchReq = new Request(*addr, blkSize, 0); 18213416Sjavier.bueno@metempsy.com Packet * prefetch; 18313416Sjavier.bueno@metempsy.com prefetch = new Packet(prefetchReq, Packet::HardPFReq, -1); 18413416Sjavier.bueno@metempsy.com prefetch->allocate(); 18513416Sjavier.bueno@metempsy.com prefetch->req->setThreadContext(pkt->req->getCpuNum(), 18613416Sjavier.bueno@metempsy.com pkt->req->getThreadNum()); 18713416Sjavier.bueno@metempsy.com 18813416Sjavier.bueno@metempsy.com prefetch->time = time + (*delay); //@todo ADD LATENCY HERE 18913416Sjavier.bueno@metempsy.com //... initialize 19013416Sjavier.bueno@metempsy.com 19113416Sjavier.bueno@metempsy.com //Check if it is already in the cache 19213416Sjavier.bueno@metempsy.com if (cacheCheckPush) { 19313416Sjavier.bueno@metempsy.com if (inCache(prefetch)) { 19413416Sjavier.bueno@metempsy.com addr++; 19513416Sjavier.bueno@metempsy.com delay++; 19613416Sjavier.bueno@metempsy.com continue; 19713416Sjavier.bueno@metempsy.com } 19813416Sjavier.bueno@metempsy.com } 19913416Sjavier.bueno@metempsy.com 20013416Sjavier.bueno@metempsy.com //Check if it is already in the miss_queue 20113416Sjavier.bueno@metempsy.com if (inMissQueue(prefetch->getAddr())) { 20213416Sjavier.bueno@metempsy.com addr++; 20313416Sjavier.bueno@metempsy.com delay++; 20413416Sjavier.bueno@metempsy.com continue; 20513416Sjavier.bueno@metempsy.com } 20613416Sjavier.bueno@metempsy.com 20713416Sjavier.bueno@metempsy.com //Check if it is already in the pf buffer 20813416Sjavier.bueno@metempsy.com if (inPrefetch(prefetch->getAddr()) != pf.end()) { 209 pfBufferHit++; 210 addr++; 211 delay++; 212 continue; 213 } 214 215 //We just remove the head if we are full 216 if (pf.size() == size) 217 { 218 DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name()); 219 pfRemovedFull++; 220 pf.pop_front(); 221 } 222 223 pf.push_back(prefetch); 224 prefetch->flags |= CACHE_LINE_FILL; 225 226 //Make sure to request the bus, with proper delay 227 cache->setMasterRequest(Request_PF, prefetch->time); 228 229 //Increment through the list 230 addr++; 231 delay++; 232 } 233 } 234} 235 236std::list<Packet *>::iterator 237BasePrefetcher::inPrefetch(Addr address) 238{ 239 //Guaranteed to only be one match, we always check before inserting 240 std::list<Packet *>::iterator iter; 241 for (iter=pf.begin(); iter != pf.end(); iter++) { 242 if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { 243 return iter; 244 } 245 } 246 return pf.end(); 247} 248 249 250