Daniel Carvalho has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/24533 )

Change subject: mem-ruby: Use CircularQueue for prefetcher's non unit filter
......................................................................

mem-ruby: Use CircularQueue for prefetcher's non unit filter

Ruby prefetcher's non-unit filter is a circular queue, so use the class
created for this functionality.

This changes the behavior, since previously iterating through the
filter was completely arbitrary, and now it iterates from the
beginning of the queue to the end when accessing and updating
the filter's contents.

Change-Id: I3148efcbef00da0c8f6cf2dee7fb86f6c2ddb27d
Signed-off-by: Daniel R. Carvalho <oda...@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24533
Reviewed-by: Jason Lowe-Power <power...@gmail.com>
Maintainer: Jason Lowe-Power <power...@gmail.com>
Tested-by: kokoro <noreply+kok...@google.com>
---
M src/mem/ruby/structures/RubyPrefetcher.cc
M src/mem/ruby/structures/RubyPrefetcher.hh
2 files changed, 58 insertions(+), 74 deletions(-)

Approvals:
  Jason Lowe-Power: Looks good to me, approved; Looks good to me, approved
  kokoro: Regressions pass



diff --git a/src/mem/ruby/structures/RubyPrefetcher.cc b/src/mem/ruby/structures/RubyPrefetcher.cc
index 02526aa..b416269 100644
--- a/src/mem/ruby/structures/RubyPrefetcher.cc
+++ b/src/mem/ruby/structures/RubyPrefetcher.cc
@@ -58,30 +58,14 @@
     : 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 @@

     // 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);
@@ -266,14 +250,6 @@
 }

 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 @@
 }

 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 @@
     }

     // 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 @@

     // 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 ebf59bd..8e08fdf 100644
--- a/src/mem/ruby/structures/RubyPrefetcher.hh
+++ b/src/mem/ruby/structures/RubyPrefetcher.hh
@@ -97,7 +97,7 @@
     public:
         typedef RubyPrefetcherParams Params;
         RubyPrefetcher(const Params *p);
-        ~RubyPrefetcher();
+        ~RubyPrefetcher() = default;

         void issueNextPrefetch(Addr address, PrefetchEntry *stream);
         /**
@@ -139,6 +139,25 @@
             }
         };

+        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 @@
          */
         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 @@
         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;
@@ -187,8 +211,6 @@
         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 @@
          */
         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;

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/24533
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I3148efcbef00da0c8f6cf2dee7fb86f6c2ddb27d
Gerrit-Change-Number: 24533
Gerrit-PatchSet: 5
Gerrit-Owner: Daniel Carvalho <oda...@yahoo.com.br>
Gerrit-Reviewer: Bobby R. Bruce <bbr...@ucdavis.edu>
Gerrit-Reviewer: Bradford Beckmann <bradford.beckm...@gmail.com>
Gerrit-Reviewer: Daniel Carvalho <oda...@yahoo.com.br>
Gerrit-Reviewer: Jason Lowe-Power <power...@gmail.com>
Gerrit-Reviewer: kokoro <noreply+kok...@google.com>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to