mem: Tidy up the bridge with const and additional checks
authorAndreas Hansson <andreas.hansson@arm.com>
Thu, 27 Jun 2013 09:49:49 +0000 (05:49 -0400)
committerAndreas Hansson <andreas.hansson@arm.com>
Thu, 27 Jun 2013 09:49:49 +0000 (05:49 -0400)
This patch does a bit of tidying up in the bridge code, adding const
where appropriate and also removing redundant checks and adding a few
new ones.

There are no changes to the behaviour of any regressions.

src/mem/Bridge.py
src/mem/bridge.cc
src/mem/bridge.hh

index 5f2cc9f40ae912fe51706913c6e6899cbb16df6e..e488871a436f9fc63605067265e7e6859e4ab0ce 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 ARM Limited
+# Copyright (c) 2012-2013 ARM Limited
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
@@ -47,8 +47,8 @@ class Bridge(MemObject):
     cxx_header = "mem/bridge.hh"
     slave = SlavePort('Slave port')
     master = MasterPort('Master port')
-    req_size = Param.Int(16, "The number of requests to buffer")
-    resp_size = Param.Int(16, "The number of responses to buffer")
+    req_size = Param.Unsigned(16, "The number of requests to buffer")
+    resp_size = Param.Unsigned(16, "The number of responses to buffer")
     delay = Param.Latency('0ns', "The latency of this bridge")
     ranges = VectorParam.AddrRange([AllMemory],
                                    "Address ranges to pass through the bridge")
index 91bef27570d6e7fc006a88aed60f4652251c8e87..f8258086cff9aca3677d1097dea095aeaf48201a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012 ARM Limited
+ * Copyright (c) 2011-2013 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -120,13 +120,13 @@ Bridge::init()
 }
 
 bool
-Bridge::BridgeSlavePort::respQueueFull()
+Bridge::BridgeSlavePort::respQueueFull() const
 {
     return outstandingResponses == respQueueLimit;
 }
 
 bool
-Bridge::BridgeMasterPort::reqQueueFull()
+Bridge::BridgeMasterPort::reqQueueFull() const
 {
     return transmitList.size() == reqQueueLimit;
 }
@@ -155,26 +155,36 @@ Bridge::BridgeSlavePort::recvTimingReq(PacketPtr pkt)
     DPRINTF(Bridge, "recvTimingReq: %s addr 0x%x\n",
             pkt->cmdString(), pkt->getAddr());
 
-    // ensure we do not have something waiting to retry
-    if(retryReq)
-        return false;
+    // we should not see a timing request if we are already in a retry
+    assert(!retryReq);
 
     DPRINTF(Bridge, "Response queue size: %d outresp: %d\n",
             transmitList.size(), outstandingResponses);
 
