base.cc revision 8832
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 : SimObject(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 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