base.cc revision 6665:874f2ee2f115
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 "mem/cache/base.hh" 42#include "mem/cache/prefetch/base.hh" 43#include "mem/request.hh" 44 45BasePrefetcher::BasePrefetcher(const BaseCacheParams *p) 46 : size(p->prefetcher_size), pageStop(!p->prefetch_past_page), 47 serialSquash(p->prefetch_serial_squash), 48 onlyData(p->prefetch_data_accesses_only) 49{ 50} 51 52void 53BasePrefetcher::setCache(BaseCache *_cache) 54{ 55 cache = _cache; 56 blkSize = cache->getBlockSize(); 57 _name = cache->name() + "-pf"; 58} 59 60void 61BasePrefetcher::regStats(const std::string &name) 62{ 63 pfIdentified 64 .name(name + ".prefetcher.num_hwpf_identified") 65 .desc("number of hwpf identified") 66 ; 67 68 pfMSHRHit 69 .name(name + ".prefetcher.num_hwpf_already_in_mshr") 70 .desc("number of hwpf that were already in mshr") 71 ; 72 73 pfCacheHit 74 .name(name + ".prefetcher.num_hwpf_already_in_cache") 75 .desc("number of hwpf that were already in the cache") 76 ; 77 78 pfBufferHit 79 .name(name + ".prefetcher.num_hwpf_already_in_prefetcher") 80 .desc("number of hwpf that were already in the prefetch queue") 81 ; 82 83 pfRemovedFull 84 .name(name + ".prefetcher.num_hwpf_evicted") 85 .desc("number of hwpf removed due to no buffer left") 86 ; 87 88 pfRemovedMSHR 89 .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit") 90 .desc("number of hwpf removed because MSHR allocated") 91 ; 92 93 pfIssued 94 .name(name + ".prefetcher.num_hwpf_issued") 95 .desc("number of hwpf issued") 96 ; 97 98 pfSpanPage 99 .name(name + ".prefetcher.num_hwpf_span_page") 100 .desc("number of hwpf spanning a virtual page") 101 ; 102 103 pfSquashed 104 .name(name + ".prefetcher.num_hwpf_squashed_from_miss") 105 .desc("number of hwpf that got squashed due to a miss " 106 "aborting calculation time") 107 ; 108} 109 110inline bool 111BasePrefetcher::inCache(Addr addr) 112{ 113 if (cache->inCache(addr)) { 114 pfCacheHit++; 115 return true; 116 } 117 return false; 118} 119 120inline bool 121BasePrefetcher::inMissQueue(Addr addr) 122{ 123 if (cache->inMissQueue(addr)) { 124 pfMSHRHit++; 125 return true; 126 } 127 return false; 128} 129 130PacketPtr 131BasePrefetcher::getPacket() 132{ 133 DPRINTF(HWPrefetch, "Requesting a hw_pf to issue\n"); 134 135 if (pf.empty()) { 136 DPRINTF(HWPrefetch, "No HW_PF found\n"); 137 return NULL; 138 } 139 140 PacketPtr pkt; 141 bool keep_trying = false; 142 do { 143 pkt = *pf.begin(); 144 pf.pop_front(); 145 146 if (keep_trying) { 147 DPRINTF(HWPrefetch, "addr 0x%x in cache, skipping\n", 148 pkt->getAddr()); 149 delete pkt->req; 150 delete pkt; 151 } 152 153 if (pf.empty()) { 154 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 155 if (keep_trying) { 156 return NULL; // None left, all were in cache 157 } 158 } 159 } while (keep_trying); 160 161 pfIssued++; 162 assert(pkt != NULL); 163 DPRINTF(HWPrefetch, "returning 0x%x\n", pkt->getAddr()); 164 return pkt; 165} 166 167 168Tick 169BasePrefetcher::notify(PacketPtr &pkt, Tick time) 170{ 171 if (!pkt->req->isUncacheable() && !(pkt->req->isInstFetch() && onlyData)) { 172 // Calculate the blk address 173 Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); 174 175 // Check if miss is in pfq, if so remove it 176 std::list<PacketPtr>::iterator iter = inPrefetch(blk_addr); 177 if (iter != pf.end()) { 178 DPRINTF(HWPrefetch, "Saw a miss to a queued prefetch addr: " 179 "0x%x, removing it\n", blk_addr); 180 pfRemovedMSHR++; 181 delete (*iter)->req; 182 delete (*iter); 183 pf.erase(iter); 184 if (pf.empty()) 185 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 186 } 187 188 // Remove anything in queue with delay older than time 189 // since everything is inserted in time order, start from end 190 // and work until pf.empty() or time is earlier 191 // This is done to emulate Aborting the previous work on a new miss 192 // Needed for serial calculators like GHB 193 if (serialSquash) { 194 iter = pf.end(); 195 iter--; 196 while (!pf.empty() && ((*iter)->time >= time)) { 197 pfSquashed++; 198 DPRINTF(HWPrefetch, "Squashing old prefetch addr: 0x%x\n", 199 (*iter)->getAddr()); 200 delete (*iter)->req; 201 delete (*iter); 202 pf.erase(iter); 203 iter--; 204 } 205 if (pf.empty()) 206 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 207 } 208 209 210 std::list<Addr> addresses; 211 std::list<Tick> delays; 212 calculatePrefetch(pkt, addresses, delays); 213 214 std::list<Addr>::iterator addrIter = addresses.begin(); 215 std::list<Tick>::iterator delayIter = delays.begin(); 216 for (; addrIter != addresses.end(); ++addrIter, ++delayIter) { 217 Addr addr = *addrIter; 218 219 pfIdentified++; 220 221 DPRINTF(HWPrefetch, "Found a pf candidate addr: 0x%x, " 222 "inserting into prefetch queue with delay %d time %d\n", 223 addr, *delayIter, time); 224 225 // Check if it is already in the pf buffer 226 if (inPrefetch(addr) != pf.end()) { 227 pfBufferHit++; 228 DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n"); 229 continue; 230 } 231 232 // create a prefetch memreq 233 Request *prefetchReq = new Request(*addrIter, blkSize, 0); 234 PacketPtr prefetch = 235 new Packet(prefetchReq, MemCmd::HardPFReq, Packet::Broadcast); 236 prefetch->allocate(); 237 prefetch->req->setThreadContext(pkt->req->contextId(), 238 pkt->req->threadId()); 239 240 prefetch->time = time + (*delayIter); // @todo ADD LATENCY HERE 241 242 // We just remove the head if we are full 243 if (pf.size() == size) { 244 pfRemovedFull++; 245 PacketPtr old_pkt = *pf.begin(); 246 DPRINTF(HWPrefetch, "Prefetch queue full, " 247 "removing oldest 0x%x\n", old_pkt->getAddr()); 248 delete old_pkt->req; 249 delete old_pkt; 250 pf.pop_front(); 251 } 252 253 pf.push_back(prefetch); 254 } 255 } 256 257 return pf.empty() ? 0 : pf.front()->time; 258} 259 260std::list<PacketPtr>::iterator 261BasePrefetcher::inPrefetch(Addr address) 262{ 263 // Guaranteed to only be one match, we always check before inserting 264 std::list<PacketPtr>::iterator iter; 265 for (iter = pf.begin(); iter != pf.end(); iter++) { 266 if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { 267 return iter; 268 } 269 } 270 return pf.end(); 271} 272 273bool 274BasePrefetcher::samePage(Addr a, Addr b) 275{ 276 return roundDown(a, TheISA::VMPageSize) == roundDown(b, TheISA::VMPageSize); 277} 278