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