base.cc revision 3349
112SN/A/* 21762SN/A * Copyright (c) 2005 The Regents of The University of Michigan 312SN/A * All rights reserved. 412SN/A * 512SN/A * Redistribution and use in source and binary forms, with or without 612SN/A * modification, are permitted provided that the following conditions are 712SN/A * met: redistributions of source code must retain the above copyright 812SN/A * notice, this list of conditions and the following disclaimer; 912SN/A * redistributions in binary form must reproduce the above copyright 1012SN/A * notice, this list of conditions and the following disclaimer in the 1112SN/A * documentation and/or other materials provided with the distribution; 1212SN/A * neither the name of the copyright holders nor the names of its 1312SN/A * contributors may be used to endorse or promote products derived from 1412SN/A * this software without specific prior written permission. 1512SN/A * 1612SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 292665Ssaidi@eecs.umich.edu */ 3012SN/A 3112SN/A/** 3212SN/A * @file 3312SN/A * Hardware Prefetcher Definition. 34468SN/A */ 35468SN/A 36468SN/A#include "base/trace.hh" 37661SN/A#include "mem/cache/base_cache.hh" 38468SN/A#include "mem/cache/prefetch/base_prefetcher.hh" 392634Sstever@eecs.umich.edu#include "mem/request.hh" 40468SN/A#include <list> 4156SN/A 422439SN/ABasePrefetcher::BasePrefetcher(int size, bool pageStop, bool serialSquash, 4312SN/A bool cacheCheckPush, bool onlyData) 4456SN/A :size(size), pageStop(pageStop), serialSquash(serialSquash), 4512SN/A cacheCheckPush(cacheCheckPush), only_data(onlyData) 4656SN/A{ 4712SN/A} 482423SN/A 492423SN/Avoid 5012SN/ABasePrefetcher::setCache(BaseCache *_cache) 5112SN/A{ 5212SN/A cache = _cache; 5312SN/A blkSize = cache->getBlockSize(); 5412SN/A} 5512SN/A 56443SN/Avoid 57443SN/ABasePrefetcher::regStats(const std::string &name) 582207SN/A{ 592207SN/A pfIdentified 60443SN/A .name(name + ".prefetcher.num_hwpf_identified") 61468SN/A .desc("number of hwpf identified") 621708SN/A ; 631708SN/A 64443SN/A pfMSHRHit 65468SN/A .name(name + ".prefetcher.num_hwpf_already_in_mshr") 66443SN/A .desc("number of hwpf that were already in mshr") 67468SN/A ; 68443SN/A 69443SN/A pfCacheHit 70468SN/A .name(name + ".prefetcher.num_hwpf_already_in_cache") 71468SN/A .desc("number of hwpf that were already in the cache") 72443SN/A ; 73443SN/A 74443SN/A pfBufferHit 752476SN/A .name(name + ".prefetcher.num_hwpf_already_in_prefetcher") 762207SN/A .desc("number of hwpf that were already in the prefetch queue") 772207SN/A ; 782207SN/A 792207SN/A pfRemovedFull 802207SN/A .name(name + ".prefetcher.num_hwpf_evicted") 812207SN/A .desc("number of hwpf removed due to no buffer left") 822620SN/A ; 832207SN/A 842207SN/A pfRemovedMSHR 852207SN/A .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit") 862472SN/A .desc("number of hwpf removed because MSHR allocated") 872207SN/A ; 882207SN/A 892207SN/A pfIssued 902600SN/A .name(name + ".prefetcher.num_hwpf_issued") 912207SN/A .desc("number of hwpf issued") 922207SN/A ; 932207SN/A 942207SN/A pfSpanPage 952207SN/A .name(name + ".prefetcher.num_hwpf_span_page") 962207SN/A .desc("number of hwpf spanning a virtual page") 972238SN/A ; 982207SN/A 992207SN/A pfSquashed 1002207SN/A .name(name + ".prefetcher.num_hwpf_squashed_from_miss") 1012207SN/A .desc("number of hwpf that got squashed due to a miss aborting calculation time") 1022207SN/A ; 1032238SN/A} 1042207SN/A 1052207SN/APacketPtr 1062238SN/ABasePrefetcher::getPacket() 1072207SN/A{ 1082207SN/A DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name()); 1092207SN/A 1102207SN/A if (pf.empty()) { 1112238SN/A DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name()); 1122238SN/A return NULL; 1132600SN/A } 1142238SN/A 1152238SN/A PacketPtr pkt; 1162238SN/A bool keepTrying = false; 1172238SN/A do { 1182238SN/A pkt = *pf.begin(); 1192238SN/A pf.pop_front(); 1202238SN/A if (!cacheCheckPush) { 1212238SN/A keepTrying = inCache(pkt); 1222238SN/A } 1232238SN/A if (pf.empty()) { 1242600SN/A cache->clearMasterRequest(Request_PF); 1252238SN/A if (keepTrying) return NULL; //None left, all were in cache 1262238SN/A } 1272238SN/A } while (keepTrying); 1282238SN/A 1292238SN/A pfIssued++; 1302238SN/A return pkt; 1312238SN/A} 1322238SN/A 1332238SN/Avoid 1342238SN/ABasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) 1352238SN/A{ 1362238SN/A if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && only_data)) 1372238SN/A { 1382238SN/A //Calculate the blk address 1392238SN/A Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1); 1402238SN/A 1412238SN/A //Check if miss is in pfq, if so remove it 1422238SN/A std::list<PacketPtr>::iterator iter = inPrefetch(blkAddr); 1432238SN/A if (iter != pf.end()) { 1442238SN/A DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name()); 1452238SN/A pfRemovedMSHR++; 1462238SN/A pf.erase(iter); 1472600SN/A if (pf.empty()) 1482600SN/A cache->clearMasterRequest(Request_PF); 1492600SN/A } 1502600SN/A 1512600SN/A //Remove anything in queue with delay older than time 1522238SN/A //since everything is inserted in time order, start from end 1532238SN/A //and work until pf.empty() or time is earlier 1542238SN/A //This is done to emulate Aborting the previous work on a new miss 1552472SN/A //Needed for serial calculators like GHB 1562976Sgblack@eecs.umich.edu if (serialSquash) { 1572976Sgblack@eecs.umich.edu iter = pf.end(); 1582976Sgblack@eecs.umich.edu iter--; 1592976Sgblack@eecs.umich.edu while (!pf.empty() && ((*iter)->time >= time)) { 1602976Sgblack@eecs.umich.edu pfSquashed++; 1612976Sgblack@eecs.umich.edu pf.pop_back(); 1622976Sgblack@eecs.umich.edu iter--; 1632976Sgblack@eecs.umich.edu } 1642976Sgblack@eecs.umich.edu if (pf.empty()) 1652976Sgblack@eecs.umich.edu cache->clearMasterRequest(Request_PF); 1662976Sgblack@eecs.umich.edu } 1672976Sgblack@eecs.umich.edu 1682976Sgblack@eecs.umich.edu 1692976Sgblack@eecs.umich.edu std::list<Addr> addresses; 1702976Sgblack@eecs.umich.edu std::list<Tick> delays; 1712976Sgblack@eecs.umich.edu calculatePrefetch(pkt, addresses, delays); 1722976Sgblack@eecs.umich.edu 1732976Sgblack@eecs.umich.edu std::list<Addr>::iterator addr = addresses.begin(); 1742976Sgblack@eecs.umich.edu std::list<Tick>::iterator delay = delays.begin(); 1752976Sgblack@eecs.umich.edu while (addr != addresses.end()) 1762976Sgblack@eecs.umich.edu { 1772976Sgblack@eecs.umich.edu DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name()); 1782976Sgblack@eecs.umich.edu //temp calc this here... 1792976Sgblack@eecs.umich.edu pfIdentified++; 1802976Sgblack@eecs.umich.edu //create a prefetch memreq 1812976Sgblack@eecs.umich.edu Request * prefetchReq = new Request(*addr, blkSize, 0); 1822976Sgblack@eecs.umich.edu PacketPtr prefetch; 1832976Sgblack@eecs.umich.edu prefetch = new Packet(prefetchReq, Packet::HardPFReq, -1); 1842976Sgblack@eecs.umich.edu prefetch->allocate(); 1852976Sgblack@eecs.umich.edu prefetch->req->setThreadContext(pkt->req->getCpuNum(), 1862238SN/A pkt->req->getThreadNum()); 1872976Sgblack@eecs.umich.edu 18812SN/A prefetch->time = time + (*delay); //@todo ADD LATENCY HERE 18912SN/A //... initialize 19012SN/A 19112SN/A //Check if it is already in the cache 19212SN/A if (cacheCheckPush) { 193360SN/A if (inCache(prefetch)) { 194360SN/A addr++; 195360SN/A delay++; 196443SN/A continue; 19712SN/A } 198443SN/A } 199443SN/A 20012SN/A //Check if it is already in the miss_queue 201468SN/A if (inMissQueue(prefetch->getAddr())) { 2021708SN/A addr++; 2031708SN/A delay++; 20412SN/A continue; 205468SN/A } 206443SN/A 207468SN/A //Check if it is already in the pf buffer 208443SN/A if (inPrefetch(prefetch->getAddr()) != pf.end()) { 20912SN/A pfBufferHit++; 210468SN/A addr++; 211468SN/A delay++; 212443SN/A continue; 21312SN/A } 21412SN/A 215468SN/A //We just remove the head if we are full 21612SN/A if (pf.size() == size) 2172472SN/A { 218468SN/A DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name()); 219468SN/A pfRemovedFull++; 220468SN/A pf.pop_front(); 221468SN/A } 222468SN/A 223468SN/A pf.push_back(prefetch); 224468SN/A prefetch->flags |= CACHE_LINE_FILL; 225468SN/A 226468SN/A //Make sure to request the bus, with proper delay 227468SN/A cache->setMasterRequest(Request_PF, prefetch->time); 228468SN/A 229468SN/A //Increment through the list 230468SN/A addr++; 231468SN/A delay++; 232468SN/A } 233468SN/A } 234468SN/A} 235468SN/A 2362420SN/Astd::list<PacketPtr>::iterator 237468SN/ABasePrefetcher::inPrefetch(Addr address) 238468SN/A{ 239468SN/A //Guaranteed to only be one match, we always check before inserting 240468SN/A std::list<PacketPtr>::iterator iter; 241468SN/A for (iter=pf.begin(); iter != pf.end(); iter++) { 242468SN/A if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { 2432420SN/A return iter; 2442476SN/A } 245468SN/A } 246468SN/A return pf.end(); 2472420SN/A} 248468SN/A 249468SN/A 250468SN/A