blob: 9da118f25daab03aa4390dc2b6c20ad5b2e0117a [file] [log] [blame] [edit]
/*
* 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, 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, 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__