X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmem%2Fcoherent_bus.cc;h=0166872a78f2fd99c534d92fc4abf9ac30e6438b;hb=8573a69d8f7bf7b3f074e3e0ac64994801c551be;hp=9566549814ca16518b73660e42a934a759af2268;hpb=995e6e4670f52c52f798320055d74994e6539cda;p=gem5.git diff --git a/src/mem/coherent_bus.cc b/src/mem/coherent_bus.cc index 956654981..0166872a7 100644 --- a/src/mem/coherent_bus.cc +++ b/src/mem/coherent_bus.cc @@ -52,15 +52,19 @@ #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); } @@ -69,7 +73,7 @@ CoherentBus::CoherentBus(const CoherentBusParams *p) // 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); @@ -77,7 +81,7 @@ CoherentBus::CoherentBus(const CoherentBusParams *p) // 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); } @@ -88,6 +92,9 @@ CoherentBus::CoherentBus(const CoherentBusParams *p) 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(); @@ -115,7 +122,7 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id) // 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; @@ -128,11 +135,11 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id) // 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); @@ -172,14 +179,17 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID 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); } } @@ -194,7 +204,7 @@ CoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id) // 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; @@ -204,7 +214,7 @@ CoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id) 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 @@ -221,7 +231,7 @@ CoherentBus::recvTimingResp(PacketPtr pkt, PortID master_port_id) // deadlock assert(success); - layer.succeededTiming(packetFinishTime); + respLayer.succeededTiming(packetFinishTime); return true; } @@ -258,7 +268,7 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id) // 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; @@ -274,7 +284,7 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id) 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 @@ -309,7 +319,7 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id) assert(success); } - layer.succeededTiming(packetFinishTime); + snoopRespLayer.succeededTiming(packetFinishTime); return true; } @@ -318,6 +328,9 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id) 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 @@ -335,8 +348,10 @@ CoherentBus::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id) 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 @@ -350,7 +365,7 @@ CoherentBus::recvAtomic(PacketPtr pkt, PortID slave_port_id) 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 snoop_result = forwardAtomic(pkt, slave_port_id); @@ -373,7 +388,8 @@ CoherentBus::recvAtomic(PacketPtr pkt, PortID 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; } @@ -393,7 +409,8 @@ CoherentBus::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id) 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; } @@ -407,6 +424,9 @@ CoherentBus::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id) 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 @@ -451,7 +471,7 @@ CoherentBus::recvFunctional(PacketPtr pkt, PortID slave_port_id) } // 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); } @@ -483,6 +503,9 @@ CoherentBus::recvFunctionalSnoop(PacketPtr pkt, PortID master_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 @@ -501,10 +524,10 @@ CoherentBus::forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id) } 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 *