base.cc revision 5714
12810SN/A/* 22810SN/A * Copyright (c) 2005 The Regents of The University of Michigan 32810SN/A * All rights reserved. 42810SN/A * 52810SN/A * Redistribution and use in source and binary forms, with or without 62810SN/A * modification, are permitted provided that the following conditions are 72810SN/A * met: redistributions of source code must retain the above copyright 82810SN/A * notice, this list of conditions and the following disclaimer; 92810SN/A * redistributions in binary form must reproduce the above copyright 102810SN/A * notice, this list of conditions and the following disclaimer in the 112810SN/A * documentation and/or other materials provided with the distribution; 122810SN/A * neither the name of the copyright holders nor the names of its 132810SN/A * contributors may be used to endorse or promote products derived from 142810SN/A * this software without specific prior written permission. 152810SN/A * 162810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272810SN/A * 282810SN/A * Authors: Ron Dreslinski 292810SN/A */ 302810SN/A 312810SN/A/** 322810SN/A * @file 332810SN/A * Hardware Prefetcher Definition. 342810SN/A */ 352810SN/A 362810SN/A#include "base/trace.hh" 375338Sstever@gmail.com#include "mem/cache/base.hh" 385338Sstever@gmail.com#include "mem/cache/prefetch/base.hh" 392814SN/A#include "mem/request.hh" 402810SN/A#include <list> 412810SN/A 425034SN/ABasePrefetcher::BasePrefetcher(const BaseCacheParams *p) 435034SN/A : size(p->prefetcher_size), pageStop(!p->prefetch_past_page), 445034SN/A serialSquash(p->prefetch_serial_squash), 455034SN/A cacheCheckPush(p->prefetch_cache_check_push), 465034SN/A only_data(p->prefetch_data_accesses_only) 472810SN/A{ 482810SN/A} 492810SN/A 502810SN/Avoid 512810SN/ABasePrefetcher::setCache(BaseCache *_cache) 522810SN/A{ 532810SN/A cache = _cache; 542810SN/A blkSize = cache->getBlockSize(); 552810SN/A} 562810SN/A 572810SN/Avoid 582810SN/ABasePrefetcher::regStats(const std::string &name) 592810SN/A{ 602810SN/A pfIdentified 612810SN/A .name(name + ".prefetcher.num_hwpf_identified") 622810SN/A .desc("number of hwpf identified") 632810SN/A ; 642810SN/A 652810SN/A pfMSHRHit 662810SN/A .name(name + ".prefetcher.num_hwpf_already_in_mshr") 672810SN/A .desc("number of hwpf that were already in mshr") 682810SN/A ; 692810SN/A 702810SN/A pfCacheHit 712810SN/A .name(name + ".prefetcher.num_hwpf_already_in_cache") 722810SN/A .desc("number of hwpf that were already in the cache") 732810SN/A ; 742810SN/A 752810SN/A pfBufferHit 762810SN/A .name(name + ".prefetcher.num_hwpf_already_in_prefetcher") 772810SN/A .desc("number of hwpf that were already in the prefetch queue") 782810SN/A ; 792810SN/A 802810SN/A pfRemovedFull 812810SN/A .name(name + ".prefetcher.num_hwpf_evicted") 822810SN/A .desc("number of hwpf removed due to no buffer left") 832810SN/A ; 842810SN/A 852810SN/A pfRemovedMSHR 862810SN/A .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit") 872810SN/A .desc("number of hwpf removed because MSHR allocated") 882810SN/A ; 892810SN/A 902810SN/A pfIssued 912810SN/A .name(name + ".prefetcher.num_hwpf_issued") 922810SN/A .desc("number of hwpf issued") 932810SN/A ; 942810SN/A 952810SN/A pfSpanPage 962810SN/A .name(name + ".prefetcher.num_hwpf_span_page") 972810SN/A .desc("number of hwpf spanning a virtual page") 982810SN/A ; 992810SN/A 1002810SN/A pfSquashed 1012810SN/A .name(name + ".prefetcher.num_hwpf_squashed_from_miss") 1022810SN/A .desc("number of hwpf that got squashed due to a miss aborting calculation time") 1032810SN/A ; 1042810SN/A} 1052810SN/A 1063861SN/Ainline bool 1073861SN/ABasePrefetcher::inCache(Addr addr) 1083861SN/A{ 1093861SN/A if (cache->inCache(addr)) { 1103861SN/A pfCacheHit++; 1113861SN/A return true; 1123861SN/A } 1133861SN/A return false; 1143861SN/A} 1153861SN/A 1163861SN/Ainline bool 1173861SN/ABasePrefetcher::inMissQueue(Addr addr) 1183861SN/A{ 1193861SN/A if (cache->inMissQueue(addr)) { 1203861SN/A pfMSHRHit++; 1213861SN/A return true; 1223861SN/A } 1233861SN/A return false; 1243861SN/A} 1253861SN/A 1263349SN/APacketPtr 1272810SN/ABasePrefetcher::getPacket() 1282810SN/A{ 1292810SN/A DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name()); 1302810SN/A 1312810SN/A if (pf.empty()) { 1322810SN/A DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name()); 1332810SN/A return NULL; 1342810SN/A } 1352810SN/A 1363349SN/A PacketPtr pkt; 1372810SN/A bool keepTrying = false; 1382810SN/A do { 1392810SN/A pkt = *pf.begin(); 1402810SN/A pf.pop_front(); 1412810SN/A if (!cacheCheckPush) { 1423861SN/A keepTrying = cache->inCache(pkt->getAddr()); 1432810SN/A } 1442810SN/A if (pf.empty()) { 1454628SN/A cache->deassertMemSideBusRequest(BaseCache::Request_PF); 1462810SN/A if (keepTrying) return NULL; //None left, all were in cache 1472810SN/A } 1482810SN/A } while (keepTrying); 1492810SN/A 1502810SN/A pfIssued++; 1512810SN/A return pkt; 1522810SN/A} 1532810SN/A 1542810SN/Avoid 1553349SN/ABasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) 1562810SN/A{ 1572814SN/A if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && only_data)) 1582810SN/A { 1592810SN/A //Calculate the blk address 1602814SN/A Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1); 1612810SN/A 1622810SN/A //Check if miss is in pfq, if so remove it 1633349SN/A std::list<PacketPtr>::iterator iter = inPrefetch(blkAddr); 1642810SN/A if (iter != pf.end()) { 1652810SN/A DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name()); 1662810SN/A pfRemovedMSHR++; 1672810SN/A pf.erase(iter); 1682810SN/A if (pf.empty()) 1694628SN/A cache->deassertMemSideBusRequest(BaseCache::Request_PF); 1702810SN/A } 1712810SN/A 1722810SN/A //Remove anything in queue with delay older than time 1732810SN/A //since everything is inserted in time order, start from end 1742810SN/A //and work until pf.empty() or time is earlier 1752810SN/A //This is done to emulate Aborting the previous work on a new miss 1762810SN/A //Needed for serial calculators like GHB 1772810SN/A if (serialSquash) { 1782810SN/A iter = pf.end(); 1792810SN/A iter--; 1802810SN/A while (!pf.empty() && ((*iter)->time >= time)) { 1812810SN/A pfSquashed++; 1822810SN/A pf.pop_back(); 1832810SN/A iter--; 1842810SN/A } 1852810SN/A if (pf.empty()) 1864628SN/A cache->deassertMemSideBusRequest(BaseCache::Request_PF); 1872810SN/A } 1882810SN/A 1892810SN/A 1902810SN/A std::list<Addr> addresses; 1912810SN/A std::list<Tick> delays; 1922810SN/A calculatePrefetch(pkt, addresses, delays); 1932810SN/A 1942810SN/A std::list<Addr>::iterator addr = addresses.begin(); 1952810SN/A std::list<Tick>::iterator delay = delays.begin(); 1962810SN/A while (addr != addresses.end()) 1972810SN/A { 1982810SN/A DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name()); 1992810SN/A //temp calc this here... 2002810SN/A pfIdentified++; 2012810SN/A //create a prefetch memreq 2022814SN/A Request * prefetchReq = new Request(*addr, blkSize, 0); 2033349SN/A PacketPtr prefetch; 2044022SN/A prefetch = new Packet(prefetchReq, MemCmd::HardPFReq, -1); 2052825SN/A prefetch->allocate(); 2065714Shsul@eecs.umich.edu prefetch->req->setThreadContext(pkt->req->contextId(), 2075714Shsul@eecs.umich.edu pkt->req->threadId()); 2082814SN/A 2092810SN/A prefetch->time = time + (*delay); //@todo ADD LATENCY HERE 2102810SN/A //... initialize 2112810SN/A 2122810SN/A //Check if it is already in the cache 2132810SN/A if (cacheCheckPush) { 2143861SN/A if (cache->inCache(prefetch->getAddr())) { 2152810SN/A addr++; 2162810SN/A delay++; 2172810SN/A continue; 2182810SN/A } 2192810SN/A } 2202810SN/A 2212810SN/A //Check if it is already in the miss_queue 2223861SN/A if (cache->inMissQueue(prefetch->getAddr())) { 2232810SN/A addr++; 2242810SN/A delay++; 2252810SN/A continue; 2262810SN/A } 2272810SN/A 2282810SN/A //Check if it is already in the pf buffer 2292814SN/A if (inPrefetch(prefetch->getAddr()) != pf.end()) { 2302810SN/A pfBufferHit++; 2312810SN/A addr++; 2322810SN/A delay++; 2332810SN/A continue; 2342810SN/A } 2352810SN/A 2362810SN/A //We just remove the head if we are full 2372810SN/A if (pf.size() == size) 2382810SN/A { 2392810SN/A DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name()); 2402810SN/A pfRemovedFull++; 2412810SN/A pf.pop_front(); 2422810SN/A } 2432810SN/A 2442810SN/A pf.push_back(prefetch); 2452810SN/A 2462810SN/A //Make sure to request the bus, with proper delay 2474628SN/A cache->requestMemSideBus(BaseCache::Request_PF, prefetch->time); 2482810SN/A 2492810SN/A //Increment through the list 2502810SN/A addr++; 2512810SN/A delay++; 2522810SN/A } 2532810SN/A } 2542810SN/A} 2552810SN/A 2563349SN/Astd::list<PacketPtr>::iterator 2572810SN/ABasePrefetcher::inPrefetch(Addr address) 2582810SN/A{ 2592810SN/A //Guaranteed to only be one match, we always check before inserting 2603349SN/A std::list<PacketPtr>::iterator iter; 2612810SN/A for (iter=pf.begin(); iter != pf.end(); iter++) { 2622814SN/A if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { 2632810SN/A return iter; 2642810SN/A } 2652810SN/A } 2662810SN/A return pf.end(); 2672810SN/A} 2682810SN/A 2692810SN/A 270