base.cc revision 8922
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 <list> 372810SN/A 382810SN/A#include "arch/isa_traits.hh" 392810SN/A#include "base/trace.hh" 402810SN/A#include "config/the_isa.hh" 4110623Smitch.hayenga@arm.com#include "debug/HWPrefetch.hh" 422810SN/A#include "mem/cache/prefetch/base.hh" 432810SN/A#include "mem/cache/base.hh" 442810SN/A#include "mem/request.hh" 452810SN/A#include "sim/system.hh" 462810SN/A 472810SN/ABasePrefetcher::BasePrefetcher(const Params *p) 482810SN/A : SimObject(p), size(p->size), latency(p->latency), degree(p->degree), 4911793Sbrandon.potter@amd.com useMasterId(p->use_master_id), pageStop(!p->cross_pages), 5011793Sbrandon.potter@amd.com serialSquash(p->serial_squash), onlyData(p->data_accesses_only), 5112727Snikos.nikoleris@arm.com system(p->sys), masterId(system->getMasterId(name())) 526658Snate@binkert.org{ 5311438SRekai.GonzalezAlberquilla@arm.com} 545338Sstever@gmail.com 5512727Snikos.nikoleris@arm.comvoid 568832SAli.Saidi@ARM.comBasePrefetcher::setCache(BaseCache *_cache) 572810SN/A{ 5810623Smitch.hayenga@arm.com cache = _cache; 5911438SRekai.GonzalezAlberquilla@arm.com blkSize = cache->getBlockSize(); 6011438SRekai.GonzalezAlberquilla@arm.com} 6110623Smitch.hayenga@arm.com 6212680Sgiacomo.travaglini@arm.comvoid 6310466Sandreas.hansson@arm.comBasePrefetcher::regStats() 642810SN/A{ 652810SN/A pfIdentified 662810SN/A .name(name() + ".prefetcher.num_hwpf_identified") 672810SN/A .desc("number of hwpf identified") 682810SN/A ; 692810SN/A 7010360Sandreas.hansson@arm.com pfMSHRHit 712810SN/A .name(name() + ".prefetcher.num_hwpf_already_in_mshr") 722810SN/A .desc("number of hwpf that were already in mshr") 7311438SRekai.GonzalezAlberquilla@arm.com ; 742810SN/A 752810SN/A pfCacheHit 762810SN/A .name(name() + ".prefetcher.num_hwpf_already_in_cache") 778831Smrinmoy.ghosh@arm.com .desc("number of hwpf that were already in the cache") 782810SN/A ; 7911522Sstephan.diestelhorst@arm.com 8011522Sstephan.diestelhorst@arm.com pfBufferHit 812810SN/A .name(name() + ".prefetcher.num_hwpf_already_in_prefetcher") 8210623Smitch.hayenga@arm.com .desc("number of hwpf that were already in the prefetch queue") 832810SN/A ; 842810SN/A 8511438SRekai.GonzalezAlberquilla@arm.com pfRemovedFull 862810SN/A .name(name() + ".prefetcher.num_hwpf_evicted") 872810SN/A .desc("number of hwpf removed due to no buffer left") 8810623Smitch.hayenga@arm.com ; 8910623Smitch.hayenga@arm.com 9010623Smitch.hayenga@arm.com pfRemovedMSHR 9110623Smitch.hayenga@arm.com .name(name() + ".prefetcher.num_hwpf_removed_MSHR_hit") 9210623Smitch.hayenga@arm.com .desc("number of hwpf removed because MSHR allocated") 9310626SCurtis.Dunham@arm.com ; 9410626SCurtis.Dunham@arm.com 9510623Smitch.hayenga@arm.com pfIssued 9610623Smitch.hayenga@arm.com .name(name() + ".prefetcher.num_hwpf_issued") 9710623Smitch.hayenga@arm.com .desc("number of hwpf issued") 9810623Smitch.hayenga@arm.com ; 9910623Smitch.hayenga@arm.com 10010623Smitch.hayenga@arm.com pfSpanPage 10110623Smitch.hayenga@arm.com .name(name() + ".prefetcher.num_hwpf_span_page") 10210626SCurtis.Dunham@arm.com .desc("number of hwpf spanning a virtual page") 10310883Sali.jafri@arm.com ; 10410623Smitch.hayenga@arm.com 10510623Smitch.hayenga@arm.com pfSquashed 10610623Smitch.hayenga@arm.com .name(name() + ".prefetcher.num_hwpf_squashed_from_miss") 10710623Smitch.hayenga@arm.com .desc("number of hwpf that got squashed due to a miss " 10810623Smitch.hayenga@arm.com "aborting calculation time") 10910623Smitch.hayenga@arm.com ; 11010623Smitch.hayenga@arm.com} 11110623Smitch.hayenga@arm.com 11210623Smitch.hayenga@arm.cominline bool 11310623Smitch.hayenga@arm.comBasePrefetcher::inCache(Addr addr) 11410623Smitch.hayenga@arm.com{ 1153861SN/A if (cache->inCache(addr)) { 11610028SGiacomo.Gabrielli@arm.com pfCacheHit++; 1173861SN/A return true; 1183861SN/A } 1193861SN/A return false; 1203861SN/A} 1213861SN/A 12210623Smitch.hayenga@arm.cominline bool 12310623Smitch.hayenga@arm.comBasePrefetcher::inMissQueue(Addr addr) 1243861SN/A{ 12510028SGiacomo.Gabrielli@arm.com if (cache->inMissQueue(addr)) { 1263861SN/A pfMSHRHit++; 1273861SN/A return true; 1283861SN/A } 1293861SN/A return false; 1303861SN/A} 1315875Ssteve.reinhardt@amd.com 13210466Sandreas.hansson@arm.comPacketPtr 1335875Ssteve.reinhardt@amd.comBasePrefetcher::getPacket() 13410466Sandreas.hansson@arm.com{ 1355875Ssteve.reinhardt@amd.com DPRINTF(HWPrefetch, "Requesting a hw_pf to issue\n"); 1368831Smrinmoy.ghosh@arm.com 13711438SRekai.GonzalezAlberquilla@arm.com if (pf.empty()) { 13811438SRekai.GonzalezAlberquilla@arm.com DPRINTF(HWPrefetch, "No HW_PF found\n"); 13911438SRekai.GonzalezAlberquilla@arm.com return NULL; 14011438SRekai.GonzalezAlberquilla@arm.com } 14111438SRekai.GonzalezAlberquilla@arm.com 1428831Smrinmoy.ghosh@arm.com PacketPtr pkt = *pf.begin(); 14311438SRekai.GonzalezAlberquilla@arm.com while (!pf.empty()) { 14411438SRekai.GonzalezAlberquilla@arm.com pkt = *pf.begin(); 14511438SRekai.GonzalezAlberquilla@arm.com pf.pop_front(); 14611438SRekai.GonzalezAlberquilla@arm.com 14711438SRekai.GonzalezAlberquilla@arm.com Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); 14811438SRekai.GonzalezAlberquilla@arm.com 14911438SRekai.GonzalezAlberquilla@arm.com if (!inCache(blk_addr) && !inMissQueue(blk_addr)) 15011438SRekai.GonzalezAlberquilla@arm.com // we found a prefetch, return it 15111438SRekai.GonzalezAlberquilla@arm.com break; 15211438SRekai.GonzalezAlberquilla@arm.com 15311438SRekai.GonzalezAlberquilla@arm.com DPRINTF(HWPrefetch, "addr 0x%x in cache, skipping\n", pkt->getAddr()); 15411438SRekai.GonzalezAlberquilla@arm.com delete pkt->req; 15511438SRekai.GonzalezAlberquilla@arm.com delete pkt; 15611438SRekai.GonzalezAlberquilla@arm.com 15711438SRekai.GonzalezAlberquilla@arm.com if (pf.empty()) { 15811438SRekai.GonzalezAlberquilla@arm.com cache->deassertMemSideBusRequest(BaseCache::Request_PF); 15911438SRekai.GonzalezAlberquilla@arm.com return NULL; // None left, all were in cache 16011438SRekai.GonzalezAlberquilla@arm.com } 16111438SRekai.GonzalezAlberquilla@arm.com } 16211438SRekai.GonzalezAlberquilla@arm.com 16311438SRekai.GonzalezAlberquilla@arm.com pfIssued++; 16411438SRekai.GonzalezAlberquilla@arm.com assert(pkt != NULL); 16511438SRekai.GonzalezAlberquilla@arm.com DPRINTF(HWPrefetch, "returning 0x%x\n", pkt->getAddr()); 166 return pkt; 167} 168 169 170Tick 171BasePrefetcher::notify(PacketPtr &pkt, Tick time) 172{ 173 if (!pkt->req->isUncacheable() && !(pkt->req->isInstFetch() && onlyData)) { 174 // Calculate the blk address 175 Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); 176 177 // Check if miss is in pfq, if so remove it 178 std::list<PacketPtr>::iterator iter = inPrefetch(blk_addr); 179 if (iter != pf.end()) { 180 DPRINTF(HWPrefetch, "Saw a miss to a queued prefetch addr: " 181 "0x%x, removing it\n", blk_addr); 182 pfRemovedMSHR++; 183 delete (*iter)->req; 184 delete (*iter); 185 pf.erase(iter); 186 if (pf.empty()) 187 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 188 } 189 190 // Remove anything in queue with delay older than time 191 // since everything is inserted in time order, start from end 192 // and work until pf.empty() or time is earlier 193 // This is done to emulate Aborting the previous work on a new miss 194 // Needed for serial calculators like GHB 195 if (serialSquash) { 196 iter = pf.end(); 197 iter--; 198 while (!pf.empty() && ((*iter)->time >= time)) { 199 pfSquashed++; 200 DPRINTF(HWPrefetch, "Squashing old prefetch addr: 0x%x\n", 201 (*iter)->getAddr()); 202 delete (*iter)->req; 203 delete (*iter); 204 pf.erase(iter); 205 iter--; 206 } 207 if (pf.empty()) 208 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 209 } 210 211 212 std::list<Addr> addresses; 213 std::list<Tick> delays; 214 calculatePrefetch(pkt, addresses, delays); 215 216 std::list<Addr>::iterator addrIter = addresses.begin(); 217 std::list<Tick>::iterator delayIter = delays.begin(); 218 for (; addrIter != addresses.end(); ++addrIter, ++delayIter) { 219 Addr addr = *addrIter; 220 221 pfIdentified++; 222 223 DPRINTF(HWPrefetch, "Found a pf candidate addr: 0x%x, " 224 "inserting into prefetch queue with delay %d time %d\n", 225 addr, *delayIter, time); 226 227 // Check if it is already in the pf buffer 228 if (inPrefetch(addr) != pf.end()) { 229 pfBufferHit++; 230 DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n"); 231 continue; 232 } 233 234 // create a prefetch memreq 235 Request *prefetchReq = new Request(*addrIter, blkSize, 0, masterId); 236 PacketPtr prefetch = 237 new Packet(prefetchReq, MemCmd::HardPFReq, Packet::Broadcast); 238 prefetch->allocate(); 239 prefetch->req->setThreadContext(pkt->req->contextId(), 240 pkt->req->threadId()); 241 242 prefetch->time = time + (*delayIter); // @todo ADD LATENCY HERE 243 244 // We just remove the head if we are full 245 if (pf.size() == size) { 246 pfRemovedFull++; 247 PacketPtr old_pkt = *pf.begin(); 248 DPRINTF(HWPrefetch, "Prefetch queue full, " 249 "removing oldest 0x%x\n", old_pkt->getAddr()); 250 delete old_pkt->req; 251 delete old_pkt; 252 pf.pop_front(); 253 } 254 255 pf.push_back(prefetch); 256 } 257 } 258 259 return pf.empty() ? 0 : pf.front()->time; 260} 261 262std::list<PacketPtr>::iterator 263BasePrefetcher::inPrefetch(Addr address) 264{ 265 // Guaranteed to only be one match, we always check before inserting 266 std::list<PacketPtr>::iterator iter; 267 for (iter = pf.begin(); iter != pf.end(); iter++) { 268 if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { 269 return iter; 270 } 271 } 272 return pf.end(); 273} 274 275bool 276BasePrefetcher::samePage(Addr a, Addr b) 277{ 278 return roundDown(a, TheISA::VMPageSize) == roundDown(b, TheISA::VMPageSize); 279} 280 281 282