MEM: Make the bus default port yet another port
authorAndreas Hansson <andreas.hansson@arm.com>
Tue, 17 Jan 2012 18:55:09 +0000 (12:55 -0600)
committerAndreas Hansson <andreas.hansson@arm.com>
Tue, 17 Jan 2012 18:55:09 +0000 (12:55 -0600)
This patch removes the idiosyncratic nature of the default bus port
and makes it yet another port in the list of interfaces. Rather than
having a specific pointer to the default port we merely track the
identifier of this port. This change makes future port diversification
easier and overall cleans up the bus code.

src/mem/bus.cc
src/mem/bus.hh

index ea1ec7322e300945ff43bb00d2544e922e59d351..a20f90108e0c5367342884c7bed99ac2438a72e2 100644 (file)
@@ -38,6 +38,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Ali Saidi
+ *          Andreas Hansson
  */
 
 /**
@@ -45,9 +46,6 @@
  * Definition of a bus object.
  */
 
-#include <algorithm>
-#include <limits>
-
 #include "base/misc.hh"
 #include "base/trace.hh"
 #include "debug/Bus.hh"
@@ -58,8 +56,7 @@
 Bus::Bus(const BusParams *p)
     : MemObject(p), busId(p->bus_id), clock(p->clock),
       headerCycles(p->header_cycles), width(p->width), tickNextIdle(0),
-      drainEvent(NULL), busIdle(this), inRetry(false), maxId(0),
-      defaultPort(NULL),
+      drainEvent(NULL), busIdle(this), inRetry(false), defaultPortId(-1),
       useDefaultRange(p->use_default_range), defaultBlockSize(p->block_size),
       cachedBlockSize(0), cachedBlockSizeValid(false)
 {
@@ -70,28 +67,25 @@ Bus::Bus(const BusParams *p)
         fatal("Bus clock period must be positive\n");
     if (headerCycles <= 0)
         fatal("Number of header cycles must be positive\n");
-    clearBusCache();
     clearPortCache();
 }
 
 Port *
 Bus::getPort(const std::string &if_name, int idx)
 {
+    std::string portName;
+    int id = interfaces.size();
     if (if_name == "default") {
-        if (defaultPort == NULL) {
-            defaultPort = new BusPort(csprintf("%s-default",name()), this,
-                                      defaultId);
-            cachedBlockSizeValid = false;
-            return defaultPort;
+        if (defaultPortId == -1) {
+            defaultPortId = id;
+            portName = csprintf("%s-default", name());
         } else
-            fatal("Default port already set\n");
+            fatal("Default port already set on %s\n", name());
+    } else {
+        portName = csprintf("%s-p%d", name(), id);
     }
-    int id;
-    // if_name ignored?  forced to be empty?
-    id = maxId++;
-    assert(maxId < std::numeric_limits<typeof(maxId)>::max());
-    BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
-    interfaces[id] = bp;
+    BusPort *bp = new BusPort(portName, this, id);
+    interfaces.push_back(bp);
     cachedBlockSizeValid = false;
     return bp;
 }
@@ -99,16 +93,16 @@ Bus::getPort(const std::string &if_name, int idx)
 void
 Bus::init()
 {
-    m5::hash_map<short,BusPort*>::iterator intIter;
+    std::vector<BusPort*>::iterator intIter;
 
     // iterate over our interfaces and determine which of our neighbours
     // are snooping and add them as snoopers
     for (intIter = interfaces.begin(); intIter != interfaces.end();
          intIter++) {
-        if (intIter->second->getPeer()->isSnooping()) {
+        if ((*intIter)->getPeer()->isSnooping()) {
             DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n",
-                    intIter->second->getPeer()->name());
-            snoopPorts.push_back(intIter->second);
+                    (*intIter)->getPeer()->name());
+            snoopPorts.push_back(*intIter);
         }
     }
 }
