base.cc revision 8922
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 <list>
372810SN/A
382810SN/A#include "arch/isa_traits.hh"
392810SN/A#include "base/trace.hh"
402810SN/A#include "config/the_isa.hh"
4110623Smitch.hayenga@arm.com#include "debug/HWPrefetch.hh"
422810SN/A#include "mem/cache/prefetch/base.hh"
432810SN/A#include "mem/cache/base.hh"
442810SN/A#include "mem/request.hh"
452810SN/A#include "sim/system.hh"
462810SN/A
472810SN/ABasePrefetcher::BasePrefetcher(const Params *p)
482810SN/A    : SimObject(p), size(p->size), latency(p->latency), degree(p->degree),
4911793Sbrandon.potter@amd.com      useMasterId(p->use_master_id), pageStop(!p->cross_pages),
5011793Sbrandon.potter@amd.com      serialSquash(p->serial_squash), onlyData(p->data_accesses_only),
5112727Snikos.nikoleris@arm.com      system(p->sys), masterId(system->getMasterId(name()))
526658Snate@binkert.org{
5311438SRekai.GonzalezAlberquilla@arm.com}
545338Sstever@gmail.com
5512727Snikos.nikoleris@arm.comvoid
568832SAli.Saidi@ARM.comBasePrefetcher::setCache(BaseCache *_cache)
572810SN/A{
5810623Smitch.hayenga@arm.com    cache = _cache;
5911438SRekai.GonzalezAlberquilla@arm.com    blkSize = cache->getBlockSize();
6011438SRekai.GonzalezAlberquilla@arm.com}
6110623Smitch.hayenga@arm.com
6212680Sgiacomo.travaglini@arm.comvoid
6310466Sandreas.hansson@arm.comBasePrefetcher::regStats()
642810SN/A{
652810SN/A    pfIdentified
662810SN/A        .name(name() + ".prefetcher.num_hwpf_identified")
672810SN/A        .desc("number of hwpf identified")
682810SN/A        ;
692810SN/A
7010360Sandreas.hansson@arm.com    pfMSHRHit
712810SN/A        .name(name() + ".prefetcher.num_hwpf_already_in_mshr")
722810SN/A        .desc("number of hwpf that were already in mshr")
7311438SRekai.GonzalezAlberquilla@arm.com        ;
742810SN/A
752810SN/A    pfCacheHit
762810SN/A        .name(name() + ".prefetcher.num_hwpf_already_in_cache")
778831Smrinmoy.ghosh@arm.com        .desc("number of hwpf that were already in the cache")
782810SN/A        ;
7911522Sstephan.diestelhorst@arm.com
8011522Sstephan.diestelhorst@arm.com    pfBufferHit
812810SN/A        .name(name() + ".prefetcher.num_hwpf_already_in_prefetcher")
8210623Smitch.hayenga@arm.com        .desc("number of hwpf that were already in the prefetch queue")
832810SN/A        ;
842810SN/A
8511438SRekai.GonzalezAlberquilla@arm.com    pfRemovedFull
862810SN/A        .name(name() + ".prefetcher.num_hwpf_evicted")
872810SN/A        .desc("number of hwpf removed due to no buffer left")
8810623Smitch.hayenga@arm.com        ;
8910623Smitch.hayenga@arm.com
9010623Smitch.hayenga@arm.com    pfRemovedMSHR
9110623Smitch.hayenga@arm.com        .name(name() + ".prefetcher.num_hwpf_removed_MSHR_hit")
9210623Smitch.hayenga@arm.com        .desc("number of hwpf removed because MSHR allocated")
9310626SCurtis.Dunham@arm.com        ;
9410626SCurtis.Dunham@arm.com
9510623Smitch.hayenga@arm.com    pfIssued
9610623Smitch.hayenga@arm.com        .name(name() + ".prefetcher.num_hwpf_issued")
9710623Smitch.hayenga@arm.com        .desc("number of hwpf issued")
9810623Smitch.hayenga@arm.com        ;
9910623Smitch.hayenga@arm.com
10010623Smitch.hayenga@arm.com    pfSpanPage
10110623Smitch.hayenga@arm.com        .name(name() + ".prefetcher.num_hwpf_span_page")
10210626SCurtis.Dunham@arm.com        .desc("number of hwpf spanning a virtual page")
10310883Sali.jafri@arm.com        ;
10410623Smitch.hayenga@arm.com
10510623Smitch.hayenga@arm.com    pfSquashed
10610623Smitch.hayenga@arm.com        .name(name() + ".prefetcher.num_hwpf_squashed_from_miss")
10710623Smitch.hayenga@arm.com        .desc("number of hwpf that got squashed due to a miss "
10810623Smitch.hayenga@arm.com              "aborting calculation time")
10910623Smitch.hayenga@arm.com        ;
11010623Smitch.hayenga@arm.com}
11110623Smitch.hayenga@arm.com
11210623Smitch.hayenga@arm.cominline bool
11310623Smitch.hayenga@arm.comBasePrefetcher::inCache(Addr addr)
11410623Smitch.hayenga@arm.com{
1153861SN/A    if (cache->inCache(addr)) {
11610028SGiacomo.Gabrielli@arm.com        pfCacheHit++;
1173861SN/A        return true;
1183861SN/A    }
1193861SN/A    return false;
1203861SN/A}
1213861SN/A
12210623Smitch.hayenga@arm.cominline bool
12310623Smitch.hayenga@arm.comBasePrefetcher::inMissQueue(Addr addr)
1243861SN/A{
12510028SGiacomo.Gabrielli@arm.com    if (cache->inMissQueue(addr)) {
1263861SN/A        pfMSHRHit++;
1273861SN/A        return true;
1283861SN/A    }
1293861SN/A    return false;
1303861SN/A}
1315875Ssteve.reinhardt@amd.com
13210466Sandreas.hansson@arm.comPacketPtr
1335875Ssteve.reinhardt@amd.comBasePrefetcher::getPacket()
13410466Sandreas.hansson@arm.com{
1355875Ssteve.reinhardt@amd.com    DPRINTF(HWPrefetch, "Requesting a hw_pf to issue\n");
1368831Smrinmoy.ghosh@arm.com
13711438SRekai.GonzalezAlberquilla@arm.com    if (pf.empty()) {
13811438SRekai.GonzalezAlberquilla@arm.com        DPRINTF(HWPrefetch, "No HW_PF found\n");
13911438SRekai.GonzalezAlberquilla@arm.com        return NULL;
14011438SRekai.GonzalezAlberquilla@arm.com    }
14111438SRekai.GonzalezAlberquilla@arm.com
1428831Smrinmoy.ghosh@arm.com    PacketPtr pkt = *pf.begin();
14311438SRekai.GonzalezAlberquilla@arm.com    while (!pf.empty()) {
14411438SRekai.GonzalezAlberquilla@arm.com        pkt = *pf.begin();
14511438SRekai.GonzalezAlberquilla@arm.com        pf.pop_front();
14611438SRekai.GonzalezAlberquilla@arm.com
14711438SRekai.GonzalezAlberquilla@arm.com        Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1);
14811438SRekai.GonzalezAlberquilla@arm.com
14911438SRekai.GonzalezAlberquilla@arm.com        if (!inCache(blk_addr) && !inMissQueue(blk_addr))
15011438SRekai.GonzalezAlberquilla@arm.com            // we found a prefetch, return it
15111438SRekai.GonzalezAlberquilla@arm.com            break;
15211438SRekai.GonzalezAlberquilla@arm.com
15311438SRekai.GonzalezAlberquilla@arm.com        DPRINTF(HWPrefetch, "addr 0x%x in cache, skipping\n", pkt->getAddr());
15411438SRekai.GonzalezAlberquilla@arm.com        delete pkt->req;
15511438SRekai.GonzalezAlberquilla@arm.com        delete pkt;
15611438SRekai.GonzalezAlberquilla@arm.com
15711438SRekai.GonzalezAlberquilla@arm.com        if (pf.empty()) {
15811438SRekai.GonzalezAlberquilla@arm.com            cache->deassertMemSideBusRequest(BaseCache::Request_PF);
15911438SRekai.GonzalezAlberquilla@arm.com            return NULL; // None left, all were in cache
16011438SRekai.GonzalezAlberquilla@arm.com        }
16111438SRekai.GonzalezAlberquilla@arm.com    }
16211438SRekai.GonzalezAlberquilla@arm.com
16311438SRekai.GonzalezAlberquilla@arm.com    pfIssued++;
16411438SRekai.GonzalezAlberquilla@arm.com    assert(pkt != NULL);
16511438SRekai.GonzalezAlberquilla@arm.com    DPRINTF(HWPrefetch, "returning 0x%x\n", pkt->getAddr());
166    return pkt;
167}
168
169
170Tick
171BasePrefetcher::notify(PacketPtr &pkt, Tick time)
172{
173    if (!pkt->req->isUncacheable() && !(pkt->req->isInstFetch() && onlyData)) {
174        // Calculate the blk address
175        Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1);
176
177        // Check if miss is in pfq, if so remove it
178        std::list<PacketPtr>::iterator iter = inPrefetch(blk_addr);
179        if (iter != pf.end()) {
180            DPRINTF(HWPrefetch, "Saw a miss to a queued prefetch addr: "
181                    "0x%x, removing it\n", blk_addr);
182            pfRemovedMSHR++;
183            delete (*iter)->req;
184            delete (*iter);
185            pf.erase(iter);
186            if (pf.empty())
187                cache->deassertMemSideBusRequest(BaseCache::Request_PF);
188        }
189
190        // Remove anything in queue with delay older than time
191        // since everything is inserted in time order, start from end
192        // and work until pf.empty() or time is earlier
193        // This is done to emulate Aborting the previous work on a new miss
194        // Needed for serial calculators like GHB
195        if (serialSquash) {
196            iter = pf.end();
197            iter--;
198            while (!pf.empty() && ((*iter)->time >= time)) {
199                pfSquashed++;
200                DPRINTF(HWPrefetch, "Squashing old prefetch addr: 0x%x\n",
201                        (*iter)->getAddr());
202                delete (*iter)->req;
203                delete (*iter);
204                pf.erase(iter);
205                iter--;
206            }
207            if (pf.empty())
208                cache->deassertMemSideBusRequest(BaseCache::Request_PF);
209        }
210
211
212        std::list<Addr> addresses;
213        std::list<Tick> delays;
214        calculatePrefetch(pkt, addresses, delays);
215
216        std::list<Addr>::iterator addrIter = addresses.begin();
217        std::list<Tick>::iterator delayIter = delays.begin();
218        for (; addrIter != addresses.end(); ++addrIter, ++delayIter) {
219            Addr addr = *addrIter;
220
221            pfIdentified++;
222
223            DPRINTF(HWPrefetch, "Found a pf candidate addr: 0x%x, "
224                    "inserting into prefetch queue with delay %d time %d\n",
225                    addr, *delayIter, time);
226
227            // Check if it is already in the pf buffer
228            if (inPrefetch(addr) != pf.end()) {
229                pfBufferHit++;
230                DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n");
231                continue;
232            }
233
234            // create a prefetch memreq
235            Request *prefetchReq = new Request(*addrIter, blkSize, 0, masterId);
236            PacketPtr prefetch =
237                new Packet(prefetchReq, MemCmd::HardPFReq, Packet::Broadcast);
238            prefetch->allocate();
239            prefetch->req->setThreadContext(pkt->req->contextId(),
240                                            pkt->req->threadId());
241
242            prefetch->time = time + (*delayIter); // @todo ADD LATENCY HERE
243
244            // We just remove the head if we are full
245            if (pf.size() == size) {
246                pfRemovedFull++;
247                PacketPtr old_pkt = *pf.begin();
248                DPRINTF(HWPrefetch, "Prefetch queue full, "
249                        "removing oldest 0x%x\n", old_pkt->getAddr());
250                delete old_pkt->req;
251                delete old_pkt;
252                pf.pop_front();
253            }
254
255            pf.push_back(prefetch);
256        }
257    }
258
259    return pf.empty() ? 0 : pf.front()->time;
260}
261
262std::list<PacketPtr>::iterator
263BasePrefetcher::inPrefetch(Addr address)
264{
265    // Guaranteed to only be one match, we always check before inserting
266    std::list<PacketPtr>::iterator iter;
267    for (iter = pf.begin(); iter != pf.end(); iter++) {
268        if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) {
269            return iter;
270        }
271    }
272    return pf.end();
273}
274
275bool
276BasePrefetcher::samePage(Addr a, Addr b)
277{
278    return roundDown(a, TheISA::VMPageSize) == roundDown(b, TheISA::VMPageSize);
279}
280
281
282