Prefetcher.cc revision 10466
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
299363Snilay@cs.wisc.edu#include "debug/RubyPrefetcher.hh"
309363Snilay@cs.wisc.edu#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
319363Snilay@cs.wisc.edu#include "mem/ruby/structures/Prefetcher.hh"
329363Snilay@cs.wisc.edu#include "mem/ruby/system/System.hh"
339363Snilay@cs.wisc.edu
349363Snilay@cs.wisc.eduPrefetcher*
359363Snilay@cs.wisc.eduPrefetcherParams::create()
369363Snilay@cs.wisc.edu{
379363Snilay@cs.wisc.edu    return new Prefetcher(this);
389363Snilay@cs.wisc.edu}
399363Snilay@cs.wisc.edu
409363Snilay@cs.wisc.eduPrefetcher::Prefetcher(const Params *p)
419363Snilay@cs.wisc.edu    : SimObject(p), m_num_streams(p->num_streams),
429363Snilay@cs.wisc.edu    m_array(p->num_streams), m_train_misses(p->train_misses),
439363Snilay@cs.wisc.edu    m_num_startup_pfs(p->num_startup_pfs), m_num_unit_filters(p->unit_filter),
449363Snilay@cs.wisc.edu    m_num_nonunit_filters(p->nonunit_filter),
459363Snilay@cs.wisc.edu    m_unit_filter(p->unit_filter, Address(0)),
469363Snilay@cs.wisc.edu    m_negative_filter(p->unit_filter, Address(0)),
479363Snilay@cs.wisc.edu    m_nonunit_filter(p->nonunit_filter, Address(0)),
4810466Sandreas.hansson@arm.com    m_prefetch_cross_pages(p->cross_page),
4910466Sandreas.hansson@arm.com    m_page_shift(p->sys->getPageShift())
509363Snilay@cs.wisc.edu{
519363Snilay@cs.wisc.edu    assert(m_num_streams > 0);
529363Snilay@cs.wisc.edu    assert(m_num_startup_pfs <= MAX_PF_INFLIGHT);
539363Snilay@cs.wisc.edu
549363Snilay@cs.wisc.edu    // create +1 stride filter
559363Snilay@cs.wisc.edu    m_unit_filter_index = 0;
569363Snilay@cs.wisc.edu    m_unit_filter_hit = new uint32_t[m_num_unit_filters];
579363Snilay@cs.wisc.edu    for (uint32_t i =0; i < m_num_unit_filters; i++) {
589363Snilay@cs.wisc.edu        m_unit_filter_hit[i] = 0;
599363Snilay@cs.wisc.edu    }
609363Snilay@cs.wisc.edu
619363Snilay@cs.wisc.edu    // create -1 stride filter
629363Snilay@cs.wisc.edu    m_negative_filter_index = 0;
639363Snilay@cs.wisc.edu    m_negative_filter_hit = new uint32_t[m_num_unit_filters];
649363Snilay@cs.wisc.edu    for (int i =0; i < m_num_unit_filters; i++) {
659363Snilay@cs.wisc.edu        m_negative_filter_hit[i] = 0;
669363Snilay@cs.wisc.edu    }
679363Snilay@cs.wisc.edu
689363Snilay@cs.wisc.edu    // create nonunit stride filter
699363Snilay@cs.wisc.edu    m_nonunit_index = 0;
709363Snilay@cs.wisc.edu    m_nonunit_stride = new int[m_num_nonunit_filters];
719363Snilay@cs.wisc.edu    m_nonunit_hit    = new uint32_t[m_num_nonunit_filters];
729363Snilay@cs.wisc.edu    for (int i =0; i < m_num_nonunit_filters; i++) {
739363Snilay@cs.wisc.edu        m_nonunit_stride[i] = 0;
749363Snilay@cs.wisc.edu        m_nonunit_hit[i]    = 0;
759363Snilay@cs.wisc.edu    }
769363Snilay@cs.wisc.edu}
779363Snilay@cs.wisc.edu
789363Snilay@cs.wisc.eduPrefetcher::~Prefetcher()
799363Snilay@cs.wisc.edu{
809363Snilay@cs.wisc.edu    delete m_unit_filter_hit;
819363Snilay@cs.wisc.edu    delete m_negative_filter_hit;
829363Snilay@cs.wisc.edu    delete m_nonunit_stride;
839363Snilay@cs.wisc.edu    delete m_nonunit_hit;
849363Snilay@cs.wisc.edu}
859363Snilay@cs.wisc.edu
869363Snilay@cs.wisc.eduvoid
879363Snilay@cs.wisc.eduPrefetcher::regStats()
889363Snilay@cs.wisc.edu{
899363Snilay@cs.wisc.edu    numMissObserved
909363Snilay@cs.wisc.edu        .name(name() + ".miss_observed")
919363Snilay@cs.wisc.edu        .desc("number of misses observed")
929363Snilay@cs.wisc.edu        ;
939363Snilay@cs.wisc.edu
949363Snilay@cs.wisc.edu    numAllocatedStreams
959363Snilay@cs.wisc.edu        .name(name() + ".allocated_streams")
969363Snilay@cs.wisc.edu        .desc("number of streams allocated for prefetching")
979363Snilay@cs.wisc.edu        ;
989363Snilay@cs.wisc.edu
999363Snilay@cs.wisc.edu    numPrefetchRequested
1009363Snilay@cs.wisc.edu        .name(name() + ".prefetches_requested")
1019363Snilay@cs.wisc.edu        .desc("number of prefetch requests made")
1029363Snilay@cs.wisc.edu        ;
1039363Snilay@cs.wisc.edu
1049363Snilay@cs.wisc.edu    numPrefetchAccepted
1059363Snilay@cs.wisc.edu        .name(name() + ".prefetches_accepted")
1069363Snilay@cs.wisc.edu        .desc("number of prefetch requests accepted")
1079363Snilay@cs.wisc.edu        ;
1089363Snilay@cs.wisc.edu
1099363Snilay@cs.wisc.edu    numDroppedPrefetches
1109363Snilay@cs.wisc.edu        .name(name() + ".dropped_prefetches")
1119363Snilay@cs.wisc.edu        .desc("number of prefetch requests dropped")
1129363Snilay@cs.wisc.edu        ;
1139363Snilay@cs.wisc.edu
1149363Snilay@cs.wisc.edu    numHits
1159363Snilay@cs.wisc.edu        .name(name() + ".hits")
1169363Snilay@cs.wisc.edu        .desc("number of prefetched blocks accessed")
1179363Snilay@cs.wisc.edu        ;
1189363Snilay@cs.wisc.edu
1199363Snilay@cs.wisc.edu    numPartialHits
1209363Snilay@cs.wisc.edu        .name(name() + ".partial_hits")
1219363Snilay@cs.wisc.edu        .desc("number of misses observed for a block being prefetched")
1229363Snilay@cs.wisc.edu        ;
1239363Snilay@cs.wisc.edu
1249363Snilay@cs.wisc.edu    numPagesCrossed
1259363Snilay@cs.wisc.edu        .name(name() + ".pages_crossed")
1269363Snilay@cs.wisc.edu        .desc("number of prefetches across pages")
1279363Snilay@cs.wisc.edu        ;
1289363Snilay@cs.wisc.edu
1299363Snilay@cs.wisc.edu    numMissedPrefetchedBlocks
1309363Snilay@cs.wisc.edu        .name(name() + ".misses_on_prefetched_blocks")
1319363Snilay@cs.wisc.edu        .desc("number of misses for blocks that were prefetched, yet missed")
1329363Snilay@cs.wisc.edu        ;
1339363Snilay@cs.wisc.edu}
1349363Snilay@cs.wisc.edu
1359363Snilay@cs.wisc.eduvoid
1369363Snilay@cs.wisc.eduPrefetcher::observeMiss(const Address& address, const RubyRequestType& type)
1379363Snilay@cs.wisc.edu{
1389363Snilay@cs.wisc.edu    DPRINTF(RubyPrefetcher, "Observed miss for %s\n", address);
1399363Snilay@cs.wisc.edu    Address line_addr = line_address(address);
1409363Snilay@cs.wisc.edu    numMissObserved++;
1419363Snilay@cs.wisc.edu
1429363Snilay@cs.wisc.edu    // check to see if we have already issued a prefetch for this block
1439363Snilay@cs.wisc.edu    uint32_t index = 0;
1449363Snilay@cs.wisc.edu    PrefetchEntry *pfEntry = getPrefetchEntry(line_addr, index);
1459363Snilay@cs.wisc.edu    if (pfEntry != NULL) {
1469363Snilay@cs.wisc.edu        if (pfEntry->requestIssued[index]) {
1479363Snilay@cs.wisc.edu            if (pfEntry->requestCompleted[index]) {
1489363Snilay@cs.wisc.edu                // We prefetched too early and now the prefetch block no
1499363Snilay@cs.wisc.edu                // longer exists in the cache
1509363Snilay@cs.wisc.edu                numMissedPrefetchedBlocks++;
1519363Snilay@cs.wisc.edu                return;
1529363Snilay@cs.wisc.edu            } else {
1539363Snilay@cs.wisc.edu                // The controller has issued the prefetch request,
1549363Snilay@cs.wisc.edu                // but the request for the block arrived earlier.
1559363Snilay@cs.wisc.edu                numPartialHits++;
1569363Snilay@cs.wisc.edu                observePfHit(line_addr);
1579363Snilay@cs.wisc.edu                return;
1589363Snilay@cs.wisc.edu            }
1599363Snilay@cs.wisc.edu        } else {
1609363Snilay@cs.wisc.edu            // The request is still in the prefetch queue of the controller.
1619363Snilay@cs.wisc.edu            // Or was evicted because of other requests.
1629363Snilay@cs.wisc.edu            return;
1639363Snilay@cs.wisc.edu        }
1649363Snilay@cs.wisc.edu    }
1659363Snilay@cs.wisc.edu
1669363Snilay@cs.wisc.edu    // check to see if this address is in the unit stride filter
1679363Snilay@cs.wisc.edu    bool alloc = false;
1689363Snilay@cs.wisc.edu    bool hit = accessUnitFilter(m_unit_filter, m_unit_filter_hit,
1699363Snilay@cs.wisc.edu                                m_unit_filter_index, line_addr, 1, alloc);
1709363Snilay@cs.wisc.edu    if (alloc) {
1719363Snilay@cs.wisc.edu        // allocate a new prefetch stream
1729363Snilay@cs.wisc.edu        initializeStream(line_addr, 1, getLRUindex(), type);
1739363Snilay@cs.wisc.edu    }
1749363Snilay@cs.wisc.edu    if (hit) {
1759363Snilay@cs.wisc.edu        DPRINTF(RubyPrefetcher, "  *** hit in unit stride buffer\n");
1769363Snilay@cs.wisc.edu        return;
1779363Snilay@cs.wisc.edu    }
1789363Snilay@cs.wisc.edu
1799363Snilay@cs.wisc.edu    hit = accessUnitFilter(m_negative_filter, m_negative_filter_hit,
1809363Snilay@cs.wisc.edu        m_negative_filter_index, line_addr, -1, alloc);
1819363Snilay@cs.wisc.edu    if (alloc) {
1829363Snilay@cs.wisc.edu        // allocate a new prefetch stream
1839363Snilay@cs.wisc.edu        initializeStream(line_addr, -1, getLRUindex(), type);
1849363Snilay@cs.wisc.edu    }
1859363Snilay@cs.wisc.edu    if (hit) {
1869363Snilay@cs.wisc.edu        DPRINTF(RubyPrefetcher, "  *** hit in unit negative unit buffer\n");
1879363Snilay@cs.wisc.edu        return;
1889363Snilay@cs.wisc.edu    }
1899363Snilay@cs.wisc.edu
1909363Snilay@cs.wisc.edu    // check to see if this address is in the non-unit stride filter
1919363Snilay@cs.wisc.edu    int stride = 0;  // NULL value
1929363Snilay@cs.wisc.edu    hit = accessNonunitFilter(address, &stride, alloc);
1939363Snilay@cs.wisc.edu    if (alloc) {
1949363Snilay@cs.wisc.edu        assert(stride != 0);  // ensure non-zero stride prefetches
1959363Snilay@cs.wisc.edu        initializeStream(line_addr, stride, getLRUindex(), type);
1969363Snilay@cs.wisc.edu    }
1979363Snilay@cs.wisc.edu    if (hit) {
1989363Snilay@cs.wisc.edu        DPRINTF(RubyPrefetcher, "  *** hit in non-unit stride buffer\n");
1999363Snilay@cs.wisc.edu        return;
2009363Snilay@cs.wisc.edu    }
2019363Snilay@cs.wisc.edu}
2029363Snilay@cs.wisc.edu
2039363Snilay@cs.wisc.eduvoid
2049363Snilay@cs.wisc.eduPrefetcher::observePfMiss(const Address& address)
2059363Snilay@cs.wisc.edu{
2069363Snilay@cs.wisc.edu    numPartialHits++;
2079363Snilay@cs.wisc.edu    DPRINTF(RubyPrefetcher, "Observed partial hit for %s\n", address);
2089363Snilay@cs.wisc.edu    issueNextPrefetch(address, NULL);
2099363Snilay@cs.wisc.edu}
2109363Snilay@cs.wisc.edu
2119363Snilay@cs.wisc.eduvoid
2129363Snilay@cs.wisc.eduPrefetcher::observePfHit(const Address& address)
2139363Snilay@cs.wisc.edu{
2149363Snilay@cs.wisc.edu    numHits++;
2159363Snilay@cs.wisc.edu    DPRINTF(RubyPrefetcher, "Observed hit for %s\n", address);
2169363Snilay@cs.wisc.edu    issueNextPrefetch(address, NULL);
2179363Snilay@cs.wisc.edu}
2189363Snilay@cs.wisc.edu
2199363Snilay@cs.wisc.eduvoid
2209363Snilay@cs.wisc.eduPrefetcher::issueNextPrefetch(const Address &address, PrefetchEntry *stream)
2219363Snilay@cs.wisc.edu{
2229363Snilay@cs.wisc.edu    // get our corresponding stream fetcher
2239363Snilay@cs.wisc.edu    if (stream == NULL) {
2249363Snilay@cs.wisc.edu        uint32_t index = 0;
2259363Snilay@cs.wisc.edu        stream = getPrefetchEntry(address, index);
2269363Snilay@cs.wisc.edu    }
2279363Snilay@cs.wisc.edu
2289363Snilay@cs.wisc.edu    // if (for some reason), this stream is unallocated, return.
2299363Snilay@cs.wisc.edu    if (stream == NULL) {
2309363Snilay@cs.wisc.edu        DPRINTF(RubyPrefetcher, "Unallocated stream, returning\n");
2319363Snilay@cs.wisc.edu        return;
2329363Snilay@cs.wisc.edu    }
2339363Snilay@cs.wisc.edu
2349363Snilay@cs.wisc.edu    // extend this prefetching stream by 1 (or more)
23510466Sandreas.hansson@arm.com    Address page_addr = pageAddress(stream->m_address);
2369363Snilay@cs.wisc.edu    Address line_addr = next_stride_address(stream->m_address,
2379363Snilay@cs.wisc.edu                                            stream->m_stride);
2389363Snilay@cs.wisc.edu
2399363Snilay@cs.wisc.edu    // possibly stop prefetching at page boundaries
24010466Sandreas.hansson@arm.com    if (page_addr != pageAddress(line_addr)) {
2419363Snilay@cs.wisc.edu        numPagesCrossed++;
2429363Snilay@cs.wisc.edu        if (!m_prefetch_cross_pages) {
2439363Snilay@cs.wisc.edu            // Deallocate the stream since we are not prefetching
2449363Snilay@cs.wisc.edu            // across page boundries
2459363Snilay@cs.wisc.edu            stream->m_is_valid = false;
2469363Snilay@cs.wisc.edu            return;
2479363Snilay@cs.wisc.edu        }
2489363Snilay@cs.wisc.edu    }
2499363Snilay@cs.wisc.edu
2509363Snilay@cs.wisc.edu    // launch next prefetch
2519363Snilay@cs.wisc.edu    stream->m_address = line_addr;
2529475Snilay@cs.wisc.edu    stream->m_use_time = m_controller->curCycle();
2539363Snilay@cs.wisc.edu    DPRINTF(RubyPrefetcher, "Requesting prefetch for %s\n", line_addr);
2549363Snilay@cs.wisc.edu    m_controller->enqueuePrefetch(line_addr, stream->m_type);
2559363Snilay@cs.wisc.edu}
2569363Snilay@cs.wisc.edu
2579363Snilay@cs.wisc.eduuint32_t
2589363Snilay@cs.wisc.eduPrefetcher::getLRUindex(void)
2599363Snilay@cs.wisc.edu{
2609363Snilay@cs.wisc.edu    uint32_t lru_index = 0;
2619507Snilay@cs.wisc.edu    Cycles lru_access = m_array[lru_index].m_use_time;
2629363Snilay@cs.wisc.edu
2639363Snilay@cs.wisc.edu    for (uint32_t i = 0; i < m_num_streams; i++) {
2649363Snilay@cs.wisc.edu        if (!m_array[i].m_is_valid) {
2659363Snilay@cs.wisc.edu            return i;
2669363Snilay@cs.wisc.edu        }
2679363Snilay@cs.wisc.edu        if (m_array[i].m_use_time < lru_access) {
2689363Snilay@cs.wisc.edu            lru_access = m_array[i].m_use_time;
2699363Snilay@cs.wisc.edu            lru_index = i;
2709363Snilay@cs.wisc.edu        }
2719363Snilay@cs.wisc.edu    }
2729363Snilay@cs.wisc.edu
2739363Snilay@cs.wisc.edu    return lru_index;
2749363Snilay@cs.wisc.edu}
2759363Snilay@cs.wisc.edu
2769363Snilay@cs.wisc.eduvoid
2779363Snilay@cs.wisc.eduPrefetcher::clearNonunitEntry(uint32_t index)
2789363Snilay@cs.wisc.edu{
2799363Snilay@cs.wisc.edu    m_nonunit_filter[index].setAddress(0);
2809363Snilay@cs.wisc.edu    m_nonunit_stride[index] = 0;
2819363Snilay@cs.wisc.edu    m_nonunit_hit[index]    = 0;
2829363Snilay@cs.wisc.edu}
2839363Snilay@cs.wisc.edu
2849363Snilay@cs.wisc.eduvoid
2859363Snilay@cs.wisc.eduPrefetcher::initializeStream(const Address& address, int stride,
2869363Snilay@cs.wisc.edu     uint32_t index, const RubyRequestType& type)
2879363Snilay@cs.wisc.edu{
2889363Snilay@cs.wisc.edu    numAllocatedStreams++;
2899363Snilay@cs.wisc.edu
2909363Snilay@cs.wisc.edu    // initialize the stream prefetcher
2919363Snilay@cs.wisc.edu    PrefetchEntry *mystream = &(m_array[index]);
2929363Snilay@cs.wisc.edu    mystream->m_address = line_address(address);
2939363Snilay@cs.wisc.edu    mystream->m_stride = stride;
2949475Snilay@cs.wisc.edu    mystream->m_use_time = m_controller->curCycle();
2959363Snilay@cs.wisc.edu    mystream->m_is_valid = true;
2969363Snilay@cs.wisc.edu    mystream->m_type = type;
2979363Snilay@cs.wisc.edu
2989363Snilay@cs.wisc.edu    // create a number of initial prefetches for this stream
29910466Sandreas.hansson@arm.com    Address page_addr = pageAddress(mystream->m_address);
3009363Snilay@cs.wisc.edu    Address line_addr = line_address(mystream->m_address);
3019363Snilay@cs.wisc.edu    Address prev_addr = line_addr;
3029363Snilay@cs.wisc.edu
3039363Snilay@cs.wisc.edu    // insert a number of prefetches into the prefetch table
3049363Snilay@cs.wisc.edu    for (int k = 0; k < m_num_startup_pfs; k++) {
3059363Snilay@cs.wisc.edu        line_addr = next_stride_address(line_addr, stride);
3069363Snilay@cs.wisc.edu        // possibly stop prefetching at page boundaries
30710466Sandreas.hansson@arm.com        if (page_addr != pageAddress(line_addr)) {
3089363Snilay@cs.wisc.edu            numPagesCrossed++;
3099363Snilay@cs.wisc.edu            if (!m_prefetch_cross_pages) {
3109363Snilay@cs.wisc.edu                // deallocate this stream prefetcher
3119363Snilay@cs.wisc.edu                mystream->m_is_valid = false;
3129363Snilay@cs.wisc.edu                return;
3139363Snilay@cs.wisc.edu            }
3149363Snilay@cs.wisc.edu        }
3159363Snilay@cs.wisc.edu
3169363Snilay@cs.wisc.edu        // launch prefetch
3179363Snilay@cs.wisc.edu        numPrefetchRequested++;
3189363Snilay@cs.wisc.edu        DPRINTF(RubyPrefetcher, "Requesting prefetch for %s\n", line_addr);
3199363Snilay@cs.wisc.edu        m_controller->enqueuePrefetch(line_addr, m_array[index].m_type);
3209363Snilay@cs.wisc.edu        prev_addr = line_addr;
3219363Snilay@cs.wisc.edu    }
3229363Snilay@cs.wisc.edu
3239363Snilay@cs.wisc.edu    // update the address to be the last address prefetched
3249363Snilay@cs.wisc.edu    mystream->m_address = line_addr;
3259363Snilay@cs.wisc.edu}
3269363Snilay@cs.wisc.edu
3279363Snilay@cs.wisc.eduPrefetchEntry *
3289363Snilay@cs.wisc.eduPrefetcher::getPrefetchEntry(const Address &address, uint32_t &index)
3299363Snilay@cs.wisc.edu{
3309363Snilay@cs.wisc.edu    // search all streams for a match
3319363Snilay@cs.wisc.edu    for (int i = 0; i < m_num_streams; i++) {
3329363Snilay@cs.wisc.edu        // search all the outstanding prefetches for this stream
3339363Snilay@cs.wisc.edu        if (m_array[i].m_is_valid) {
3349363Snilay@cs.wisc.edu            for (int j = 0; j < m_num_startup_pfs; j++) {
3359363Snilay@cs.wisc.edu                if (next_stride_address(m_array[i].m_address,
3369363Snilay@cs.wisc.edu                    -(m_array[i].m_stride*j)) == address) {
3379363Snilay@cs.wisc.edu                    return &(m_array[i]);
3389363Snilay@cs.wisc.edu                }
3399363Snilay@cs.wisc.edu            }
3409363Snilay@cs.wisc.edu        }
3419363Snilay@cs.wisc.edu    }
3429363Snilay@cs.wisc.edu    return NULL;
3439363Snilay@cs.wisc.edu}
3449363Snilay@cs.wisc.edu
3459363Snilay@cs.wisc.edubool
3469363Snilay@cs.wisc.eduPrefetcher::accessUnitFilter(std::vector<Address>& filter_table,
3479363Snilay@cs.wisc.edu    uint32_t *filter_hit, uint32_t &index, const Address &address,
3489363Snilay@cs.wisc.edu    int stride, bool &alloc)
3499363Snilay@cs.wisc.edu{
3509363Snilay@cs.wisc.edu    //reset the alloc flag
3519363Snilay@cs.wisc.edu    alloc = false;
3529363Snilay@cs.wisc.edu
3539363Snilay@cs.wisc.edu    Address line_addr = line_address(address);
3549363Snilay@cs.wisc.edu    for (int i = 0; i < m_num_unit_filters; i++) {
3559363Snilay@cs.wisc.edu        if (filter_table[i] == line_addr) {
3569363Snilay@cs.wisc.edu            filter_table[i] = next_stride_address(filter_table[i], stride);
3579363Snilay@cs.wisc.edu            filter_hit[i]++;
3589363Snilay@cs.wisc.edu            if (filter_hit[i] >= m_train_misses) {
3599363Snilay@cs.wisc.edu                alloc = true;
3609363Snilay@cs.wisc.edu            }
3619363Snilay@cs.wisc.edu            return true;
3629363Snilay@cs.wisc.edu        }
3639363Snilay@cs.wisc.edu    }
3649363Snilay@cs.wisc.edu
3659363Snilay@cs.wisc.edu    // enter this address in the table
3669363Snilay@cs.wisc.edu    int local_index = index;
3679363Snilay@cs.wisc.edu    filter_table[local_index] = next_stride_address(line_addr, stride);
3689363Snilay@cs.wisc.edu    filter_hit[local_index] = 0;
3699363Snilay@cs.wisc.edu    local_index = local_index + 1;
3709363Snilay@cs.wisc.edu    if (local_index >= m_num_unit_filters) {
3719363Snilay@cs.wisc.edu        local_index = 0;
3729363Snilay@cs.wisc.edu    }
3739363Snilay@cs.wisc.edu
3749363Snilay@cs.wisc.edu    index = local_index;
3759363Snilay@cs.wisc.edu    return false;
3769363Snilay@cs.wisc.edu}
3779363Snilay@cs.wisc.edu
3789363Snilay@cs.wisc.edubool
3799363Snilay@cs.wisc.eduPrefetcher::accessNonunitFilter(const Address& address, int *stride,
3809363Snilay@cs.wisc.edu    bool &alloc)
3819363Snilay@cs.wisc.edu{
3829363Snilay@cs.wisc.edu    //reset the alloc flag
3839363Snilay@cs.wisc.edu    alloc = false;
3849363Snilay@cs.wisc.edu
3859363Snilay@cs.wisc.edu    /// look for non-unit strides based on a (user-defined) page size
38610466Sandreas.hansson@arm.com    Address page_addr = pageAddress(address);
3879363Snilay@cs.wisc.edu    Address line_addr = line_address(address);
3889363Snilay@cs.wisc.edu
3899363Snilay@cs.wisc.edu    for (uint32_t i = 0; i < m_num_nonunit_filters; i++) {
39010466Sandreas.hansson@arm.com        if (pageAddress(m_nonunit_filter[i]) == page_addr) {
3919363Snilay@cs.wisc.edu            // hit in the non-unit filter
3929363Snilay@cs.wisc.edu            // compute the actual stride (for this reference)
3939363Snilay@cs.wisc.edu            int delta = line_addr.getAddress() - m_nonunit_filter[i].getAddress();
3949363Snilay@cs.wisc.edu
3959363Snilay@cs.wisc.edu            if (delta != 0) {
3969363Snilay@cs.wisc.edu                // no zero stride prefetches
3979363Snilay@cs.wisc.edu                // check that the stride matches (for the last N times)
3989363Snilay@cs.wisc.edu                if (delta == m_nonunit_stride[i]) {
3999363Snilay@cs.wisc.edu                    // -> stride hit
4009363Snilay@cs.wisc.edu                    // increment count (if > 2) allocate stream
4019363Snilay@cs.wisc.edu                    m_nonunit_hit[i]++;
4029363Snilay@cs.wisc.edu                    if (m_nonunit_hit[i] > m_train_misses) {
4039363Snilay@cs.wisc.edu                        //This stride HAS to be the multiplicative constant of
4049363Snilay@cs.wisc.edu                        //dataBlockBytes (bc next_stride_address is calculated based
4059363Snilay@cs.wisc.edu                        //on this multiplicative constant!)
4069363Snilay@cs.wisc.edu                        *stride = m_nonunit_stride[i]/RubySystem::getBlockSizeBytes();
4079363Snilay@cs.wisc.edu
4089363Snilay@cs.wisc.edu                        // clear this filter entry
4099363Snilay@cs.wisc.edu                        clearNonunitEntry(i);
4109363Snilay@cs.wisc.edu                        alloc = true;
4119363Snilay@cs.wisc.edu                    }
4129363Snilay@cs.wisc.edu                } else {
4139363Snilay@cs.wisc.edu                    // delta didn't match ... reset m_nonunit_hit count for this entry
4149363Snilay@cs.wisc.edu                    m_nonunit_hit[i] = 0;
4159363Snilay@cs.wisc.edu                }
4169363Snilay@cs.wisc.edu
4179363Snilay@cs.wisc.edu                // update the last address seen & the stride
4189363Snilay@cs.wisc.edu                m_nonunit_stride[i] = delta;
4199363Snilay@cs.wisc.edu                m_nonunit_filter[i] = line_addr;
4209363Snilay@cs.wisc.edu                return true;
4219363Snilay@cs.wisc.edu            } else {
4229363Snilay@cs.wisc.edu                return false;
4239363Snilay@cs.wisc.edu            }
4249363Snilay@cs.wisc.edu        }
4259363Snilay@cs.wisc.edu    }
4269363Snilay@cs.wisc.edu
4279363Snilay@cs.wisc.edu    // not found: enter this address in the table
4289363Snilay@cs.wisc.edu    m_nonunit_filter[m_nonunit_index] = line_addr;
4299363Snilay@cs.wisc.edu    m_nonunit_stride[m_nonunit_index] = 0;
4309363Snilay@cs.wisc.edu    m_nonunit_hit[m_nonunit_index]    = 0;
4319363Snilay@cs.wisc.edu
4329363Snilay@cs.wisc.edu    m_nonunit_index = m_nonunit_index + 1;
4339363Snilay@cs.wisc.edu    if (m_nonunit_index >= m_num_nonunit_filters) {
4349363Snilay@cs.wisc.edu        m_nonunit_index = 0;
4359363Snilay@cs.wisc.edu    }
4369363Snilay@cs.wisc.edu    return false;
4379363Snilay@cs.wisc.edu}
4389363Snilay@cs.wisc.edu
4399363Snilay@cs.wisc.eduvoid
4409363Snilay@cs.wisc.eduPrefetcher::print(std::ostream& out) const
4419363Snilay@cs.wisc.edu{
4429363Snilay@cs.wisc.edu    out << name() << " Prefetcher State\n";
4439363Snilay@cs.wisc.edu    // print out unit filter
4449363Snilay@cs.wisc.edu    out << "unit table:\n";
4459363Snilay@cs.wisc.edu    for (int i = 0; i < m_num_unit_filters; i++) {
4469363Snilay@cs.wisc.edu        out << m_unit_filter[i] << std::endl;
4479363Snilay@cs.wisc.edu    }
4489363Snilay@cs.wisc.edu
4499363Snilay@cs.wisc.edu    out << "negative table:\n";
4509363Snilay@cs.wisc.edu    for (int i = 0; i < m_num_unit_filters; i++) {
4519363Snilay@cs.wisc.edu        out << m_negative_filter[i] << std::endl;
4529363Snilay@cs.wisc.edu    }
4539363Snilay@cs.wisc.edu
4549363Snilay@cs.wisc.edu    // print out non-unit stride filter
4559363Snilay@cs.wisc.edu    out << "non-unit table:\n";
4569363Snilay@cs.wisc.edu    for (int i = 0; i < m_num_nonunit_filters; i++) {
4579363Snilay@cs.wisc.edu        out << m_nonunit_filter[i] << " "
4589363Snilay@cs.wisc.edu            << m_nonunit_stride[i] << " "
4599363Snilay@cs.wisc.edu            << m_nonunit_hit[i] << std::endl;
4609363Snilay@cs.wisc.edu    }
4619363Snilay@cs.wisc.edu
4629363Snilay@cs.wisc.edu    // print out allocated stream buffers
4639363Snilay@cs.wisc.edu    out << "streams:\n";
4649363Snilay@cs.wisc.edu    for (int i = 0; i < m_num_streams; i++) {
4659363Snilay@cs.wisc.edu        out << m_array[i].m_address << " "
4669363Snilay@cs.wisc.edu            << m_array[i].m_stride << " "
4679363Snilay@cs.wisc.edu            << m_array[i].m_is_valid << " "
4689363Snilay@cs.wisc.edu            << m_array[i].m_use_time << std::endl;
4699363Snilay@cs.wisc.edu    }
4709363Snilay@cs.wisc.edu}
47110466Sandreas.hansson@arm.com
47210466Sandreas.hansson@arm.comAddress
47310466Sandreas.hansson@arm.comPrefetcher::pageAddress(const Address& addr) const
47410466Sandreas.hansson@arm.com{
47510466Sandreas.hansson@arm.com    Address temp = addr;
47610466Sandreas.hansson@arm.com    temp.maskLowOrderBits(m_page_shift);
47710466Sandreas.hansson@arm.com    return temp;
47810466Sandreas.hansson@arm.com}
479