19363Snilay@cs.wisc.edu/*
29363Snilay@cs.wisc.edu * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood
39363Snilay@cs.wisc.edu * All rights reserved.
49363Snilay@cs.wisc.edu *
59363Snilay@cs.wisc.edu * Redistribution and use in source and binary forms, with or without
69363Snilay@cs.wisc.edu * modification, are permitted provided that the following conditions are
79363Snilay@cs.wisc.edu * met: redistributions of source code must retain the above copyright
89363Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer;
99363Snilay@cs.wisc.edu * redistributions in binary form must reproduce the above copyright
109363Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer in the
119363Snilay@cs.wisc.edu * documentation and/or other materials provided with the distribution;
129363Snilay@cs.wisc.edu * neither the name of the copyright holders nor the names of its
139363Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from
149363Snilay@cs.wisc.edu * this software without specific prior written permission.
159363Snilay@cs.wisc.edu *
169363Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179363Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189363Snilay@cs.wisc.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199363Snilay@cs.wisc.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209363Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219363Snilay@cs.wisc.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229363Snilay@cs.wisc.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239363Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249363Snilay@cs.wisc.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259363Snilay@cs.wisc.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269363Snilay@cs.wisc.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279363Snilay@cs.wisc.edu */
289363Snilay@cs.wisc.edu
2911793Sbrandon.potter@amd.com#include "mem/ruby/structures/Prefetcher.hh"
3011793Sbrandon.potter@amd.com
319363Snilay@cs.wisc.edu#include "debug/RubyPrefetcher.hh"
329363Snilay@cs.wisc.edu#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
3311108Sdavid.hashe@amd.com#include "mem/ruby/system/RubySystem.hh"
349363Snilay@cs.wisc.edu
359363Snilay@cs.wisc.eduPrefetcher*
369363Snilay@cs.wisc.eduPrefetcherParams::create()
379363Snilay@cs.wisc.edu{
389363Snilay@cs.wisc.edu    return new Prefetcher(this);
399363Snilay@cs.wisc.edu}
409363Snilay@cs.wisc.edu
419363Snilay@cs.wisc.eduPrefetcher::Prefetcher(const Params *p)
429363Snilay@cs.wisc.edu    : SimObject(p), m_num_streams(p->num_streams),
439363Snilay@cs.wisc.edu    m_array(p->num_streams), m_train_misses(p->train_misses),
449363Snilay@cs.wisc.edu    m_num_startup_pfs(p->num_startup_pfs), m_num_unit_filters(p->unit_filter),
459363Snilay@cs.wisc.edu    m_num_nonunit_filters(p->nonunit_filter),
4611025Snilay@cs.wisc.edu    m_unit_filter(p->unit_filter, 0),
4711025Snilay@cs.wisc.edu    m_negative_filter(p->unit_filter, 0),
4811025Snilay@cs.wisc.edu    m_nonunit_filter(p->nonunit_filter, 0),
4910466Sandreas.hansson@arm.com    m_prefetch_cross_pages(p->cross_page),
5010466Sandreas.hansson@arm.com    m_page_shift(p->sys->getPageShift())
519363Snilay@cs.wisc.edu{
529363Snilay@cs.wisc.edu    assert(m_num_streams > 0);
539363Snilay@cs.wisc.edu    assert(m_num_startup_pfs <= MAX_PF_INFLIGHT);
549363Snilay@cs.wisc.edu
559363Snilay@cs.wisc.edu    // create +1 stride filter
569363Snilay@cs.wisc.edu    m_unit_filter_index = 0;
579363Snilay@cs.wisc.edu    m_unit_filter_hit = new uint32_t[m_num_unit_filters];
589363Snilay@cs.wisc.edu    for (uint32_t i =0; i < m_num_unit_filters; i++) {
599363Snilay@cs.wisc.edu        m_unit_filter_hit[i] = 0;
609363Snilay@cs.wisc.edu    }
619363Snilay@cs.wisc.edu
629363Snilay@cs.wisc.edu    // create -1 stride filter
639363Snilay@cs.wisc.edu    m_negative_filter_index = 0;
649363Snilay@cs.wisc.edu    m_negative_filter_hit = new uint32_t[m_num_unit_filters];
659363Snilay@cs.wisc.edu    for (int i =0; i < m_num_unit_filters; i++) {
669363Snilay@cs.wisc.edu        m_negative_filter_hit[i] = 0;
679363Snilay@cs.wisc.edu    }
689363Snilay@cs.wisc.edu
699363Snilay@cs.wisc.edu    // create nonunit stride filter
709363Snilay@cs.wisc.edu    m_nonunit_index = 0;
719363Snilay@cs.wisc.edu    m_nonunit_stride = new int[m_num_nonunit_filters];
729363Snilay@cs.wisc.edu    m_nonunit_hit    = new uint32_t[m_num_nonunit_filters];
739363Snilay@cs.wisc.edu    for (int i =0; i < m_num_nonunit_filters; i++) {
749363Snilay@cs.wisc.edu        m_nonunit_stride[i] = 0;
759363Snilay@cs.wisc.edu        m_nonunit_hit[i]    = 0;
769363Snilay@cs.wisc.edu    }
779363Snilay@cs.wisc.edu}
789363Snilay@cs.wisc.edu
799363Snilay@cs.wisc.eduPrefetcher::~Prefetcher()
809363Snilay@cs.wisc.edu{
819363Snilay@cs.wisc.edu    delete m_unit_filter_hit;
829363Snilay@cs.wisc.edu    delete m_negative_filter_hit;
839363Snilay@cs.wisc.edu    delete m_nonunit_stride;
849363Snilay@cs.wisc.edu    delete m_nonunit_hit;
859363Snilay@cs.wisc.edu}
869363Snilay@cs.wisc.edu
879363Snilay@cs.wisc.eduvoid
889363Snilay@cs.wisc.eduPrefetcher::regStats()
899363Snilay@cs.wisc.edu{
9011523Sdavid.guillen@arm.com    SimObject::regStats();
9111523Sdavid.guillen@arm.com
929363Snilay@cs.wisc.edu    numMissObserved
939363Snilay@cs.wisc.edu        .name(name() + ".miss_observed")
949363Snilay@cs.wisc.edu        .desc("number of misses observed")
959363Snilay@cs.wisc.edu        ;
969363Snilay@cs.wisc.edu
979363Snilay@cs.wisc.edu    numAllocatedStreams
989363Snilay@cs.wisc.edu        .name(name() + ".allocated_streams")
999363Snilay@cs.wisc.edu        .desc("number of streams allocated for prefetching")
1009363Snilay@cs.wisc.edu        ;
1019363Snilay@cs.wisc.edu
1029363Snilay@cs.wisc.edu    numPrefetchRequested
1039363Snilay@cs.wisc.edu        .name(name() + ".prefetches_requested")
1049363Snilay@cs.wisc.edu        .desc("number of prefetch requests made")
1059363Snilay@cs.wisc.edu        ;
1069363Snilay@cs.wisc.edu
1079363Snilay@cs.wisc.edu    numPrefetchAccepted
1089363Snilay@cs.wisc.edu        .name(name() + ".prefetches_accepted")
1099363Snilay@cs.wisc.edu        .desc("number of prefetch requests accepted")
1109363Snilay@cs.wisc.edu        ;
1119363Snilay@cs.wisc.edu
1129363Snilay@cs.wisc.edu    numDroppedPrefetches
1139363Snilay@cs.wisc.edu        .name(name() + ".dropped_prefetches")
1149363Snilay@cs.wisc.edu        .desc("number of prefetch requests dropped")
1159363Snilay@cs.wisc.edu        ;
1169363Snilay@cs.wisc.edu
1179363Snilay@cs.wisc.edu    numHits
1189363Snilay@cs.wisc.edu        .name(name() + ".hits")
1199363Snilay@cs.wisc.edu        .desc("number of prefetched blocks accessed")
1209363Snilay@cs.wisc.edu        ;
1219363Snilay@cs.wisc.edu
1229363Snilay@cs.wisc.edu    numPartialHits
1239363Snilay@cs.wisc.edu        .name(name() + ".partial_hits")
1249363Snilay@cs.wisc.edu        .desc("number of misses observed for a block being prefetched")
1259363Snilay@cs.wisc.edu        ;
1269363Snilay@cs.wisc.edu
1279363Snilay@cs.wisc.edu    numPagesCrossed
1289363Snilay@cs.wisc.edu        .name(name() + ".pages_crossed")
1299363Snilay@cs.wisc.edu        .desc("number of prefetches across pages")
1309363Snilay@cs.wisc.edu        ;
1319363Snilay@cs.wisc.edu
1329363Snilay@cs.wisc.edu    numMissedPrefetchedBlocks
1339363Snilay@cs.wisc.edu        .name(name() + ".misses_on_prefetched_blocks")
1349363Snilay@cs.wisc.edu        .desc("number of misses for blocks that were prefetched, yet missed")
1359363Snilay@cs.wisc.edu        ;
1369363Snilay@cs.wisc.edu}
1379363Snilay@cs.wisc.edu
1389363Snilay@cs.wisc.eduvoid
13911025Snilay@cs.wisc.eduPrefetcher::observeMiss(Addr address, const RubyRequestType& type)
1409363Snilay@cs.wisc.edu{
14111118Snilay@cs.wisc.edu    DPRINTF(RubyPrefetcher, "Observed miss for %#x\n", address);
14211025Snilay@cs.wisc.edu    Addr line_addr = makeLineAddress(address);
1439363Snilay@cs.wisc.edu    numMissObserved++;
1449363Snilay@cs.wisc.edu
1459363Snilay@cs.wisc.edu    // check to see if we have already issued a prefetch for this block
1469363Snilay@cs.wisc.edu    uint32_t index = 0;
1479363Snilay@cs.wisc.edu    PrefetchEntry *pfEntry = getPrefetchEntry(line_addr, index);
1489363Snilay@cs.wisc.edu    if (pfEntry != NULL) {
1499363Snilay@cs.wisc.edu        if (pfEntry->requestIssued[index]) {
1509363Snilay@cs.wisc.edu            if (pfEntry->requestCompleted[index]) {
1519363Snilay@cs.wisc.edu                // We prefetched too early and now the prefetch block no
1529363Snilay@cs.wisc.edu                // longer exists in the cache
1539363Snilay@cs.wisc.edu                numMissedPrefetchedBlocks++;
1549363Snilay@cs.wisc.edu                return;
1559363Snilay@cs.wisc.edu            } else {
1569363Snilay@cs.wisc.edu                // The controller has issued the prefetch request,
1579363Snilay@cs.wisc.edu                // but the request for the block arrived earlier.
1589363Snilay@cs.wisc.edu                numPartialHits++;
1599363Snilay@cs.wisc.edu                observePfHit(line_addr);
1609363Snilay@cs.wisc.edu                return;
1619363Snilay@cs.wisc.edu            }
1629363Snilay@cs.wisc.edu        } else {
1639363Snilay@cs.wisc.edu            // The request is still in the prefetch queue of the controller.
1649363Snilay@cs.wisc.edu            // Or was evicted because of other requests.
1659363Snilay@cs.wisc.edu            return;
1669363Snilay@cs.wisc.edu        }
1679363Snilay@cs.wisc.edu    }
1689363Snilay@cs.wisc.edu
1699363Snilay@cs.wisc.edu    // check to see if this address is in the unit stride filter
1709363Snilay@cs.wisc.edu    bool alloc = false;
1719363Snilay@cs.wisc.edu    bool hit = accessUnitFilter(m_unit_filter, m_unit_filter_hit,
1729363Snilay@cs.wisc.edu                                m_unit_filter_index, line_addr, 1, alloc);
1739363Snilay@cs.wisc.edu    if (alloc) {
1749363Snilay@cs.wisc.edu        // allocate a new prefetch stream
1759363Snilay@cs.wisc.edu        initializeStream(line_addr, 1, getLRUindex(), type);
1769363Snilay@cs.wisc.edu    }
1779363Snilay@cs.wisc.edu    if (hit) {
1789363Snilay@cs.wisc.edu        DPRINTF(RubyPrefetcher, "  *** hit in unit stride buffer\n");
1799363Snilay@cs.wisc.edu        return;
1809363Snilay@cs.wisc.edu    }
1819363Snilay@cs.wisc.edu
1829363Snilay@cs.wisc.edu    hit = accessUnitFilter(m_negative_filter, m_negative_filter_hit,
1839363Snilay@cs.wisc.edu        m_negative_filter_index, line_addr, -1, alloc);
1849363Snilay@cs.wisc.edu    if (alloc) {
1859363Snilay@cs.wisc.edu        // allocate a new prefetch stream
1869363Snilay@cs.wisc.edu        initializeStream(line_addr, -1, getLRUindex(), type);
1879363Snilay@cs.wisc.edu    }
1889363Snilay@cs.wisc.edu    if (hit) {
1899363Snilay@cs.wisc.edu        DPRINTF(RubyPrefetcher, "  *** hit in unit negative unit buffer\n");
1909363Snilay@cs.wisc.edu        return;
1919363Snilay@cs.wisc.edu    }
1929363Snilay@cs.wisc.edu
1939363Snilay@cs.wisc.edu    // check to see if this address is in the non-unit stride filter
1949363Snilay@cs.wisc.edu    int stride = 0;  // NULL value
1959363Snilay@cs.wisc.edu    hit = accessNonunitFilter(address, &stride, alloc);
1969363Snilay@cs.wisc.edu    if (alloc) {
1979363Snilay@cs.wisc.edu        assert(stride != 0);  // ensure non-zero stride prefetches
1989363Snilay@cs.wisc.edu        initializeStream(line_addr, stride, getLRUindex(), type);
1999363Snilay@cs.wisc.edu    }
2009363Snilay@cs.wisc.edu    if (hit) {
2019363Snilay@cs.wisc.edu        DPRINTF(RubyPrefetcher, "  *** hit in non-unit stride buffer\n");
2029363Snilay@cs.wisc.edu        return;
2039363Snilay@cs.wisc.edu    }
2049363Snilay@cs.wisc.edu}
2059363Snilay@cs.wisc.edu
2069363Snilay@cs.wisc.eduvoid
20711025Snilay@cs.wisc.eduPrefetcher::observePfMiss(Addr address)
2089363Snilay@cs.wisc.edu{
2099363Snilay@cs.wisc.edu    numPartialHits++;
21011118Snilay@cs.wisc.edu    DPRINTF(RubyPrefetcher, "Observed partial hit for %#x\n", address);
2119363Snilay@cs.wisc.edu    issueNextPrefetch(address, NULL);
2129363Snilay@cs.wisc.edu}
2139363Snilay@cs.wisc.edu
2149363Snilay@cs.wisc.eduvoid
21511025Snilay@cs.wisc.eduPrefetcher::observePfHit(Addr address)
2169363Snilay@cs.wisc.edu{
2179363Snilay@cs.wisc.edu    numHits++;
21811118Snilay@cs.wisc.edu    DPRINTF(RubyPrefetcher, "Observed hit for %#x\n", address);
2199363Snilay@cs.wisc.edu    issueNextPrefetch(address, NULL);
2209363Snilay@cs.wisc.edu}
2219363Snilay@cs.wisc.edu
2229363Snilay@cs.wisc.eduvoid
22311025Snilay@cs.wisc.eduPrefetcher::issueNextPrefetch(Addr address, PrefetchEntry *stream)
2249363Snilay@cs.wisc.edu{
2259363Snilay@cs.wisc.edu    // get our corresponding stream fetcher
2269363Snilay@cs.wisc.edu    if (stream == NULL) {
2279363Snilay@cs.wisc.edu        uint32_t index = 0;
2289363Snilay@cs.wisc.edu        stream = getPrefetchEntry(address, index);
2299363Snilay@cs.wisc.edu    }
2309363Snilay@cs.wisc.edu
2319363Snilay@cs.wisc.edu    // if (for some reason), this stream is unallocated, return.
2329363Snilay@cs.wisc.edu    if (stream == NULL) {
2339363Snilay@cs.wisc.edu        DPRINTF(RubyPrefetcher, "Unallocated stream, returning\n");
2349363Snilay@cs.wisc.edu        return;
2359363Snilay@cs.wisc.edu    }
2369363Snilay@cs.wisc.edu
2379363Snilay@cs.wisc.edu    // extend this prefetching stream by 1 (or more)
23811025Snilay@cs.wisc.edu    Addr page_addr = pageAddress(stream->m_address);
23911025Snilay@cs.wisc.edu    Addr line_addr = makeNextStrideAddress(stream->m_address,
24011025Snilay@cs.wisc.edu                                         stream->m_stride);
2419363Snilay@cs.wisc.edu
2429363Snilay@cs.wisc.edu    // possibly stop prefetching at page boundaries
24310466Sandreas.hansson@arm.com    if (page_addr != pageAddress(line_addr)) {
2449363Snilay@cs.wisc.edu        numPagesCrossed++;
2459363Snilay@cs.wisc.edu        if (!m_prefetch_cross_pages) {
2469363Snilay@cs.wisc.edu            // Deallocate the stream since we are not prefetching
2479363Snilay@cs.wisc.edu            // across page boundries
2489363Snilay@cs.wisc.edu            stream->m_is_valid = false;
2499363Snilay@cs.wisc.edu            return;
2509363Snilay@cs.wisc.edu        }
2519363Snilay@cs.wisc.edu    }
2529363Snilay@cs.wisc.edu
2539363Snilay@cs.wisc.edu    // launch next prefetch
2549363Snilay@cs.wisc.edu    stream->m_address = line_addr;
2559475Snilay@cs.wisc.edu    stream->m_use_time = m_controller->curCycle();
25611118Snilay@cs.wisc.edu    DPRINTF(RubyPrefetcher, "Requesting prefetch for %#x\n", line_addr);
2579363Snilay@cs.wisc.edu    m_controller->enqueuePrefetch(line_addr, stream->m_type);
2589363Snilay@cs.wisc.edu}
2599363Snilay@cs.wisc.edu
2609363Snilay@cs.wisc.eduuint32_t
2619363Snilay@cs.wisc.eduPrefetcher::getLRUindex(void)
2629363Snilay@cs.wisc.edu{
2639363Snilay@cs.wisc.edu    uint32_t lru_index = 0;
2649507Snilay@cs.wisc.edu    Cycles lru_access = m_array[lru_index].m_use_time;
2659363Snilay@cs.wisc.edu
2669363Snilay@cs.wisc.edu    for (uint32_t i = 0; i < m_num_streams; i++) {
2679363Snilay@cs.wisc.edu        if (!m_array[i].m_is_valid) {
2689363Snilay@cs.wisc.edu            return i;
2699363Snilay@cs.wisc.edu        }
2709363Snilay@cs.wisc.edu        if (m_array[i].m_use_time < lru_access) {
2719363Snilay@cs.wisc.edu            lru_access = m_array[i].m_use_time;
2729363Snilay@cs.wisc.edu            lru_index = i;
2739363Snilay@cs.wisc.edu        }
2749363Snilay@cs.wisc.edu    }
2759363Snilay@cs.wisc.edu
2769363Snilay@cs.wisc.edu    return lru_index;
2779363Snilay@cs.wisc.edu}
2789363Snilay@cs.wisc.edu
2799363Snilay@cs.wisc.eduvoid
2809363Snilay@cs.wisc.eduPrefetcher::clearNonunitEntry(uint32_t index)
2819363Snilay@cs.wisc.edu{
28211025Snilay@cs.wisc.edu    m_nonunit_filter[index] = 0;
2839363Snilay@cs.wisc.edu    m_nonunit_stride[index] = 0;
2849363Snilay@cs.wisc.edu    m_nonunit_hit[index]    = 0;
2859363Snilay@cs.wisc.edu}
2869363Snilay@cs.wisc.edu
2879363Snilay@cs.wisc.eduvoid
28811025Snilay@cs.wisc.eduPrefetcher::initializeStream(Addr address, int stride,
2899363Snilay@cs.wisc.edu     uint32_t index, const RubyRequestType& type)
2909363Snilay@cs.wisc.edu{
2919363Snilay@cs.wisc.edu    numAllocatedStreams++;
2929363Snilay@cs.wisc.edu
2939363Snilay@cs.wisc.edu    // initialize the stream prefetcher
2949363Snilay@cs.wisc.edu    PrefetchEntry *mystream = &(m_array[index]);
29511025Snilay@cs.wisc.edu    mystream->m_address = makeLineAddress(address);
2969363Snilay@cs.wisc.edu    mystream->m_stride = stride;
2979475Snilay@cs.wisc.edu    mystream->m_use_time = m_controller->curCycle();
2989363Snilay@cs.wisc.edu    mystream->m_is_valid = true;
2999363Snilay@cs.wisc.edu    mystream->m_type = type;
3009363Snilay@cs.wisc.edu
3019363Snilay@cs.wisc.edu    // create a number of initial prefetches for this stream
30211025Snilay@cs.wisc.edu    Addr page_addr = pageAddress(mystream->m_address);
30311025Snilay@cs.wisc.edu    Addr line_addr = makeLineAddress(mystream->m_address);
3049363Snilay@cs.wisc.edu
3059363Snilay@cs.wisc.edu    // insert a number of prefetches into the prefetch table
3069363Snilay@cs.wisc.edu    for (int k = 0; k < m_num_startup_pfs; k++) {
30711025Snilay@cs.wisc.edu        line_addr = makeNextStrideAddress(line_addr, stride);
3089363Snilay@cs.wisc.edu        // possibly stop prefetching at page boundaries
30910466Sandreas.hansson@arm.com        if (page_addr != pageAddress(line_addr)) {
3109363Snilay@cs.wisc.edu            numPagesCrossed++;
3119363Snilay@cs.wisc.edu            if (!m_prefetch_cross_pages) {
3129363Snilay@cs.wisc.edu                // deallocate this stream prefetcher
3139363Snilay@cs.wisc.edu                mystream->m_is_valid = false;
3149363Snilay@cs.wisc.edu                return;
3159363Snilay@cs.wisc.edu            }
3169363Snilay@cs.wisc.edu        }
3179363Snilay@cs.wisc.edu
3189363Snilay@cs.wisc.edu        // launch prefetch
3199363Snilay@cs.wisc.edu        numPrefetchRequested++;
32011118Snilay@cs.wisc.edu        DPRINTF(RubyPrefetcher, "Requesting prefetch for %#x\n", line_addr);
3219363Snilay@cs.wisc.edu        m_controller->enqueuePrefetch(line_addr, m_array[index].m_type);
3229363Snilay@cs.wisc.edu    }
3239363Snilay@cs.wisc.edu
3249363Snilay@cs.wisc.edu    // update the address to be the last address prefetched
3259363Snilay@cs.wisc.edu    mystream->m_address = line_addr;
3269363Snilay@cs.wisc.edu}
3279363Snilay@cs.wisc.edu
3289363Snilay@cs.wisc.eduPrefetchEntry *
32911025Snilay@cs.wisc.eduPrefetcher::getPrefetchEntry(Addr address, uint32_t &index)
3309363Snilay@cs.wisc.edu{
3319363Snilay@cs.wisc.edu    // search all streams for a match
3329363Snilay@cs.wisc.edu    for (int i = 0; i < m_num_streams; i++) {
3339363Snilay@cs.wisc.edu        // search all the outstanding prefetches for this stream
3349363Snilay@cs.wisc.edu        if (m_array[i].m_is_valid) {
3359363Snilay@cs.wisc.edu            for (int j = 0; j < m_num_startup_pfs; j++) {
33611025Snilay@cs.wisc.edu                if (makeNextStrideAddress(m_array[i].m_address,
3379363Snilay@cs.wisc.edu                    -(m_array[i].m_stride*j)) == address) {
3389363Snilay@cs.wisc.edu                    return &(m_array[i]);
3399363Snilay@cs.wisc.edu                }
3409363Snilay@cs.wisc.edu            }
3419363Snilay@cs.wisc.edu        }
3429363Snilay@cs.wisc.edu    }
3439363Snilay@cs.wisc.edu    return NULL;
3449363Snilay@cs.wisc.edu}
3459363Snilay@cs.wisc.edu
3469363Snilay@cs.wisc.edubool
34711025Snilay@cs.wisc.eduPrefetcher::accessUnitFilter(std::vector<Addr>& filter_table,
34811025Snilay@cs.wisc.edu    uint32_t *filter_hit, uint32_t &index, Addr address,
3499363Snilay@cs.wisc.edu    int stride, bool &alloc)
3509363Snilay@cs.wisc.edu{
3519363Snilay@cs.wisc.edu    //reset the alloc flag
3529363Snilay@cs.wisc.edu    alloc = false;
3539363Snilay@cs.wisc.edu
35411025Snilay@cs.wisc.edu    Addr line_addr = makeLineAddress(address);
3559363Snilay@cs.wisc.edu    for (int i = 0; i < m_num_unit_filters; i++) {
3569363Snilay@cs.wisc.edu        if (filter_table[i] == line_addr) {
35711025Snilay@cs.wisc.edu            filter_table[i] = makeNextStrideAddress(filter_table[i], stride);
3589363Snilay@cs.wisc.edu            filter_hit[i]++;
3599363Snilay@cs.wisc.edu            if (filter_hit[i] >= m_train_misses) {
3609363Snilay@cs.wisc.edu                alloc = true;
3619363Snilay@cs.wisc.edu            }
3629363Snilay@cs.wisc.edu            return true;
3639363Snilay@cs.wisc.edu        }
3649363Snilay@cs.wisc.edu    }
3659363Snilay@cs.wisc.edu
3669363Snilay@cs.wisc.edu    // enter this address in the table
3679363Snilay@cs.wisc.edu    int local_index = index;
36811025Snilay@cs.wisc.edu    filter_table[local_index] = makeNextStrideAddress(line_addr, stride);
3699363Snilay@cs.wisc.edu    filter_hit[local_index] = 0;
3709363Snilay@cs.wisc.edu    local_index = local_index + 1;
3719363Snilay@cs.wisc.edu    if (local_index >= m_num_unit_filters) {
3729363Snilay@cs.wisc.edu        local_index = 0;
3739363Snilay@cs.wisc.edu    }
3749363Snilay@cs.wisc.edu
3759363Snilay@cs.wisc.edu    index = local_index;
3769363Snilay@cs.wisc.edu    return false;
3779363Snilay@cs.wisc.edu}
3789363Snilay@cs.wisc.edu
3799363Snilay@cs.wisc.edubool
38011025Snilay@cs.wisc.eduPrefetcher::accessNonunitFilter(Addr address, int *stride,
3819363Snilay@cs.wisc.edu    bool &alloc)
3829363Snilay@cs.wisc.edu{
3839363Snilay@cs.wisc.edu    //reset the alloc flag
3849363Snilay@cs.wisc.edu    alloc = false;
3859363Snilay@cs.wisc.edu
3869363Snilay@cs.wisc.edu    /// look for non-unit strides based on a (user-defined) page size
38711025Snilay@cs.wisc.edu    Addr page_addr = pageAddress(address);
38811025Snilay@cs.wisc.edu    Addr line_addr = makeLineAddress(address);
3899363Snilay@cs.wisc.edu
3909363Snilay@cs.wisc.edu    for (uint32_t i = 0; i < m_num_nonunit_filters; i++) {
39110466Sandreas.hansson@arm.com        if (pageAddress(m_nonunit_filter[i]) == page_addr) {
3929363Snilay@cs.wisc.edu            // hit in the non-unit filter
3939363Snilay@cs.wisc.edu            // compute the actual stride (for this reference)
39411025Snilay@cs.wisc.edu            int delta = line_addr - m_nonunit_filter[i];
3959363Snilay@cs.wisc.edu
3969363Snilay@cs.wisc.edu            if (delta != 0) {
3979363Snilay@cs.wisc.edu                // no zero stride prefetches
3989363Snilay@cs.wisc.edu                // check that the stride matches (for the last N times)
3999363Snilay@cs.wisc.edu                if (delta == m_nonunit_stride[i]) {
4009363Snilay@cs.wisc.edu                    // -> stride hit
4019363Snilay@cs.wisc.edu                    // increment count (if > 2) allocate stream
4029363Snilay@cs.wisc.edu                    m_nonunit_hit[i]++;
4039363Snilay@cs.wisc.edu                    if (m_nonunit_hit[i] > m_train_misses) {
40411025Snilay@cs.wisc.edu                        // This stride HAS to be the multiplicative constant of
40511025Snilay@cs.wisc.edu                        // dataBlockBytes (bc makeNextStrideAddress is
40611025Snilay@cs.wisc.edu                        // calculated based on this multiplicative constant!)
40711025Snilay@cs.wisc.edu                        *stride = m_nonunit_stride[i] /
40811025Snilay@cs.wisc.edu                                    RubySystem::getBlockSizeBytes();
4099363Snilay@cs.wisc.edu
4109363Snilay@cs.wisc.edu                        // clear this filter entry
4119363Snilay@cs.wisc.edu                        clearNonunitEntry(i);
4129363Snilay@cs.wisc.edu                        alloc = true;
4139363Snilay@cs.wisc.edu                    }
4149363Snilay@cs.wisc.edu                } else {
41511025Snilay@cs.wisc.edu                    // delta didn't match ... reset m_nonunit_hit count for
41611025Snilay@cs.wisc.edu                    // this entry
4179363Snilay@cs.wisc.edu                    m_nonunit_hit[i] = 0;
4189363Snilay@cs.wisc.edu                }
4199363Snilay@cs.wisc.edu
4209363Snilay@cs.wisc.edu                // update the last address seen & the stride
4219363Snilay@cs.wisc.edu                m_nonunit_stride[i] = delta;
4229363Snilay@cs.wisc.edu                m_nonunit_filter[i] = line_addr;
4239363Snilay@cs.wisc.edu                return true;
4249363Snilay@cs.wisc.edu            } else {
4259363Snilay@cs.wisc.edu                return false;
4269363Snilay@cs.wisc.edu            }
4279363Snilay@cs.wisc.edu        }
4289363Snilay@cs.wisc.edu    }
4299363Snilay@cs.wisc.edu
4309363Snilay@cs.wisc.edu    // not found: enter this address in the table
4319363Snilay@cs.wisc.edu    m_nonunit_filter[m_nonunit_index] = line_addr;
4329363Snilay@cs.wisc.edu    m_nonunit_stride[m_nonunit_index] = 0;
4339363Snilay@cs.wisc.edu    m_nonunit_hit[m_nonunit_index]    = 0;
4349363Snilay@cs.wisc.edu
4359363Snilay@cs.wisc.edu    m_nonunit_index = m_nonunit_index + 1;
4369363Snilay@cs.wisc.edu    if (m_nonunit_index >= m_num_nonunit_filters) {
4379363Snilay@cs.wisc.edu        m_nonunit_index = 0;
4389363Snilay@cs.wisc.edu    }
4399363Snilay@cs.wisc.edu    return false;
4409363Snilay@cs.wisc.edu}
4419363Snilay@cs.wisc.edu
4429363Snilay@cs.wisc.eduvoid
4439363Snilay@cs.wisc.eduPrefetcher::print(std::ostream& out) const
4449363Snilay@cs.wisc.edu{
4459363Snilay@cs.wisc.edu    out << name() << " Prefetcher State\n";
4469363Snilay@cs.wisc.edu    // print out unit filter
4479363Snilay@cs.wisc.edu    out << "unit table:\n";
4489363Snilay@cs.wisc.edu    for (int i = 0; i < m_num_unit_filters; i++) {
4499363Snilay@cs.wisc.edu        out << m_unit_filter[i] << std::endl;
4509363Snilay@cs.wisc.edu    }
4519363Snilay@cs.wisc.edu
4529363Snilay@cs.wisc.edu    out << "negative table:\n";
4539363Snilay@cs.wisc.edu    for (int i = 0; i < m_num_unit_filters; i++) {
4549363Snilay@cs.wisc.edu        out << m_negative_filter[i] << std::endl;
4559363Snilay@cs.wisc.edu    }
4569363Snilay@cs.wisc.edu
4579363Snilay@cs.wisc.edu    // print out non-unit stride filter
4589363Snilay@cs.wisc.edu    out << "non-unit table:\n";
4599363Snilay@cs.wisc.edu    for (int i = 0; i < m_num_nonunit_filters; i++) {
4609363Snilay@cs.wisc.edu        out << m_nonunit_filter[i] << " "
4619363Snilay@cs.wisc.edu            << m_nonunit_stride[i] << " "
4629363Snilay@cs.wisc.edu            << m_nonunit_hit[i] << std::endl;
4639363Snilay@cs.wisc.edu    }
4649363Snilay@cs.wisc.edu
4659363Snilay@cs.wisc.edu    // print out allocated stream buffers
4669363Snilay@cs.wisc.edu    out << "streams:\n";
4679363Snilay@cs.wisc.edu    for (int i = 0; i < m_num_streams; i++) {
4689363Snilay@cs.wisc.edu        out << m_array[i].m_address << " "
4699363Snilay@cs.wisc.edu            << m_array[i].m_stride << " "
4709363Snilay@cs.wisc.edu            << m_array[i].m_is_valid << " "
4719363Snilay@cs.wisc.edu            << m_array[i].m_use_time << std::endl;
4729363Snilay@cs.wisc.edu    }
4739363Snilay@cs.wisc.edu}
47410466Sandreas.hansson@arm.com
47511025Snilay@cs.wisc.eduAddr
47611025Snilay@cs.wisc.eduPrefetcher::pageAddress(Addr addr) const
47710466Sandreas.hansson@arm.com{
47811025Snilay@cs.wisc.edu    return maskLowOrderBits(addr, m_page_shift);
47910466Sandreas.hansson@arm.com}
480