diff --git a/src/mem/port.cc b/src/mem/port.cc index 883b592568..47e94f4714 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -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(&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(); } diff --git a/src/mem/port.hh b/src/mem/port.hh index d84e46f207..eadf7f44aa 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -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__