base.cc revision 4022
12155SN/A/*
22155SN/A * Copyright (c) 2005 The Regents of The University of Michigan
32155SN/A * All rights reserved.
42155SN/A *
52155SN/A * Redistribution and use in source and binary forms, with or without
62155SN/A * modification, are permitted provided that the following conditions are
72155SN/A * met: redistributions of source code must retain the above copyright
82155SN/A * notice, this list of conditions and the following disclaimer;
92155SN/A * redistributions in binary form must reproduce the above copyright
102155SN/A * notice, this list of conditions and the following disclaimer in the
112155SN/A * documentation and/or other materials provided with the distribution;
122155SN/A * neither the name of the copyright holders nor the names of its
132155SN/A * contributors may be used to endorse or promote products derived from
142155SN/A * this software without specific prior written permission.
152155SN/A *
162155SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172155SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182155SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192155SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202155SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212155SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222155SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232155SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242155SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252155SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262155SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272155SN/A *
282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski
292665Ssaidi@eecs.umich.edu */
302155SN/A
314202Sbinkertn@umich.edu/**
322155SN/A * @file
339850Sandreas.hansson@arm.com * Hardware Prefetcher Definition.
349850Sandreas.hansson@arm.com */
359850Sandreas.hansson@arm.com
367768SAli.Saidi@ARM.com#include "base/trace.hh"
377768SAli.Saidi@ARM.com#include "mem/cache/base_cache.hh"
382178SN/A#include "mem/cache/prefetch/base_prefetcher.hh"
392178SN/A#include "mem/request.hh"
402178SN/A#include <list>
412178SN/A
422178SN/ABasePrefetcher::BasePrefetcher(int size, bool pageStop, bool serialSquash,
432178SN/A                               bool cacheCheckPush, bool onlyData)
442178SN/A    :size(size), pageStop(pageStop), serialSquash(serialSquash),
452178SN/A     cacheCheckPush(cacheCheckPush), only_data(onlyData)
462178SN/A{
472178SN/A}
482178SN/A
492155SN/Avoid
505865Sksewell@umich.eduBasePrefetcher::setCache(BaseCache *_cache)
516181Sksewell@umich.edu{
526181Sksewell@umich.edu    cache = _cache;
535865Sksewell@umich.edu    blkSize = cache->getBlockSize();
543918Ssaidi@eecs.umich.edu}
555865Sksewell@umich.edu
562623SN/Avoid
573918Ssaidi@eecs.umich.eduBasePrefetcher::regStats(const std::string &name)
582155SN/A{
592155SN/A    pfIdentified
602292SN/A        .name(name + ".prefetcher.num_hwpf_identified")
616181Sksewell@umich.edu        .desc("number of hwpf identified")
626181Sksewell@umich.edu        ;
633918Ssaidi@eecs.umich.edu
642292SN/A    pfMSHRHit
652292SN/A        .name(name + ".prefetcher.num_hwpf_already_in_mshr")
662292SN/A        .desc("number of hwpf that were already in mshr")
673918Ssaidi@eecs.umich.edu        ;
682292SN/A
692292SN/A    pfCacheHit
702766Sktlim@umich.edu        .name(name + ".prefetcher.num_hwpf_already_in_cache")
712766Sktlim@umich.edu        .desc("number of hwpf that were already in the cache")
722766Sktlim@umich.edu        ;
732921Sktlim@umich.edu
748887Sgeoffrey.blake@arm.com    pfBufferHit
758887Sgeoffrey.blake@arm.com        .name(name + ".prefetcher.num_hwpf_already_in_prefetcher")
762766Sktlim@umich.edu        .desc("number of hwpf that were already in the prefetch queue")
774762Snate@binkert.org        ;
782155SN/A
792155SN/A    pfRemovedFull
802155SN/A        .name(name + ".prefetcher.num_hwpf_evicted")
812155SN/A        .desc("number of hwpf removed due to no buffer left")
822155SN/A        ;
832155SN/A
842766Sktlim@umich.edu    pfRemovedMSHR
852155SN/A        .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit")
865865Sksewell@umich.edu        .desc("number of hwpf removed because MSHR allocated")
872155SN/A        ;
882155SN/A
892155SN/A    pfIssued
902155SN/A        .name(name + ".prefetcher.num_hwpf_issued")
912178SN/A        .desc("number of hwpf issued")
922178SN/A        ;
937756SAli.Saidi@ARM.com
942766Sktlim@umich.edu    pfSpanPage
952178SN/A        .name(name + ".prefetcher.num_hwpf_span_page")
962178SN/A        .desc("number of hwpf spanning a virtual page")
976994Snate@binkert.org        ;
982178SN/A
992766Sktlim@umich.edu    pfSquashed
1002766Sktlim@umich.edu        .name(name + ".prefetcher.num_hwpf_squashed_from_miss")
1012788Sktlim@umich.edu        .desc("number of hwpf that got squashed due to a miss aborting calculation time")
1022178SN/A        ;
1034486Sbinkertn@umich.edu}
1044486Sbinkertn@umich.edu
1054776Sgblack@eecs.umich.eduinline bool
1064776Sgblack@eecs.umich.eduBasePrefetcher::inCache(Addr addr)
1078739Sgblack@eecs.umich.edu{
1086365Sgblack@eecs.umich.edu    if (cache->inCache(addr)) {
1094486Sbinkertn@umich.edu        pfCacheHit++;
1104202Sbinkertn@umich.edu        return true;
1114202Sbinkertn@umich.edu    }
1124202Sbinkertn@umich.edu    return false;
1134202Sbinkertn@umich.edu}
1144202Sbinkertn@umich.edu
1154776Sgblack@eecs.umich.eduinline bool
1168739Sgblack@eecs.umich.eduBasePrefetcher::inMissQueue(Addr addr)
1176365Sgblack@eecs.umich.edu{
1184202Sbinkertn@umich.edu    if (cache->inMissQueue(addr)) {
1198777Sgblack@eecs.umich.edu        pfMSHRHit++;
1204202Sbinkertn@umich.edu        return true;
1219913Ssteve.reinhardt@amd.com    }
1224202Sbinkertn@umich.edu    return false;
1234202Sbinkertn@umich.edu}
1245217Ssaidi@eecs.umich.edu
1254202Sbinkertn@umich.eduPacketPtr
1262155SN/ABasePrefetcher::getPacket()
1278793Sgblack@eecs.umich.edu{
1288793Sgblack@eecs.umich.edu    DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name());
1298793Sgblack@eecs.umich.edu
1304776Sgblack@eecs.umich.edu    if (pf.empty()) {
1318887Sgeoffrey.blake@arm.com        DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name());
13210201SAndrew.Bardsley@arm.com        return NULL;
1338887Sgeoffrey.blake@arm.com    }
1349340SAndreas.Sandberg@arm.com
1358887Sgeoffrey.blake@arm.com    PacketPtr pkt;
1365192Ssaidi@eecs.umich.edu    bool keepTrying = false;
1378335Snate@binkert.org    do {
1388335Snate@binkert.org        pkt = *pf.begin();
1398335Snate@binkert.org        pf.pop_front();
1408335Snate@binkert.org        if (!cacheCheckPush) {
1418335Snate@binkert.org            keepTrying = cache->inCache(pkt->getAddr());
1429534SAndreas.Sandberg@ARM.com        }
1439534SAndreas.Sandberg@ARM.com        if (pf.empty()) {
1449534SAndreas.Sandberg@ARM.com            cache->clearMasterRequest(Request_PF);
1458335Snate@binkert.org            if (keepTrying) return NULL; //None left, all were in cache
1469534SAndreas.Sandberg@ARM.com        }
1479534SAndreas.Sandberg@ARM.com    } while (keepTrying);
1488335Snate@binkert.org
1499534SAndreas.Sandberg@ARM.com    pfIssued++;
1509534SAndreas.Sandberg@ARM.com    return pkt;
1519534SAndreas.Sandberg@ARM.com}
1529534SAndreas.Sandberg@ARM.com
1539534SAndreas.Sandberg@ARM.comvoid
1549534SAndreas.Sandberg@ARM.comBasePrefetcher::handleMiss(PacketPtr &pkt, Tick time)
1559534SAndreas.Sandberg@ARM.com{
1569534SAndreas.Sandberg@ARM.com    if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && only_data))
1579534SAndreas.Sandberg@ARM.com    {
1589534SAndreas.Sandberg@ARM.com        //Calculate the blk address
1598335Snate@binkert.org        Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1);
1608335Snate@binkert.org
1618471SGiacomo.Gabrielli@arm.com        //Check if miss is in pfq, if so remove it
1628335Snate@binkert.org        std::list<PacketPtr>::iterator iter = inPrefetch(blkAddr);
1638335Snate@binkert.org        if (iter != pf.end()) {
1645192Ssaidi@eecs.umich.edu            DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name());
1658232Snate@binkert.org            pfRemovedMSHR++;
1668232Snate@binkert.org            pf.erase(iter);
1678232Snate@binkert.org            if (pf.empty())
1688300Schander.sudanthi@arm.com                cache->clearMasterRequest(Request_PF);
1698300Schander.sudanthi@arm.com        }
1705192Ssaidi@eecs.umich.edu
1718300Schander.sudanthi@arm.com        //Remove anything in queue with delay older than time
1728300Schander.sudanthi@arm.com        //since everything is inserted in time order, start from end
1736036Sksewell@umich.edu        //and work until pf.empty() or time is earlier
1748300Schander.sudanthi@arm.com        //This is done to emulate Aborting the previous work on a new miss
1758300Schander.sudanthi@arm.com        //Needed for serial calculators like GHB
176        if (serialSquash) {
177            iter = pf.end();
178            iter--;
179            while (!pf.empty() && ((*iter)->time >= time)) {
180                pfSquashed++;
181                pf.pop_back();
182                iter--;
183            }
184            if (pf.empty())
185                cache->clearMasterRequest(Request_PF);
186        }
187
188
189        std::list<Addr> addresses;
190        std::list<Tick> delays;
191        calculatePrefetch(pkt, addresses, delays);
192
193        std::list<Addr>::iterator addr = addresses.begin();
194        std::list<Tick>::iterator delay = delays.begin();
195        while (addr != addresses.end())
196        {
197            DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name());
198            //temp calc this here...
199            pfIdentified++;
200            //create a prefetch memreq
201            Request * prefetchReq = new Request(*addr, blkSize, 0);
202            PacketPtr prefetch;
203            prefetch = new Packet(prefetchReq, MemCmd::HardPFReq, -1);
204            prefetch->allocate();
205            prefetch->req->setThreadContext(pkt->req->getCpuNum(),
206                                            pkt->req->getThreadNum());
207
208            prefetch->time = time + (*delay); //@todo ADD LATENCY HERE
209            //... initialize
210
211            //Check if it is already in the cache
212            if (cacheCheckPush) {
213                if (cache->inCache(prefetch->getAddr())) {
214                    addr++;
215                    delay++;
216                    continue;
217                }
218            }
219
220            //Check if it is already in the miss_queue
221            if (cache->inMissQueue(prefetch->getAddr())) {
222                addr++;
223                delay++;
224                continue;
225            }
226
227            //Check if it is already in the pf buffer
228            if (inPrefetch(prefetch->getAddr()) != pf.end()) {
229                pfBufferHit++;
230                addr++;
231                delay++;
232                continue;
233            }
234
235            //We just remove the head if we are full
236            if (pf.size() == size)
237            {
238                DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name());
239                pfRemovedFull++;
240                pf.pop_front();
241            }
242
243            pf.push_back(prefetch);
244            prefetch->flags |= CACHE_LINE_FILL;
245
246            //Make sure to request the bus, with proper delay
247            cache->setMasterRequest(Request_PF, prefetch->time);
248
249            //Increment through the list
250            addr++;
251            delay++;
252        }
253    }
254}
255
256std::list<PacketPtr>::iterator
257BasePrefetcher::inPrefetch(Addr address)
258{
259    //Guaranteed to only be one match, we always check before inserting
260    std::list<PacketPtr>::iterator iter;
261    for (iter=pf.begin(); iter != pf.end(); iter++) {
262        if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) {
263            return iter;
264        }
265    }
266    return pf.end();
267}
268
269
270