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