1/* 2 * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#ifndef __MEM_RUBY_STRUCTURES_PREFETCHER_HH__ 30#define __MEM_RUBY_STRUCTURES_PREFETCHER_HH__ 31 32// Implements Power 4 like prefetching 33 34#include <bitset> 35 36#include "base/statistics.hh" 37#include "mem/ruby/common/Address.hh" 38#include "mem/ruby/network/MessageBuffer.hh" 39#include "mem/ruby/slicc_interface/AbstractController.hh" 40#include "mem/ruby/slicc_interface/RubyRequest.hh" 41#include "mem/ruby/system/RubySystem.hh" 42#include "params/Prefetcher.hh" 43#include "sim/sim_object.hh" 44#include "sim/system.hh" 45 46#define MAX_PF_INFLIGHT 8 47 48class PrefetchEntry 49{ 50 public: 51 /// constructor 52 PrefetchEntry() 53 { 54 // default: 1 cache-line stride 55 m_stride = (1 << RubySystem::getBlockSizeBits()); 56 m_use_time = Cycles(0); 57 m_is_valid = false; 58 } 59 60 //! The base address for the stream prefetch 61 Addr m_address; 62 63 //! stride distance to get next address from 64 int m_stride; 65 66 //! the last time that any prefetched request was used 67 Cycles m_use_time; 68 69 //! valid bit for each stream 70 bool m_is_valid; 71 72 //! L1D prefetches loads and stores 73 RubyRequestType m_type; 74 75 //! Bitset for tracking prefetches for which addresses have been 76 //! issued, which ones have completed. 77 std::bitset<MAX_PF_INFLIGHT> requestIssued; 78 std::bitset<MAX_PF_INFLIGHT> requestCompleted; 79}; 80 81class Prefetcher : public SimObject 82{ 83 public: 84 typedef PrefetcherParams Params; 85 Prefetcher(const Params *p); 86 ~Prefetcher(); 87 88 void issueNextPrefetch(Addr address, PrefetchEntry *stream); 89 /** 90 * Implement the prefetch hit(miss) callback interface. 91 * These functions are called by the cache when it hits(misses) 92 * on a line with the line's prefetch bit set. If this address 93 * hits in m_array we will continue prefetching the stream. 94 */ 95 void observePfHit(Addr address); 96 void observePfMiss(Addr address); 97 98 /** 99 * Observe a memory miss from the cache. 100 * 101 * @param address The physical address that missed out of the cache. 102 */ 103 void observeMiss(Addr address, const RubyRequestType& type); 104 105 /** 106 * Print out some statistics 107 */ 108 void print(std::ostream& out) const; 109 void setController(AbstractController *_ctrl) 110 { m_controller = _ctrl; } 111 112 void regStats(); 113 114 private: 115 /** 116 * Returns an unused stream buffer (or if all are used, returns the 117 * least recently used (accessed) stream buffer). 118 * @return The index of the least recently used stream buffer. 119 */ 120 uint32_t getLRUindex(void); 121 122 //! clear a non-unit stride prefetcher entry 123 void clearNonunitEntry(uint32_t index); 124 125 //! allocate a new stream buffer at a specific index 126 void initializeStream(Addr address, int stride, 127 uint32_t index, const RubyRequestType& type); 128 129 //! get pointer to the matching stream entry, returns NULL if not found 130 //! index holds the multiple of the stride this address is. 131 PrefetchEntry* getPrefetchEntry(Addr address, 132 uint32_t &index); 133 134 /// access a unit stride filter to determine if there is a hit 135 bool accessUnitFilter(std::vector<Addr>& filter_table, 136 uint32_t *hit_table, uint32_t &index, Addr address, 137 int stride, bool &alloc); 138 139 /// access a unit stride filter to determine if there is a hit 140 bool accessNonunitFilter(Addr address, int *stride, 141 bool &alloc); 142 143 /// determine the page aligned address 144 Addr pageAddress(Addr addr) const; 145 146 //! number of prefetch streams available 147 uint32_t m_num_streams; 148 //! an array of the active prefetch streams 149 std::vector<PrefetchEntry> m_array; 150 151 //! number of misses I must see before allocating a stream 152 uint32_t m_train_misses; 153 //! number of initial prefetches to startup a stream 154 uint32_t m_num_startup_pfs; 155 //! number of stride filters 156 uint32_t m_num_unit_filters; 157 //! number of non-stride filters 158 uint32_t m_num_nonunit_filters; 159 160 /// a unit stride filter array: helps reduce BW requirement of 161 /// prefetching 162 std::vector<Addr> m_unit_filter; 163 /// a round robin pointer into the unit filter group 164 uint32_t m_unit_filter_index; 165 //! An array used to count the of times particular filter entries 166 //! have been hit 167 uint32_t *m_unit_filter_hit; 168 169 //! a negative nit stride filter array: helps reduce BW requirement 170 //! of prefetching 171 std::vector<Addr> m_negative_filter; 172 /// a round robin pointer into the negative filter group 173 uint32_t m_negative_filter_index; 174 /// An array used to count the of times particular filter entries 175 /// have been hit 176 uint32_t *m_negative_filter_hit; 177 178 /// a non-unit stride filter array: helps reduce BW requirement of 179 /// prefetching 180 std::vector<Addr> m_nonunit_filter; 181 /// An array of strides (in # of cache lines) for the filter entries 182 int *m_nonunit_stride; 183 /// An array used to count the of times particular filter entries 184 /// have been hit 185 uint32_t *m_nonunit_hit; 186 /// a round robin pointer into the unit filter group 187 uint32_t m_nonunit_index; 188 189 /// Used for allowing prefetches across pages. 190 bool m_prefetch_cross_pages; 191 192 AbstractController *m_controller; 193 194 const Addr m_page_shift; 195 196 //! Count of accesses to the prefetcher 197 Stats::Scalar numMissObserved; 198 //! Count of prefetch streams allocated 199 Stats::Scalar numAllocatedStreams; 200 //! Count of prefetch requests made 201 Stats::Scalar numPrefetchRequested; 202 //! Count of prefetch requests accepted 203 Stats::Scalar numPrefetchAccepted; 204 //! Count of prefetches dropped 205 Stats::Scalar numDroppedPrefetches; 206 //! Count of successful prefetches 207 Stats::Scalar numHits; 208 //! Count of partial successful prefetches 209 Stats::Scalar numPartialHits; 210 //! Count of pages crossed 211 Stats::Scalar numPagesCrossed; 212 //! Count of misses incurred for blocks that were prefetched 213 Stats::Scalar numMissedPrefetchedBlocks; 214}; 215 216#endif // __MEM_RUBY_STRUCTURES_PREFETCHER_HH__ 217