| /* |
| * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer; |
| * redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution; |
| * neither the name of the copyright holders nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef __MEM_RUBY_STRUCTURES_PREFETCHER_HH__ |
| #define __MEM_RUBY_STRUCTURES_PREFETCHER_HH__ |
| |
| // Implements Power 4 like prefetching |
| |
| #include <bitset> |
| |
| #include "base/statistics.hh" |
| #include "mem/ruby/common/Address.hh" |
| #include "mem/ruby/network/MessageBuffer.hh" |
| #include "mem/ruby/slicc_interface/AbstractController.hh" |
| #include "mem/ruby/slicc_interface/RubyRequest.hh" |
| #include "mem/ruby/system/RubySystem.hh" |
| #include "params/Prefetcher.hh" |
| #include "sim/sim_object.hh" |
| #include "sim/system.hh" |
| |
| #define MAX_PF_INFLIGHT 8 |
| |
| class PrefetchEntry |
| { |
| public: |
| /// constructor |
| PrefetchEntry() |
| { |
| // default: 1 cache-line stride |
| m_stride = (1 << RubySystem::getBlockSizeBits()); |
| m_use_time = Cycles(0); |
| m_is_valid = false; |
| } |
| |
| //! The base address for the stream prefetch |
| Addr m_address; |
| |
| //! stride distance to get next address from |
| int m_stride; |
| |
| //! the last time that any prefetched request was used |
| Cycles m_use_time; |
| |
| //! valid bit for each stream |
| bool m_is_valid; |
| |
| //! L1D prefetches loads and stores |
| RubyRequestType m_type; |
| |
| //! Bitset for tracking prefetches for which addresses have been |
| //! issued, which ones have completed. |
| std::bitset<MAX_PF_INFLIGHT> requestIssued; |
| std::bitset<MAX_PF_INFLIGHT> requestCompleted; |
| }; |
| |
| class Prefetcher : public SimObject |
| { |
| public: |
| typedef PrefetcherParams Params; |
| Prefetcher(const Params *p); |
| ~Prefetcher(); |
| |
| void issueNextPrefetch(Addr address, PrefetchEntry *stream); |
| /** |
| * Implement the prefetch hit(miss) callback interface. |
| * These functions are called by the cache when it hits(misses) |
| * on a line with the line's prefetch bit set. If this address |
| * hits in m_array we will continue prefetching the stream. |
| */ |
| void observePfHit(Addr address); |
| void observePfMiss(Addr address); |
| |
| /** |
| * Observe a memory miss from the cache. |
| * |
| * @param address The physical address that missed out of the cache. |
| */ |
| void observeMiss(Addr address, const RubyRequestType& type); |
| |
| /** |
| * Print out some statistics |
| */ |
| void print(std::ostream& out) const; |
| void setController(AbstractController *_ctrl) |
| { m_controller = _ctrl; } |
| |
| void regStats(); |
| |
| private: |
| /** |
| * Returns an unused stream buffer (or if all are used, returns the |
| * least recently used (accessed) stream buffer). |
| * @return The index of the least recently used stream buffer. |
| */ |
| uint32_t getLRUindex(void); |
| |
| //! clear a non-unit stride prefetcher entry |
| void clearNonunitEntry(uint32_t index); |
| |
| //! allocate a new stream buffer at a specific index |
| void initializeStream(Addr address, int stride, |
| uint32_t index, const RubyRequestType& type); |
| |
| //! get pointer to the matching stream entry, returns NULL if not found |
| //! index holds the multiple of the stride this address is. |
| PrefetchEntry* getPrefetchEntry(Addr address, |
| uint32_t &index); |
| |
| /// access a unit stride filter to determine if there is a hit |
| bool accessUnitFilter(std::vector<Addr>& filter_table, |
| uint32_t *hit_table, uint32_t &index, Addr address, |
| int stride, bool &alloc); |
| |
| /// access a unit stride filter to determine if there is a hit |
| bool accessNonunitFilter(Addr address, int *stride, |
| bool &alloc); |
| |
| /// determine the page aligned address |
| Addr pageAddress(Addr addr) const; |
| |
| //! number of prefetch streams available |
| uint32_t m_num_streams; |
| //! an array of the active prefetch streams |
| std::vector<PrefetchEntry> m_array; |
| |
| //! number of misses I must see before allocating a stream |
| uint32_t m_train_misses; |
| //! number of initial prefetches to startup a stream |
| uint32_t m_num_startup_pfs; |
| //! number of stride filters |
| uint32_t m_num_unit_filters; |
| //! number of non-stride filters |
| uint32_t m_num_nonunit_filters; |
| |
| /// a unit stride filter array: helps reduce BW requirement of |
| /// prefetching |
| std::vector<Addr> m_unit_filter; |
| /// a round robin pointer into the unit filter group |
| uint32_t m_unit_filter_index; |
| //! An array used to count the of times particular filter entries |
| //! have been hit |
| uint32_t *m_unit_filter_hit; |
| |
| //! a negative nit stride filter array: helps reduce BW requirement |
| //! of prefetching |
| std::vector<Addr> m_negative_filter; |
| /// a round robin pointer into the negative filter group |
| uint32_t m_negative_filter_index; |
| /// An array used to count the of times particular filter entries |
| /// have been hit |
| uint32_t *m_negative_filter_hit; |
| |
| /// a non-unit stride filter array: helps reduce BW requirement of |
| /// prefetching |
| std::vector<Addr> m_nonunit_filter; |
| /// An array of strides (in # of cache lines) for the filter entries |
| int *m_nonunit_stride; |
| /// An array used to count the of times particular filter entries |
| /// have been hit |
| uint32_t *m_nonunit_hit; |
| /// a round robin pointer into the unit filter group |
| uint32_t m_nonunit_index; |
| |
| /// Used for allowing prefetches across pages. |
| bool m_prefetch_cross_pages; |
| |
| AbstractController *m_controller; |
| |
| const Addr m_page_shift; |
| |
| //! Count of accesses to the prefetcher |
| Stats::Scalar numMissObserved; |
| //! Count of prefetch streams allocated |
| Stats::Scalar numAllocatedStreams; |
| //! Count of prefetch requests made |
| Stats::Scalar numPrefetchRequested; |
| //! Count of prefetch requests accepted |
| Stats::Scalar numPrefetchAccepted; |
| //! Count of prefetches dropped |
| Stats::Scalar numDroppedPrefetches; |
| //! Count of successful prefetches |
| Stats::Scalar numHits; |
| //! Count of partial successful prefetches |
| Stats::Scalar numPartialHits; |
| //! Count of pages crossed |
| Stats::Scalar numPagesCrossed; |
| //! Count of misses incurred for blocks that were prefetched |
| Stats::Scalar numMissedPrefetchedBlocks; |
| }; |
| |
| #endif // __MEM_RUBY_STRUCTURES_PREFETCHER_HH__ |