#include "mem/coherent_bus.hh"
CoherentBus::CoherentBus(const CoherentBusParams *p)
- : BaseBus(p)
+ : BaseBus(p), reqLayer(*this, ".reqLayer", p->clock),
+ respLayer(*this, ".respLayer", p->clock),
+ snoopRespLayer(*this, ".snoopRespLayer", p->clock)
{
// create the ports based on the size of the master and slave
// vector ports, and the presence of the default port, the ports
// are enumerated starting from zero
for (int i = 0; i < p->port_master_connection_count; ++i) {
- std::string portName = csprintf("%s-p%d", name(), i);
+ std::string portName = csprintf("%s.master[%d]", name(), i);
MasterPort* bp = new CoherentBusMasterPort(portName, *this, i);
masterPorts.push_back(bp);
}
// our corresponding master port
if (p->port_default_connection_count) {
defaultPortID = masterPorts.size();
- std::string portName = csprintf("%s-default", name());
+ std::string portName = name() + ".default";
MasterPort* bp = new CoherentBusMasterPort(portName, *this,
defaultPortID);
masterPorts.push_back(bp);
// create the slave ports, once again starting at zero
for (int i = 0; i < p->port_slave_connection_count; ++i) {
- std::string portName = csprintf("%s-p%d", name(), i);
+ std::string portName = csprintf("%s.slave[%d]", name(), i);
SlavePort* bp = new CoherentBusSlavePort(portName, *this, i);
slavePorts.push_back(bp);
}
void
CoherentBus::init()
{
+ // the base class is responsible for determining the block size
+ BaseBus::init();
+
// iterate over our slave ports and determine which of our
// neighbouring master ports are snooping and add them as snoopers
for (SlavePortConstIter p = slavePorts.begin(); p != slavePorts.end();
// determine the source port based on the id
SlavePort *src_port = slavePorts[slave_port_id];
+ // remember if the packet is an express snoop
+ bool is_express_snoop = pkt->isExpressSnoop();
+
// test if the bus should be considered occupied for the current
// port, and exclude express snoops from the check
- if (!pkt->isExpressSnoop() && isOccupied(src_port)) {
+ if (!is_express_snoop && !reqLayer.tryTiming(src_port)) {
DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x BUSY\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
return false;
}
- DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x\n",
- src_port->name(), pkt->cmdString(), pkt->getAddr());
+ DPRINTF(CoherentBus, "recvTimingReq: src %s %s expr %d 0x%x\n",
+ src_port->name(), pkt->cmdString(), is_express_snoop,
+ pkt->getAddr());
// set the source port for routing of the response
pkt->setSrc(slave_port_id);
- Tick headerFinishTime = pkt->isExpressSnoop() ? 0 : calcPacketTiming(pkt);
- Tick packetFinishTime = pkt->isExpressSnoop() ? 0 : pkt->finishTime;
+ Tick headerFinishTime = is_express_snoop ? 0 : calcPacketTiming(pkt);
+ Tick packetFinishTime = is_express_snoop ? 0 : pkt->finishTime;
// uncacheable requests need never be snooped
if (!pkt->req->isUncacheable()) {
// necessary, if the packet needs a response, we should add it
// as outstanding and express snoops never fail so there is
// not need to worry about them
- bool add_outstanding = !pkt->isExpressSnoop() && pkt->needsResponse();
+ bool add_outstanding = !is_express_snoop && pkt->needsResponse();
// keep track that we have an outstanding request packet
// matching this request, this is used by the coherency
// based on the address and attempt to send the packet
bool success = masterPorts[findPort(pkt->getAddr())]->sendTimingReq(pkt);
- if (!success) {
- // inhibited packets should never be forced to retry
- assert(!pkt->memInhibitAsserted());
-
- // if it was added as outstanding and the send failed, then
- // erase it again
- if (add_outstanding)
- outstandingReq.erase(pkt->req);
-
- DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x RETRY\n",
- src_port->name(), pkt->cmdString(), pkt->getAddr());
-
- addToRetryList(src_port);
- occupyBus(headerFinishTime);
-
- return false;
+ // if this is an express snoop, we are done at this point
+ if (is_express_snoop) {
+ assert(success);
+ } else {
+ // for normal requests, check if successful
+ if (!success) {
+ // inhibited packets should never be forced to retry
+ assert(!pkt->memInhibitAsserted());
+
+ // if it was added as outstanding and the send failed, then
+ // erase it again
+ if (add_outstanding)
+ outstandingReq.erase(pkt->req);
+
+ DPRINTF(CoherentBus, "recvTimingReq: src %s %s 0x%x RETRY\n",
+ src_port->name(), pkt->cmdString(), pkt->getAddr());
+
+ // update the bus state and schedule an idle event
+ reqLayer.failedTiming(src_port, headerFinishTime);
+ } else {
+ // update the bus state and schedule an idle event
+ reqLayer.succeededTiming(packetFinishTime);
+ }
}
- succeededTiming(packetFinishTime);
-
- return true;
+ return success;
}
bool
// test if the bus should be considered occupied for the current
// port
- if (isOccupied(src_port)) {
+ if (!respLayer.tryTiming(src_port)) {
DPRINTF(CoherentBus, "recvTimingResp: src %s %s 0x%x BUSY\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
return false;
// deadlock
assert(success);
- succeededTiming(packetFinishTime);
+ respLayer.succeededTiming(packetFinishTime);
return true;
}
// wrong, hence there is nothing further to do as the packet
// would be going back to where it came from
assert(master_port_id == findPort(pkt->getAddr()));
-
- // this is an express snoop and is never forced to retry
- assert(!inRetry);
}
bool
// test if the bus should be considered occupied for the current
// port
- if (isOccupied(src_port)) {
+ if (!snoopRespLayer.tryTiming(src_port)) {
DPRINTF(CoherentBus, "recvTimingSnoopResp: src %s %s 0x%x BUSY\n",
src_port->name(), pkt->cmdString(), pkt->getAddr());
return false;
assert(success);
}
- succeededTiming(packetFinishTime);
+ snoopRespLayer.succeededTiming(packetFinishTime);
return true;
}
}
}
+void
+CoherentBus::recvRetry()
+{
+ // responses and snoop responses never block on forwarding them,
+ // so the retry will always be coming from a port to which we
+ // tried to forward a request
+ reqLayer.recvRetry();
+}
+
Tick
CoherentBus::recvAtomic(PacketPtr pkt, PortID slave_port_id)
{
}
}
+unsigned int
+CoherentBus::drain(DrainManager *dm)
+{
+ // sum up the individual layers
+ return reqLayer.drain(dm) + respLayer.drain(dm) + snoopRespLayer.drain(dm);
+}
+
CoherentBus *
CoherentBusParams::create()
{