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