@@ -188,16 +182,7 @@ Bus::recvTiming(PacketPtr pkt)
 {
     short src = pkt->getSrc();
 
-    BusPort *src_port;
-    if (src == defaultId)
-        src_port = defaultPort;
-    else {
-        src_port = checkBusCache(src);
-        if (src_port == NULL) {
-            src_port = interfaces[src];
-            updateBusCache(src, src_port);
-        }
-    }
+    BusPort *src_port = interfaces[src];
 
     // If the bus is busy, or other devices are in line ahead of the current
     // one, put this device on the retry list.
@@ -223,8 +208,7 @@ Bus::recvTiming(PacketPtr pkt)
 
     if (dest == Packet::Broadcast) {
         dest_port_id = findPort(pkt->getAddr());
-        dest_port = (dest_port_id == defaultId) ?
-            defaultPort : interfaces[dest_port_id];
+        dest_port = interfaces[dest_port_id];
         SnoopIter s_end = snoopPorts.end();
         for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
             BusPort *p = *s_iter;
@@ -235,20 +219,10 @@ Bus::recvTiming(PacketPtr pkt)
             }
         }
     } else {
-        assert(dest < maxId);
+        assert(dest < interfaces.size());
         assert(dest != src); // catch infinite loops
         dest_port_id = dest;
-        if (dest_port_id == defaultId)
-            dest_port = defaultPort;
-        else {
-            dest_port = checkBusCache(dest);
-            if (dest_port == NULL) {
-                dest_port = interfaces[dest_port_id];
-            // updateBusCache(dest_port_id, dest_port);
-            }
-        }
-        dest_port = (dest_port_id == defaultId) ?
-            defaultPort : interfaces[dest_port_id];
+        dest_port = interfaces[dest_port_id];
     }
 
     if (dest_port_id == src) {
@@ -346,7 +320,7 @@ Bus::findPort(Addr addr)
         for (AddrRangeIter i = defaultRange.begin(); i != a_end; i++) {
             if (*i == addr) {
                 DPRINTF(Bus, "  found addr %#llx on default\n", addr);
-                return defaultId;
+                return defaultPortId;
             }
         }
 
@@ -355,7 +329,7 @@ Bus::findPort(Addr addr)
 
     DPRINTF(Bus, "Unable to find destination for addr %#llx, "
             "will use default port\n", addr);
-    return defaultId;
+    return defaultPortId;
 }
 
 
@@ -379,16 +353,7 @@ Bus::recvAtomic(PacketPtr pkt)
     int orig_src = pkt->getSrc();
 
     int target_port_id = findPort(pkt->getAddr());
-    BusPort *target_port;
-    if (target_port_id == defaultId)
-        target_port = defaultPort;
-    else {
-      target_port = checkBusCache(target_port_id);
-      if (target_port == NULL) {
-          target_port = interfaces[target_port_id];
-          updateBusCache(target_port_id, target_port);
-      }
-    }
+    BusPort *target_port = interfaces[target_port_id];
 
     SnoopIter s_end = snoopPorts.end();
     for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
@@ -444,7 +409,7 @@ Bus::recvFunctional(PacketPtr pkt)
     assert(pkt->getDest() == Packet::Broadcast);
 
     int port_id = findPort(pkt->getAddr());
-    Port *port = (port_id == defaultId) ? defaultPort : interfaces[port_id];
+    Port *port = interfaces[port_id];
     // The packet may be changed by another bus on snoops, restore the
     // id after each
     int src_id = pkt->getSrc();
@@ -491,11 +456,11 @@ Bus::recvRangeChange(int id)
     DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);
 
     clearPortCache();
