#include "debug/BusAddrRanges.hh"
#include "debug/CoherentBus.hh"
#include "mem/coherent_bus.hh"
+#include "sim/system.hh"
CoherentBus::CoherentBus(const CoherentBusParams *p)
- : BaseBus(p), layer(*this, ".layer", p->clock)
+ : BaseBus(p), reqLayer(*this, ".reqLayer"),
+ respLayer(*this, ".respLayer"),
+ snoopRespLayer(*this, ".snoopRespLayer"),
+ system(p->system)
{
// 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();
// test if the bus should be considered occupied for the current
// port, and exclude express snoops from the check
- if (!is_express_snoop && !layer.tryTiming(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;
// set the source port for routing of the response
pkt->setSrc(slave_port_id);
- Tick headerFinishTime = is_express_snoop ? 0 : calcPacketTiming(pkt);
- Tick packetFinishTime = is_express_snoop ? 0 : pkt->finishTime;
+ calcPacketTiming(pkt);
+ Tick packetFinishTime = pkt->busLastWordDelay + curTick();
// uncacheable requests need never be snooped
- if (!pkt->req->isUncacheable()) {
+ if (!pkt->req->isUncacheable() && !system->bypassCaches()) {
// the packet is a memory-mapped request and should be
// broadcasted to our snoopers but the source
forwardTiming(pkt, slave_port_id);
if (add_outstanding)
outstandingReq.erase(pkt->req);
+ // undo the calculation so we can check for 0 again
+ pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
+
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
- layer.failedTiming(src_port, headerFinishTime);
+ reqLayer.failedTiming(src_port, clockEdge(Cycles(headerCycles)));
} else {
// update the bus state and schedule an idle event
- layer.succeededTiming(packetFinishTime);
+ reqLayer.succeededTiming(packetFinishTime);
}
}
// test if the bus should be considered occupied for the current
// port
- if (!layer.tryTiming(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;
src_port->name(), pkt->cmdString(), pkt->getAddr());
calcPacketTiming(pkt);
- Tick packetFinishTime = pkt->finishTime;
+ Tick packetFinishTime = pkt->busLastWordDelay + curTick();
// the packet is a normal response to a request that we should
// have seen passing through the bus
// deadlock
assert(success);
- layer.succeededTiming(packetFinishTime);
+ respLayer.succeededTiming(packetFinishTime);
return true;
}
// test if the bus should be considered occupied for the current
// port
- if (!layer.tryTiming(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(!pkt->isExpressSnoop());
calcPacketTiming(pkt);
- Tick packetFinishTime = pkt->finishTime;
+ Tick packetFinishTime = pkt->busLastWordDelay + curTick();
// determine if the response is from a snoop request we
// created as the result of a normal request (in which case it
assert(success);
}
- layer.succeededTiming(packetFinishTime);
+ snoopRespLayer.succeededTiming(packetFinishTime);
return true;
}
void
CoherentBus::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id)
{
+ // snoops should only happen if the system isn't bypassing caches
+ assert(!system->bypassCaches());
+
for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
SlavePort *p = *s;
// we could have gotten this request from a snooping master
void
CoherentBus::recvRetry()
{
- // only one layer that can deal with it
- layer.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
Tick snoop_response_latency = 0;
// uncacheable requests need never be snooped
- if (!pkt->req->isUncacheable()) {
+ if (!pkt->req->isUncacheable() && !system->bypassCaches()) {
// forward to all snoopers but the source
std::pair<MemCmd, Tick> snoop_result =
forwardAtomic(pkt, slave_port_id);
response_latency = snoop_response_latency;
}
- pkt->finishTime = curTick() + response_latency;
+ // @todo: Not setting first-word time
+ pkt->busLastWordDelay = response_latency;
return response_latency;
}
if (snoop_response_cmd != MemCmd::InvalidCmd)
pkt->cmd = snoop_response_cmd;
- pkt->finishTime = curTick() + snoop_response_latency;
+ // @todo: Not setting first-word time
+ pkt->busLastWordDelay = snoop_response_latency;
return snoop_response_latency;
}
MemCmd snoop_response_cmd = MemCmd::InvalidCmd;
Tick snoop_response_latency = 0;
+ // snoops should only happen if the system isn't bypassing caches
+ assert(!system->bypassCaches());
+
for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
SlavePort *p = *s;
// we could have gotten this request from a snooping master
}
// uncacheable requests need never be snooped
- if (!pkt->req->isUncacheable()) {
+ if (!pkt->req->isUncacheable() && !system->bypassCaches()) {
// forward to all snoopers but the source
forwardFunctional(pkt, slave_port_id);
}
void
CoherentBus::forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id)
{
+ // snoops should only happen if the system isn't bypassing caches
+ assert(!system->bypassCaches());
+
for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
SlavePort *p = *s;
// we could have gotten this request from a snooping master
}
unsigned int
-CoherentBus::drain(Event *de)
+CoherentBus::drain(DrainManager *dm)
{
- // only one layer to worry about at the moment
- return layer.drain(de);
+ // sum up the individual layers
+ return reqLayer.drain(dm) + respLayer.drain(dm) + snoopRespLayer.drain(dm);
}
CoherentBus *