Yan Lee has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/62892?usp=email )

Change subject: base: add extensible type
......................................................................

base: add extensible type

Extensible is for carrying additional user-defined
information. Each type of the extension will have a unique
extension ID and there is a linked list of extension in every
Extensible object. There will be most one extension with the same type in
the linked list. With the shared_ptr, the extension will be
deleted automatically. That is, the caller should allocate
the extension and add into the packet.

Change-Id: I54729536a305c91c751d5fb059bd2f9a3db05523
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/62892
Tested-by: kokoro <noreply+kok...@google.com>
Reviewed-by: Giacomo Travaglini <giacomo.travagl...@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travagl...@arm.com>
---
M src/base/SConscript
A src/base/extensible.hh
A src/base/extensible.test.cc
3 files changed, 320 insertions(+), 0 deletions(-)

Approvals:
  Giacomo Travaglini: Looks good to me, approved; Looks good to me, approved
  kokoro: Regressions pass




diff --git a/src/base/SConscript b/src/base/SConscript
index 4a6b65f..29f106a 100644
--- a/src/base/SConscript
+++ b/src/base/SConscript
@@ -90,6 +90,7 @@
 GTest('channel_addr.test', 'channel_addr.test.cc', 'channel_addr.cc')
 GTest('circlebuf.test', 'circlebuf.test.cc')
 GTest('circular_queue.test', 'circular_queue.test.cc')
+GTest('extensible.test', 'extensible.test.cc')
 GTest('sat_counter.test', 'sat_counter.test.cc')
 GTest('refcnt.test','refcnt.test.cc')
 GTest('condcodes.test', 'condcodes.test.cc')