-    if (id == defaultId) {
+    if (id == defaultPortId) {
         defaultRange.clear();
         // Only try to update these ranges if the user set a default responder.
         if (useDefaultRange) {
-            AddrRangeList ranges = defaultPort->getPeer()->getAddrRanges();
+            AddrRangeList ranges = interfaces[id]->getPeer()->getAddrRanges();
             for(iter = ranges.begin(); iter != ranges.end(); iter++) {
                 defaultRange.push_back(*iter);
                 DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n",
@@ -504,7 +469,7 @@ Bus::recvRangeChange(int id)
         }
     } else {
 
-        assert((id < maxId && id >= 0) || id == defaultId);
+        assert(id < interfaces.size() && id >= 0);
         BusPort *port = interfaces[id];
 
         // Clean out any previously existent ids
@@ -533,14 +498,12 @@ Bus::recvRangeChange(int id)
 
     // tell all our peers that our address range has changed.
     // Don't tell the device that caused this change, it already knows
-    m5::hash_map<short,BusPort*>::iterator intIter;
+    std::vector<BusPort*>::const_iterator intIter;
 
     for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
-        if (intIter->first != id)
-            intIter->second->sendRangeChange();
+        if ((*intIter)->getId() != id)
+            (*intIter)->sendRangeChange();
 
-    if (id != defaultId && defaultPort)
-        defaultPort->sendRangeChange();
     inRecvRangeChange.erase(id);
 }
 
index 2ad17cf3bd34e635537074ddf97ced0762fabcdc..5b8b373a54df82789b66b69d7745073ebd67bf89 100644 (file)
@@ -39,6 +39,7 @@
  *
  * Authors: Ron Dreslinski
  *          Ali Saidi
+ *          Andreas Hansson
  */
 
 /**
@@ -91,7 +92,7 @@ class Bus : public MemObject
         void onRetryList(bool newVal)
         { _onRetryList = newVal; }
 
-        int getId() { return id; }
+        int getId() const { return id; }
 
         /**
          * Determine if this port should be considered a snooper. This
@@ -167,9 +168,6 @@ class Bus : public MemObject
 
     Event * drainEvent;
 
-
-    static const int defaultId = -3; //Make it unique from Broadcast
-
     typedef range_map<Addr,int>::iterator PortIter;
     range_map<Addr, int> portMap;
 
@@ -297,12 +295,9 @@ class Bus : public MemObject
     bool inRetry;
     std::set<int> inRecvRangeChange;
 
-    /** max number of bus ids we've handed out so far */
-    short maxId;
-
-    /** An array of pointers to the peer port interfaces
+    /** An ordered vector of pointers to the peer port interfaces
         connected to this bus.*/
-    m5::hash_map<short,BusPort*> interfaces;
+    std::vector<BusPort*> interfaces;
 
     /** An array of pointers to ports that retry should be called on because the
      * original send failed for whatever reason.*/
@@ -331,7 +326,7 @@ class Bus : public MemObject
     }
 
     /** Port that handles requests that don't match any of the interfaces.*/
-    BusPort *defaultPort;
+    short defaultPortId;
 
     /** If true, use address range provided by default device.  Any
        address not handled by another port and not in default device's
@@ -343,54 +338,6 @@ class Bus : public MemObject
     unsigned cachedBlockSize;
     bool cachedBlockSizeValid;
 
-   // Cache for the peer port interfaces
-    struct BusCache {
-        bool  valid;
-        short id;
-        BusPort  *port;
-    };
-
-    BusCache busCache[3];
-
-    // Checks the peer port interfaces cache for the port id and returns
-    // a pointer to the matching port
-    inline BusPort* checkBusCache(short id) {
-        if (busCache[0].valid && id == busCache[0].id) {
-            return busCache[0].port;
-        }
-        if (busCache[1].valid && id == busCache[1].id) {
-            return busCache[1].port;
-        }
-        if (busCache[2].valid && id == busCache[2].id) {
-            return busCache[2].port;
-        }
-
-        return NULL;
-    }
-
-    // Replaces the earliest entry in the cache with a new entry
-    inline void updateBusCache(short id, BusPort *port) {
-        busCache[2].valid = busCache[1].valid;
-        busCache[2].id    = busCache[1].id;
-        busCache[2].port  = busCache[1].port;
-
-        busCache[1].valid = busCache[0].valid;
-        busCache[1].id    = busCache[0].id;
-        busCache[1].port  = busCache[0].port;
-
-        busCache[0].valid = true;
-        busCache[0].id    = id;
-        busCache[0].port  = port;
-    }
-
-    // Invalidates the cache. Needs to be called in constructor.
-    inline void clearBusCache() {
-        busCache[2].valid = false;
-        busCache[1].valid = false;
-        busCache[0].valid = false;
-    }
-
-
   public:
 
     /** A function used to return the port associated with this bus object. */