// note that we might have blocked on the receiving port being
// busy (rather than the bus itself) and now call retry before the
// destination called retry on the bus
- retryList.front()->sendRetry();
+ if (dynamic_cast<SlavePort*>(retryList.front()) != NULL)
+ (dynamic_cast<SlavePort*>(retryList.front()))->sendRetry();
+ else
+ (dynamic_cast<MasterPort*>(retryList.front()))->sendRetry();
// If inRetry is still true, sendTiming wasn't called in zero time
// (e.g. the cache does this)
#include "mem/port.hh"
Port::Port(const std::string &_name, MemObject& _owner, PortID _id)
- : portName(_name), id(_id), peer(NULL), owner(_owner)
+ : portName(_name), id(_id), owner(_owner)
{
}
{
// master port keeps track of the slave port
_slavePort = &slave_port;
- peer = &slave_port;
// slave port also keeps track of master port
_slavePort->bind(*this);
return _slavePort->recvTimingSnoopResp(pkt);
}
+void
+MasterPort::sendRetry()
+{
+ _slavePort->recvRetry();
+}
+
void
MasterPort::printAddr(Addr a)
{
SlavePort::bind(MasterPort& master_port)
{
_masterPort = &master_port;
- peer = &master_port;
}
MasterPort&
assert(pkt->isRequest());
_masterPort->recvTimingSnoopReq(pkt);
}
+
+void
+SlavePort::sendRetry()
+{
+ _masterPort->recvRetry();
+}
/**
* Ports are used to interface memory objects to each other. A port is
* either a master or a slave and the connected peer is always of the
- * opposite role.
- *
- * Each port has a name and an owner, and enables three basic types of
- * accesses to the peer port: functional, atomic and timing.
+ * opposite role. Each port has a name, an owner, and an identifier.
*/
class Port
{
*/
const PortID id;
- /** A pointer to the peer port. */
- Port* peer;
-
/** A reference to the MemObject that owns this port. */
MemObject& owner;
/** Get the port id. */
PortID getId() const { return id; }
- protected:
-
- /**
- * Called by a peer port if sendTimingReq, sendTimingResp or
- * sendTimingSnoopResp was unsuccesful, and had to wait.
- */
- virtual void recvRetry() = 0;
-
- public:
-
- /**
- * Send a retry to a peer port that previously attempted a
- * sendTimingReq, sendTimingResp or sendTimingSnoopResp which was
- * unsuccessful.
- */
- void sendRetry() { return peer->recvRetry(); }
-
};
/** Forward declaration */
*/
bool sendTimingSnoopResp(PacketPtr pkt);
+ /**
+ * Send a retry to the slave port that previously attempted a
+ * sendTimingResp to this master port and failed.
+ */
+ void sendRetry();
+
/**
* Determine if this master port is snooping or not. The default
* implementation returns false and thus tells the neighbour we
panic("%s was not expecting a timing snoop request\n", name());
}
+ /**
+ * Called by the slave port if sendTimingReq or
+ * sendTimingSnoopResp was called on this master port (causing
+ * recvTimingReq and recvTimingSnoopResp to be called on the
+ * slave port) and was unsuccesful.
+ */
+ virtual void recvRetry() = 0;
+
/**
* Called to receive an address range change from the peer slave
* port. the default implementation ignored the change and does
*/
void sendTimingSnoopReq(PacketPtr pkt);
+ /**
+ * Send a retry to the master port that previously attempted a
+ * sendTimingReq or sendTimingSnoopResp to this slave port and
+ * failed.
+ */
+ void sendRetry();
+
/**
* Called by a peer port in order to determine the block size of
* the owner of this port.
panic("%s was not expecting a timing snoop response\n", name());
}
+ /**
+ * Called by the master port if sendTimingResp was called on this
+ * slave port (causing recvTimingResp to be called on the master
+ * port) and was unsuccesful.
+ */
+ virtual void recvRetry() = 0;
+
};
#endif //__MEM_PORT_HH__