base.cc revision 4022
12155SN/A/* 22155SN/A * Copyright (c) 2005 The Regents of The University of Michigan 32155SN/A * All rights reserved. 42155SN/A * 52155SN/A * Redistribution and use in source and binary forms, with or without 62155SN/A * modification, are permitted provided that the following conditions are 72155SN/A * met: redistributions of source code must retain the above copyright 82155SN/A * notice, this list of conditions and the following disclaimer; 92155SN/A * redistributions in binary form must reproduce the above copyright 102155SN/A * notice, this list of conditions and the following disclaimer in the 112155SN/A * documentation and/or other materials provided with the distribution; 122155SN/A * neither the name of the copyright holders nor the names of its 132155SN/A * contributors may be used to endorse or promote products derived from 142155SN/A * this software without specific prior written permission. 152155SN/A * 162155SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172155SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182155SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192155SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202155SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212155SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222155SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232155SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242155SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252155SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262155SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272155SN/A * 282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 292665Ssaidi@eecs.umich.edu */ 302155SN/A 314202Sbinkertn@umich.edu/** 322155SN/A * @file 339850Sandreas.hansson@arm.com * Hardware Prefetcher Definition. 349850Sandreas.hansson@arm.com */ 359850Sandreas.hansson@arm.com 367768SAli.Saidi@ARM.com#include "base/trace.hh" 377768SAli.Saidi@ARM.com#include "mem/cache/base_cache.hh" 382178SN/A#include "mem/cache/prefetch/base_prefetcher.hh" 392178SN/A#include "mem/request.hh" 402178SN/A#include <list> 412178SN/A 422178SN/ABasePrefetcher::BasePrefetcher(int size, bool pageStop, bool serialSquash, 432178SN/A bool cacheCheckPush, bool onlyData) 442178SN/A :size(size), pageStop(pageStop), serialSquash(serialSquash), 452178SN/A cacheCheckPush(cacheCheckPush), only_data(onlyData) 462178SN/A{ 472178SN/A} 482178SN/A 492155SN/Avoid 505865Sksewell@umich.eduBasePrefetcher::setCache(BaseCache *_cache) 516181Sksewell@umich.edu{ 526181Sksewell@umich.edu cache = _cache; 535865Sksewell@umich.edu blkSize = cache->getBlockSize(); 543918Ssaidi@eecs.umich.edu} 555865Sksewell@umich.edu 562623SN/Avoid 573918Ssaidi@eecs.umich.eduBasePrefetcher::regStats(const std::string &name) 582155SN/A{ 592155SN/A pfIdentified 602292SN/A .name(name + ".prefetcher.num_hwpf_identified") 616181Sksewell@umich.edu .desc("number of hwpf identified") 626181Sksewell@umich.edu ; 633918Ssaidi@eecs.umich.edu 642292SN/A pfMSHRHit 652292SN/A .name(name + ".prefetcher.num_hwpf_already_in_mshr") 662292SN/A .desc("number of hwpf that were already in mshr") 673918Ssaidi@eecs.umich.edu ; 682292SN/A 692292SN/A pfCacheHit 702766Sktlim@umich.edu .name(name + ".prefetcher.num_hwpf_already_in_cache") 712766Sktlim@umich.edu .desc("number of hwpf that were already in the cache") 722766Sktlim@umich.edu ; 732921Sktlim@umich.edu 748887Sgeoffrey.blake@arm.com pfBufferHit 758887Sgeoffrey.blake@arm.com .name(name + ".prefetcher.num_hwpf_already_in_prefetcher") 762766Sktlim@umich.edu .desc("number of hwpf that were already in the prefetch queue") 774762Snate@binkert.org ; 782155SN/A 792155SN/A pfRemovedFull 802155SN/A .name(name + ".prefetcher.num_hwpf_evicted") 812155SN/A .desc("number of hwpf removed due to no buffer left") 822155SN/A ; 832155SN/A 842766Sktlim@umich.edu pfRemovedMSHR 852155SN/A .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit") 865865Sksewell@umich.edu .desc("number of hwpf removed because MSHR allocated") 872155SN/A ; 882155SN/A 892155SN/A pfIssued 902155SN/A .name(name + ".prefetcher.num_hwpf_issued") 912178SN/A .desc("number of hwpf issued") 922178SN/A ; 937756SAli.Saidi@ARM.com 942766Sktlim@umich.edu pfSpanPage 952178SN/A .name(name + ".prefetcher.num_hwpf_span_page") 962178SN/A .desc("number of hwpf spanning a virtual page") 976994Snate@binkert.org ; 982178SN/A 992766Sktlim@umich.edu pfSquashed 1002766Sktlim@umich.edu .name(name + ".prefetcher.num_hwpf_squashed_from_miss") 1012788Sktlim@umich.edu .desc("number of hwpf that got squashed due to a miss aborting calculation time") 1022178SN/A ; 1034486Sbinkertn@umich.edu} 1044486Sbinkertn@umich.edu 1054776Sgblack@eecs.umich.eduinline bool 1064776Sgblack@eecs.umich.eduBasePrefetcher::inCache(Addr addr) 1078739Sgblack@eecs.umich.edu{ 1086365Sgblack@eecs.umich.edu if (cache->inCache(addr)) { 1094486Sbinkertn@umich.edu pfCacheHit++; 1104202Sbinkertn@umich.edu return true; 1114202Sbinkertn@umich.edu } 1124202Sbinkertn@umich.edu return false; 1134202Sbinkertn@umich.edu} 1144202Sbinkertn@umich.edu 1154776Sgblack@eecs.umich.eduinline bool 1168739Sgblack@eecs.umich.eduBasePrefetcher::inMissQueue(Addr addr) 1176365Sgblack@eecs.umich.edu{ 1184202Sbinkertn@umich.edu if (cache->inMissQueue(addr)) { 1198777Sgblack@eecs.umich.edu pfMSHRHit++; 1204202Sbinkertn@umich.edu return true; 1219913Ssteve.reinhardt@amd.com } 1224202Sbinkertn@umich.edu return false; 1234202Sbinkertn@umich.edu} 1245217Ssaidi@eecs.umich.edu 1254202Sbinkertn@umich.eduPacketPtr 1262155SN/ABasePrefetcher::getPacket() 1278793Sgblack@eecs.umich.edu{ 1288793Sgblack@eecs.umich.edu DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name()); 1298793Sgblack@eecs.umich.edu 1304776Sgblack@eecs.umich.edu if (pf.empty()) { 1318887Sgeoffrey.blake@arm.com DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name()); 13210201SAndrew.Bardsley@arm.com return NULL; 1338887Sgeoffrey.blake@arm.com } 1349340SAndreas.Sandberg@arm.com 1358887Sgeoffrey.blake@arm.com PacketPtr pkt; 1365192Ssaidi@eecs.umich.edu bool keepTrying = false; 1378335Snate@binkert.org do { 1388335Snate@binkert.org pkt = *pf.begin(); 1398335Snate@binkert.org pf.pop_front(); 1408335Snate@binkert.org if (!cacheCheckPush) { 1418335Snate@binkert.org keepTrying = cache->inCache(pkt->getAddr()); 1429534SAndreas.Sandberg@ARM.com } 1439534SAndreas.Sandberg@ARM.com if (pf.empty()) { 1449534SAndreas.Sandberg@ARM.com cache->clearMasterRequest(Request_PF); 1458335Snate@binkert.org if (keepTrying) return NULL; //None left, all were in cache 1469534SAndreas.Sandberg@ARM.com } 1479534SAndreas.Sandberg@ARM.com } while (keepTrying); 1488335Snate@binkert.org 1499534SAndreas.Sandberg@ARM.com pfIssued++; 1509534SAndreas.Sandberg@ARM.com return pkt; 1519534SAndreas.Sandberg@ARM.com} 1529534SAndreas.Sandberg@ARM.com 1539534SAndreas.Sandberg@ARM.comvoid 1549534SAndreas.Sandberg@ARM.comBasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) 1559534SAndreas.Sandberg@ARM.com{ 1569534SAndreas.Sandberg@ARM.com if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && only_data)) 1579534SAndreas.Sandberg@ARM.com { 1589534SAndreas.Sandberg@ARM.com //Calculate the blk address 1598335Snate@binkert.org Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1); 1608335Snate@binkert.org 1618471SGiacomo.Gabrielli@arm.com //Check if miss is in pfq, if so remove it 1628335Snate@binkert.org std::list<PacketPtr>::iterator iter = inPrefetch(blkAddr); 1638335Snate@binkert.org if (iter != pf.end()) { 1645192Ssaidi@eecs.umich.edu DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name()); 1658232Snate@binkert.org pfRemovedMSHR++; 1668232Snate@binkert.org pf.erase(iter); 1678232Snate@binkert.org if (pf.empty()) 1688300Schander.sudanthi@arm.com cache->clearMasterRequest(Request_PF); 1698300Schander.sudanthi@arm.com } 1705192Ssaidi@eecs.umich.edu 1718300Schander.sudanthi@arm.com //Remove anything in queue with delay older than time 1728300Schander.sudanthi@arm.com //since everything is inserted in time order, start from end 1736036Sksewell@umich.edu //and work until pf.empty() or time is earlier 1748300Schander.sudanthi@arm.com //This is done to emulate Aborting the previous work on a new miss 1758300Schander.sudanthi@arm.com //Needed for serial calculators like GHB 176 if (serialSquash) { 177 iter = pf.end(); 178 iter--; 179 while (!pf.empty() && ((*iter)->time >= time)) { 180 pfSquashed++; 181 pf.pop_back(); 182 iter--; 183 } 184 if (pf.empty()) 185 cache->clearMasterRequest(Request_PF); 186 } 187 188 189 std::list<Addr> addresses; 190 std::list<Tick> delays; 191 calculatePrefetch(pkt, addresses, delays); 192 193 std::list<Addr>::iterator addr = addresses.begin(); 194 std::list<Tick>::iterator delay = delays.begin(); 195 while (addr != addresses.end()) 196 { 197 DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name()); 198 //temp calc this here... 199 pfIdentified++; 200 //create a prefetch memreq 201 Request * prefetchReq = new Request(*addr, blkSize, 0); 202 PacketPtr prefetch; 203 prefetch = new Packet(prefetchReq, MemCmd::HardPFReq, -1); 204 prefetch->allocate(); 205 prefetch->req->setThreadContext(pkt->req->getCpuNum(), 206 pkt->req->getThreadNum()); 207 208 prefetch->time = time + (*delay); //@todo ADD LATENCY HERE 209 //... initialize 210 211 //Check if it is already in the cache 212 if (cacheCheckPush) { 213 if (cache->inCache(prefetch->getAddr())) { 214 addr++; 215 delay++; 216 continue; 217 } 218 } 219 220 //Check if it is already in the miss_queue 221 if (cache->inMissQueue(prefetch->getAddr())) { 222 addr++; 223 delay++; 224 continue; 225 } 226 227 //Check if it is already in the pf buffer 228 if (inPrefetch(prefetch->getAddr()) != pf.end()) { 229 pfBufferHit++; 230 addr++; 231 delay++; 232 continue; 233 } 234 235 //We just remove the head if we are full 236 if (pf.size() == size) 237 { 238 DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name()); 239 pfRemovedFull++; 240 pf.pop_front(); 241 } 242 243 pf.push_back(prefetch); 244 prefetch->flags |= CACHE_LINE_FILL; 245 246 //Make sure to request the bus, with proper delay 247 cache->setMasterRequest(Request_PF, prefetch->time); 248 249 //Increment through the list 250 addr++; 251 delay++; 252 } 253 } 254} 255 256std::list<PacketPtr>::iterator 257BasePrefetcher::inPrefetch(Addr address) 258{ 259 //Guaranteed to only be one match, we always check before inserting 260 std::list<PacketPtr>::iterator iter; 261 for (iter=pf.begin(); iter != pf.end(); iter++) { 262 if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { 263 return iter; 264 } 265 } 266 return pf.end(); 267} 268 269 270