base.cc revision 5875
17949SAli.Saidi@ARM.com/* 27949SAli.Saidi@ARM.com * Copyright (c) 2005 The Regents of The University of Michigan 37949SAli.Saidi@ARM.com * All rights reserved. 47949SAli.Saidi@ARM.com * 57949SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67949SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77949SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87949SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97949SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107949SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117949SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127949SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137949SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 147949SAli.Saidi@ARM.com * this software without specific prior written permission. 157949SAli.Saidi@ARM.com * 167949SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177949SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187949SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197949SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207949SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217949SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227949SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237949SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247949SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257949SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267949SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277949SAli.Saidi@ARM.com * 287949SAli.Saidi@ARM.com * Authors: Ron Dreslinski 297949SAli.Saidi@ARM.com */ 307949SAli.Saidi@ARM.com 317949SAli.Saidi@ARM.com/** 327949SAli.Saidi@ARM.com * @file 337949SAli.Saidi@ARM.com * Hardware Prefetcher Definition. 347949SAli.Saidi@ARM.com */ 357949SAli.Saidi@ARM.com 367949SAli.Saidi@ARM.com#include "arch/isa_traits.hh" 377949SAli.Saidi@ARM.com#include "base/trace.hh" 387949SAli.Saidi@ARM.com#include "mem/cache/base.hh" 397949SAli.Saidi@ARM.com#include "mem/cache/prefetch/base.hh" 407949SAli.Saidi@ARM.com#include "mem/request.hh" 417949SAli.Saidi@ARM.com#include <list> 427949SAli.Saidi@ARM.com 437949SAli.Saidi@ARM.comBasePrefetcher::BasePrefetcher(const BaseCacheParams *p) 447949SAli.Saidi@ARM.com : size(p->prefetcher_size), pageStop(!p->prefetch_past_page), 457949SAli.Saidi@ARM.com serialSquash(p->prefetch_serial_squash), 468635Schris.emmons@arm.com cacheCheckPush(p->prefetch_cache_check_push), 477949SAli.Saidi@ARM.com onlyData(p->prefetch_data_accesses_only) 488635Schris.emmons@arm.com{ 498635Schris.emmons@arm.com} 507949SAli.Saidi@ARM.com 517949SAli.Saidi@ARM.comvoid 527949SAli.Saidi@ARM.comBasePrefetcher::setCache(BaseCache *_cache) 538229Snate@binkert.org{ 548229Snate@binkert.org cache = _cache; 558229Snate@binkert.org blkSize = cache->getBlockSize(); 568229Snate@binkert.org _name = cache->name() + "-pf"; 577949SAli.Saidi@ARM.com} 588635Schris.emmons@arm.com 597949SAli.Saidi@ARM.comvoid 608635Schris.emmons@arm.comBasePrefetcher::regStats(const std::string &name) 617949SAli.Saidi@ARM.com{ 627949SAli.Saidi@ARM.com pfIdentified 638232Snate@binkert.org .name(name + ".prefetcher.num_hwpf_identified") 647949SAli.Saidi@ARM.com .desc("number of hwpf identified") 658635Schris.emmons@arm.com ; 667949SAli.Saidi@ARM.com 677949SAli.Saidi@ARM.com pfMSHRHit 687949SAli.Saidi@ARM.com .name(name + ".prefetcher.num_hwpf_already_in_mshr") 699330Schander.sudanthi@arm.com .desc("number of hwpf that were already in mshr") 709330Schander.sudanthi@arm.com ; 719330Schander.sudanthi@arm.com 729330Schander.sudanthi@arm.com pfCacheHit 737949SAli.Saidi@ARM.com .name(name + ".prefetcher.num_hwpf_already_in_cache") 747949SAli.Saidi@ARM.com .desc("number of hwpf that were already in the cache") 757949SAli.Saidi@ARM.com ; 767949SAli.Saidi@ARM.com 777949SAli.Saidi@ARM.com pfBufferHit 787949SAli.Saidi@ARM.com .name(name + ".prefetcher.num_hwpf_already_in_prefetcher") 797949SAli.Saidi@ARM.com .desc("number of hwpf that were already in the prefetch queue") 807949SAli.Saidi@ARM.com ; 817949SAli.Saidi@ARM.com 827949SAli.Saidi@ARM.com pfRemovedFull 837949SAli.Saidi@ARM.com .name(name + ".prefetcher.num_hwpf_evicted") 847949SAli.Saidi@ARM.com .desc("number of hwpf removed due to no buffer left") 857949SAli.Saidi@ARM.com ; 867949SAli.Saidi@ARM.com 877949SAli.Saidi@ARM.com pfRemovedMSHR 887949SAli.Saidi@ARM.com .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit") 897949SAli.Saidi@ARM.com .desc("number of hwpf removed because MSHR allocated") 907949SAli.Saidi@ARM.com ; 917949SAli.Saidi@ARM.com 927949SAli.Saidi@ARM.com pfIssued 937949SAli.Saidi@ARM.com .name(name + ".prefetcher.num_hwpf_issued") 947949SAli.Saidi@ARM.com .desc("number of hwpf issued") 957949SAli.Saidi@ARM.com ; 967949SAli.Saidi@ARM.com 977949SAli.Saidi@ARM.com pfSpanPage 987949SAli.Saidi@ARM.com .name(name + ".prefetcher.num_hwpf_span_page") 997949SAli.Saidi@ARM.com .desc("number of hwpf spanning a virtual page") 1007949SAli.Saidi@ARM.com ; 1017949SAli.Saidi@ARM.com 1027949SAli.Saidi@ARM.com pfSquashed 1037949SAli.Saidi@ARM.com .name(name + ".prefetcher.num_hwpf_squashed_from_miss") 1047949SAli.Saidi@ARM.com .desc("number of hwpf that got squashed due to a miss " 1057949SAli.Saidi@ARM.com "aborting calculation time") 1067949SAli.Saidi@ARM.com ; 1077949SAli.Saidi@ARM.com} 1089330Schander.sudanthi@arm.com 10910360Sandreas.hansson@arm.cominline bool 11010360Sandreas.hansson@arm.comBasePrefetcher::inCache(Addr addr) 1117949SAli.Saidi@ARM.com{ 1127949SAli.Saidi@ARM.com if (cache->inCache(addr)) { 1137949SAli.Saidi@ARM.com pfCacheHit++; 1147949SAli.Saidi@ARM.com return true; 1157949SAli.Saidi@ARM.com } 1167949SAli.Saidi@ARM.com return false; 1177949SAli.Saidi@ARM.com} 1187949SAli.Saidi@ARM.com 1197949SAli.Saidi@ARM.cominline bool 1207949SAli.Saidi@ARM.comBasePrefetcher::inMissQueue(Addr addr) 1217949SAli.Saidi@ARM.com{ 1227949SAli.Saidi@ARM.com if (cache->inMissQueue(addr)) { 1237949SAli.Saidi@ARM.com pfMSHRHit++; 1247949SAli.Saidi@ARM.com return true; 1257949SAli.Saidi@ARM.com } 1267949SAli.Saidi@ARM.com return false; 1277949SAli.Saidi@ARM.com} 1287949SAli.Saidi@ARM.com 1297949SAli.Saidi@ARM.comPacketPtr 1307949SAli.Saidi@ARM.comBasePrefetcher::getPacket() 1317949SAli.Saidi@ARM.com{ 1327949SAli.Saidi@ARM.com DPRINTF(HWPrefetch, "Requesting a hw_pf to issue\n"); 1337949SAli.Saidi@ARM.com 1347949SAli.Saidi@ARM.com if (pf.empty()) { 1357949SAli.Saidi@ARM.com DPRINTF(HWPrefetch, "No HW_PF found\n"); 1367949SAli.Saidi@ARM.com return NULL; 1377949SAli.Saidi@ARM.com } 1387949SAli.Saidi@ARM.com 1397949SAli.Saidi@ARM.com PacketPtr pkt; 1407949SAli.Saidi@ARM.com bool keep_trying = false; 1417949SAli.Saidi@ARM.com do { 1427949SAli.Saidi@ARM.com pkt = *pf.begin(); 1437949SAli.Saidi@ARM.com pf.pop_front(); 1447949SAli.Saidi@ARM.com if (!cacheCheckPush) { 1457949SAli.Saidi@ARM.com keep_trying = cache->inCache(pkt->getAddr()); 1467949SAli.Saidi@ARM.com } 1477949SAli.Saidi@ARM.com 1487949SAli.Saidi@ARM.com if (keep_trying) { 1497949SAli.Saidi@ARM.com DPRINTF(HWPrefetch, "addr 0x%x in cache, skipping\n", 1507949SAli.Saidi@ARM.com pkt->getAddr()); 1517949SAli.Saidi@ARM.com delete pkt->req; 1527949SAli.Saidi@ARM.com delete pkt; 1537949SAli.Saidi@ARM.com } 1547949SAli.Saidi@ARM.com 1557949SAli.Saidi@ARM.com if (pf.empty()) { 1567949SAli.Saidi@ARM.com cache->deassertMemSideBusRequest(BaseCache::Request_PF); 1577949SAli.Saidi@ARM.com if (keep_trying) { 1587949SAli.Saidi@ARM.com return NULL; // None left, all were in cache 1597949SAli.Saidi@ARM.com } 1607949SAli.Saidi@ARM.com } 1617949SAli.Saidi@ARM.com } while (keep_trying); 1627949SAli.Saidi@ARM.com 1637949SAli.Saidi@ARM.com pfIssued++; 1647949SAli.Saidi@ARM.com assert(pkt != NULL); 1657949SAli.Saidi@ARM.com DPRINTF(HWPrefetch, "returning 0x%x\n", pkt->getAddr()); 1667949SAli.Saidi@ARM.com return pkt; 1677949SAli.Saidi@ARM.com} 1687949SAli.Saidi@ARM.com 1697949SAli.Saidi@ARM.com 1707949SAli.Saidi@ARM.comTick 1717949SAli.Saidi@ARM.comBasePrefetcher::notify(PacketPtr &pkt, Tick time) 1727949SAli.Saidi@ARM.com{ 1737949SAli.Saidi@ARM.com if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && onlyData)) { 1747949SAli.Saidi@ARM.com // Calculate the blk address 1757949SAli.Saidi@ARM.com Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1); 1767949SAli.Saidi@ARM.com 1777949SAli.Saidi@ARM.com // Check if miss is in pfq, if so remove it 17810156Sandreas@sandberg.pp.se std::list<PacketPtr>::iterator iter = inPrefetch(blk_addr); 17910156Sandreas@sandberg.pp.se if (iter != pf.end()) { 18010156Sandreas@sandberg.pp.se DPRINTF(HWPrefetch, "Saw a miss to a queued prefetch addr: " 18110156Sandreas@sandberg.pp.se "0x%x, removing it\n", blk_addr); 18210156Sandreas@sandberg.pp.se pfRemovedMSHR++; 1837949SAli.Saidi@ARM.com delete (*iter)->req; 1847949SAli.Saidi@ARM.com delete (*iter); 1857949SAli.Saidi@ARM.com pf.erase(iter); 1867949SAli.Saidi@ARM.com if (pf.empty()) 1877949SAli.Saidi@ARM.com cache->deassertMemSideBusRequest(BaseCache::Request_PF); 1887949SAli.Saidi@ARM.com } 1897949SAli.Saidi@ARM.com 1907949SAli.Saidi@ARM.com // Remove anything in queue with delay older than time 1917949SAli.Saidi@ARM.com // since everything is inserted in time order, start from end 1927949SAli.Saidi@ARM.com // and work until pf.empty() or time is earlier 1937949SAli.Saidi@ARM.com // This is done to emulate Aborting the previous work on a new miss 1947949SAli.Saidi@ARM.com // Needed for serial calculators like GHB 1957949SAli.Saidi@ARM.com if (serialSquash) { 1967949SAli.Saidi@ARM.com iter = pf.end(); 1977949SAli.Saidi@ARM.com iter--; 1987949SAli.Saidi@ARM.com while (!pf.empty() && ((*iter)->time >= time)) { 1997949SAli.Saidi@ARM.com pfSquashed++; 2007949SAli.Saidi@ARM.com DPRINTF(HWPrefetch, "Squashing old prefetch addr: 0x%x\n", 2017949SAli.Saidi@ARM.com (*iter)->getAddr()); 2027949SAli.Saidi@ARM.com delete (*iter)->req; 2037949SAli.Saidi@ARM.com delete (*iter); 2047949SAli.Saidi@ARM.com pf.erase(iter); 2057949SAli.Saidi@ARM.com iter--; 2067949SAli.Saidi@ARM.com } 2077949SAli.Saidi@ARM.com if (pf.empty()) 2087949SAli.Saidi@ARM.com cache->deassertMemSideBusRequest(BaseCache::Request_PF); 2097949SAli.Saidi@ARM.com } 2107949SAli.Saidi@ARM.com 2117949SAli.Saidi@ARM.com 2127949SAli.Saidi@ARM.com std::list<Addr> addresses; 2137949SAli.Saidi@ARM.com std::list<Tick> delays; 2147949SAli.Saidi@ARM.com calculatePrefetch(pkt, addresses, delays); 2157949SAli.Saidi@ARM.com 2167949SAli.Saidi@ARM.com std::list<Addr>::iterator addrIter = addresses.begin(); 2177949SAli.Saidi@ARM.com std::list<Tick>::iterator delayIter = delays.begin(); 2187949SAli.Saidi@ARM.com for (; addrIter != addresses.end(); ++addrIter, ++delayIter) { 2197949SAli.Saidi@ARM.com Addr addr = *addrIter; 2207949SAli.Saidi@ARM.com 2217949SAli.Saidi@ARM.com pfIdentified++; 2227949SAli.Saidi@ARM.com 2237949SAli.Saidi@ARM.com DPRINTF(HWPrefetch, "Found a pf candidate addr: 0x%x, " 2247949SAli.Saidi@ARM.com "inserting into prefetch queue with delay %d time %d\n", 2257949SAli.Saidi@ARM.com addr, *delayIter, time); 2267949SAli.Saidi@ARM.com 2277949SAli.Saidi@ARM.com // Check if it is already in the cache 2287949SAli.Saidi@ARM.com if (cacheCheckPush && cache->inCache(addr)) { 2297949SAli.Saidi@ARM.com DPRINTF(HWPrefetch, "Prefetch addr already in cache\n"); 2307949SAli.Saidi@ARM.com continue; 2317949SAli.Saidi@ARM.com } 2327949SAli.Saidi@ARM.com 2337949SAli.Saidi@ARM.com // Check if it is already in the miss_queue 2347949SAli.Saidi@ARM.com if (cache->inMissQueue(addr)) { 2357949SAli.Saidi@ARM.com DPRINTF(HWPrefetch, "Prefetch addr already in miss queue\n"); 2367949SAli.Saidi@ARM.com continue; 2377949SAli.Saidi@ARM.com } 2387949SAli.Saidi@ARM.com 2397949SAli.Saidi@ARM.com // Check if it is already in the pf buffer 2407949SAli.Saidi@ARM.com if (inPrefetch(addr) != pf.end()) { 2417949SAli.Saidi@ARM.com pfBufferHit++; 2427949SAli.Saidi@ARM.com DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n"); 2437949SAli.Saidi@ARM.com continue; 2447949SAli.Saidi@ARM.com } 2457949SAli.Saidi@ARM.com 2467949SAli.Saidi@ARM.com // create a prefetch memreq 2477949SAli.Saidi@ARM.com Request *prefetchReq = new Request(*addrIter, blkSize, 0); 2488871SChander.Sudanthi@arm.com PacketPtr prefetch = 2498871SChander.Sudanthi@arm.com new Packet(prefetchReq, MemCmd::HardPFReq, Packet::Broadcast); 2507949SAli.Saidi@ARM.com prefetch->allocate(); 2518871SChander.Sudanthi@arm.com prefetch->req->setThreadContext(pkt->req->contextId(), 2528871SChander.Sudanthi@arm.com pkt->req->threadId()); 2537949SAli.Saidi@ARM.com 2548871SChander.Sudanthi@arm.com prefetch->time = time + (*delayIter); // @todo ADD LATENCY HERE 2558871SChander.Sudanthi@arm.com 2567949SAli.Saidi@ARM.com // We just remove the head if we are full 2578871SChander.Sudanthi@arm.com if (pf.size() == size) { 2588871SChander.Sudanthi@arm.com pfRemovedFull++; 2597949SAli.Saidi@ARM.com PacketPtr old_pkt = *pf.begin(); 2608871SChander.Sudanthi@arm.com DPRINTF(HWPrefetch, "Prefetch queue full, " 2618871SChander.Sudanthi@arm.com "removing oldest 0x%x\n", old_pkt->getAddr()); 2628871SChander.Sudanthi@arm.com delete old_pkt->req; 2637949SAli.Saidi@ARM.com delete old_pkt; 2647949SAli.Saidi@ARM.com pf.pop_front(); 2657949SAli.Saidi@ARM.com } 2667949SAli.Saidi@ARM.com 2677949SAli.Saidi@ARM.com pf.push_back(prefetch); 2687949SAli.Saidi@ARM.com } 2697949SAli.Saidi@ARM.com } 2707949SAli.Saidi@ARM.com 2717949SAli.Saidi@ARM.com return pf.empty() ? 0 : pf.front()->time; 2727949SAli.Saidi@ARM.com} 2737949SAli.Saidi@ARM.com 2747949SAli.Saidi@ARM.comstd::list<PacketPtr>::iterator 2757949SAli.Saidi@ARM.comBasePrefetcher::inPrefetch(Addr address) 2767949SAli.Saidi@ARM.com{ 2777949SAli.Saidi@ARM.com // Guaranteed to only be one match, we always check before inserting 2787949SAli.Saidi@ARM.com std::list<PacketPtr>::iterator iter; 2797949SAli.Saidi@ARM.com for (iter = pf.begin(); iter != pf.end(); iter++) { 2807949SAli.Saidi@ARM.com if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { 2817949SAli.Saidi@ARM.com return iter; 2827949SAli.Saidi@ARM.com } 2837949SAli.Saidi@ARM.com } 2847949SAli.Saidi@ARM.com return pf.end(); 2857949SAli.Saidi@ARM.com} 2867949SAli.Saidi@ARM.com 2877949SAli.Saidi@ARM.combool 2887949SAli.Saidi@ARM.comBasePrefetcher::samePage(Addr a, Addr b) 2897949SAli.Saidi@ARM.com{ 2907949SAli.Saidi@ARM.com return roundDown(a, TheISA::VMPageSize) == roundDown(b, TheISA::VMPageSize); 2917949SAli.Saidi@ARM.com} 2927949SAli.Saidi@ARM.com