| /** |
| * Copyright (c) 2018 Metempsy Technology Consulting |
| * 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. |
| * |
| * Authors: Javier Bueno |
| */ |
| |
| /** |
| * Implementation of the Signature Path Prefetcher |
| * |
| * References: |
| * Lookahead prefetching with signature path |
| * J Kim, PV Gratz, ALN Reddy |
| * The 2nd Data Prefetching Championship (DPC2) |
| * The filter feature described in the paper is not implemented, as it |
| * redundant prefetches are dropped by the cache. |
| */ |
| |
| #ifndef __MEM_CACHE_PREFETCH_SIGNATURE_PATH_HH__ |
| #define __MEM_CACHE_PREFETCH_SIGNATURE_PATH_HH__ |
| |
| #include "base/sat_counter.hh" |
| #include "mem/cache/prefetch/associative_set.hh" |
| #include "mem/cache/prefetch/queued.hh" |
| #include "mem/packet.hh" |
| |
| struct SignaturePathPrefetcherParams; |
| |
| class SignaturePathPrefetcher : public QueuedPrefetcher |
| { |
| protected: |
| /** Signature type */ |
| typedef uint16_t signature_t; |
| /** Stride type */ |
| typedef int16_t stride_t; |
| |
| /** Number of strides stored in each pattern entry */ |
| const unsigned stridesPerPatternEntry; |
| /** Number of bits to shift when generating a new signature */ |
| const uint8_t signatureShift; |
| /** Size of the signature, in bits */ |
| const signature_t signatureBits; |
| /** Minimum confidence to issue a prefetch */ |
| const double prefetchConfidenceThreshold; |
| /** Minimum confidence to keep navigating lookahead entries */ |
| const double lookaheadConfidenceThreshold; |
| |
| /** Signature entry data type */ |
| struct SignatureEntry : public TaggedEntry |
| { |
| /** Path signature */ |
| signature_t signature; |
| /** Last accessed block within a page */ |
| stride_t lastBlock; |
| SignatureEntry() : signature(0), lastBlock(0) |
| {} |
| }; |
| /** Signature table */ |
| AssociativeSet<SignatureEntry> signatureTable; |
| |
| /** A stride entry with its counter */ |
| struct PatternStrideEntry |
| { |
| /** stride in a page in blkSize increments */ |
| stride_t stride; |
| /** Saturating counter */ |
| SatCounter counter; |
| PatternStrideEntry(unsigned bits) : stride(0), counter(bits) |
| {} |
| }; |
| /** Pattern entry data type, a set of stride and counter entries */ |
| struct PatternEntry : public TaggedEntry |
| { |
| /** group of stides */ |
| std::vector<PatternStrideEntry> strideEntries; |
| /** use counter, used by SPPv2 */ |
| SatCounter counter; |
| PatternEntry(size_t num_strides, unsigned counter_bits) |
| : strideEntries(num_strides, counter_bits), counter(counter_bits) |
| {} |
| |
| /** Reset the entries to their initial values */ |
| void reset() override |
| { |
| for (auto &entry : strideEntries) { |
| entry.counter.reset(); |
| entry.stride = 0; |
| } |
| counter.reset(); |
| } |
| |
| /** |
| * Returns the entry with the desired stride |
| * @param stride the stride to find |
| * @result a pointer to the entry, if the stride was found, or nullptr, |
| * if the stride was not found |
| */ |
| PatternStrideEntry *findStride(stride_t stride) |
| { |
| PatternStrideEntry *found_entry = nullptr; |
| for (auto &entry : strideEntries) { |
| if (entry.stride == stride) { |
| found_entry = &entry; |
| break; |
| } |
| } |
| return found_entry; |
| } |
| |
| /** |
| * Gets the entry with the provided stride, if there is no entry with |
| * the associated stride, it replaces one of them. |
| * @param stride the stride to find |
| * @result reference to the selected entry |
| */ |
| PatternStrideEntry &getStrideEntry(stride_t stride); |
| }; |
| /** Pattern table */ |
| AssociativeSet<PatternEntry> patternTable; |
| |
| /** |
| * Generates a new signature from an existing one and a new stride |
| * @param sig current signature |
| * @param str stride to add to the new signature |
| * @result the new signature |
| */ |
| inline signature_t updateSignature(signature_t sig, stride_t str) const { |
| sig <<= signatureShift; |
| sig ^= str; |
| sig &= mask(signatureBits); |
| return sig; |
| } |
| |
| /** |
| * Generates an address to be prefetched. |
| * @param ppn page number to prefetch from |
| * @param last_block last accessed block within the page ppn |
| * @param delta difference, in number of blocks, from the last_block |
| * accessed to the block to prefetch. The block to prefetch is |
| * computed by this formula: |
| * ppn * pageBytes + (last_block + delta) * blkSize |
| * This value can be negative. |
| * @param path_confidence the confidence factor of this prefetch |
| * @param signature the current path signature |
| * @param is_secure whether this page is inside the secure memory area |
| * @param addresses addresses to prefetch will be added to this vector |
| */ |
| void addPrefetch(Addr ppn, stride_t last_block, stride_t delta, |
| double path_confidence, signature_t signature, |
| bool is_secure, |
| std::vector<AddrPriority> &addresses); |
| |
| /** |
| * Obtains the SignatureEntry of the given page, if the page is not found, |
| * it allocates a new one, replacing an existing entry if needed |
| * It also provides the stride of the current block and the initial |
| * path confidence of the corresponding entry |
| * @param ppn physical page number of the page |
| * @param is_secure whether this page is inside the secure memory area |
| * @param block accessed block within the page |
| * @param miss if the entry is not found, this will be set to true |
| * @param stride set to the computed stride |
| * @param initial_confidence set to the initial confidence value |
| * @result a reference to the SignatureEntry |
| */ |
| SignatureEntry &getSignatureEntry(Addr ppn, bool is_secure, stride_t block, |
| bool &miss, stride_t &stride, double &initial_confidence); |
| /** |
| * Obtains the PatternEntry of the given signature, if the signature is |
| * not found, it allocates a new one, replacing an existing entry if needed |
| * @param signature the signature of the desired entry |
| * @result a reference to the PatternEntry |
| */ |
| PatternEntry& getPatternEntry(Addr signature); |
| |
| /** |
| * Updates the pattern table with the provided signature and stride |
| * @param signature the signature to use to index the pattern table |
| * @param stride the stride to use to index the set of strides of the |
| * pattern table entry |
| */ |
| void updatePatternTable(Addr signature, stride_t stride); |
| |
| /** |
| * Computes the lookahead path confidence of the provided pattern entry |
| * @param sig the PatternEntry to use |
| * @param lookahead PatternStrideEntry within the provided PatternEntry |
| * @return the computed confidence factor |
| */ |
| virtual double calculateLookaheadConfidence(PatternEntry const &sig, |
| PatternStrideEntry const &lookahead) const; |
| |
| /** |
| * Computes the prefetch confidence of the provided pattern entry |
| * @param sig the PatternEntry to use |
| * @param entry PatternStrideEntry within the provided PatternEntry |
| * @return the computed confidence factor |
| */ |
| virtual double calculatePrefetchConfidence(PatternEntry const &sig, |
| PatternStrideEntry const &entry) const; |
| |
| /** |
| * Increases the counter of a given PatternEntry/PatternStrideEntry |
| * @param pattern_entry the corresponding PatternEntry |
| * @param pstride_entry the PatternStrideEntry within the PatternEntry |
| */ |
| virtual void increasePatternEntryCounter(PatternEntry &pattern_entry, |
| PatternStrideEntry &pstride_entry); |
| |
| /** |
| * Whenever a new SignatureEntry is allocated, it computes the new |
| * signature to be used with the new entry, the resulting stride and the |
| * initial path confidence of the new entry. |
| * @param current_block accessed block within the page of the associated |
| entry |
| * @param new_signature new signature of the allocated entry |
| * @param new_conf the initial path confidence of this entry |
| * @param new_stride the resulting current stride |
| */ |
| virtual void handleSignatureTableMiss(stride_t current_block, |
| signature_t &new_signature, double &new_conf, |
| stride_t &new_stride); |
| |
| /** |
| * Auxiliar prefetch mechanism used at the end of calculatePrefetch. |
| * This prefetcher uses this to activate the next line prefetcher if |
| * no prefetch candidates have been found. |
| * @param ppn physical page number of the current accessed page |
| * @param current_block last accessed block within the page ppn |
| * @param is_secure whether this page is inside the secure memory area |
| * @param addresses the addresses to be prefetched are added to this vector |
| * @param updated_filter_entries set of addresses containing these that |
| * their filter has been updated, if this call updates a new entry |
| */ |
| virtual void auxiliaryPrefetcher(Addr ppn, stride_t current_block, |
| bool is_secure, std::vector<AddrPriority> &addresses); |
| |
| /** |
| * Handles the situation when the lookahead process has crossed the |
| * boundaries of the current page. This is not fully described in the |
| * paper that was used to implement this code, however, the article |
| * describing the upgraded version of this prefetcher provides some |
| * details. For this prefetcher, there are no specific actions to be |
| * done. |
| * @param signature the lookahead signature that crossed the page |
| * @param delta the current stride that caused it |
| * @param last_offset the last accessed block within the page |
| * @param path_confidence the path confidence at the moment of crossing |
| */ |
| virtual void handlePageCrossingLookahead(signature_t signature, |
| stride_t last_offset, stride_t delta, double path_confidence) { |
| } |
| |
| public: |
| SignaturePathPrefetcher(const SignaturePathPrefetcherParams* p); |
| ~SignaturePathPrefetcher() {} |
| void calculatePrefetch(const PrefetchInfo &pfi, |
| std::vector<AddrPriority> &addresses) override; |
| }; |
| |
| #endif//__MEM_CACHE_PREFETCH_SIGNATURE_PATH_HH__ |