Prefetcher.cc revision 11793
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