base.cc revision 8509:afb40c3d4ba6
1/* 2 * Copyright (c) 2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Ron Dreslinski 29 */ 30 31/** 32 * @file 33 * Hardware Prefetcher Definition. 34 */ 35 36#include <list> 37 38#include "arch/isa_traits.hh" 39#include "base/trace.hh" 40#include "config/the_isa.hh" 41#include "debug/HWPrefetch.hh" 42#include "mem/cache/prefetch/base.hh" 43#include "mem/cache/base.hh" 44#include "mem/request.hh" 45 46BasePrefetcher::BasePrefetcher(const BaseCacheParams *p) 47 : size(p->prefetcher_size), pageStop(!p->prefetch_past_page), 48 serialSquash(p->prefetch_serial_squash), 49 onlyData(p->prefetch_data_accesses_only) 50{ 51} 52 53void 54BasePrefetcher::setCache(BaseCache *_cache) 55{ 56 cache = _cache; 57 blkSize = cache->getBlockSize(); 58 _name = cache->name() + "-pf"; 59} 60 61void 62BasePrefetcher::regStats(const std::string &name) 63{ 64 pfIdentified 65 .name(name + ".prefetcher.num_hwpf_identified") 66 .desc("number of hwpf identified") 67 ; 68 69 pfMSHRHit 70 .name(name + ".prefetcher.num_hwpf_already_in_mshr") 71 .desc("number of hwpf that were already in mshr") 72 ; 73 74 pfCacheHit 75 .name(name + ".prefetcher.num_hwpf_already_in_cache") 76 .desc("number of hwpf that were already in the cache") 77 ; 78 79 pfBufferHit 80 .name(name + ".prefetcher.num_hwpf_already_in_prefetcher") 81 .desc("number of hwpf that were already in the prefetch queue") 82 ; 83 84 pfRemovedFull 85 .name(name + ".prefetcher.num_hwpf_evicted") 86 .desc("number of hwpf removed due to no buffer left") 87 ; 88 89 pfRemovedMSHR 90 .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit") 91 .desc("number of hwpf removed because MSHR allocated") 92 ; 93 94 pfIssued 95 .name(name + ".prefetcher.num_hwpf_issued") 96 .desc("number of hwpf issued") 97 ; 98 99 pfSpanPage 100 .name(name + ".prefetcher.num_hwpf_span_page") 101 .desc("number of hwpf spanning a virtual page") 102 ; 103 104 pfSquashed 105 .name(name + ".prefetcher.num_hwpf_squashed_from_miss") 106 .desc("number of hwpf that got squashed due to a miss " 107 "aborting calculation time") 108 ; 109} 110 111inline bool 112BasePrefetcher::inCache(Addr addr) 113{ 114 if (cache->inCache(addr)) { 115 pfCacheHit++; 116 return true; 117 } 118 return false; 119} 120 121inline bool 122BasePrefetcher::inMissQueue(Addr addr) 123{ 124 if (cache->inMissQueue(addr)) { 125 pfMSHRHit++; 126 return true; 127 } 128 return false; 129} 130 131PacketPtr 132BasePrefetcher::getPacket() 133{ 134 DPRINTF(HWPrefetch, "Requesting a hw_pf to issue\n"); 135 136 if (pf.empty()) { 137 DPRINTF(HWPrefetch, "No HW_PF found\n"); 138 return NULL; 139 } 140 141 PacketPtr pkt; 142 while (!pf.empty()) { 143 pkt = *pf.begin(); 144 pf.pop_front(); 145 146 Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); 147 148 if (!inCache(blk_addr) && !inMissQueue(blk_addr)) 149 // we found a prefetch, return it 150 break; 151 152 DPRINTF(HWPrefetch, "addr 0x%x in cache, skipping\n", pkt->getAddr()); 153 delete pkt->req; 154 delete pkt; 155 156 if (pf.empty()) { 157 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 158 return NULL; // None left, all were in cache 159 } 160 } 161 162 pfIssued++; 163 assert(pkt != NULL); 164 DPRINTF(HWPrefetch, "returning 0x%x\n", pkt->getAddr()); 165 return pkt; 166} 167 168 169Tick 170BasePrefetcher::notify(PacketPtr &pkt, Tick time) 171{ 172 if (!pkt->req->isUncacheable() && !(pkt->req->isInstFetch() && onlyData)) { 173 // Calculate the blk address 174 Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); 175 176 // Check if miss is in pfq, if so remove it 177 std::list<PacketPtr>::iterator iter = inPrefetch(blk_addr); 178 if (iter != pf.end()) { 179 DPRINTF(HWPrefetch, "Saw a miss to a queued prefetch addr: " 180 "0x%x, removing it\n", blk_addr); 181 pfRemovedMSHR++; 182 delete (*iter)->req; 183 delete (*iter); 184 pf.erase(iter); 185 if (pf.empty()) 186 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 187 } 188 189 // Remove anything in queue with delay older than time 190 // since everything is inserted in time order, start from end 191 // and work until pf.empty() or time is earlier 192 // This is done to emulate Aborting the previous work on a new miss 193 // Needed for serial calculators like GHB 194 if (serialSquash) { 195 iter = pf.end(); 196 iter--; 197 while (!pf.empty() && ((*iter)->time >= time)) { 198 pfSquashed++; 199 DPRINTF(HWPrefetch, "Squashing old prefetch addr: 0x%x\n", 200 (*iter)->getAddr()); 201 delete (*iter)->req; 202 delete (*iter); 203 pf.erase(iter); 204 iter--; 205 } 206 if (pf.empty()) 207 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 208 } 209 210 211 std::list<Addr> addresses; 212 std::list<Tick> delays; 213 calculatePrefetch(pkt, addresses, delays); 214 215 std::list<Addr>::iterator addrIter = addresses.begin(); 216 std::list<Tick>::iterator delayIter = delays.begin(); 217 for (; addrIter != addresses.end(); ++addrIter, ++delayIter) { 218 Addr addr = *addrIter; 219 220 pfIdentified++; 221 222 DPRINTF(HWPrefetch, "Found a pf candidate addr: 0x%x, " 223 "inserting into prefetch queue with delay %d time %d\n", 224 addr, *delayIter, time); 225 226 // Check if it is already in the pf buffer 227 if (inPrefetch(addr) != pf.end()) { 228 pfBufferHit++; 229 DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n"); 230 continue; 231 } 232 233 // create a prefetch memreq 234 Request *prefetchReq = new Request(*addrIter, blkSize, 0); 235 PacketPtr prefetch = 236 new Packet(prefetchReq, MemCmd::HardPFReq, Packet::Broadcast); 237 prefetch->allocate(); 238 prefetch->req->setThreadContext(pkt->req->contextId(), 239 pkt->req->threadId()); 240 241 prefetch->time = time + (*delayIter); // @todo ADD LATENCY HERE 242 243 // We just remove the head if we are full 244 if (pf.size() == size) { 245 pfRemovedFull++; 246 PacketPtr old_pkt = *pf.begin(); 247 DPRINTF(HWPrefetch, "Prefetch queue full, " 248 "removing oldest 0x%x\n", old_pkt->getAddr()); 249 delete old_pkt->req; 250 delete old_pkt; 251 pf.pop_front(); 252 } 253 254 pf.push_back(prefetch); 255 } 256 } 257 258 return pf.empty() ? 0 : pf.front()->time; 259} 260 261std::list<PacketPtr>::iterator 262BasePrefetcher::inPrefetch(Addr address) 263{ 264 // Guaranteed to only be one match, we always check before inserting 265 std::list<PacketPtr>::iterator iter; 266 for (iter = pf.begin(); iter != pf.end(); iter++) { 267 if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { 268 return iter; 269 } 270 } 271 return pf.end(); 272} 273 274bool 275BasePrefetcher::samePage(Addr a, Addr b) 276{ 277 return roundDown(a, TheISA::VMPageSize) == roundDown(b, TheISA::VMPageSize); 278} 279