: SimObject(p), m_num_streams(p->num_streams),
m_array(p->num_streams), m_train_misses(p->train_misses),
m_num_startup_pfs(p->num_startup_pfs),
- m_num_nonunit_filters(p->nonunit_filter),
unitFilter(p->unit_filter),
negativeFilter(p->unit_filter),
- m_nonunit_filter(p->nonunit_filter, 0),
+ nonUnitFilter(p->nonunit_filter),
m_prefetch_cross_pages(p->cross_page),
m_page_shift(p->sys->getPageShift())
{
assert(m_num_streams > 0);
assert(m_num_startup_pfs <= MAX_PF_INFLIGHT);
-
- // create nonunit stride filter
- m_nonunit_index = 0;
- m_nonunit_stride = new int[m_num_nonunit_filters];
- m_nonunit_hit = new uint32_t[m_num_nonunit_filters];
- for (int i =0; i < m_num_nonunit_filters; i++) {
- m_nonunit_stride[i] = 0;
- m_nonunit_hit[i] = 0;
- }
-}
-
-RubyPrefetcher::~RubyPrefetcher()
-{
- delete m_nonunit_stride;
- delete m_nonunit_hit;
}
void
// check to see if this address is in the non-unit stride filter
int stride = 0; // NULL value
- hit = accessNonunitFilter(address, &stride, alloc);
+ hit = accessNonunitFilter(line_addr, &stride, alloc);
if (alloc) {
assert(stride != 0); // ensure non-zero stride prefetches
initializeStream(line_addr, stride, getLRUindex(), type);
return lru_index;
}
-void
-RubyPrefetcher::clearNonunitEntry(uint32_t index)
-{
- m_nonunit_filter[index] = 0;
- m_nonunit_stride[index] = 0;
- m_nonunit_hit[index] = 0;
-}
-
void
RubyPrefetcher::initializeStream(Addr address, int stride,
uint32_t index, const RubyRequestType& type)
}
bool
-RubyPrefetcher::accessNonunitFilter(Addr address, int *stride,
- bool &alloc)
+RubyPrefetcher::accessNonunitFilter(Addr line_addr, int *stride, bool &alloc)
{
//reset the alloc flag
alloc = false;
/// look for non-unit strides based on a (user-defined) page size
- Addr page_addr = pageAddress(address);
- Addr line_addr = makeLineAddress(address);
+ Addr page_addr = pageAddress(line_addr);
- for (uint32_t i = 0; i < m_num_nonunit_filters; i++) {
- if (pageAddress(m_nonunit_filter[i]) == page_addr) {
+ for (auto& entry : nonUnitFilter) {
+ if (pageAddress(entry.addr) == page_addr) {
// hit in the non-unit filter
// compute the actual stride (for this reference)
- int delta = line_addr - m_nonunit_filter[i];
+ int delta = line_addr - entry.addr;
if (delta != 0) {
// no zero stride prefetches
// check that the stride matches (for the last N times)
- if (delta == m_nonunit_stride[i]) {
+ if (delta == entry.stride) {
// -> stride hit
// increment count (if > 2) allocate stream
- m_nonunit_hit[i]++;
- if (m_nonunit_hit[i] > m_train_misses) {
+ entry.hits++;
+ if (entry.hits > m_train_misses) {
// This stride HAS to be the multiplicative constant of
// dataBlockBytes (bc makeNextStrideAddress is
// calculated based on this multiplicative constant!)
- *stride = m_nonunit_stride[i] /
- RubySystem::getBlockSizeBytes();
+ *stride = entry.stride /
+ RubySystem::getBlockSizeBytes();
// clear this filter entry
- clearNonunitEntry(i);
+ entry.clear();
alloc = true;
}
} else {
- // delta didn't match ... reset m_nonunit_hit count for
- // this entry
- m_nonunit_hit[i] = 0;
+ // If delta didn't match reset entry's hit count
+ entry.hits = 0;
}
// update the last address seen & the stride
- m_nonunit_stride[i] = delta;
- m_nonunit_filter[i] = line_addr;
+ entry.addr = line_addr;
+ entry.stride = delta;
return true;
} else {
return false;
}
// not found: enter this address in the table
- m_nonunit_filter[m_nonunit_index] = line_addr;
- m_nonunit_stride[m_nonunit_index] = 0;
- m_nonunit_hit[m_nonunit_index] = 0;
+ nonUnitFilter.push_back(NonUnitFilterEntry(line_addr));
- m_nonunit_index = m_nonunit_index + 1;
- if (m_nonunit_index >= m_num_nonunit_filters) {
- m_nonunit_index = 0;
- }
return false;
}
// print out non-unit stride filter
out << "non-unit table:\n";
- for (int i = 0; i < m_num_nonunit_filters; i++) {
- out << m_nonunit_filter[i] << " "
- << m_nonunit_stride[i] << " "
- << m_nonunit_hit[i] << std::endl;
+ for (const auto& entry : nonUnitFilter) {
+ out << entry.addr << " "
+ << entry.stride << " "
+ << entry.hits << std::endl;
}
// print out allocated stream buffers
public:
typedef RubyPrefetcherParams Params;
RubyPrefetcher(const Params *p);
- ~RubyPrefetcher();
+ ~RubyPrefetcher() = default;
void issueNextPrefetch(Addr address, PrefetchEntry *stream);
/**
}
};
+ struct NonUnitFilterEntry : public UnitFilterEntry
+ {
+ /** Stride (in # of cache lines). */
+ int stride;
+
+ NonUnitFilterEntry(Addr _addr = 0)
+ : UnitFilterEntry(_addr), stride(0)
+ {
+ }
+
+ void
+ clear()
+ {
+ addr = 0;
+ stride = 0;
+ hits = 0;
+ }
+ };
+
/**
* Returns an unused stream buffer (or if all are used, returns the
* least recently used (accessed) 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);
bool accessUnitFilter(CircularQueue<UnitFilterEntry>* const filter,
Addr line_addr, int stride, bool &alloc);
- /// access a unit stride filter to determine if there is a hit
- bool accessNonunitFilter(Addr address, int *stride,
- bool &alloc);
+ /**
+ * Access a non-unit stride filter to determine if there is a hit, and
+ * update it otherwise.
+ *
+ * @param line_addr Address being accessed, block aligned.
+ * @param stride The stride value.
+ * @param alloc Whether a stream should be allocated on a hit.
+ * @return True if a corresponding entry was found and its stride is
+ * not zero.
+ */
+ bool accessNonunitFilter(Addr line_addr, int *stride, bool &alloc);
/// determine the page aligned address
Addr pageAddress(Addr addr) const;
uint32_t m_train_misses;
//! number of initial prefetches to startup a stream
uint32_t m_num_startup_pfs;
- //! number of non-stride filters
- uint32_t m_num_nonunit_filters;
/**
* A unit stride filter array: helps reduce BW requirement
*/
CircularQueue<UnitFilterEntry> negativeFilter;
- /// 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;
+ /**
+ * A non-unit stride filter array: helps reduce BW requirement of
+ * prefetching.
+ */
+ CircularQueue<NonUnitFilterEntry> nonUnitFilter;
/// Used for allowing prefetches across pages.
bool m_prefetch_cross_pages;