#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)
{
}
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);
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();
}
* 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)
{
}
void
SlavePort::slaveUnbind()
{
- _masterPort = NULL;
+ _masterPort = &defaultMasterPort;
Port::unbind();
}
private:
MasterPort* _masterPort;
+
bool defaultBackdoorWarned;
protected:
/**
* 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
Tick
sendAtomicSnoop(PacketPtr pkt)
{
- return AtomicResponseProtocol::sendSnoop(_masterPort, pkt);
+ try {
+ return AtomicResponseProtocol::sendSnoop(_masterPort, pkt);
+ } catch (UnboundPortException) {
+ reportUnbound();
+ }
}
public:
void
sendFunctionalSnoop(PacketPtr pkt) const
{
- FunctionalResponseProtocol::sendSnoop(_masterPort, pkt);
+ try {
+ FunctionalResponseProtocol::sendSnoop(_masterPort, pkt);
+ } catch (UnboundPortException) {
+ reportUnbound();
+ }
}
public:
bool
sendTimingResp(PacketPtr pkt)
{
- return TimingResponseProtocol::sendResp(_masterPort, pkt);
+ try {
+ return TimingResponseProtocol::sendResp(_masterPort, pkt);
+ } catch (UnboundPortException) {
+ reportUnbound();
+ }
}
/**
void
sendTimingSnoopReq(PacketPtr pkt)
{
- TimingResponseProtocol::sendSnoopReq(_masterPort, pkt);
+ try {
+ TimingResponseProtocol::sendSnoopReq(_masterPort, pkt);
+ } catch (UnboundPortException) {
+ reportUnbound();
+ }
}
/**
void
sendRetryReq()
{
- TimingResponseProtocol::sendRetryReq(_masterPort);
+ try {
+ TimingResponseProtocol::sendRetryReq(_masterPort);
+ } catch (UnboundPortException) {
+ reportUnbound();
+ }
}
/**
void
sendRetrySnoopResp()
{
- TimingResponseProtocol::sendRetrySnoopResp(_masterPort);
+ try {
+ TimingResponseProtocol::sendRetrySnoopResp(_masterPort);
+ } catch (UnboundPortException) {
+ reportUnbound();
+ }
}
protected:
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__