ruby: move stall and wakeup functions to AbstractController
[gem5.git] / src / mem / coherent_bus.cc
index 9566549814ca16518b73660e42a934a759af2268..0166872a78f2fd99c534d92fc4abf9ac30e6438b 100644 (file)
 #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<MemCmd, Tick> 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 *