base.cc revision 5875
17949SAli.Saidi@ARM.com/*
27949SAli.Saidi@ARM.com * Copyright (c) 2005 The Regents of The University of Michigan
37949SAli.Saidi@ARM.com * All rights reserved.
47949SAli.Saidi@ARM.com *
57949SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
67949SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
77949SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
87949SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
97949SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
107949SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
117949SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
127949SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
137949SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
147949SAli.Saidi@ARM.com * this software without specific prior written permission.
157949SAli.Saidi@ARM.com *
167949SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177949SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187949SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197949SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207949SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217949SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227949SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237949SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247949SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257949SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267949SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277949SAli.Saidi@ARM.com *
287949SAli.Saidi@ARM.com * Authors: Ron Dreslinski
297949SAli.Saidi@ARM.com */
307949SAli.Saidi@ARM.com
317949SAli.Saidi@ARM.com/**
327949SAli.Saidi@ARM.com * @file
337949SAli.Saidi@ARM.com * Hardware Prefetcher Definition.
347949SAli.Saidi@ARM.com */
357949SAli.Saidi@ARM.com
367949SAli.Saidi@ARM.com#include "arch/isa_traits.hh"
377949SAli.Saidi@ARM.com#include "base/trace.hh"
387949SAli.Saidi@ARM.com#include "mem/cache/base.hh"
397949SAli.Saidi@ARM.com#include "mem/cache/prefetch/base.hh"
407949SAli.Saidi@ARM.com#include "mem/request.hh"
417949SAli.Saidi@ARM.com#include <list>
427949SAli.Saidi@ARM.com
437949SAli.Saidi@ARM.comBasePrefetcher::BasePrefetcher(const BaseCacheParams *p)
447949SAli.Saidi@ARM.com    : size(p->prefetcher_size), pageStop(!p->prefetch_past_page),
457949SAli.Saidi@ARM.com      serialSquash(p->prefetch_serial_squash),
468635Schris.emmons@arm.com      cacheCheckPush(p->prefetch_cache_check_push),
477949SAli.Saidi@ARM.com      onlyData(p->prefetch_data_accesses_only)
488635Schris.emmons@arm.com{
498635Schris.emmons@arm.com}
507949SAli.Saidi@ARM.com
517949SAli.Saidi@ARM.comvoid
527949SAli.Saidi@ARM.comBasePrefetcher::setCache(BaseCache *_cache)
538229Snate@binkert.org{
548229Snate@binkert.org    cache = _cache;
558229Snate@binkert.org    blkSize = cache->getBlockSize();
568229Snate@binkert.org    _name = cache->name() + "-pf";
577949SAli.Saidi@ARM.com}
588635Schris.emmons@arm.com
597949SAli.Saidi@ARM.comvoid
608635Schris.emmons@arm.comBasePrefetcher::regStats(const std::string &name)
617949SAli.Saidi@ARM.com{
627949SAli.Saidi@ARM.com    pfIdentified
638232Snate@binkert.org        .name(name + ".prefetcher.num_hwpf_identified")
647949SAli.Saidi@ARM.com        .desc("number of hwpf identified")
658635Schris.emmons@arm.com        ;
667949SAli.Saidi@ARM.com
677949SAli.Saidi@ARM.com    pfMSHRHit
687949SAli.Saidi@ARM.com        .name(name + ".prefetcher.num_hwpf_already_in_mshr")
699330Schander.sudanthi@arm.com        .desc("number of hwpf that were already in mshr")
709330Schander.sudanthi@arm.com        ;
719330Schander.sudanthi@arm.com
729330Schander.sudanthi@arm.com    pfCacheHit
737949SAli.Saidi@ARM.com        .name(name + ".prefetcher.num_hwpf_already_in_cache")
747949SAli.Saidi@ARM.com        .desc("number of hwpf that were already in the cache")
757949SAli.Saidi@ARM.com        ;
767949SAli.Saidi@ARM.com
777949SAli.Saidi@ARM.com    pfBufferHit
787949SAli.Saidi@ARM.com        .name(name + ".prefetcher.num_hwpf_already_in_prefetcher")
797949SAli.Saidi@ARM.com        .desc("number of hwpf that were already in the prefetch queue")
807949SAli.Saidi@ARM.com        ;
817949SAli.Saidi@ARM.com
827949SAli.Saidi@ARM.com    pfRemovedFull
837949SAli.Saidi@ARM.com        .name(name + ".prefetcher.num_hwpf_evicted")
847949SAli.Saidi@ARM.com        .desc("number of hwpf removed due to no buffer left")
857949SAli.Saidi@ARM.com        ;
867949SAli.Saidi@ARM.com
877949SAli.Saidi@ARM.com    pfRemovedMSHR
887949SAli.Saidi@ARM.com        .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit")
897949SAli.Saidi@ARM.com        .desc("number of hwpf removed because MSHR allocated")
907949SAli.Saidi@ARM.com        ;
917949SAli.Saidi@ARM.com
927949SAli.Saidi@ARM.com    pfIssued
937949SAli.Saidi@ARM.com        .name(name + ".prefetcher.num_hwpf_issued")
947949SAli.Saidi@ARM.com        .desc("number of hwpf issued")
957949SAli.Saidi@ARM.com        ;
967949SAli.Saidi@ARM.com
977949SAli.Saidi@ARM.com    pfSpanPage
987949SAli.Saidi@ARM.com        .name(name + ".prefetcher.num_hwpf_span_page")
997949SAli.Saidi@ARM.com        .desc("number of hwpf spanning a virtual page")
1007949SAli.Saidi@ARM.com        ;
1017949SAli.Saidi@ARM.com
1027949SAli.Saidi@ARM.com    pfSquashed
1037949SAli.Saidi@ARM.com        .name(name + ".prefetcher.num_hwpf_squashed_from_miss")
1047949SAli.Saidi@ARM.com        .desc("number of hwpf that got squashed due to a miss "
1057949SAli.Saidi@ARM.com              "aborting calculation time")
1067949SAli.Saidi@ARM.com        ;
1077949SAli.Saidi@ARM.com}
1089330Schander.sudanthi@arm.com
10910360Sandreas.hansson@arm.cominline bool
11010360Sandreas.hansson@arm.comBasePrefetcher::inCache(Addr addr)
1117949SAli.Saidi@ARM.com{
1127949SAli.Saidi@ARM.com    if (cache->inCache(addr)) {
1137949SAli.Saidi@ARM.com        pfCacheHit++;
1147949SAli.Saidi@ARM.com        return true;
1157949SAli.Saidi@ARM.com    }
1167949SAli.Saidi@ARM.com    return false;
1177949SAli.Saidi@ARM.com}
1187949SAli.Saidi@ARM.com
1197949SAli.Saidi@ARM.cominline bool
1207949SAli.Saidi@ARM.comBasePrefetcher::inMissQueue(Addr addr)
1217949SAli.Saidi@ARM.com{
1227949SAli.Saidi@ARM.com    if (cache->inMissQueue(addr)) {
1237949SAli.Saidi@ARM.com        pfMSHRHit++;
1247949SAli.Saidi@ARM.com        return true;
1257949SAli.Saidi@ARM.com    }
1267949SAli.Saidi@ARM.com    return false;
1277949SAli.Saidi@ARM.com}
1287949SAli.Saidi@ARM.com
1297949SAli.Saidi@ARM.comPacketPtr
1307949SAli.Saidi@ARM.comBasePrefetcher::getPacket()
1317949SAli.Saidi@ARM.com{
1327949SAli.Saidi@ARM.com    DPRINTF(HWPrefetch, "Requesting a hw_pf to issue\n");
1337949SAli.Saidi@ARM.com
1347949SAli.Saidi@ARM.com    if (pf.empty()) {
1357949SAli.Saidi@ARM.com        DPRINTF(HWPrefetch, "No HW_PF found\n");
1367949SAli.Saidi@ARM.com        return NULL;
1377949SAli.Saidi@ARM.com    }
1387949SAli.Saidi@ARM.com
1397949SAli.Saidi@ARM.com    PacketPtr pkt;
1407949SAli.Saidi@ARM.com    bool keep_trying = false;
1417949SAli.Saidi@ARM.com    do {
1427949SAli.Saidi@ARM.com        pkt = *pf.begin();
1437949SAli.Saidi@ARM.com        pf.pop_front();
1447949SAli.Saidi@ARM.com        if (!cacheCheckPush) {
1457949SAli.Saidi@ARM.com            keep_trying = cache->inCache(pkt->getAddr());
1467949SAli.Saidi@ARM.com        }
1477949SAli.Saidi@ARM.com
1487949SAli.Saidi@ARM.com        if (keep_trying) {
1497949SAli.Saidi@ARM.com            DPRINTF(HWPrefetch, "addr 0x%x in cache, skipping\n",
1507949SAli.Saidi@ARM.com                    pkt->getAddr());
1517949SAli.Saidi@ARM.com            delete pkt->req;
1527949SAli.Saidi@ARM.com            delete pkt;
1537949SAli.Saidi@ARM.com        }
1547949SAli.Saidi@ARM.com
1557949SAli.Saidi@ARM.com        if (pf.empty()) {
1567949SAli.Saidi@ARM.com            cache->deassertMemSideBusRequest(BaseCache::Request_PF);
1577949SAli.Saidi@ARM.com            if (keep_trying) {
1587949SAli.Saidi@ARM.com                return NULL; // None left, all were in cache
1597949SAli.Saidi@ARM.com            }
1607949SAli.Saidi@ARM.com        }
1617949SAli.Saidi@ARM.com    } while (keep_trying);
1627949SAli.Saidi@ARM.com
1637949SAli.Saidi@ARM.com    pfIssued++;
1647949SAli.Saidi@ARM.com    assert(pkt != NULL);
1657949SAli.Saidi@ARM.com    DPRINTF(HWPrefetch, "returning 0x%x\n", pkt->getAddr());
1667949SAli.Saidi@ARM.com    return pkt;
1677949SAli.Saidi@ARM.com}
1687949SAli.Saidi@ARM.com
1697949SAli.Saidi@ARM.com
1707949SAli.Saidi@ARM.comTick
1717949SAli.Saidi@ARM.comBasePrefetcher::notify(PacketPtr &pkt, Tick time)
1727949SAli.Saidi@ARM.com{
1737949SAli.Saidi@ARM.com    if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && onlyData)) {
1747949SAli.Saidi@ARM.com        // Calculate the blk address
1757949SAli.Saidi@ARM.com        Addr blk_addr = pkt->getAddr() & ~(Addr)(blkSize-1);
1767949SAli.Saidi@ARM.com
1777949SAli.Saidi@ARM.com        // Check if miss is in pfq, if so remove it
17810156Sandreas@sandberg.pp.se        std::list<PacketPtr>::iterator iter = inPrefetch(blk_addr);
17910156Sandreas@sandberg.pp.se        if (iter != pf.end()) {
18010156Sandreas@sandberg.pp.se            DPRINTF(HWPrefetch, "Saw a miss to a queued prefetch addr: "
18110156Sandreas@sandberg.pp.se                    "0x%x, removing it\n", blk_addr);
18210156Sandreas@sandberg.pp.se            pfRemovedMSHR++;
1837949SAli.Saidi@ARM.com            delete (*iter)->req;
1847949SAli.Saidi@ARM.com            delete (*iter);
1857949SAli.Saidi@ARM.com            pf.erase(iter);
1867949SAli.Saidi@ARM.com            if (pf.empty())
1877949SAli.Saidi@ARM.com                cache->deassertMemSideBusRequest(BaseCache::Request_PF);
1887949SAli.Saidi@ARM.com        }
1897949SAli.Saidi@ARM.com
1907949SAli.Saidi@ARM.com        // Remove anything in queue with delay older than time
1917949SAli.Saidi@ARM.com        // since everything is inserted in time order, start from end
1927949SAli.Saidi@ARM.com        // and work until pf.empty() or time is earlier
1937949SAli.Saidi@ARM.com        // This is done to emulate Aborting the previous work on a new miss
1947949SAli.Saidi@ARM.com        // Needed for serial calculators like GHB
1957949SAli.Saidi@ARM.com        if (serialSquash) {
1967949SAli.Saidi@ARM.com            iter = pf.end();
1977949SAli.Saidi@ARM.com            iter--;
1987949SAli.Saidi@ARM.com            while (!pf.empty() && ((*iter)->time >= time)) {
1997949SAli.Saidi@ARM.com                pfSquashed++;
2007949SAli.Saidi@ARM.com                DPRINTF(HWPrefetch, "Squashing old prefetch addr: 0x%x\n",
2017949SAli.Saidi@ARM.com                        (*iter)->getAddr());
2027949SAli.Saidi@ARM.com                delete (*iter)->req;
2037949SAli.Saidi@ARM.com                delete (*iter);
2047949SAli.Saidi@ARM.com                pf.erase(iter);
2057949SAli.Saidi@ARM.com                iter--;
2067949SAli.Saidi@ARM.com            }
2077949SAli.Saidi@ARM.com            if (pf.empty())
2087949SAli.Saidi@ARM.com                cache->deassertMemSideBusRequest(BaseCache::Request_PF);
2097949SAli.Saidi@ARM.com        }
2107949SAli.Saidi@ARM.com
2117949SAli.Saidi@ARM.com
2127949SAli.Saidi@ARM.com        std::list<Addr> addresses;
2137949SAli.Saidi@ARM.com        std::list<Tick> delays;
2147949SAli.Saidi@ARM.com        calculatePrefetch(pkt, addresses, delays);
2157949SAli.Saidi@ARM.com
2167949SAli.Saidi@ARM.com        std::list<Addr>::iterator addrIter = addresses.begin();
2177949SAli.Saidi@ARM.com        std::list<Tick>::iterator delayIter = delays.begin();
2187949SAli.Saidi@ARM.com        for (; addrIter != addresses.end(); ++addrIter, ++delayIter) {
2197949SAli.Saidi@ARM.com            Addr addr = *addrIter;
2207949SAli.Saidi@ARM.com
2217949SAli.Saidi@ARM.com            pfIdentified++;
2227949SAli.Saidi@ARM.com
2237949SAli.Saidi@ARM.com            DPRINTF(HWPrefetch, "Found a pf candidate addr: 0x%x, "
2247949SAli.Saidi@ARM.com                    "inserting into prefetch queue with delay %d time %d\n",
2257949SAli.Saidi@ARM.com                    addr, *delayIter, time);
2267949SAli.Saidi@ARM.com
2277949SAli.Saidi@ARM.com            // Check if it is already in the cache
2287949SAli.Saidi@ARM.com            if (cacheCheckPush && cache->inCache(addr)) {
2297949SAli.Saidi@ARM.com                DPRINTF(HWPrefetch, "Prefetch addr already in cache\n");
2307949SAli.Saidi@ARM.com                continue;
2317949SAli.Saidi@ARM.com            }
2327949SAli.Saidi@ARM.com
2337949SAli.Saidi@ARM.com            // Check if it is already in the miss_queue
2347949SAli.Saidi@ARM.com            if (cache->inMissQueue(addr)) {
2357949SAli.Saidi@ARM.com                DPRINTF(HWPrefetch, "Prefetch addr already in miss queue\n");
2367949SAli.Saidi@ARM.com                continue;
2377949SAli.Saidi@ARM.com            }
2387949SAli.Saidi@ARM.com
2397949SAli.Saidi@ARM.com            // Check if it is already in the pf buffer
2407949SAli.Saidi@ARM.com            if (inPrefetch(addr) != pf.end()) {
2417949SAli.Saidi@ARM.com                pfBufferHit++;
2427949SAli.Saidi@ARM.com                DPRINTF(HWPrefetch, "Prefetch addr already in pf buffer\n");
2437949SAli.Saidi@ARM.com                continue;
2447949SAli.Saidi@ARM.com            }
2457949SAli.Saidi@ARM.com
2467949SAli.Saidi@ARM.com            // create a prefetch memreq
2477949SAli.Saidi@ARM.com            Request *prefetchReq = new Request(*addrIter, blkSize, 0);
2488871SChander.Sudanthi@arm.com            PacketPtr prefetch =
2498871SChander.Sudanthi@arm.com                new Packet(prefetchReq, MemCmd::HardPFReq, Packet::Broadcast);
2507949SAli.Saidi@ARM.com            prefetch->allocate();
2518871SChander.Sudanthi@arm.com            prefetch->req->setThreadContext(pkt->req->contextId(),
2528871SChander.Sudanthi@arm.com                                            pkt->req->threadId());
2537949SAli.Saidi@ARM.com
2548871SChander.Sudanthi@arm.com            prefetch->time = time + (*delayIter); // @todo ADD LATENCY HERE
2558871SChander.Sudanthi@arm.com
2567949SAli.Saidi@ARM.com            // We just remove the head if we are full
2578871SChander.Sudanthi@arm.com            if (pf.size() == size) {
2588871SChander.Sudanthi@arm.com                pfRemovedFull++;
2597949SAli.Saidi@ARM.com                PacketPtr old_pkt = *pf.begin();
2608871SChander.Sudanthi@arm.com                DPRINTF(HWPrefetch, "Prefetch queue full, "
2618871SChander.Sudanthi@arm.com                        "removing oldest 0x%x\n", old_pkt->getAddr());
2628871SChander.Sudanthi@arm.com                delete old_pkt->req;
2637949SAli.Saidi@ARM.com                delete old_pkt;
2647949SAli.Saidi@ARM.com                pf.pop_front();
2657949SAli.Saidi@ARM.com            }
2667949SAli.Saidi@ARM.com
2677949SAli.Saidi@ARM.com            pf.push_back(prefetch);
2687949SAli.Saidi@ARM.com        }
2697949SAli.Saidi@ARM.com    }
2707949SAli.Saidi@ARM.com
2717949SAli.Saidi@ARM.com    return pf.empty() ? 0 : pf.front()->time;
2727949SAli.Saidi@ARM.com}
2737949SAli.Saidi@ARM.com
2747949SAli.Saidi@ARM.comstd::list<PacketPtr>::iterator
2757949SAli.Saidi@ARM.comBasePrefetcher::inPrefetch(Addr address)
2767949SAli.Saidi@ARM.com{
2777949SAli.Saidi@ARM.com    // Guaranteed to only be one match, we always check before inserting
2787949SAli.Saidi@ARM.com    std::list<PacketPtr>::iterator iter;
2797949SAli.Saidi@ARM.com    for (iter = pf.begin(); iter != pf.end(); iter++) {
2807949SAli.Saidi@ARM.com        if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) {
2817949SAli.Saidi@ARM.com            return iter;
2827949SAli.Saidi@ARM.com        }
2837949SAli.Saidi@ARM.com    }
2847949SAli.Saidi@ARM.com    return pf.end();
2857949SAli.Saidi@ARM.com}
2867949SAli.Saidi@ARM.com
2877949SAli.Saidi@ARM.combool
2887949SAli.Saidi@ARM.comBasePrefetcher::samePage(Addr a, Addr b)
2897949SAli.Saidi@ARM.com{
2907949SAli.Saidi@ARM.com    return roundDown(a, TheISA::VMPageSize) == roundDown(b, TheISA::VMPageSize);
2917949SAli.Saidi@ARM.com}
2927949SAli.Saidi@ARM.com