base.cc revision 10466
11897Sstever@eecs.umich.edu/* 24130Ssaidi@eecs.umich.edu * Copyright (c) 2013 ARM Limited 31897Sstever@eecs.umich.edu * All rights reserved. 41897Sstever@eecs.umich.edu * 51897Sstever@eecs.umich.edu * The license below extends only to copyright in the software and shall 61897Sstever@eecs.umich.edu * not be construed as granting a license to any other intellectual 71897Sstever@eecs.umich.edu * property including but not limited to intellectual property relating 81897Sstever@eecs.umich.edu * to a hardware implementation of the functionality of the software 91897Sstever@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 101897Sstever@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 111897Sstever@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 121897Sstever@eecs.umich.edu * modified or unmodified, in source code or in binary form. 131897Sstever@eecs.umich.edu * 141897Sstever@eecs.umich.edu * Copyright (c) 2005 The Regents of The University of Michigan 151897Sstever@eecs.umich.edu * All rights reserved. 161897Sstever@eecs.umich.edu * 171897Sstever@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 181897Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are 191897Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright 201897Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 211897Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 221897Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 231897Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution; 241897Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its 251897Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from 261897Sstever@eecs.umich.edu * this software without specific prior written permission. 271897Sstever@eecs.umich.edu * 281897Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 291897Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 301897Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 311897Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 321897Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 331897Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 341897Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 351897Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 361897Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 371897Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 381897Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 391897Sstever@eecs.umich.edu * 401897Sstever@eecs.umich.edu * Authors: Ron Dreslinski 411897Sstever@eecs.umich.edu */ 424130Ssaidi@eecs.umich.edu 433099Sstever@eecs.umich.edu/** 443099Sstever@eecs.umich.edu * @file 451897Sstever@eecs.umich.edu * Hardware Prefetcher Definition. 463709Sstever@eecs.umich.edu */ 473099Sstever@eecs.umich.edu 483099Sstever@eecs.umich.edu#include <list> 491897Sstever@eecs.umich.edu 503099Sstever@eecs.umich.edu#include "base/trace.hh" 513725Sstever@eecs.umich.edu#include "debug/HWPrefetch.hh" 523725Sstever@eecs.umich.edu#include "mem/cache/prefetch/base.hh" 531897Sstever@eecs.umich.edu#include "mem/cache/base.hh" 541897Sstever@eecs.umich.edu#include "mem/request.hh" 551897Sstever@eecs.umich.edu#include "sim/system.hh" 561897Sstever@eecs.umich.edu 571897Sstever@eecs.umich.eduBasePrefetcher::BasePrefetcher(const Params *p) 581897Sstever@eecs.umich.edu : ClockedObject(p), size(p->size), cache(nullptr), blkSize(0), 591897Sstever@eecs.umich.edu latency(p->latency), degree(p->degree), 601897Sstever@eecs.umich.edu useMasterId(p->use_master_id), pageStop(!p->cross_pages), 611897Sstever@eecs.umich.edu serialSquash(p->serial_squash), onlyData(p->data_accesses_only), 621897Sstever@eecs.umich.edu onMissOnly(p->on_miss_only), onReadOnly(p->on_read_only), 631897Sstever@eecs.umich.edu onPrefetch(p->on_prefetch), system(p->sys), 641897Sstever@eecs.umich.edu masterId(system->getMasterId(name())), 651897Sstever@eecs.umich.edu pageBytes(system->getPageBytes()) 661897Sstever@eecs.umich.edu{ 671897Sstever@eecs.umich.edu} 681897Sstever@eecs.umich.edu 691897Sstever@eecs.umich.eduvoid 701897Sstever@eecs.umich.eduBasePrefetcher::setCache(BaseCache *_cache) 711897Sstever@eecs.umich.edu{ 721897Sstever@eecs.umich.edu assert(!cache); 731897Sstever@eecs.umich.edu cache = _cache; 741897Sstever@eecs.umich.edu blkSize = cache->getBlockSize(); 751897Sstever@eecs.umich.edu} 761897Sstever@eecs.umich.edu 771897Sstever@eecs.umich.eduvoid 781897Sstever@eecs.umich.eduBasePrefetcher::regStats() 791897Sstever@eecs.umich.edu{ 803734Sstever@eecs.umich.edu pfIdentified 813734Sstever@eecs.umich.edu .name(name() + ".prefetcher.num_hwpf_identified") 823734Sstever@eecs.umich.edu .desc("number of hwpf identified") 833734Sstever@eecs.umich.edu ; 843734Sstever@eecs.umich.edu 853077Sstever@eecs.umich.edu pfMSHRHit 863077Sstever@eecs.umich.edu .name(name() + ".prefetcher.num_hwpf_already_in_mshr") 873077Sstever@eecs.umich.edu .desc("number of hwpf that were already in mshr") 883077Sstever@eecs.umich.edu ; 893077Sstever@eecs.umich.edu 903077Sstever@eecs.umich.edu pfCacheHit 913077Sstever@eecs.umich.edu .name(name() + ".prefetcher.num_hwpf_already_in_cache") 923077Sstever@eecs.umich.edu .desc("number of hwpf that were already in the cache") 931897Sstever@eecs.umich.edu ; 943725Sstever@eecs.umich.edu 953725Sstever@eecs.umich.edu pfBufferHit 963725Sstever@eecs.umich.edu .name(name() + ".prefetcher.num_hwpf_already_in_prefetcher") 973725Sstever@eecs.umich.edu .desc("number of hwpf that were already in the prefetch queue") 983725Sstever@eecs.umich.edu ; 991897Sstever@eecs.umich.edu 1001897Sstever@eecs.umich.edu pfRemovedFull 1011897Sstever@eecs.umich.edu .name(name() + ".prefetcher.num_hwpf_evicted") 1021897Sstever@eecs.umich.edu .desc("number of hwpf removed due to no buffer left") 1031897Sstever@eecs.umich.edu ; 1041897Sstever@eecs.umich.edu 105 pfRemovedMSHR 106 .name(name() + ".prefetcher.num_hwpf_removed_MSHR_hit") 107 .desc("number of hwpf removed because MSHR allocated") 108 ; 109 110 pfIssued 111 .name(name() + ".prefetcher.num_hwpf_issued") 112 .desc("number of hwpf issued") 113 ; 114 115 pfSpanPage 116 .name(name() + ".prefetcher.num_hwpf_span_page") 117 .desc("number of hwpf spanning a virtual page") 118 ; 119 120 pfSquashed 121 .name(name() + ".prefetcher.num_hwpf_squashed_from_miss") 122 .desc("number of hwpf that got squashed due to a miss " 123 "aborting calculation time") 124 ; 125} 126 127inline bool 128BasePrefetcher::inCache(Addr addr, bool is_secure) 129{ 130 if (cache->inCache(addr, is_secure)) { 131 pfCacheHit++; 132 return true; 133 } 134 return false; 135} 136 137inline bool 138BasePrefetcher::inMissQueue(Addr addr, bool is_secure) 139{ 140 if (cache->inMissQueue(addr, is_secure)) { 141 pfMSHRHit++; 142 return true; 143 } 144 return false; 145} 146 147PacketPtr 148BasePrefetcher::getPacket() 149{ 150 DPRINTF(HWPrefetch, "Requesting a hw_pf to issue\n"); 151 152 if (pf.empty()) { 153 DPRINTF(HWPrefetch, "No HW_PF found\n"); 154 return NULL; 155 } 156 157 PacketPtr pkt = pf.begin()->pkt; 158 while (!pf.empty()) { 159 pkt = pf.begin()->pkt; 160 pf.pop_front(); 161 162 Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); 163 bool is_secure = pkt->isSecure(); 164 165 if (!inCache(blk_addr, is_secure) && !inMissQueue(blk_addr, is_secure)) 166 // we found a prefetch, return it 167 break; 168 169 DPRINTF(HWPrefetch, "addr 0x%x (%s) in cache, skipping\n", 170 pkt->getAddr(), is_secure ? "s" : "ns"); 171 delete pkt->req; 172 delete pkt; 173 174 if (pf.empty()) { 175 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 176 return NULL; // None left, all were in cache 177 } 178 } 179 180 pfIssued++; 181 assert(pkt != NULL); 182 DPRINTF(HWPrefetch, "returning 0x%x (%s)\n", pkt->getAddr(), 183 pkt->isSecure() ? "s" : "ns"); 184 return pkt; 185} 186 187 188Tick 189BasePrefetcher::notify(PacketPtr &pkt, Tick tick) 190{ 191 // Don't consult the prefetcher if any of the following conditons are true 192 // 1) The request is uncacheable 193 // 2) The request is a fetch, but we are only prefeching data 194 // 3) The request is a cache hit, but we are only training on misses 195 // 4) THe request is a write, but we are only training on reads 196 if (!pkt->req->isUncacheable() && !(pkt->req->isInstFetch() && onlyData) && 197 !(onMissOnly && inCache(pkt->getAddr(), true)) && 198 !(onReadOnly && !pkt->isRead())) { 199 // Calculate the blk address 200 Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); 201 bool is_secure = pkt->isSecure(); 202 203 // Check if miss is in pfq, if so remove it 204 std::list<DeferredPacket>::iterator iter = inPrefetch(blk_addr, 205 is_secure); 206 if (iter != pf.end()) { 207 DPRINTF(HWPrefetch, "Saw a miss to a queued prefetch addr: " 208 "0x%x (%s), removing it\n", blk_addr, 209 is_secure ? "s" : "ns"); 210 pfRemovedMSHR++; 211 delete iter->pkt->req; 212 delete iter->pkt; 213 iter = pf.erase(iter); 214 if (pf.empty()) 215 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 216 } 217 218 // Remove anything in queue with delay older than time 219 // since everything is inserted in time order, start from end 220 // and work until pf.empty() or time is earlier 221 // This is done to emulate Aborting the previous work on a new miss 222 // Needed for serial calculators like GHB 223 if (serialSquash) { 224 iter = pf.end(); 225 if (iter != pf.begin()) 226 iter--; 227 while (!pf.empty() && iter->tick >= tick) { 228 pfSquashed++; 229 DPRINTF(HWPrefetch, "Squashing old prefetch addr: 0x%x\n", 230 iter->pkt->getAddr()); 231 delete iter->pkt->req; 232 delete iter->pkt; 233 iter = pf.erase(iter); 234 if (iter != pf.begin()) 235 iter--; 236 } 237 if (pf.empty()) 238 cache->deassertMemSideBusRequest(BaseCache::Request_PF); 239 } 240 241 242 std::list<Addr> addresses; 243 std::list<Cycles> delays; 244 calculatePrefetch(pkt, addresses, delays); 245 246 std::list<Addr>::iterator addrIter = addresses.begin(); 247 std::list<Cycles>::iterator delayIter = delays.begin(); 248 for (; addrIter != addresses.end(); ++addrIter, ++delayIter) { 249 Addr addr = *addrIter; 250 251 pfIdentified++; 252 253 DPRINTF(HWPrefetch, "Found a pf candidate addr: 0x%x, " 254 "inserting into prefetch queue with delay %d time %d\n", 255 addr, *delayIter, time); 256 257 // Check if it is already in the pf buffer 258 if (inPrefetch(addr, is_secure) != pf.end()) { 259 pfBufferHit++; 260 DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n"); 261 continue; 262 } 263 264 // create a prefetch memreq 265 Request *prefetchReq = new Request(*addrIter, blkSize, 0, masterId); 266 if (is_secure) 267 prefetchReq->setFlags(Request::SECURE); 268 prefetchReq->taskId(ContextSwitchTaskId::Prefetcher); 269 PacketPtr prefetch = 270 new Packet(prefetchReq, MemCmd::HardPFReq); 271 prefetch->allocate(); 272 prefetch->req->setThreadContext(pkt->req->contextId(), 273 pkt->req->threadId()); 274 275 // Tag orefetch reqeuests with corresponding PC to train lower 276 // cache-level prefetchers 277 if (onPrefetch && pkt->req->hasPC()) 278 prefetch->req->setPC(pkt->req->getPC()); 279 280 // We just remove the head if we are full 281 if (pf.size() == size) { 282 pfRemovedFull++; 283 PacketPtr old_pkt = pf.begin()->pkt; 284 DPRINTF(HWPrefetch, "Prefetch queue full, " 285 "removing oldest 0x%x\n", old_pkt->getAddr()); 286 delete old_pkt->req; 287 delete old_pkt; 288 pf.pop_front(); 289 } 290 291 pf.push_back(DeferredPacket(tick + clockPeriod() * *delayIter, 292 prefetch)); 293 } 294 } 295 296 return pf.empty() ? 0 : pf.front().tick; 297} 298 299std::list<BasePrefetcher::DeferredPacket>::iterator 300BasePrefetcher::inPrefetch(Addr address, bool is_secure) 301{ 302 // Guaranteed to only be one match, we always check before inserting 303 std::list<DeferredPacket>::iterator iter; 304 for (iter = pf.begin(); iter != pf.end(); iter++) { 305 if (((*iter).pkt->getAddr() & ~(Addr)(blkSize-1)) == address && 306 (*iter).pkt->isSecure() == is_secure) { 307 return iter; 308 } 309 } 310 return pf.end(); 311} 312 313bool 314BasePrefetcher::samePage(Addr a, Addr b) const 315{ 316 return roundDown(a, pageBytes) == roundDown(b, pageBytes); 317} 318 319 320