base.cc revision 9288
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#include "sim/system.hh" 46 47BasePrefetcher::BasePrefetcher(const Params *p) 48 : ClockedObject(p), size(p->size), latency(p->latency), degree(p->degree), 49 useMasterId(p->use_master_id), pageStop(!p->cross_pages), 50 serialSquash(p->serial_squash), onlyData(p->data_accesses_only), 51 system(p->sys), masterId(system->getMasterId(name())) 52{ 53} 54 55void 56BasePrefetcher::setCache(BaseCache *_cache) 57{ 58 cache = _cache; 59 blkSize = cache->getBlockSize(); 60} 61 62void 63BasePrefetcher::regStats() 64{ 65 pfIdentified 66 .name(name() + ".prefetcher.num_hwpf_identified") 67 .desc("number of hwpf identified") 68 ; 69 70 pfMSHRHit 71 .name(name() + ".prefetcher.num_hwpf_already_in_mshr") 72 .desc("number of hwpf that were already in mshr") 73 ; 74 75 pfCacheHit 76 .name(name() + ".prefetcher.num_hwpf_already_in_cache") 77 .desc("number of hwpf that were already in the cache") 78 ; 79 80 pfBufferHit 81 .name(name() + ".prefetcher.num_hwpf_already_in_prefetcher") 82 .desc("number of hwpf that were already in the prefetch queue") 83 ; 84 85 pfRemovedFull 86 .name(name() + ".prefetcher.num_hwpf_evicted") 87 .desc("number of hwpf removed due to no buffer left") 88 ; 89 90 pfRemovedMSHR 91 .name(name() + ".prefetcher.num_hwpf_removed_MSHR_hit") 92 .desc("number of hwpf removed because MSHR allocated") 93 ; 94 95 pfIssued 96 .name(name() + ".prefetcher.num_hwpf_issued") 97 .desc("number of hwpf issued") 98 ; 99 100 pfSpanPage 101 .name(name() + ".prefetcher.num_hwpf_span_page") 102 .desc("number of hwpf spanning a virtual page") 103 ; 104 105 pfSquashed 106 .name(name() + ".prefetcher.num_hwpf_squashed_from_miss") 107 .desc("number of hwpf that got squashed due to a miss " 108 "aborting calculation time") 109 ; 110} 111 112inline bool 113BasePrefetcher::inCache(Addr addr) 114{ 115 if (cache->inCache(addr)) { 116 pfCacheHit++; 117 return true; 118 } 119 return false; 120} 121 122inline bool 123BasePrefetcher::inMissQueue(Addr addr) 124{ 125 if (cache->inMissQueue(addr)) { 126 pfMSHRHit++; 127 return true; 128 } 129 return false; 130} 131 132PacketPtr 133BasePrefetcher::getPacket() 134{ 135 DPRINTF(HWPrefetch, "Requesting a hw_pf to issue\n"); 136 137 if (pf.empty()) { 138 DPRINTF(HWPrefetch, "No HW_PF found\n"); 139 return NULL; 140 } 141 142 PacketPtr pkt = *pf.begin(); 143 while (!pf.empty()) { 144 pkt = *pf.begin(); 145 pf.pop_front(); 146 147 Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); 148 149 if (!inCache(blk_addr) && !inMissQueue(blk_addr)) 150 // we found a prefetch, return it 151 break; 152 153 DPRINTF(HWPrefetch, "addr 0x%x in cache, skipping\n", pkt->getAddr()); 154 delete pkt->req; 155 delete pkt; 156 157 if (pf.empty()) { 158 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 159 return NULL; // None left, all were in cache 160 } 161 } 162 163 pfIssued++; 164 assert(pkt != NULL); 165 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 iter = 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 if (iter != pf.begin()) 198 iter--; 199 while (!pf.empty() && ((*iter)->time >= time)) { 200 pfSquashed++; 201 DPRINTF(HWPrefetch, "Squashing old prefetch addr: 0x%x\n", 202 (*iter)->getAddr()); 203 delete (*iter)->req; 204 delete (*iter); 205 iter = pf.erase(iter); 206 if (iter != pf.begin()) 207 iter--; 208 } 209 if (pf.empty()) 210 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 211 } 212 213 214 std::list<Addr> addresses; 215 std::list<Cycles> delays; 216 calculatePrefetch(pkt, addresses, delays); 217 218 std::list<Addr>::iterator addrIter = addresses.begin(); 219 std::list<Cycles>::iterator delayIter = delays.begin(); 220 for (; addrIter != addresses.end(); ++addrIter, ++delayIter) { 221 Addr addr = *addrIter; 222 223 pfIdentified++; 224 225 DPRINTF(HWPrefetch, "Found a pf candidate addr: 0x%x, " 226 "inserting into prefetch queue with delay %d time %d\n", 227 addr, *delayIter, time); 228 229 // Check if it is already in the pf buffer 230 if (inPrefetch(addr) != pf.end()) { 231 pfBufferHit++; 232 DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n"); 233 continue; 234 } 235 236 // create a prefetch memreq 237 Request *prefetchReq = new Request(*addrIter, blkSize, 0, masterId); 238 PacketPtr prefetch = 239 new Packet(prefetchReq, MemCmd::HardPFReq); 240 prefetch->allocate(); 241 prefetch->req->setThreadContext(pkt->req->contextId(), 242 pkt->req->threadId()); 243 244 prefetch->time = time + clock * *delayIter; 245 246 // We just remove the head if we are full 247 if (pf.size() == size) { 248 pfRemovedFull++; 249 PacketPtr old_pkt = *pf.begin(); 250 DPRINTF(HWPrefetch, "Prefetch queue full, " 251 "removing oldest 0x%x\n", old_pkt->getAddr()); 252 delete old_pkt->req; 253 delete old_pkt; 254 pf.pop_front(); 255 } 256 257 pf.push_back(prefetch); 258 } 259 } 260 261 return pf.empty() ? 0 : pf.front()->time; 262} 263 264std::list<PacketPtr>::iterator 265BasePrefetcher::inPrefetch(Addr address) 266{ 267 // Guaranteed to only be one match, we always check before inserting 268 std::list<PacketPtr>::iterator iter; 269 for (iter = pf.begin(); iter != pf.end(); iter++) { 270 if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { 271 return iter; 272 } 273 } 274 return pf.end(); 275} 276 277bool 278BasePrefetcher::samePage(Addr a, Addr b) 279{ 280 return roundDown(a, TheISA::VMPageSize) == roundDown(b, TheISA::VMPageSize); 281} 282 283 284