diff --git a/src/mem/ruby/structures/RubyPrefetcher.cc b/src/mem/ruby/structures/RubyPrefetcher.cc index 02526aa57e..b416269e36 100644 --- a/src/mem/ruby/structures/RubyPrefetcher.cc +++ b/src/mem/ruby/structures/RubyPrefetcher.cc @@ -58,30 +58,14 @@ RubyPrefetcher::RubyPrefetcher(const Params *p) : 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 @@ -180,7 +164,7 @@ RubyPrefetcher::observeMiss(Addr address, const RubyRequestType& type) // 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); @@ -265,14 +249,6 @@ RubyPrefetcher::getLRUindex(void) 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) @@ -358,49 +334,46 @@ RubyPrefetcher::accessUnitFilter(CircularQueue* const filter, } 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; @@ -409,14 +382,8 @@ RubyPrefetcher::accessNonunitFilter(Addr address, int *stride, } // 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; } @@ -437,10 +404,10 @@ RubyPrefetcher::print(std::ostream& out) const // 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 diff --git a/src/mem/ruby/structures/RubyPrefetcher.hh b/src/mem/ruby/structures/RubyPrefetcher.hh index ebf59bd3b8..8e08fdf621 100644 --- a/src/mem/ruby/structures/RubyPrefetcher.hh +++ b/src/mem/ruby/structures/RubyPrefetcher.hh @@ -97,7 +97,7 @@ class RubyPrefetcher : public SimObject public: typedef RubyPrefetcherParams Params; RubyPrefetcher(const Params *p); - ~RubyPrefetcher(); + ~RubyPrefetcher() = default; void issueNextPrefetch(Addr address, PrefetchEntry *stream); /** @@ -139,6 +139,25 @@ class RubyPrefetcher : public SimObject } }; + 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). @@ -146,9 +165,6 @@ class RubyPrefetcher : public SimObject */ 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); @@ -171,9 +187,17 @@ class RubyPrefetcher : public SimObject bool accessUnitFilter(CircularQueue* 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; @@ -187,8 +211,6 @@ class RubyPrefetcher : public SimObject 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 @@ -202,16 +224,11 @@ class RubyPrefetcher : public SimObject */ CircularQueue negativeFilter; - /// a non-unit stride filter array: helps reduce BW requirement of - /// prefetching - std::vector 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 nonUnitFilter; /// Used for allowing prefetches across pages. bool m_prefetch_cross_pages;