Prefetcher.cc revision 11118
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" 3211108Sdavid.hashe@amd.com#include "mem/ruby/system/RubySystem.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), 4511025Snilay@cs.wisc.edu m_unit_filter(p->unit_filter, 0), 4611025Snilay@cs.wisc.edu m_negative_filter(p->unit_filter, 0), 4711025Snilay@cs.wisc.edu m_nonunit_filter(p->nonunit_filter, 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 13611025Snilay@cs.wisc.eduPrefetcher::observeMiss(Addr address, const RubyRequestType& type) 1379363Snilay@cs.wisc.edu{ 13811118Snilay@cs.wisc.edu DPRINTF(RubyPrefetcher, "Observed miss for %#x\n", address); 13911025Snilay@cs.wisc.edu Addr line_addr = makeLineAddress(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 20411025Snilay@cs.wisc.eduPrefetcher::observePfMiss(Addr address) 2059363Snilay@cs.wisc.edu{ 2069363Snilay@cs.wisc.edu numPartialHits++; 20711118Snilay@cs.wisc.edu DPRINTF(RubyPrefetcher, "Observed partial hit for %#x\n", address); 2089363Snilay@cs.wisc.edu issueNextPrefetch(address, NULL); 2099363Snilay@cs.wisc.edu} 2109363Snilay@cs.wisc.edu 2119363Snilay@cs.wisc.eduvoid 21211025Snilay@cs.wisc.eduPrefetcher::observePfHit(Addr address) 2139363Snilay@cs.wisc.edu{ 2149363Snilay@cs.wisc.edu numHits++; 21511118Snilay@cs.wisc.edu DPRINTF(RubyPrefetcher, "Observed hit for %#x\n", address); 2169363Snilay@cs.wisc.edu issueNextPrefetch(address, NULL); 2179363Snilay@cs.wisc.edu} 2189363Snilay@cs.wisc.edu 2199363Snilay@cs.wisc.eduvoid 22011025Snilay@cs.wisc.eduPrefetcher::issueNextPrefetch(Addr 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) 23511025Snilay@cs.wisc.edu Addr page_addr = pageAddress(stream->m_address); 23611025Snilay@cs.wisc.edu Addr line_addr = makeNextStrideAddress(stream->m_address, 23711025Snilay@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(); 25311118Snilay@cs.wisc.edu DPRINTF(RubyPrefetcher, "Requesting prefetch for %#x\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{ 27911025Snilay@cs.wisc.edu m_nonunit_filter[index] = 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 28511025Snilay@cs.wisc.eduPrefetcher::initializeStream(Addr 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]); 29211025Snilay@cs.wisc.edu mystream->m_address = makeLineAddress(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 29911025Snilay@cs.wisc.edu Addr page_addr = pageAddress(mystream->m_address); 30011025Snilay@cs.wisc.edu Addr line_addr = makeLineAddress(mystream->m_address); 3019363Snilay@cs.wisc.edu 3029363Snilay@cs.wisc.edu // insert a number of prefetches into the prefetch table 3039363Snilay@cs.wisc.edu for (int k = 0; k < m_num_startup_pfs; k++) { 30411025Snilay@cs.wisc.edu line_addr = makeNextStrideAddress(line_addr, stride); 3059363Snilay@cs.wisc.edu // possibly stop prefetching at page boundaries 30610466Sandreas.hansson@arm.com if (page_addr != pageAddress(line_addr)) { 3079363Snilay@cs.wisc.edu numPagesCrossed++; 3089363Snilay@cs.wisc.edu if (!m_prefetch_cross_pages) { 3099363Snilay@cs.wisc.edu // deallocate this stream prefetcher 3109363Snilay@cs.wisc.edu mystream->m_is_valid = false; 3119363Snilay@cs.wisc.edu return; 3129363Snilay@cs.wisc.edu } 3139363Snilay@cs.wisc.edu } 3149363Snilay@cs.wisc.edu 3159363Snilay@cs.wisc.edu // launch prefetch 3169363Snilay@cs.wisc.edu numPrefetchRequested++; 31711118Snilay@cs.wisc.edu DPRINTF(RubyPrefetcher, "Requesting prefetch for %#x\n", line_addr); 3189363Snilay@cs.wisc.edu m_controller->enqueuePrefetch(line_addr, m_array[index].m_type); 3199363Snilay@cs.wisc.edu } 3209363Snilay@cs.wisc.edu 3219363Snilay@cs.wisc.edu // update the address to be the last address prefetched 3229363Snilay@cs.wisc.edu mystream->m_address = line_addr; 3239363Snilay@cs.wisc.edu} 3249363Snilay@cs.wisc.edu 3259363Snilay@cs.wisc.eduPrefetchEntry * 32611025Snilay@cs.wisc.eduPrefetcher::getPrefetchEntry(Addr address, uint32_t &index) 3279363Snilay@cs.wisc.edu{ 3289363Snilay@cs.wisc.edu // search all streams for a match 3299363Snilay@cs.wisc.edu for (int i = 0; i < m_num_streams; i++) { 3309363Snilay@cs.wisc.edu // search all the outstanding prefetches for this stream 3319363Snilay@cs.wisc.edu if (m_array[i].m_is_valid) { 3329363Snilay@cs.wisc.edu for (int j = 0; j < m_num_startup_pfs; j++) { 33311025Snilay@cs.wisc.edu if (makeNextStrideAddress(m_array[i].m_address, 3349363Snilay@cs.wisc.edu -(m_array[i].m_stride*j)) == address) { 3359363Snilay@cs.wisc.edu return &(m_array[i]); 3369363Snilay@cs.wisc.edu } 3379363Snilay@cs.wisc.edu } 3389363Snilay@cs.wisc.edu } 3399363Snilay@cs.wisc.edu } 3409363Snilay@cs.wisc.edu return NULL; 3419363Snilay@cs.wisc.edu} 3429363Snilay@cs.wisc.edu 3439363Snilay@cs.wisc.edubool 34411025Snilay@cs.wisc.eduPrefetcher::accessUnitFilter(std::vector<Addr>& filter_table, 34511025Snilay@cs.wisc.edu uint32_t *filter_hit, uint32_t &index, Addr address, 3469363Snilay@cs.wisc.edu int stride, bool &alloc) 3479363Snilay@cs.wisc.edu{ 3489363Snilay@cs.wisc.edu //reset the alloc flag 3499363Snilay@cs.wisc.edu alloc = false; 3509363Snilay@cs.wisc.edu 35111025Snilay@cs.wisc.edu Addr line_addr = makeLineAddress(address); 3529363Snilay@cs.wisc.edu for (int i = 0; i < m_num_unit_filters; i++) { 3539363Snilay@cs.wisc.edu if (filter_table[i] == line_addr) { 35411025Snilay@cs.wisc.edu filter_table[i] = makeNextStrideAddress(filter_table[i], stride); 3559363Snilay@cs.wisc.edu filter_hit[i]++; 3569363Snilay@cs.wisc.edu if (filter_hit[i] >= m_train_misses) { 3579363Snilay@cs.wisc.edu alloc = true; 3589363Snilay@cs.wisc.edu } 3599363Snilay@cs.wisc.edu return true; 3609363Snilay@cs.wisc.edu } 3619363Snilay@cs.wisc.edu } 3629363Snilay@cs.wisc.edu 3639363Snilay@cs.wisc.edu // enter this address in the table 3649363Snilay@cs.wisc.edu int local_index = index; 36511025Snilay@cs.wisc.edu filter_table[local_index] = makeNextStrideAddress(line_addr, stride); 3669363Snilay@cs.wisc.edu filter_hit[local_index] = 0; 3679363Snilay@cs.wisc.edu local_index = local_index + 1; 3689363Snilay@cs.wisc.edu if (local_index >= m_num_unit_filters) { 3699363Snilay@cs.wisc.edu local_index = 0; 3709363Snilay@cs.wisc.edu } 3719363Snilay@cs.wisc.edu 3729363Snilay@cs.wisc.edu index = local_index; 3739363Snilay@cs.wisc.edu return false; 3749363Snilay@cs.wisc.edu} 3759363Snilay@cs.wisc.edu 3769363Snilay@cs.wisc.edubool 37711025Snilay@cs.wisc.eduPrefetcher::accessNonunitFilter(Addr address, int *stride, 3789363Snilay@cs.wisc.edu bool &alloc) 3799363Snilay@cs.wisc.edu{ 3809363Snilay@cs.wisc.edu //reset the alloc flag 3819363Snilay@cs.wisc.edu alloc = false; 3829363Snilay@cs.wisc.edu 3839363Snilay@cs.wisc.edu /// look for non-unit strides based on a (user-defined) page size 38411025Snilay@cs.wisc.edu Addr page_addr = pageAddress(address); 38511025Snilay@cs.wisc.edu Addr line_addr = makeLineAddress(address); 3869363Snilay@cs.wisc.edu 3879363Snilay@cs.wisc.edu for (uint32_t i = 0; i < m_num_nonunit_filters; i++) { 38810466Sandreas.hansson@arm.com if (pageAddress(m_nonunit_filter[i]) == page_addr) { 3899363Snilay@cs.wisc.edu // hit in the non-unit filter 3909363Snilay@cs.wisc.edu // compute the actual stride (for this reference) 39111025Snilay@cs.wisc.edu int delta = line_addr - m_nonunit_filter[i]; 3929363Snilay@cs.wisc.edu 3939363Snilay@cs.wisc.edu if (delta != 0) { 3949363Snilay@cs.wisc.edu // no zero stride prefetches 3959363Snilay@cs.wisc.edu // check that the stride matches (for the last N times) 3969363Snilay@cs.wisc.edu if (delta == m_nonunit_stride[i]) { 3979363Snilay@cs.wisc.edu // -> stride hit 3989363Snilay@cs.wisc.edu // increment count (if > 2) allocate stream 3999363Snilay@cs.wisc.edu m_nonunit_hit[i]++; 4009363Snilay@cs.wisc.edu if (m_nonunit_hit[i] > m_train_misses) { 40111025Snilay@cs.wisc.edu // This stride HAS to be the multiplicative constant of 40211025Snilay@cs.wisc.edu // dataBlockBytes (bc makeNextStrideAddress is 40311025Snilay@cs.wisc.edu // calculated based on this multiplicative constant!) 40411025Snilay@cs.wisc.edu *stride = m_nonunit_stride[i] / 40511025Snilay@cs.wisc.edu RubySystem::getBlockSizeBytes(); 4069363Snilay@cs.wisc.edu 4079363Snilay@cs.wisc.edu // clear this filter entry 4089363Snilay@cs.wisc.edu clearNonunitEntry(i); 4099363Snilay@cs.wisc.edu alloc = true; 4109363Snilay@cs.wisc.edu } 4119363Snilay@cs.wisc.edu } else { 41211025Snilay@cs.wisc.edu // delta didn't match ... reset m_nonunit_hit count for 41311025Snilay@cs.wisc.edu // 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 47211025Snilay@cs.wisc.eduAddr 47311025Snilay@cs.wisc.eduPrefetcher::pageAddress(Addr addr) const 47410466Sandreas.hansson@arm.com{ 47511025Snilay@cs.wisc.edu return maskLowOrderBits(addr, m_page_shift); 47610466Sandreas.hansson@arm.com} 477