blob: a7e25fe02610a06fa3b0aa4ad0808ca30e6b6c21 [file] [log] [blame]
/**
* Copyright (c) 2019 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 Spatio-Temporal Memory Streaming Prefetcher (STeMS)
* Reference:
* Spatio-temporal memory streaming.
* Somogyi, S., Wenisch, T. F., Ailamaki, A., & Falsafi, B. (2009).
* ACM SIGARCH Computer Architecture News, 37(3), 69-80.
*
* Notes:
* - The functionality described in the paper as Streamed Value Buffer (SVB)
* is not implemented here, as this is handled by the QueuedPrefetcher class
*/
#ifndef __MEM_CACHE_PREFETCH_SPATIO_TEMPORAL_MEMORY_STREAMING_HH__
#define __MEM_CACHE_PREFETCH_SPATIO_TEMPORAL_MEMORY_STREAMING_HH__
#include <vector>
#include "mem/cache/prefetch/associative_set.hh"
#include "mem/cache/prefetch/queued.hh"
struct STeMSPrefetcherParams;
class STeMSPrefetcher : public QueuedPrefetcher
{
/** Size of each spatial region */
const size_t spatialRegionSize;
/** log_2 of the spatial region size */
const size_t spatialRegionSizeBits;
/** Number of reconstruction entries */
const unsigned int reconstructionEntries;
/**
* Entry data type for the Active Generation Table (AGT) and the Pattern
* Sequence Table (PST)
*/
struct ActiveGenerationTableEntry : public TaggedEntry {
/** Physical address of the spatial region */
Addr paddress;
/** PC that started this generation */
Addr pc;
/** Counter to keep track of the interleaving between sequences */
unsigned int seqCounter;
/** Sequence entry data type */
struct SequenceEntry {
/** 2-bit confidence counter */
unsigned int counter;
/** Offset, in cache lines, within the spatial region */
unsigned int offset;
/** Intearleaving position on the global access sequence */
unsigned int delta;
SequenceEntry() : counter(0), offset(0), delta(0)
{}
};
/** Sequence of accesses */
std::vector<SequenceEntry> sequence;
ActiveGenerationTableEntry(int num_positions) : paddress(0), pc(0),
seqCounter(0), sequence(num_positions)
{}
void reset() override
{
paddress = 0;
pc = 0;
seqCounter = 0;
for (auto &seq_entry : sequence) {
seq_entry.counter = 0;
seq_entry.offset = 0;
seq_entry.delta = 0;
}
}
/**
* Update the entry data with an entry from a generation that just
* ended. This operation can not be done with the copy constructor,
* becasuse the TaggedEntry component must not be copied.
* @param e entry which generation has ended
*/
void update(ActiveGenerationTableEntry const &e)
{
paddress = e.paddress;
pc = e.pc;
seqCounter = e.seqCounter;
sequence = e.sequence;
}
/**
* Add a new access to the sequence
* @param offset offset in cachelines within the spatial region
*/
void addOffset(unsigned int offset) {
// Search for the offset in the deltas array, if it exist, update
// the corresponding counter, if not, add the offset to the array
for (auto &seq_entry : sequence) {
if (seq_entry.counter > 0) {
if (seq_entry.offset == offset) {
//2 bit counter, saturates at 3
if (seq_entry.counter < 3) {
seq_entry.counter += 1;
}
}
} else {
// If the counter is 0 it means that this position is not
// being used, and we can allocate the new offset here
seq_entry.counter = 1;
seq_entry.offset = offset;
seq_entry.delta = seqCounter;
break;
}
}
seqCounter = 0;
}
};
/** Active Generation Table (AGT) */
AssociativeSet<ActiveGenerationTableEntry> activeGenerationTable;
/** Pattern Sequence Table (PST) */
AssociativeSet<ActiveGenerationTableEntry> patternSequenceTable;
/** Data type of the Region Miss Order Buffer entry */
struct RegionMissOrderBufferEntry {
/** Address of the spatial region */
Addr srAddress;
/**
* Address used to index the PST table, generated using the PC and the
* offset within the spatial region
*/
Addr pstAddress;
/** Delta within the global miss order sequence */
unsigned int delta;
/** Valid bit */
bool valid;
};
/** Region Miss Order Buffer (RMOB) */
std::vector<RegionMissOrderBufferEntry> rmob;
/** First free position (or older, if it is full) of the RMOB */
unsigned int rmobHead;
/** Counter to keep the count of accesses between trigger accesses */
unsigned int lastTriggerCounter;
/** Checks if the active generations have ended */
void checkForActiveGenerationsEnd();
/**
* Adds an entry to the RMOB
* @param sr_addr Spatial region address
* @param pst_addr Corresponding PST address
* @param delta Number of entries skipped in the global miss order
*/
void addToRMOB(Addr sr_addr, Addr pst_addr, unsigned int delta);
/**
* Reconstructs a sequence of accesses and generates the prefetch
* addresses, adding them to the addresses vector
* @param rmob_idx rmob position to start generating from
* @param addresses vector to add the addresses to be prefetched
*/
void reconstructSequence(unsigned int rmob_idx,
std::vector<AddrPriority> &addresses);
public:
STeMSPrefetcher(const STeMSPrefetcherParams* p);
~STeMSPrefetcher() {}
void calculatePrefetch(const PrefetchInfo &pfi,
std::vector<AddrPriority> &addresses) override;
};
#endif//__MEM_CACHE_PREFETCH_SPATIO_TEMPORAL_MEMORY_STREAMING_HH__