mem: Use the new unbound port reporting mechanism in the mem ports.

There was an add-hoc check added to getAddrRanges, but the other methods
would just segfault if they tried to talk to their peers. This change
wraps all the calls in try blocks and catches the exception which the
peer will throw if it's the default and the port is not actually
connected to anything.

Change-Id: Ie46be0230f33f74305c599b251ca319a65ba008d
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/30296
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2020-06-12 21:33:51 -07:00
parent 35d9bf99a8
commit d2beb1ffc8
2 changed files with 137 additions and 32 deletions

View File

@@ -47,11 +47,72 @@
#include "base/trace.hh"
#include "sim/sim_object.hh"
namespace
{
class DefaultMasterPort : public MasterPort
{
protected:
[[noreturn]] void
blowUp() const
{
throw UnboundPortException();
}
public:
DefaultMasterPort() : MasterPort("default_master_port", nullptr) {}
// Atomic protocol.
Tick recvAtomicSnoop(PacketPtr) override { blowUp(); }
// Timing protocol.
bool recvTimingResp(PacketPtr) override { blowUp(); }
void recvTimingSnoopReq(PacketPtr) override { blowUp(); }
void recvReqRetry() override { blowUp(); }
void recvRetrySnoopResp() override { blowUp(); }
// Functional protocol.
void recvFunctionalSnoop(PacketPtr) override { blowUp(); }
};
class DefaultSlavePort : public SlavePort
{
protected:
[[noreturn]] void
blowUp() const
{
throw UnboundPortException();
}
public:
DefaultSlavePort() : SlavePort("default_slave_port", nullptr) {}
// Atomic protocol.
Tick recvAtomic(PacketPtr) override { blowUp(); }
// Timing protocol.
bool recvTimingReq(PacketPtr) override { blowUp(); }
bool tryTiming(PacketPtr) override { blowUp(); }
bool recvTimingSnoopResp(PacketPtr) override { blowUp(); }
void recvRespRetry() override { blowUp(); }
// Functional protocol.
void recvFunctional(PacketPtr) override { blowUp(); }
// General.
AddrRangeList getAddrRanges() const override { return AddrRangeList(); }
};
DefaultMasterPort defaultMasterPort;
DefaultSlavePort defaultSlavePort;
} // anonymous namespace
/**
* Master port
*/
MasterPort::MasterPort(const std::string& name, SimObject* _owner, PortID _id)
: Port(name, _id), _slavePort(NULL), owner(*_owner)
: Port(name, _id), _slavePort(&defaultSlavePort), owner(*_owner)
{
}
@@ -63,10 +124,8 @@ void
MasterPort::bind(Port &peer)
{
auto *slave_port = dynamic_cast<SlavePort *>(&peer);
if (!slave_port) {
fatal("Attempt to bind port %s to non-slave port %s.",
name(), peer.name());
}
fatal_if(!slave_port, "Can't bind port %s to non-slave port %s.",
name(), peer.name());
// master port keeps track of the slave port
_slavePort = slave_port;
Port::bind(peer);
@@ -77,11 +136,10 @@ MasterPort::bind(Port &peer)
void
MasterPort::unbind()
{
if (_slavePort == NULL)
panic("Attempting to unbind master port %s that is not connected\n",
name());
panic_if(!isConnected(), "Can't unbind master port %s which is not bound.",
name());
_slavePort->slaveUnbind();
_slavePort = nullptr;
_slavePort = &defaultSlavePort;
Port::unbind();
}
@@ -108,8 +166,8 @@ MasterPort::printAddr(Addr a)
* Slave port
*/
SlavePort::SlavePort(const std::string& name, SimObject* _owner, PortID id)
: Port(name, id), _masterPort(NULL), defaultBackdoorWarned(false),
owner(*_owner)
: Port(name, id), _masterPort(&defaultMasterPort),
defaultBackdoorWarned(false), owner(*_owner)
{
}
@@ -120,7 +178,7 @@ SlavePort::~SlavePort()
void
SlavePort::slaveUnbind()
{
_masterPort = NULL;
_masterPort = &defaultMasterPort;
Port::unbind();
}

View File

@@ -258,6 +258,7 @@ class SlavePort : public Port, public AtomicResponseProtocol,
private:
MasterPort* _masterPort;
bool defaultBackdoorWarned;
protected:
@@ -278,13 +279,7 @@ class SlavePort : public Port, public AtomicResponseProtocol,
/**
* Called by the owner to send a range change
*/
void
sendRangeChange() const
{
fatal_if(!_masterPort,
"%s cannot sendRangeChange() without master port.", name());
_masterPort->recvRangeChange();
}
void sendRangeChange() const { _masterPort->recvRangeChange(); }
/**
* Get a list of the non-overlapping address ranges the owner is
@@ -316,7 +311,11 @@ class SlavePort : public Port, public AtomicResponseProtocol,
Tick
sendAtomicSnoop(PacketPtr pkt)
{
return AtomicResponseProtocol::sendSnoop(_masterPort, pkt);
try {
return AtomicResponseProtocol::sendSnoop(_masterPort, pkt);
} catch (UnboundPortException) {
reportUnbound();
}
}
public:
@@ -332,7 +331,11 @@ class SlavePort : public Port, public AtomicResponseProtocol,
void
sendFunctionalSnoop(PacketPtr pkt) const
{
FunctionalResponseProtocol::sendSnoop(_masterPort, pkt);
try {
FunctionalResponseProtocol::sendSnoop(_masterPort, pkt);
} catch (UnboundPortException) {
reportUnbound();
}
}
public:
@@ -352,7 +355,11 @@ class SlavePort : public Port, public AtomicResponseProtocol,
bool
sendTimingResp(PacketPtr pkt)
{
return TimingResponseProtocol::sendResp(_masterPort, pkt);
try {
return TimingResponseProtocol::sendResp(_masterPort, pkt);
} catch (UnboundPortException) {
reportUnbound();
}
}
/**
@@ -365,7 +372,11 @@ class SlavePort : public Port, public AtomicResponseProtocol,
void
sendTimingSnoopReq(PacketPtr pkt)
{
TimingResponseProtocol::sendSnoopReq(_masterPort, pkt);
try {
TimingResponseProtocol::sendSnoopReq(_masterPort, pkt);
} catch (UnboundPortException) {
reportUnbound();
}
}
/**
@@ -375,7 +386,11 @@ class SlavePort : public Port, public AtomicResponseProtocol,
void
sendRetryReq()
{
TimingResponseProtocol::sendRetryReq(_masterPort);
try {
TimingResponseProtocol::sendRetryReq(_masterPort);
} catch (UnboundPortException) {
reportUnbound();
}
}
/**
@@ -385,7 +400,11 @@ class SlavePort : public Port, public AtomicResponseProtocol,
void
sendRetrySnoopResp()
{
TimingResponseProtocol::sendRetrySnoopResp(_masterPort);
try {
TimingResponseProtocol::sendRetrySnoopResp(_masterPort);
} catch (UnboundPortException) {
reportUnbound();
}
}
protected:
@@ -422,43 +441,71 @@ class SlavePort : public Port, public AtomicResponseProtocol,
inline Tick
MasterPort::sendAtomic(PacketPtr pkt)
{
return AtomicRequestProtocol::send(_slavePort, pkt);
try {
return AtomicRequestProtocol::send(_slavePort, pkt);
} catch (UnboundPortException) {
reportUnbound();
}
}
inline Tick
MasterPort::sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor)
{
return AtomicRequestProtocol::sendBackdoor(_slavePort, pkt, backdoor);
try {
return AtomicRequestProtocol::sendBackdoor(_slavePort, pkt, backdoor);
} catch (UnboundPortException) {
reportUnbound();
}
}
inline void
MasterPort::sendFunctional(PacketPtr pkt) const
{
return FunctionalRequestProtocol::send(_slavePort, pkt);
try {
return FunctionalRequestProtocol::send(_slavePort, pkt);
} catch (UnboundPortException) {
reportUnbound();
}
}
inline bool
MasterPort::sendTimingReq(PacketPtr pkt)
{
return TimingRequestProtocol::sendReq(_slavePort, pkt);
try {
return TimingRequestProtocol::sendReq(_slavePort, pkt);
} catch (UnboundPortException) {
reportUnbound();
}
}
inline bool
MasterPort::tryTiming(PacketPtr pkt) const
{
return TimingRequestProtocol::trySend(_slavePort, pkt);
try {
return TimingRequestProtocol::trySend(_slavePort, pkt);
} catch (UnboundPortException) {
reportUnbound();
}
}
inline bool
MasterPort::sendTimingSnoopResp(PacketPtr pkt)
{
return TimingRequestProtocol::sendSnoopResp(_slavePort, pkt);
try {
return TimingRequestProtocol::sendSnoopResp(_slavePort, pkt);
} catch (UnboundPortException) {
reportUnbound();
}
}
inline void
MasterPort::sendRetryResp()
{
TimingRequestProtocol::sendRetryResp(_slavePort);
try {
TimingRequestProtocol::sendRetryResp(_slavePort);
} catch (UnboundPortException) {
reportUnbound();
}
}
#endif //__MEM_PORT_HH__