base.cc revision 3013
12810SN/A/*
210623Smitch.hayenga@arm.com * Copyright (c) 2005 The Regents of The University of Michigan
39546Sandreas.hansson@arm.com * All rights reserved.
49546Sandreas.hansson@arm.com *
59546Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
69546Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
79546Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
89546Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
99546Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
109546Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
119546Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
129546Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
139546Sandreas.hansson@arm.com * 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"
372810SN/A#include "mem/cache/base_cache.hh"
382810SN/A#include "mem/cache/prefetch/base_prefetcher.hh"
392810SN/A#include "mem/request.hh"
402810SN/A#include <list>
4110623Smitch.hayenga@arm.com
422810SN/ABasePrefetcher::BasePrefetcher(int size, bool pageStop, bool serialSquash,
432810SN/A                               bool cacheCheckPush, bool onlyData)
442810SN/A    :size(size), pageStop(pageStop), serialSquash(serialSquash),
452810SN/A     cacheCheckPush(cacheCheckPush), only_data(onlyData)
462810SN/A{
472810SN/A}
482810SN/A
4911793Sbrandon.potter@amd.comvoid
5011793Sbrandon.potter@amd.comBasePrefetcher::setCache(BaseCache *_cache)
5112727Snikos.nikoleris@arm.com{
526658Snate@binkert.org    cache = _cache;
5311438SRekai.GonzalezAlberquilla@arm.com    blkSize = cache->getBlockSize();
5413416Sjavier.bueno@metempsy.com}
555338Sstever@gmail.com
5612727Snikos.nikoleris@arm.comvoid
578832SAli.Saidi@ARM.comBasePrefetcher::regStats(const std::string &name)
582810SN/A{
5913416Sjavier.bueno@metempsy.com    pfIdentified
6013416Sjavier.bueno@metempsy.com        .name(name + ".prefetcher.num_hwpf_identified")
6113416Sjavier.bueno@metempsy.com        .desc("number of hwpf identified")
6213416Sjavier.bueno@metempsy.com        ;
6313416Sjavier.bueno@metempsy.com
6413416Sjavier.bueno@metempsy.com    pfMSHRHit
6510623Smitch.hayenga@arm.com        .name(name + ".prefetcher.num_hwpf_already_in_mshr")
6613416Sjavier.bueno@metempsy.com        .desc("number of hwpf that were already in mshr")
6711438SRekai.GonzalezAlberquilla@arm.com        ;
6810623Smitch.hayenga@arm.com
6912680Sgiacomo.travaglini@arm.com    pfCacheHit
7013416Sjavier.bueno@metempsy.com        .name(name + ".prefetcher.num_hwpf_already_in_cache")
7113416Sjavier.bueno@metempsy.com        .desc("number of hwpf that were already in the cache")
722810SN/A        ;
732810SN/A
742810SN/A    pfBufferHit
752810SN/A        .name(name + ".prefetcher.num_hwpf_already_in_prefetcher")
762810SN/A        .desc("number of hwpf that were already in the prefetch queue")
772810SN/A        ;
7810360Sandreas.hansson@arm.com
792810SN/A    pfRemovedFull
802810SN/A        .name(name + ".prefetcher.num_hwpf_evicted")
8111438SRekai.GonzalezAlberquilla@arm.com        .desc("number of hwpf removed due to no buffer left")
822810SN/A        ;
832810SN/A
842810SN/A    pfRemovedMSHR
858831Smrinmoy.ghosh@arm.com        .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit")
862810SN/A        .desc("number of hwpf removed because MSHR allocated")
8711522Sstephan.diestelhorst@arm.com        ;
8811522Sstephan.diestelhorst@arm.com
892810SN/A    pfIssued
9010623Smitch.hayenga@arm.com        .name(name + ".prefetcher.num_hwpf_issued")
912810SN/A        .desc("number of hwpf issued")
922810SN/A        ;
9311438SRekai.GonzalezAlberquilla@arm.com
942810SN/A    pfSpanPage
952810SN/A        .name(name + ".prefetcher.num_hwpf_span_page")
9610623Smitch.hayenga@arm.com        .desc("number of hwpf spanning a virtual page")
9710623Smitch.hayenga@arm.com        ;
9810623Smitch.hayenga@arm.com
9910623Smitch.hayenga@arm.com    pfSquashed
10010623Smitch.hayenga@arm.com        .name(name + ".prefetcher.num_hwpf_squashed_from_miss")
10110626SCurtis.Dunham@arm.com        .desc("number of hwpf that got squashed due to a miss aborting calculation time")
10210626SCurtis.Dunham@arm.com        ;
10310623Smitch.hayenga@arm.com}
10410623Smitch.hayenga@arm.com
10510623Smitch.hayenga@arm.comPacket *
10610623Smitch.hayenga@arm.comBasePrefetcher::getPacket()
10710623Smitch.hayenga@arm.com{
10810623Smitch.hayenga@arm.com    DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name());
10910623Smitch.hayenga@arm.com
11010626SCurtis.Dunham@arm.com    if (pf.empty()) {
11110883Sali.jafri@arm.com        DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name());
11210623Smitch.hayenga@arm.com        return NULL;
11310623Smitch.hayenga@arm.com    }
11410623Smitch.hayenga@arm.com
11510623Smitch.hayenga@arm.com    Packet * pkt;
11610623Smitch.hayenga@arm.com    bool keepTrying = false;
11710623Smitch.hayenga@arm.com    do {
11810623Smitch.hayenga@arm.com        pkt = *pf.begin();
11910623Smitch.hayenga@arm.com        pf.pop_front();
12010623Smitch.hayenga@arm.com        if (!cacheCheckPush) {
12110623Smitch.hayenga@arm.com            keepTrying = inCache(pkt);
12210623Smitch.hayenga@arm.com        }
1233861SN/A        if (pf.empty()) {
12410028SGiacomo.Gabrielli@arm.com            cache->clearMasterRequest(Request_PF);
1253861SN/A            if (keepTrying) return NULL; //None left, all were in cache
1263861SN/A        }
1273861SN/A    } while (keepTrying);
1283861SN/A
1293861SN/A    pfIssued++;
13010623Smitch.hayenga@arm.com    return pkt;
13110623Smitch.hayenga@arm.com}
1323861SN/A
13310028SGiacomo.Gabrielli@arm.comvoid
1343861SN/ABasePrefetcher::handleMiss(Packet * &pkt, Tick time)
1353861SN/A{
1363861SN/A    if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && only_data))
1373861SN/A    {
1383861SN/A        //Calculate the blk address
1395875Ssteve.reinhardt@amd.com        Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1);
14010466Sandreas.hansson@arm.com
1415875Ssteve.reinhardt@amd.com        //Check if miss is in pfq, if so remove it
14210466Sandreas.hansson@arm.com        std::list<Packet *>::iterator iter = inPrefetch(blkAddr);
1435875Ssteve.reinhardt@amd.com        if (iter != pf.end()) {
1448831Smrinmoy.ghosh@arm.com            DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name());
14511438SRekai.GonzalezAlberquilla@arm.com            pfRemovedMSHR++;
14611438SRekai.GonzalezAlberquilla@arm.com            pf.erase(iter);
14711438SRekai.GonzalezAlberquilla@arm.com            if (pf.empty())
14811438SRekai.GonzalezAlberquilla@arm.com                cache->clearMasterRequest(Request_PF);
14911438SRekai.GonzalezAlberquilla@arm.com        }
1508831Smrinmoy.ghosh@arm.com
15111438SRekai.GonzalezAlberquilla@arm.com        //Remove anything in queue with delay older than time
15211438SRekai.GonzalezAlberquilla@arm.com        //since everything is inserted in time order, start from end
15311438SRekai.GonzalezAlberquilla@arm.com        //and work until pf.empty() or time is earlier
15411438SRekai.GonzalezAlberquilla@arm.com        //This is done to emulate Aborting the previous work on a new miss
15511438SRekai.GonzalezAlberquilla@arm.com        //Needed for serial calculators like GHB
15611438SRekai.GonzalezAlberquilla@arm.com        if (serialSquash) {
15711438SRekai.GonzalezAlberquilla@arm.com            iter = pf.end();
15811438SRekai.GonzalezAlberquilla@arm.com            iter--;
15911438SRekai.GonzalezAlberquilla@arm.com            while (!pf.empty() && ((*iter)->time >= time)) {
16011438SRekai.GonzalezAlberquilla@arm.com                pfSquashed++;
16111438SRekai.GonzalezAlberquilla@arm.com                pf.pop_back();
16211438SRekai.GonzalezAlberquilla@arm.com                iter--;
16311438SRekai.GonzalezAlberquilla@arm.com            }
16411438SRekai.GonzalezAlberquilla@arm.com            if (pf.empty())
16511438SRekai.GonzalezAlberquilla@arm.com                cache->clearMasterRequest(Request_PF);
16611438SRekai.GonzalezAlberquilla@arm.com        }
16711438SRekai.GonzalezAlberquilla@arm.com
16811438SRekai.GonzalezAlberquilla@arm.com
16911438SRekai.GonzalezAlberquilla@arm.com        std::list<Addr> addresses;
17011438SRekai.GonzalezAlberquilla@arm.com        std::list<Tick> delays;
17111438SRekai.GonzalezAlberquilla@arm.com        calculatePrefetch(pkt, addresses, delays);
17211438SRekai.GonzalezAlberquilla@arm.com
17311438SRekai.GonzalezAlberquilla@arm.com        std::list<Addr>::iterator addr = addresses.begin();
17413416Sjavier.bueno@metempsy.com        std::list<Tick>::iterator delay = delays.begin();
17513416Sjavier.bueno@metempsy.com        while (addr != addresses.end())
17613416Sjavier.bueno@metempsy.com        {
17713416Sjavier.bueno@metempsy.com            DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name());
17813416Sjavier.bueno@metempsy.com            //temp calc this here...
17913416Sjavier.bueno@metempsy.com            pfIdentified++;
18013416Sjavier.bueno@metempsy.com            //create a prefetch memreq
18113416Sjavier.bueno@metempsy.com            Request * prefetchReq = new Request(*addr, blkSize, 0);
18213416Sjavier.bueno@metempsy.com            Packet * prefetch;
18313416Sjavier.bueno@metempsy.com            prefetch = new Packet(prefetchReq, Packet::HardPFReq, -1);
18413416Sjavier.bueno@metempsy.com            prefetch->allocate();
18513416Sjavier.bueno@metempsy.com            prefetch->req->setThreadContext(pkt->req->getCpuNum(),
18613416Sjavier.bueno@metempsy.com                                            pkt->req->getThreadNum());
18713416Sjavier.bueno@metempsy.com
18813416Sjavier.bueno@metempsy.com            prefetch->time = time + (*delay); //@todo ADD LATENCY HERE
18913416Sjavier.bueno@metempsy.com            //... initialize
19013416Sjavier.bueno@metempsy.com
19113416Sjavier.bueno@metempsy.com            //Check if it is already in the cache
19213416Sjavier.bueno@metempsy.com            if (cacheCheckPush) {
19313416Sjavier.bueno@metempsy.com                if (inCache(prefetch)) {
19413416Sjavier.bueno@metempsy.com                    addr++;
19513416Sjavier.bueno@metempsy.com                    delay++;
19613416Sjavier.bueno@metempsy.com                    continue;
19713416Sjavier.bueno@metempsy.com                }
19813416Sjavier.bueno@metempsy.com            }
19913416Sjavier.bueno@metempsy.com
20013416Sjavier.bueno@metempsy.com            //Check if it is already in the miss_queue
20113416Sjavier.bueno@metempsy.com            if (inMissQueue(prefetch->getAddr())) {
20213416Sjavier.bueno@metempsy.com                addr++;
20313416Sjavier.bueno@metempsy.com                delay++;
20413416Sjavier.bueno@metempsy.com                continue;
20513416Sjavier.bueno@metempsy.com            }
20613416Sjavier.bueno@metempsy.com
20713416Sjavier.bueno@metempsy.com            //Check if it is already in the pf buffer
20813416Sjavier.bueno@metempsy.com            if (inPrefetch(prefetch->getAddr()) != pf.end()) {
209                pfBufferHit++;
210                addr++;
211                delay++;
212                continue;
213            }
214
215            //We just remove the head if we are full
216            if (pf.size() == size)
217            {
218                DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name());
219                pfRemovedFull++;
220                pf.pop_front();
221            }
222
223            pf.push_back(prefetch);
224            prefetch->flags |= CACHE_LINE_FILL;
225
226            //Make sure to request the bus, with proper delay
227            cache->setMasterRequest(Request_PF, prefetch->time);
228
229            //Increment through the list
230            addr++;
231            delay++;
232        }
233    }
234}
235
236std::list<Packet *>::iterator
237BasePrefetcher::inPrefetch(Addr address)
238{
239    //Guaranteed to only be one match, we always check before inserting
240    std::list<Packet *>::iterator iter;
241    for (iter=pf.begin(); iter != pf.end(); iter++) {
242        if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) {
243            return iter;
244        }
245    }
246    return pf.end();
247}
248
249
250