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