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