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