diff --git a/src/base/extensible.hh b/src/base/extensible.hh
new file mode 100644
index 0000000..eb79c71
--- /dev/null
+++ b/src/base/extensible.hh
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2023 Google, Inc.
+ *
+ * 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.
+ */
+
+/* @file
+ * Extensible Object Base Class Declaration
+ */
+
+#ifndef __BASE_EXTENSIBLE_HH__
+#define __BASE_EXTENSIBLE_HH__
+
+#include <list>
+#include <memory>
+#include <utility>
+
+namespace gem5
+{
+
+/**
+ * This is base of every extension.
+ */
+class ExtensionBase
+{
+  public:
+    explicit ExtensionBase(const unsigned int id)
+        : extID(id) {}
+
+    virtual ~ExtensionBase() = default;
+
+    virtual std::unique_ptr<ExtensionBase> clone() const = 0;
+
+    static unsigned int
+    maxNumExtensions()
+    {
+        static unsigned int max_num = 0;
+        return ++max_num;
+    }
+
+    unsigned int getExtensionID() const { return extID; }
+
+  private:
+    const unsigned int extID;
+};
+
+/**
+ * This is the extension for carrying additional information.
+ * Each type of extension will have a unique extensionID.
+ * This extensionID will assign to base class for comparsion.
+ */
+template <typename Target, typename T>
+class Extension : public ExtensionBase
+{
+  public:
+    Extension() : ExtensionBase(extensionID) {}
+
+    const static unsigned int extensionID;
+};
+
+template <typename Target, typename T>
+const unsigned int Extension<Target, T>::extensionID =
+        ExtensionBase::maxNumExtensions() - 1;
+
+template <typename Target>
+class Extensible
+{
+  public:
+     Extensible() = default;
+     Extensible(const Extensible& other)
+     {
+        // Clone every extension from other.
+        for (auto& ext : other.extensions) {
+            extensions.emplace_back(ext->clone());
+        }
+     }
+     virtual ~Extensible() = default;
+
+    /**
+     * Set a new extension to the packet and replace the old one, if there
+     * already exists the same type of extension in this packet. This new
+     * extension will be deleted automatically with the shared_ptr<>.
+     *
+     * @param ext Extension to set
+     */
+    template <typename T>
+    void
+    setExtension(std::shared_ptr<T> ext)
+    {
+        static_assert(std::is_base_of<ExtensionBase, T>::value,
+                      "Extension should inherit from ExtensionBase.");
+        assert(ext.get() != nullptr);
+
+        auto it = findExtension<T>();
+
+        if (it != extensions.end()) {
+            // There exists the same type of extension in the list.
+            // Replace it to the new one.
+            *it = std::move(ext);
+        } else {
+            // Add ext into the linked list.
+            extensions.emplace_back(std::move(ext));
+        }
+    }
+
+    /**
+     * Remove the extension based on its type.
+     *
+     * @param ext Extension to remove
+     */
+    template <typename T>
+    void
+    removeExtension(void)
+    {
+        static_assert(std::is_base_of<ExtensionBase, T>::value,
+                      "Extension should inherit from ExtensionBase.");
+
+        auto it = findExtension<T>();
+        if (it != extensions.end())
+            extensions.erase(it);
+    }
+
+    /**
+     * Get the extension pointer by linear search with the extensionID.
+     */
+    template <typename T>
+    std::shared_ptr<T>
+    getExtension()
+    {
+        static_assert(std::is_base_of<ExtensionBase, T>::value,
+                      "Extension should inherit from ExtensionBase.");
+        auto it = findExtension<T>();
+        if (it == extensions.end())
+            return nullptr;
+        return std::static_pointer_cast<T>(*it);
+    }
+
+  protected:
+
+    /**
+ * Go through the extension list and return the iterator to the instance of + * the type of extension. If there is no such an extension, return the end
+     * iterator of the list.
+     *
+     *  @return The iterator to the extension type T if there exists.
+     */
+    template <typename T>
+    std::list<std::shared_ptr<ExtensionBase>>::iterator
+    findExtension()
+    {
+        auto it = extensions.begin();
+        while (it != extensions.end()) {
+            if ((*it)->getExtensionID() == T::extensionID)
+                break;
+            it++;
+        }
+        return it;
+    }
+
+    // Linked list of extensions.
+    std::list<std::shared_ptr<ExtensionBase>> extensions;
+};
+
+} // namespace gem5
+
+#endif //__BASE_EXTENSIBLE_HH__
diff --git a/src/base/extensible.test.cc b/src/base/extensible.test.cc
new file mode 100644
index 0000000..66cbbda
--- /dev/null
+++ b/src/base/extensible.test.cc
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2023 Google, Inc.
+ *
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <memory>
+
+#include "base/extensible.hh"
+
+using namespace gem5;
+
+namespace {
+
+class TestTarget : public Extensible<TestTarget>
+{
+};
+
+class IntegerExtension : public Extension<TestTarget, IntegerExtension>
+{
+  public:
+    explicit IntegerExtension(uint32_t data)
+        : data_(data) {}
+
+    std::unique_ptr<gem5::ExtensionBase> clone() const override
+    {
+ return std::unique_ptr<IntegerExtension>(new IntegerExtension(data_));
+    }
+
+    uint32_t getData() const { return data_; }
+
+  private:
+    uint32_t data_;
+};
+
+class BoolExtension : public Extension<TestTarget, BoolExtension>
+{
+  public:
+    explicit BoolExtension(bool data)
+        : data_(data) {}
+
+    std::unique_ptr<gem5::ExtensionBase> clone() const override
+    {
+        return std::unique_ptr<BoolExtension>(new BoolExtension(data_));
+    }
+
+    bool getData() const { return data_; }
+
+  private:
+    bool data_;
+};
+
+} // namespace
+
+TEST(ExtensibleTest, ExtensionID)
+{
+    std::shared_ptr<IntegerExtension> ext1(new IntegerExtension(0xabcd));
+    EXPECT_EQ(0, ext1->getExtensionID());
+
+    std::shared_ptr<BoolExtension> ext2(new BoolExtension(true));
+    EXPECT_EQ(1, ext2->getExtensionID());
+}
+
+TEST(ExtensibleTest, SetAndRemoveExtension)
+{
+    const uint32_t data = 0xbeef;
+    std::shared_ptr<IntegerExtension> ext(new IntegerExtension(data));
+    std::unique_ptr<TestTarget> target(new TestTarget);
+    target->setExtension(ext);
+    EXPECT_EQ(data, target->getExtension<IntegerExtension>()->getData());
+
+    target->removeExtension<IntegerExtension>();
+    EXPECT_EQ(nullptr, target->getExtension<IntegerExtension>());
+}
+
+TEST(ExtensibleTest, ReplaceExtension)
+{
+    const uint32_t data = 0xbeef;
+    std::shared_ptr<IntegerExtension> ext(new IntegerExtension(data));
+    std::unique_ptr<TestTarget> target(new TestTarget);
+    target->setExtension(ext);
+    EXPECT_EQ(data, target->getExtension<IntegerExtension>()->getData());
+
+    const uint32_t new_data = 0xa5a5;
+ std::shared_ptr<IntegerExtension> new_ext(new IntegerExtension(new_data));
+    target->setExtension(new_ext);
+ EXPECT_EQ(new_data, target->getExtension<IntegerExtension>()->getData());
+}

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/62892?usp=email 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: I54729536a305c91c751d5fb059bd2f9a3db05523
Gerrit-Change-Number: 62892
Gerrit-PatchSet: 11
Gerrit-Owner: Yan Lee <yan...@google.com>
Gerrit-Reviewer: Bobby 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: Nikos Nikoleris <nikos.nikole...@arm.com>
Gerrit-Reviewer: Yan Lee <yan...@google.com>
Gerrit-Reviewer: Yu-hsin Wang <yuhsi...@google.com>
Gerrit-Reviewer: kokoro <noreply+kok...@google.com>
Gerrit-CC: Earl Ou <shunhsin...@google.com>
Gerrit-CC: Jason Lowe-Power <power...@gmail.com>
Gerrit-CC: John Alsop <johnathan.al...@amd.com>
Gerrit-CC: Jui-min Lee <f...@google.com>
Gerrit-CC: Richard Cooper <richard.coo...@arm.com>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org

Reply via email to