base.cc revision 5875:d82be3235ab4
12131SN/A/*
25268Sksewell@umich.edu * Copyright (c) 2005 The Regents of The University of Michigan
35254Sksewell@umich.edu * All rights reserved.
45254Sksewell@umich.edu *
52131SN/A * Redistribution and use in source and binary forms, with or without
65254Sksewell@umich.edu * modification, are permitted provided that the following conditions are
75254Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
85254Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
95254Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
105254Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
115254Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
125254Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
135254Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
145254Sksewell@umich.edu * this software without specific prior written permission.
155254Sksewell@umich.edu *
162131SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175254Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185254Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195254Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205254Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215254Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225254Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235254Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245254Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255254Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265254Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275254Sksewell@umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski
295254Sksewell@umich.edu */
305254Sksewell@umich.edu
315222Sksewell@umich.edu/**
322131SN/A * @file
332131SN/A * Hardware Prefetcher Definition.
342239SN/A */
352680Sktlim@umich.edu
362447SN/A#include "arch/isa_traits.hh"
372447SN/A#include "base/trace.hh"
385222Sksewell@umich.edu#include "mem/cache/base.hh"
392800Ssaidi@eecs.umich.edu#include "mem/cache/prefetch/base.hh"
402800Ssaidi@eecs.umich.edu#include "mem/request.hh"
412800Ssaidi@eecs.umich.edu#include <list>
422800Ssaidi@eecs.umich.edu
432131SN/ABasePrefetcher::BasePrefetcher(const BaseCacheParams *p)
442447SN/A    : size(p->prefetcher_size), pageStop(!p->prefetch_past_page),
452447SN/A      serialSquash(p->prefetch_serial_squash),
462131SN/A      cacheCheckPush(p->prefetch_cache_check_push),
472479SN/A      onlyData(p->prefetch_data_accesses_only)
482447SN/A{
492447SN/A}
502131SN/A
512479SN/Avoid
522447SN/ABasePrefetcher::setCache(BaseCache *_cache)
532447SN/A{
542447SN/A    cache = _cache;
555224Sksewell@umich.edu    blkSize = cache->getBlockSize();
565222Sksewell@umich.edu    _name = cache->name() + "-pf";
575222Sksewell@umich.edu}
585222Sksewell@umich.edu
595222Sksewell@umich.eduvoid
605222Sksewell@umich.eduBasePrefetcher::regStats(const std::string &name)
612447SN/A{
622447SN/A    pfIdentified
635222Sksewell@umich.edu        .name(name + ".prefetcher.num_hwpf_identified")
645222Sksewell@umich.edu        .desc("number of hwpf identified")
655222Sksewell@umich.edu        ;
665222Sksewell@umich.edu
675222Sksewell@umich.edu    pfMSHRHit
685222Sksewell@umich.edu        .name(name + ".prefetcher.num_hwpf_already_in_mshr")
695222Sksewell@umich.edu        .desc("number of hwpf that were already in mshr")
705222Sksewell@umich.edu        ;
715222Sksewell@umich.edu
725222Sksewell@umich.edu    pfCacheHit
735222Sksewell@umich.edu        .name(name + ".prefetcher.num_hwpf_already_in_cache")
745222Sksewell@umich.edu        .desc("number of hwpf that were already in the cache")
755222Sksewell@umich.edu        ;
765224Sksewell@umich.edu
775222Sksewell@umich.edu    pfBufferHit
784661Sksewell@umich.edu        .name(name + ".prefetcher.num_hwpf_already_in_prefetcher")
794661Sksewell@umich.edu        .desc("number of hwpf that were already in the prefetch queue")
805224Sksewell@umich.edu        ;
815222Sksewell@umich.edu
824661Sksewell@umich.edu    pfRemovedFull
834661Sksewell@umich.edu        .name(name + ".prefetcher.num_hwpf_evicted")
845224Sksewell@umich.edu        .desc("number of hwpf removed due to no buffer left")
854661Sksewell@umich.edu        ;
864661Sksewell@umich.edu
874661Sksewell@umich.edu    pfRemovedMSHR
885222Sksewell@umich.edu        .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit")
895222Sksewell@umich.edu        .desc("number of hwpf removed because MSHR allocated")
902447SN/A        ;
912447SN/A
924661Sksewell@umich.edu    pfIssued
934661Sksewell@umich.edu        .name(name + ".prefetcher.num_hwpf_issued")
944661Sksewell@umich.edu        .desc("number of hwpf issued")
954661Sksewell@umich.edu        ;
962447SN/A
975222Sksewell@umich.edu    pfSpanPage
982447SN/A        .name(name + ".prefetcher.num_hwpf_span_page")
992447SN/A        .desc("number of hwpf spanning a virtual page")
1005222Sksewell@umich.edu        ;
1015222Sksewell@umich.edu
1025222Sksewell@umich.edu    pfSquashed
1035222Sksewell@umich.edu        .name(name + ".prefetcher.num_hwpf_squashed_from_miss")
1045222Sksewell@umich.edu        .desc("number of hwpf that got squashed due to a miss "
1055222Sksewell@umich.edu              "aborting calculation time")
1065222Sksewell@umich.edu        ;
1075222Sksewell@umich.edu}
1085222Sksewell@umich.edu
1095222Sksewell@umich.eduinline bool
1105222Sksewell@umich.eduBasePrefetcher::inCache(Addr addr)
1115222Sksewell@umich.edu{
1125222Sksewell@umich.edu    if (cache->inCache(addr)) {
1135222Sksewell@umich.edu        pfCacheHit++;
1145222Sksewell@umich.edu        return true;
1155222Sksewell@umich.edu    }
1165222Sksewell@umich.edu    return false;
1175222Sksewell@umich.edu}
1185222Sksewell@umich.edu
1195222Sksewell@umich.eduinline bool
1205222Sksewell@umich.eduBasePrefetcher::inMissQueue(Addr addr)
1215222Sksewell@umich.edu{
1225222Sksewell@umich.edu    if (cache->inMissQueue(addr)) {
1235222Sksewell@umich.edu        pfMSHRHit++;
1245222Sksewell@umich.edu        return true;
1255222Sksewell@umich.edu    }
1265222Sksewell@umich.edu    return false;
1275222Sksewell@umich.edu}
1282447SN/A
1292447SN/APacketPtr
1302447SN/ABasePrefetcher::getPacket()
1312447SN/A{
1322447SN/A    DPRINTF(HWPrefetch, "Requesting a hw_pf to issue\n");
1332447SN/A
1342447SN/A    if (pf.empty()) {
1352447SN/A        DPRINTF(HWPrefetch, "No HW_PF found\n");
1362447SN/A        return NULL;
1372447SN/A    }
1382447SN/A
1392447SN/A    PacketPtr pkt;
1402447SN/A    bool keep_trying = false;
1412447SN/A    do {
1422447SN/A        pkt = *pf.begin();
1432447SN/A        pf.pop_front();
1445222Sksewell@umich.edu        if (!cacheCheckPush) {
1455222Sksewell@umich.edu            keep_trying = cache->inCache(pkt->getAddr());
1465222Sksewell@umich.edu        }
1472447SN/A
1485222Sksewell@umich.edu        if (keep_trying) {
1495222Sksewell@umich.edu            DPRINTF(HWPrefetch, "addr 0x%x in cache, skipping\n",
1505222Sksewell@umich.edu                    pkt->getAddr());
1512447SN/A            delete pkt->req;
1525222Sksewell@umich.edu            delete pkt;
1535222Sksewell@umich.edu        }
1545222Sksewell@umich.edu
1552447SN/A        if (pf.empty()) {
1565222Sksewell@umich.edu            cache->deassertMemSideBusRequest(BaseCache::Request_PF);
1572447SN/A            if (keep_trying) {
1582447SN/A                return NULL; // None left, all were in cache
1592447SN/A            }
1605222Sksewell@umich.edu        }
1612447SN/A    } while (keep_trying);
1622447SN/A
1632447SN/A    pfIssued++;
1645222Sksewell@umich.edu    assert(pkt != NULL);
1654661Sksewell@umich.edu    DPRINTF(HWPrefetch, "returning 0x%x\n", pkt->getAddr());
1664661Sksewell@umich.edu    return pkt;
1674661Sksewell@umich.edu}
1685222Sksewell@umich.edu
1696378Sgblack@eecs.umich.edu
1706378Sgblack@eecs.umich.eduTick
1715222Sksewell@umich.eduBasePrefetcher::notify(PacketPtr &pkt, Tick time)
1726378Sgblack@eecs.umich.edu{
1736378Sgblack@eecs.umich.edu    if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && onlyData)) {
1746378Sgblack@eecs.umich.edu        // Calculate the blk address
1755222Sksewell@umich.edu        Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1);
1765222Sksewell@umich.edu
1776378Sgblack@eecs.umich.edu        // Check if miss is in pfq, if so remove it
1786379Sgblack@eecs.umich.edu        std::list<PacketPtr>::iterator iter = inPrefetch(blk_addr);
1795222Sksewell@umich.edu        if (iter != pf.end()) {
1806378Sgblack@eecs.umich.edu            DPRINTF(HWPrefetch, "Saw a miss to a queued prefetch addr: "
1816379Sgblack@eecs.umich.edu                    "0x%x, removing it\n", blk_addr);
1826379Sgblack@eecs.umich.edu            pfRemovedMSHR++;
1836378Sgblack@eecs.umich.edu            delete (*iter)->req;
1846379Sgblack@eecs.umich.edu            delete (*iter);
1856379Sgblack@eecs.umich.edu            pf.erase(iter);
1866379Sgblack@eecs.umich.edu            if (pf.empty())
1876379Sgblack@eecs.umich.edu                cache->deassertMemSideBusRequest(BaseCache::Request_PF);
1885222Sksewell@umich.edu        }
1895222Sksewell@umich.edu
1906378Sgblack@eecs.umich.edu        // Remove anything in queue with delay older than time
1916379Sgblack@eecs.umich.edu        // since everything is inserted in time order, start from end
1926379Sgblack@eecs.umich.edu        // and work until pf.empty() or time is earlier
1935222Sksewell@umich.edu        // This is done to emulate Aborting the previous work on a new miss
1946378Sgblack@eecs.umich.edu        // Needed for serial calculators like GHB
1956378Sgblack@eecs.umich.edu        if (serialSquash) {
1966378Sgblack@eecs.umich.edu            iter = pf.end();
1976378Sgblack@eecs.umich.edu            iter--;
1986378Sgblack@eecs.umich.edu            while (!pf.empty() && ((*iter)->time >= time)) {
1996379Sgblack@eecs.umich.edu                pfSquashed++;
2006378Sgblack@eecs.umich.edu                DPRINTF(HWPrefetch, "Squashing old prefetch addr: 0x%x\n",
2016379Sgblack@eecs.umich.edu                        (*iter)->getAddr());
2026378Sgblack@eecs.umich.edu                delete (*iter)->req;
2036379Sgblack@eecs.umich.edu                delete (*iter);
2046378Sgblack@eecs.umich.edu                pf.erase(iter);
2056379Sgblack@eecs.umich.edu                iter--;
2066378Sgblack@eecs.umich.edu            }
2076379Sgblack@eecs.umich.edu            if (pf.empty())
2086378Sgblack@eecs.umich.edu                cache->deassertMemSideBusRequest(BaseCache::Request_PF);
2095222Sksewell@umich.edu        }
2106378Sgblack@eecs.umich.edu
2116379Sgblack@eecs.umich.edu
2126379Sgblack@eecs.umich.edu        std::list<Addr> addresses;
2136379Sgblack@eecs.umich.edu        std::list<Tick> delays;
2146379Sgblack@eecs.umich.edu        calculatePrefetch(pkt, addresses, delays);
2156379Sgblack@eecs.umich.edu
2166378Sgblack@eecs.umich.edu        std::list<Addr>::iterator addrIter = addresses.begin();
2176378Sgblack@eecs.umich.edu        std::list<Tick>::iterator delayIter = delays.begin();
2186378Sgblack@eecs.umich.edu        for (; addrIter != addresses.end(); ++addrIter, ++delayIter) {
2196378Sgblack@eecs.umich.edu            Addr addr = *addrIter;
2206378Sgblack@eecs.umich.edu
2216378Sgblack@eecs.umich.edu            pfIdentified++;
2226378Sgblack@eecs.umich.edu
2236378Sgblack@eecs.umich.edu            DPRINTF(HWPrefetch, "Found a pf candidate addr: 0x%x, "
2246378Sgblack@eecs.umich.edu                    "inserting into prefetch queue with delay %d time %d\n",
2256378Sgblack@eecs.umich.edu                    addr, *delayIter, time);
2266379Sgblack@eecs.umich.edu
2276378Sgblack@eecs.umich.edu            // Check if it is already in the cache
2286378Sgblack@eecs.umich.edu            if (cacheCheckPush && cache->inCache(addr)) {
2296379Sgblack@eecs.umich.edu                DPRINTF(HWPrefetch, "Prefetch addr already in cache\n");
2306378Sgblack@eecs.umich.edu                continue;
2316379Sgblack@eecs.umich.edu            }
2326378Sgblack@eecs.umich.edu
2336378Sgblack@eecs.umich.edu            // Check if it is already in the miss_queue
2346378Sgblack@eecs.umich.edu            if (cache->inMissQueue(addr)) {
2356378Sgblack@eecs.umich.edu                DPRINTF(HWPrefetch, "Prefetch addr already in miss queue\n");
2366378Sgblack@eecs.umich.edu                continue;
2376378Sgblack@eecs.umich.edu            }
2386378Sgblack@eecs.umich.edu
2396378Sgblack@eecs.umich.edu            // Check if it is already in the pf buffer
2406378Sgblack@eecs.umich.edu            if (inPrefetch(addr) != pf.end()) {
2416378Sgblack@eecs.umich.edu                pfBufferHit++;
2426378Sgblack@eecs.umich.edu                DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n");
2436379Sgblack@eecs.umich.edu                continue;
2446378Sgblack@eecs.umich.edu            }
2456378Sgblack@eecs.umich.edu
2466378Sgblack@eecs.umich.edu            // create a prefetch memreq
2476378Sgblack@eecs.umich.edu            Request *prefetchReq = new Request(*addrIter, blkSize, 0);
2486379Sgblack@eecs.umich.edu            PacketPtr prefetch =
2496378Sgblack@eecs.umich.edu                new Packet(prefetchReq, MemCmd::HardPFReq, Packet::Broadcast);
2506378Sgblack@eecs.umich.edu            prefetch->allocate();
2516378Sgblack@eecs.umich.edu            prefetch->req->setThreadContext(pkt->req->contextId(),
2526378Sgblack@eecs.umich.edu                                            pkt->req->threadId());
2536378Sgblack@eecs.umich.edu
2546378Sgblack@eecs.umich.edu            prefetch->time = time + (*delayIter); // @todo ADD LATENCY HERE
2556378Sgblack@eecs.umich.edu
2566378Sgblack@eecs.umich.edu            // We just remove the head if we are full
2576378Sgblack@eecs.umich.edu            if (pf.size() == size) {
2586378Sgblack@eecs.umich.edu                pfRemovedFull++;
2596378Sgblack@eecs.umich.edu                PacketPtr old_pkt = *pf.begin();
2606378Sgblack@eecs.umich.edu                DPRINTF(HWPrefetch, "Prefetch queue full, "
2616379Sgblack@eecs.umich.edu                        "removing oldest 0x%x\n", old_pkt->getAddr());
2626378Sgblack@eecs.umich.edu                delete old_pkt->req;
2636378Sgblack@eecs.umich.edu                delete old_pkt;
2646378Sgblack@eecs.umich.edu                pf.pop_front();
2656378Sgblack@eecs.umich.edu            }
2666378Sgblack@eecs.umich.edu
2676378Sgblack@eecs.umich.edu            pf.push_back(prefetch);
2686378Sgblack@eecs.umich.edu        }
2696378Sgblack@eecs.umich.edu    }
2706378Sgblack@eecs.umich.edu
2716378Sgblack@eecs.umich.edu    return pf.empty() ? 0 : pf.front()->time;
2726378Sgblack@eecs.umich.edu}
2736379Sgblack@eecs.umich.edu
2746378Sgblack@eecs.umich.edustd::list<PacketPtr>::iterator
2756378Sgblack@eecs.umich.eduBasePrefetcher::inPrefetch(Addr address)
2766378Sgblack@eecs.umich.edu{
2776378Sgblack@eecs.umich.edu    // Guaranteed to only be one match, we always check before inserting
2786378Sgblack@eecs.umich.edu    std::list<PacketPtr>::iterator iter;
2796378Sgblack@eecs.umich.edu    for (iter = pf.begin(); iter != pf.end(); iter++) {
2806378Sgblack@eecs.umich.edu        if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) {
2816378Sgblack@eecs.umich.edu            return iter;
2826379Sgblack@eecs.umich.edu        }
2836379Sgblack@eecs.umich.edu    }
2846379Sgblack@eecs.umich.edu    return pf.end();
2856379Sgblack@eecs.umich.edu}
2866379Sgblack@eecs.umich.edu
2876379Sgblack@eecs.umich.edubool
2886379Sgblack@eecs.umich.eduBasePrefetcher::samePage(Addr a, Addr b)
2896379Sgblack@eecs.umich.edu{
2906379Sgblack@eecs.umich.edu    return roundDown(a, TheISA::VMPageSize) == roundDown(b, TheISA::VMPageSize);
2916379Sgblack@eecs.umich.edu}
2926378Sgblack@eecs.umich.edu