Earl Ou has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/67232?usp=email )

Change subject: mem: create port_wrapper classes
......................................................................

mem: create port_wrapper classes

The port_wrapper classes convert the Request/ResponsePort from
inherit-base to callback registrations. This help 'composition over
inheritance' that most design pattern follows, which help reducing
code length and increase reusability.

Change-Id: Ia13cc62507ac8425bd7cf143a2e080d041c173f9
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67232
Maintainer: Jason Lowe-Power <power...@gmail.com>
Reviewed-by: Jason Lowe-Power <power...@gmail.com>
Tested-by: kokoro <noreply+kok...@google.com>
---
M src/mem/SConscript
A src/mem/port_wrapper.cc
A src/mem/port_wrapper.hh
3 files changed, 347 insertions(+), 0 deletions(-)

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




diff --git a/src/mem/SConscript b/src/mem/SConscript
index 3bcfc0d..ca164c1 100644
--- a/src/mem/SConscript
+++ b/src/mem/SConscript
@@ -88,6 +88,7 @@
 Source('port.cc')
 Source('packet_queue.cc')
 Source('port_proxy.cc')
+Source('port_wrapper.cc')
 Source('physical.cc')
 Source('shared_memory_server.cc')
 Source('simple_mem.cc')
diff --git a/src/mem/port_wrapper.cc b/src/mem/port_wrapper.cc
new file mode 100644
index 0000000..fd5ebbd
--- /dev/null
+++ b/src/mem/port_wrapper.cc
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2023 Google, LLC.
+ *
+ * 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 "mem/port_wrapper.hh"
+
+namespace gem5
+{
+
+RequestPortWrapper::RequestPortWrapper(const std::string& name,
+                                       SimObject* _owner, PortID id)
+    : RequestPort(name, _owner, id)
+{
+}
+
+void
+RequestPortWrapper::recvRangeChange()
+{
+    if (!recvRangeChangeCb) {
+        RequestPort::recvRangeChange();
+        return;
+    }
+    recvRangeChangeCb();
+}
+
+bool
+RequestPortWrapper::recvTimingResp(PacketPtr packet)
+{
+    panic_if(!recvTimingRespCb, "RecvTimingRespCallback is empty.");
+    return recvTimingRespCb(packet);
+}
+
+void
+RequestPortWrapper::recvReqRetry()
+{
+    panic_if(!recvReqRetryCb, "RecvReqRetryCallback is empty.");
+    recvReqRetryCb();
+}
+
+void
+RequestPortWrapper::setRangeChangeCallback(RecvReqRetryCallback cb)
+{
+    recvRangeChangeCb = std::move(cb);
+}
+
+void
+RequestPortWrapper::setTimingCallbacks(RecvTimingRespCallback resp_cb,
+                                       RecvReqRetryCallback retry_cb)
+{
+    recvTimingRespCb = std::move(resp_cb);
+    recvReqRetryCb = std::move(retry_cb);
+}
+
+ResponsePortWrapper::ResponsePortWrapper(const std::string& name,
+                                         SimObject* _owner, PortID id)
+    : ResponsePort(name, _owner, id)
+{
+}
+
+AddrRangeList
+ResponsePortWrapper::getAddrRanges() const
+{
+    panic_if(!getAddrRangesCb, "GetAddrRangesCallback is empty.");
+    return getAddrRangesCb();
+}
+
+bool
+ResponsePortWrapper::recvTimingReq(PacketPtr packet)
+{
+    panic_if(!recvTimingReqCb, "RecvTimingReqCallback is empty.");
+    return recvTimingReqCb(packet);
+}
+
+void
+ResponsePortWrapper::recvRespRetry()
+{
+    panic_if(!recvRespRetryCb, "RecvRespRetryCallback is empty.");
+    recvRespRetryCb();
+}
+
+Tick
+ResponsePortWrapper::recvAtomic(PacketPtr packet)
+{
+    panic_if(!recvAtomicCb, "RecvAtomicCallback is empty.");
+    return recvAtomicCb(packet);
+}
+
+Tick
+ResponsePortWrapper::recvAtomicBackdoor(PacketPtr packet,
+                                        MemBackdoorPtr& backdoor)
+{
+    if (!recvAtomicBackdoorCb) {
+        return ResponsePort::recvAtomicBackdoor(packet, backdoor);
+    }
+    return recvAtomicBackdoorCb(packet, backdoor);
+}
+
+void
+ResponsePortWrapper::recvFunctional(PacketPtr packet)
+{
+    panic_if(!recvFunctionalCb, "RecvFunctionalCallback is empty.");
+    recvTimingReqCb(packet);
+}
+
+void
+ResponsePortWrapper::recvMemBackdoorReq(const MemBackdoorReq& req,
+                                        MemBackdoorPtr& backdoor)
+{
+    if (!recvMemBackdoorReqCb) {
+        ResponsePort::recvMemBackdoorReq(req, backdoor);
+        return;
+    }
+    recvMemBackdoorReqCb(req, backdoor);
+}
+
+void
+ResponsePortWrapper::setGetAddrRangesCallback(GetAddrRangesCallback cb)
+{
+    getAddrRangesCb = std::move(cb);
+}
+
+void
+ResponsePortWrapper::setTimingCallbacks(RecvTimingReqCallback timing_cb,
+                                        RecvRespRetryCallback retry_cb)
+{
+    recvTimingReqCb = std::move(timing_cb);
+    recvRespRetryCb = std::move(retry_cb);
+}
+
+void
+ResponsePortWrapper::setAtomicCallbacks(RecvAtomicCallback atomic_cb,
+ RecvAtomicBackdoorCallback backdoor_cb)
+{
+    recvAtomicCb = std::move(atomic_cb);
+    recvAtomicBackdoorCb = std::move(backdoor_cb);
+}
+
+void
+ResponsePortWrapper::setFunctionalCallbacks(
+    RecvFunctionalCallback func_cb, RecvMemBackdoorReqCallback backdoor_cb)
+{
+    recvFunctionalCb = std::move(func_cb);
+    recvMemBackdoorReqCb = std::move(backdoor_cb);
+}
+
+}  // namespace gem5
diff --git a/src/mem/port_wrapper.hh b/src/mem/port_wrapper.hh
new file mode 100644
index 0000000..5dcdd5d
--- /dev/null
+++ b/src/mem/port_wrapper.hh
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2023 Google, LLC.
+ *
+ * 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
+ * PortWrapper Object Declaration.
+ *
+ * The RequestPortWrapper and ResponsePortWrapper converts inherit-based
+ * RequestPort and ResponsePort into callback-based. This help reducing
+ * redundant code and increase code reusability in most cases, allowing
+ * composition over inheritance pattern.
+ *
+ * Example usage:
+ *
+ * class MySimObject : public SimObject
+ * {
+ *   public:
+ *       ResponsePortWrapper inPort;
+ *
+ *       MySimObject(...) : inPort("in_port", this)... {
+ *         inPort.setGetAddrRangesCallback([this]() {
+ *           return getRange();
+ *         });
+ *
+ *         inPort.setAtomicCallbacks([this](PacketPtr packet) {
+ *           // process the packet
+ *           ...
+ *           return Tick();
+ *         });
+ *       }
+ *
+ *   private:
+ *       AddrRangeList getRange() const {...}
+ * };
+ */
+
+#ifndef __MEM_PORT_WRAPPER_HH__
+#define __MEM_PORT_WRAPPER_HH__
+
+#include <functional>
+
+#include "mem/port.hh"
+
+namespace gem5
+{
+
+/**
+ * The RequestPortWrapper converts inherit-based RequestPort into
+ * callback-based.
+ */
+class RequestPortWrapper : public RequestPort
+{
+  public:
+    using RecvRangeChangeCallback = std::function<void()>;
+    // Timing Protocol
+    using RecvTimingRespCallback = std::function<bool(PacketPtr)>;
+    using RecvReqRetryCallback = std::function<void()>;
+
+    RequestPortWrapper(const std::string& name, SimObject* _owner,
+                       PortID id = InvalidPortID);
+
+    void recvRangeChange() override;
+
+    // TimingRequestProtocol
+    bool recvTimingResp(PacketPtr) override;
+    void recvReqRetry() override;
+
+    void setRangeChangeCallback(RecvReqRetryCallback);
+    void setTimingCallbacks(RecvTimingRespCallback, RecvReqRetryCallback);
+
+  private:
+    RecvRangeChangeCallback recvRangeChangeCb = nullptr;
+    RecvTimingRespCallback recvTimingRespCb = nullptr;
+    RecvReqRetryCallback recvReqRetryCb = nullptr;
+};
+
+/**
+ * The ResponsePortWrapper converts inherit-based ResponsePort into
+ * callback-based.
+ */
+class ResponsePortWrapper : public ResponsePort
+{
+  public:
+    using GetAddrRangesCallback = std::function<AddrRangeList()>;
+    // Timing Protocol
+    using RecvTimingReqCallback = std::function<bool(PacketPtr)>;
+    // Atomic Protocol
+    using RecvAtomicCallback = std::function<Tick(PacketPtr)>;
+    using RecvAtomicBackdoorCallback =
+        std::function<Tick(PacketPtr, MemBackdoorPtr&)>;
+
+    // Functional Protocol
+    using RecvFunctionalCallback = std::function<void(PacketPtr)>;
+    using RecvMemBackdoorReqCallback =
+        std::function<void(const MemBackdoorReq&, MemBackdoorPtr&)>;
+
+    using RecvRespRetryCallback = std::function<void()>;
+
+    ResponsePortWrapper(const std::string& name, SimObject* _owner,
+                        PortID id = InvalidPortID);
+
+    AddrRangeList getAddrRanges() const override;
+
+    // TimingResponseProtocol
+    bool recvTimingReq(PacketPtr) override;
+    void recvRespRetry() override;
+
+    // AtomicResponseProtocol
+    Tick recvAtomic(PacketPtr) override;
+    Tick recvAtomicBackdoor(PacketPtr, MemBackdoorPtr&) override;
+
+    // FunctionalResponseProtocol
+    void recvFunctional(PacketPtr) override;
+ void recvMemBackdoorReq(const MemBackdoorReq&, MemBackdoorPtr&) override;
+
+    void setGetAddrRangesCallback(GetAddrRangesCallback);
+    void setTimingCallbacks(RecvTimingReqCallback, RecvRespRetryCallback);
+    void setAtomicCallbacks(RecvAtomicCallback,
+                            RecvAtomicBackdoorCallback = nullptr);
+    void setFunctionalCallbacks(RecvFunctionalCallback,
+                                RecvMemBackdoorReqCallback = nullptr);
+
+  private:
+    GetAddrRangesCallback getAddrRangesCb = nullptr;
+    RecvTimingReqCallback recvTimingReqCb = nullptr;
+    RecvRespRetryCallback recvRespRetryCb = nullptr;
+    RecvAtomicCallback recvAtomicCb = nullptr;
+    RecvAtomicBackdoorCallback recvAtomicBackdoorCb = nullptr;
+    RecvFunctionalCallback recvFunctionalCb = nullptr;
+    RecvMemBackdoorReqCallback recvMemBackdoorReqCb = nullptr;
+};
+
+}  // namespace gem5
+
+#endif  //__MEM_PORT_WRAPPER_HH__

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/67232?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: Ia13cc62507ac8425bd7cf143a2e080d041c173f9
Gerrit-Change-Number: 67232
Gerrit-PatchSet: 6
Gerrit-Owner: Earl Ou <shunhsin...@google.com>
Gerrit-Reviewer: Earl Ou <shunhsin...@google.com>
Gerrit-Reviewer: Gabe Black <gabe.bl...@gmail.com>
Gerrit-Reviewer: Jason Lowe-Power <power...@gmail.com>
Gerrit-Reviewer: Nikos Nikoleris <nikos.nikole...@arm.com>
Gerrit-Reviewer: Yu-hsin Wang <yuhsi...@google.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

Reply via email to