* 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.
- *
- * Authors: Steve Reinhardt
- * Andreas Hansson
- * William Wang
*/
/**
#include "mem/port.hh"
#include "base/trace.hh"
-#include "mem/mem_object.hh"
+#include "sim/sim_object.hh"
-Port::Port(const std::string &_name, MemObject& _owner, PortID _id)
- : portName(_name), id(_id), owner(_owner)
+namespace
{
-}
-Port::~Port()
+class DefaultRequestPort : public RequestPort
{
-}
+ protected:
+ [[noreturn]] void
+ blowUp() const
+ {
+ throw UnboundPortException();
+ }
-BaseMasterPort::BaseMasterPort(const std::string& name, MemObject* owner,
- PortID _id)
- : Port(name, *owner, _id), _baseSlavePort(NULL)
-{
-}
+ public:
+ DefaultRequestPort() : RequestPort("default_request_port", nullptr) {}
-BaseMasterPort::~BaseMasterPort()
-{
-}
+ // Atomic protocol.
+ Tick recvAtomicSnoop(PacketPtr) override { blowUp(); }
-BaseSlavePort&
-BaseMasterPort::getSlavePort() const
-{
- if (_baseSlavePort == NULL)
- panic("Cannot getSlavePort on master port %s that is not connected\n",
- name());
+ // Timing protocol.
+ bool recvTimingResp(PacketPtr) override { blowUp(); }
+ void recvTimingSnoopReq(PacketPtr) override { blowUp(); }
+ void recvReqRetry() override { blowUp(); }
+ void recvRetrySnoopResp() override { blowUp(); }
- return *_baseSlavePort;
-}
+ // Functional protocol.
+ void recvFunctionalSnoop(PacketPtr) override { blowUp(); }
+};
-bool
-BaseMasterPort::isConnected() const
+class DefaultResponsePort : public ResponsePort
{
- return _baseSlavePort != NULL;
-}
+ protected:
+ [[noreturn]] void
+ blowUp() const
+ {
+ throw UnboundPortException();
+ }
-BaseSlavePort::BaseSlavePort(const std::string& name, MemObject* owner,
- PortID _id)
- : Port(name, *owner, _id), _baseMasterPort(NULL)
-{
-}
+ public:
+ DefaultResponsePort() : ResponsePort("default_response_port", nullptr) {}
-BaseSlavePort::~BaseSlavePort()
-{
-}
+ // Atomic protocol.
+ Tick recvAtomic(PacketPtr) override { blowUp(); }
-BaseMasterPort&
-BaseSlavePort::getMasterPort() const
-{
- if (_baseMasterPort == NULL)
- panic("Cannot getMasterPort on slave port %s that is not connected\n",
- name());
+ // Timing protocol.
+ bool recvTimingReq(PacketPtr) override { blowUp(); }
+ bool tryTiming(PacketPtr) override { blowUp(); }
+ bool recvTimingSnoopResp(PacketPtr) override { blowUp(); }
+ void recvRespRetry() override { blowUp(); }
- return *_baseMasterPort;
-}
+ // Functional protocol.
+ void recvFunctional(PacketPtr) override { blowUp(); }
-bool
-BaseSlavePort::isConnected() const
-{
- return _baseMasterPort != NULL;
-}
+ // General.
+ AddrRangeList getAddrRanges() const override { return AddrRangeList(); }
+};
+
+DefaultRequestPort defaultRequestPort;
+DefaultResponsePort defaultResponsePort;
+
+} // anonymous namespace
/**
- * Master port
+ * Request port
*/
-MasterPort::MasterPort(const std::string& name, MemObject* owner, PortID _id)
- : BaseMasterPort(name, owner, _id), _slavePort(NULL)
+RequestPort::RequestPort(const std::string& name, SimObject* _owner,
+ PortID _id) : Port(name, _id), _responsePort(&defaultResponsePort),
+ owner(*_owner)
{
}
-MasterPort::~MasterPort()
+RequestPort::~RequestPort()
{
}
void
-MasterPort::bind(BaseSlavePort& slave_port)
+RequestPort::bind(Port &peer)
{
- // bind on the level of the base ports
- _baseSlavePort = &slave_port;
-
- // also attempt to base the slave to the appropriate type
- SlavePort* cast_slave_port = dynamic_cast<SlavePort*>(&slave_port);
-
- // if this port is compatible, then proceed with the binding
- if (cast_slave_port != NULL) {
- // master port keeps track of the slave port
- _slavePort = cast_slave_port;
- // slave port also keeps track of master port
- _slavePort->bind(*this);
- } else {
- fatal("Master port %s cannot bind to %s\n", name(),
- slave_port.name());
- }
+ auto *response_port = dynamic_cast<ResponsePort *>(&peer);
+ fatal_if(!response_port, "Can't bind port %s to non-response port %s.",
+ name(), peer.name());
+ // request port keeps track of the response port
+ _responsePort = response_port;
+ Port::bind(peer);
+ // response port also keeps track of request port
+ _responsePort->responderBind(*this);
}
void
-MasterPort::unbind()
+RequestPort::unbind()
{
- if (_slavePort == NULL)
- panic("Attempting to unbind master port %s that is not connected\n",
- name());
- _slavePort->unbind();
- _slavePort = NULL;
- _baseSlavePort = NULL;
+ panic_if(!isConnected(), "Can't unbind request port %s which is "
+ "not bound.", name());
+ _responsePort->responderUnbind();
+ _responsePort = &defaultResponsePort;
+ Port::unbind();
}
AddrRangeList
-MasterPort::getAddrRanges() const
+RequestPort::getAddrRanges() const
{
- return _slavePort->getAddrRanges();
-}
-
-Tick
-MasterPort::sendAtomic(PacketPtr pkt)
-{
- assert(pkt->isRequest());
- return _slavePort->recvAtomic(pkt);
+ return _responsePort->getAddrRanges();
}
void
-MasterPort::sendFunctional(PacketPtr pkt)
+RequestPort::printAddr(Addr a)
{
- assert(pkt->isRequest());
- return _slavePort->recvFunctional(pkt);
-}
-
-bool
-MasterPort::sendTimingReq(PacketPtr pkt)
-{
- assert(pkt->isRequest());
- return _slavePort->recvTimingReq(pkt);
-}
+ auto req = std::make_shared<Request>(
+ a, 1, 0, Request::funcRequestorId);
-bool
-MasterPort::tryTiming(PacketPtr pkt) const
-{
- assert(pkt->isRequest());
- return _slavePort->tryTiming(pkt);
-}
-
-bool
-MasterPort::sendTimingSnoopResp(PacketPtr pkt)
-{
- assert(pkt->isResponse());
- return _slavePort->recvTimingSnoopResp(pkt);
-}
-
-void
-MasterPort::sendRetryResp()
-{
- _slavePort->recvRespRetry();
-}
-
-void
-MasterPort::printAddr(Addr a)
-{
- Request req(a, 1, 0, Request::funcMasterId);
- Packet pkt(&req, MemCmd::PrintReq);
+ Packet pkt(req, MemCmd::PrintReq);
Packet::PrintReqState prs(std::cerr);
pkt.senderState = &prs;
}
/**
- * Slave port
+ * Response port
*/
-SlavePort::SlavePort(const std::string& name, MemObject* owner, PortID id)
- : BaseSlavePort(name, owner, id), _masterPort(NULL)
+ResponsePort::ResponsePort(const std::string& name, SimObject* _owner,
+ PortID id) : Port(name, id), _requestPort(&defaultRequestPort),
+ defaultBackdoorWarned(false), owner(*_owner)
{
}
-SlavePort::~SlavePort()
+ResponsePort::~ResponsePort()
{
}
void
-SlavePort::unbind()
+ResponsePort::responderUnbind()
{
- _baseMasterPort = NULL;
- _masterPort = NULL;
+ _requestPort = &defaultRequestPort;
+ Port::unbind();
}
void
-SlavePort::bind(MasterPort& master_port)
+ResponsePort::responderBind(RequestPort& request_port)
{
- _baseMasterPort = &master_port;
- _masterPort = &master_port;
+ _requestPort = &request_port;
+ Port::bind(request_port);
}
Tick
-SlavePort::sendAtomicSnoop(PacketPtr pkt)
-{
- assert(pkt->isRequest());
- return _masterPort->recvAtomicSnoop(pkt);
-}
-
-void
-SlavePort::sendFunctionalSnoop(PacketPtr pkt)
+ResponsePort::recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor)
{
- assert(pkt->isRequest());
- return _masterPort->recvFunctionalSnoop(pkt);
-}
-
-bool
-SlavePort::sendTimingResp(PacketPtr pkt)
-{
- assert(pkt->isResponse());
- return _masterPort->recvTimingResp(pkt);
-}
-
-void
-SlavePort::sendTimingSnoopReq(PacketPtr pkt)
-{
- assert(pkt->isRequest());
- _masterPort->recvTimingSnoopReq(pkt);
-}
-
-void
-SlavePort::sendRetryReq()
-{
- _masterPort->recvReqRetry();
-}
-
-void
-SlavePort::sendRetrySnoopResp()
-{
- _masterPort->recvRetrySnoopResp();
+ if (!defaultBackdoorWarned) {
+ warn("Port %s doesn't support requesting a back door.", name());
+ defaultBackdoorWarned = true;
+ }
+ return recvAtomic(pkt);
}