+    // if the request queue is full then there is no hope
     if (masterPort.reqQueueFull()) {
         DPRINTF(Bridge, "Request queue full\n");
         retryReq = true;
-    } else if (pkt->needsResponse()) {
-        if (respQueueFull()) {
-            DPRINTF(Bridge, "Response queue full\n");
-            retryReq = true;
-        } else {
-            DPRINTF(Bridge, "Reserving space for response\n");
-            assert(outstandingResponses != respQueueLimit);
-            ++outstandingResponses;
-            retryReq = false;
+    } else {
+        // look at the response queue if we expect to see a response
+        bool expects_response = pkt->needsResponse() &&
+            !pkt->memInhibitAsserted();
+        if (expects_response) {
+            if (respQueueFull()) {
+                DPRINTF(Bridge, "Response queue full\n");
+                retryReq = true;
+            } else {
+                // ok to send the request with space for the response
+                DPRINTF(Bridge, "Reserving space for response\n");
+                assert(outstandingResponses != respQueueLimit);
+                ++outstandingResponses;
+
+                // no need to set retryReq to false as this is already the
+                // case
+            }
+        }
 
+        if (!retryReq) {
             // @todo: We need to pay for this and not just zero it out
             pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
 
@@ -274,9 +284,9 @@ Bridge::BridgeMasterPort::trySendTiming()
 
         // If there are more packets to send, schedule event to try again.
         if (!transmitList.empty()) {
-            req = transmitList.front();
+            DeferredPacket next_req = transmitList.front();
             DPRINTF(Bridge, "Scheduling next send\n");
-            bridge.schedule(sendEvent, std::max(req.tick,
+            bridge.schedule(sendEvent, std::max(next_req.tick,
                                                 bridge.clockEdge()));
         }
 
@@ -315,9 +325,9 @@ Bridge::BridgeSlavePort::trySendTiming()
 
         // If there are more packets to send, schedule event to try again.
         if (!transmitList.empty()) {
-            resp = transmitList.front();
+            DeferredPacket next_resp = transmitList.front();
             DPRINTF(Bridge, "Scheduling next send\n");
-            bridge.schedule(sendEvent, std::max(resp.tick,
+            bridge.schedule(sendEvent, std::max(next_resp.tick,
                                                 bridge.clockEdge()));
         }
 
@@ -338,21 +348,13 @@ Bridge::BridgeSlavePort::trySendTiming()
 void
 Bridge::BridgeMasterPort::recvRetry()
 {
-    Tick nextReady = transmitList.front().tick;
-    if (nextReady <= curTick())
-        trySendTiming();
-    else
-        bridge.schedule(sendEvent, nextReady);
+    trySendTiming();
 }
 
 void
 Bridge::BridgeSlavePort::recvRetry()
 {
-    Tick nextReady = transmitList.front().tick;
-    if (nextReady <= curTick())
-        trySendTiming();
-    else
-        bridge.schedule(sendEvent, nextReady);
+    trySendTiming();
 }
 
 Tick
@@ -364,12 +366,10 @@ Bridge::BridgeSlavePort::recvAtomic(PacketPtr pkt)
 void
 Bridge::BridgeSlavePort::recvFunctional(PacketPtr pkt)
 {
-    std::list<DeferredPacket>::iterator i;
-
     pkt->pushLabel(name());
 
     // check the response queue
-    for (i = transmitList.begin();  i != transmitList.end(); ++i) {
+    for (auto i = transmitList.begin();  i != transmitList.end(); ++i) {
         if (pkt->checkFunctional((*i).pkt)) {
             pkt->makeResponse();
             return;
@@ -391,7 +391,7 @@ bool
 Bridge::BridgeMasterPort::checkFunctional(PacketPtr pkt)
 {
     bool found = false;
-    std::list<DeferredPacket>::iterator i = transmitList.begin();
+    auto i = transmitList.begin();
 
     while(i != transmitList.end() && !found) {
         if (pkt->checkFunctional((*i).pkt)) {
index 2e594a30ae255c562ec7d6ae07b4dc3f95da7ea8..e672c1f7a5111edfc0a9cc14d8f1f8676704dd98 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012 ARM Limited
+ * Copyright (c) 2011-2013 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -51,7 +51,7 @@
 #ifndef __MEM_BRIDGE_HH__
 #define __MEM_BRIDGE_HH__
 
-#include <list>
+#include <deque>
 
 #include "base/types.hh"
 #include "mem/mem_object.hh"
@@ -84,7 +84,7 @@ class Bridge : public MemObject
 
       public:
 
-        PortID origSrc;
+        const PortID origSrc;
 
         RequestState(PortID orig_src) : origSrc(orig_src)
         { }
@@ -100,8 +100,8 @@ class Bridge : public MemObject
 
       public:
 
-        Tick tick;
-        PacketPtr pkt;
+        const Tick tick;
+        const PacketPtr pkt;
 
         DeferredPacket(PacketPtr _pkt, Tick _tick) : tick(_tick), pkt(_pkt)
         { }
@@ -131,17 +131,18 @@ class Bridge : public MemObject
         BridgeMasterPort& masterPort;
 
         /** Minimum request delay though this bridge. */
-        Cycles delay;
+        const Cycles delay;
 
         /** Address ranges to pass through the bridge */
-        AddrRangeList ranges;
+        const AddrRangeList ranges;
 
         /**
          * Response packet queue. Response packets are held in this
          * queue for a specified delay to model the processing delay
-         * of the bridge.
+         * of the bridge. We use a deque as we need to iterate over
+         * the items for functional accesses.
          */
-        std::list<DeferredPacket> transmitList;
+        std::deque<DeferredPacket> transmitList;
 
         /** Counter to track the outstanding responses. */
         unsigned int outstandingResponses;
@@ -157,7 +158,7 @@ class Bridge : public MemObject
          *
          * @return true if the reserved space has reached the set limit
          */
-        bool respQueueFull();
+        bool respQueueFull() const;
 
         /**
          * Handle send event, scheduled when the packet at the head of
@@ -246,17 +247,18 @@ class Bridge : public MemObject
         BridgeSlavePort& slavePort;
 
         /** Minimum delay though this bridge. */
-        Cycles delay;
+        const Cycles delay;
 
         /**
          * Request packet queue. Request packets are held in this
          * queue for a specified delay to model the processing delay
-         * of the bridge.
+         * of the bridge.  We use a deque as we need to iterate over
+         * the items for functional accesses.
          */
-        std::list<DeferredPacket> transmitList;
+        std::deque<DeferredPacket> transmitList;
 
         /** Max queue size for request packets */
-        unsigned int reqQueueLimit;
+        const unsigned int reqQueueLimit;
 
         /**
          * Handle send event, scheduled when the packet at the head of
@@ -289,7 +291,7 @@ class Bridge : public MemObject
          *
          * @return true if the occupied space has reached the set limit
          */
-        bool reqQueueFull();
+        bool reqQueueFull() const;
 
         /**
          * Queue a request packet to be sent out later and also schedule