Gabe Black has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/38718 )

Change subject: base: Add a setNext method to the ChunkGenerator.
......................................................................

base: Add a setNext method to the ChunkGenerator.

This method lets you stretch the current chunk, if you want to skip over
some of the upcoming chunks since you've already handled their bytes.

For instance, if you were iterating over pages in a range of virtual
addresses, you might be able to handle multiple page sized chunks at
once if they were represented by a single large sized page table entry.
This mechanism would let you move past all the pages you had just
handled without having to walk through them all one by one.

Change-Id: I7d962f548947b77f0aa1b725036dbcc9e1b28659
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/38718
Reviewed-by: Gabe Black <gabe.bl...@gmail.com>
Maintainer: Gabe Black <gabe.bl...@gmail.com>
Tested-by: kokoro <noreply+kok...@google.com>
---
M src/base/chunk_generator.hh
M src/base/chunk_generator.test.cc
2 files changed, 72 insertions(+), 3 deletions(-)

Approvals:
  Gabe Black: Looks good to me, approved; Looks good to me, approved
  kokoro: Regressions pass



diff --git a/src/base/chunk_generator.hh b/src/base/chunk_generator.hh
index 4c749b2..e95f4fd 100644
--- a/src/base/chunk_generator.hh
+++ b/src/base/chunk_generator.hh
@@ -35,6 +35,7 @@
  */

 #include <algorithm>
+#include <cassert>

 #include "base/intmath.hh"
 #include "base/types.hh"
@@ -61,6 +62,8 @@
     Addr nextAddr;
     /** The size of the current chunk (in bytes). */
     Addr curSize;
+    /** The size of the next chunk (in bytes). */
+    Addr nextSize;
/** The number of bytes remaining in the region after the current chunk. */
     Addr sizeLeft;
     /** The start address so we can calculate offset in writing block. */
@@ -96,12 +99,13 @@
                 // ... even if startAddr is already chunk-aligned
                 nextAddr += chunkSize;
             }
+            nextAddr = std::min(nextAddr, startAddr + totalSize);
         }

// How many bytes are left between curAddr and the end of this chunk?
-        Addr left_in_chunk = nextAddr - curAddr;
-        curSize = std::min(totalSize, left_in_chunk);
+        curSize = nextAddr - curAddr;
         sizeLeft = totalSize - curSize;
+        nextSize = std::min(sizeLeft, chunkSize);
     }

     /**
@@ -142,6 +146,32 @@
     bool last() const { return sizeLeft == 0; }

     /**
+     * Grow this chunk to cover additional bytes which are already handled.
+     * @param next The first byte of the next chunk.
+     *
+     * @ingroup api_chunk_generator
+     */
+    void
+    setNext(Addr next)
+    {
+        assert(next >= nextAddr);
+
+        const Addr skipping = std::min(next - nextAddr, sizeLeft);
+
+        sizeLeft -= skipping;
+        curSize += skipping;
+        nextAddr = next;
+
+        assert(chunkSize);
+
+        // nextSize will be enough to get to an alignment boundary,
+        nextSize = roundUp(next, chunkSize) - next;
+ // or if it's already aligned, to the following boundary or the end.
+        if (!nextSize)
+            nextSize = std::min(sizeLeft, chunkSize);
+    }
+
+    /**
      * Advance generator to next chunk.
      * @return True if successful, false if unsuccessful
      * (because we were at the last chunk).
@@ -157,9 +187,10 @@
         }

         curAddr = nextAddr;
-        curSize = std::min(sizeLeft, chunkSize);
+        curSize = nextSize;
         sizeLeft -= curSize;
         nextAddr += curSize;
+        nextSize = std::min(sizeLeft, chunkSize);
         return true;
     }
 };
diff --git a/src/base/chunk_generator.test.cc b/src/base/chunk_generator.test.cc
index 91895cb..f5d7048 100644
--- a/src/base/chunk_generator.test.cc
+++ b/src/base/chunk_generator.test.cc
@@ -60,6 +60,44 @@
 }

 /*
+ * A test to check skipping over bytes.
+ */
+TEST(ChunkGeneratorTest, SkipBytes)
+{
+    ChunkGenerator chunk_generator(0, 1024, 8);
+    EXPECT_EQ(0, chunk_generator.addr());
+    EXPECT_TRUE(chunk_generator.next());
+    EXPECT_EQ(8, chunk_generator.addr());
+
+    chunk_generator.setNext(23);
+    EXPECT_EQ(23 - 8, chunk_generator.size());
+    EXPECT_TRUE(chunk_generator.next());
+    EXPECT_EQ(23, chunk_generator.addr());
+    EXPECT_EQ(1, chunk_generator.size());
+    EXPECT_TRUE(chunk_generator.next());
+    EXPECT_EQ(24, chunk_generator.addr());
+    EXPECT_EQ(8, chunk_generator.size());
+
+    chunk_generator.setNext(32);
+    EXPECT_EQ(32 - 24, chunk_generator.size());
+    EXPECT_TRUE(chunk_generator.next());
+    EXPECT_EQ(32, chunk_generator.addr());
+    EXPECT_EQ(8, chunk_generator.size());
+
+    chunk_generator.setNext(64);
+    EXPECT_EQ(64 - 32, chunk_generator.size());
+    EXPECT_TRUE(chunk_generator.next());
+    EXPECT_EQ(64, chunk_generator.addr());
+    EXPECT_EQ(8, chunk_generator.size());
+
+    chunk_generator.setNext(2048);
+    EXPECT_EQ(1024 - 64, chunk_generator.size());
+    EXPECT_TRUE(chunk_generator.last());
+    EXPECT_FALSE(chunk_generator.next());
+    EXPECT_TRUE(chunk_generator.done());
+}
+
+/*
  * A test to consume chunks until the last chunk.
  */
 TEST(ChunkGeneratorTest, AdvanceToLastChunk)

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/38718
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: I7d962f548947b77f0aa1b725036dbcc9e1b28659
Gerrit-Change-Number: 38718
Gerrit-PatchSet: 9
Gerrit-Owner: Gabe Black <gabe.bl...@gmail.com>
Gerrit-Reviewer: Alexandru Duțu <alexandru.d...@amd.com>
Gerrit-Reviewer: Bobby R. Bruce <bbr...@ucdavis.edu>
Gerrit-Reviewer: Daniel Carvalho <oda...@yahoo.com.br>
Gerrit-Reviewer: Gabe Black <gabe.bl...@gmail.com>
Gerrit-Reviewer: Giacomo Travaglini <giacomo.travagl...@arm.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