Commiting a version of the multi-phase snoop atomic bus so people can see the framewo...
authorRon Dreslinski <rdreslin@umich.edu>
Tue, 22 Aug 2006 20:08:18 +0000 (16:08 -0400)
committerRon Dreslinski <rdreslin@umich.edu>
Tue, 22 Aug 2006 20:08:18 +0000 (16:08 -0400)
Working on pulling out the changes in the cache so that it remains working.

src/mem/bus.cc:
    Changes for multi-phase snoop
    Some code for registering snoop ranges (a version that compiles and runs, but does nothing)
src/mem/bus.hh:
    Changes for multi-phase snoop
src/mem/packet.hh:
    Flag for multi-phase snoop
src/mem/port.hh:
    Status for multi-phase snoop

--HG--
extra : convert_revision : 4c2e5263bba16e3bcf03aabe36ff45ec36de4720

src/mem/bus.cc
src/mem/bus.hh
src/mem/packet.hh
src/mem/port.hh

index b945f93b324432ca1e462bb49b5a539371b76885..bca209cd7443d3ab3e94273caa0cd70cb11b5701 100644 (file)
@@ -79,7 +79,17 @@ Bus::recvTiming(Packet *pkt)
 
     short dest = pkt->getDest();
     if (dest == Packet::Broadcast) {
-        port = findPort(pkt->getAddr(), pkt->getSrc());
+        if ( timingSnoopPhase1(pkt) )
+        {
+            timingSnoopPhase2(pkt);
+            port = findPort(pkt->getAddr(), pkt->getSrc());
+        }
+        else
+        {
+            //Snoop didn't succeed
+            retryList.push_back(interfaces[pkt->getSrc()]);
+            return false;
+        }
     } else {
         assert(dest >= 0 && dest < interfaces.size());
         assert(dest != pkt->getSrc()); // catch infinite loops
@@ -151,6 +161,77 @@ Bus::findPort(Addr addr, int id)
     return interfaces[dest_id];
 }
 
+std::vector<int>
+Bus::findSnoopPorts(Addr addr, int id)
+{
+    int i = 0;
+    AddrRangeIter iter;
+    std::vector<int> ports;
+
+    while (i < portSnoopList.size())
+    {
+        if (portSnoopList[i].range == addr && portSnoopList[i].portId != id) {
+            //Careful  to not overlap ranges
+            //or snoop will be called more than once on the port
+            ports.push_back(portSnoopList[i].portId);
+            DPRINTF(Bus, "  found snoop addr 0x%llx on device%d\n", addr,
+                    portSnoopList[i].portId);
+        }
+        i++;
+    }
+    return ports;
+}
+
+void
+Bus::atomicSnoop(Packet *pkt)
+{
+    std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc());
+
+    while (!ports.empty())
+    {
+        interfaces[ports.back()]->sendAtomic(pkt);
+        ports.pop_back();
+    }
+}
+
+bool
+Bus::timingSnoopPhase1(Packet *pkt)
+{
+    std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc());
+    bool success = true;
+
+    while (!ports.empty() && success)
+    {
+        snoopCallbacks.push_back(ports.back());
+        success = interfaces[ports.back()]->sendTiming(pkt);
+        ports.pop_back();
+    }
+    if (!success)
+    {
+        while (!snoopCallbacks.empty())
+        {
+            interfaces[snoopCallbacks.back()]->sendStatusChange(Port::SnoopSquash);
+            snoopCallbacks.pop_back();
+        }
+        return false;
+    }
+    return true;
+}
+
+void
+Bus::timingSnoopPhase2(Packet *pkt)
+{
+    bool success;
+    pkt->flags |= SNOOP_COMMIT;
+    while (!snoopCallbacks.empty())
+    {
+        success = interfaces[snoopCallbacks.back()]->sendTiming(pkt);
+        //We should not fail on snoop callbacks
+        assert(success);
+        snoopCallbacks.pop_back();
+    }
+}
+
 /** Function called by the port when the bus is receiving a Atomic
  * transaction.*/
 Tick
@@ -159,6 +240,7 @@ Bus::recvAtomic(Packet *pkt)
     DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",
             pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
     assert(pkt->getDest() == Packet::Broadcast);
+    atomicSnoop(pkt);
     return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt);
 }
 
@@ -193,7 +275,7 @@ Bus::recvStatusChange(Port::Status status, int id)
         assert(snoops.size() == 0);
         for(iter = ranges.begin(); iter != ranges.end(); iter++) {
             defaultRange.push_back(*iter);
-            DPRINTF(BusAddrRanges, "Adding range %llx - %llx for default\n",
+            DPRINTF(BusAddrRanges, "Adding range %llx - %llx for default range\n",
                     iter->start, iter->end);
         }
     } else {
@@ -201,6 +283,7 @@ Bus::recvStatusChange(Port::Status status, int id)
         assert((id < interfaces.size() && id >= 0) || id == -1);
         Port *port = interfaces[id];
         std::vector<DevMap>::iterator portIter;
+        std::vector<DevMap>::iterator snoopIter;
 
         // Clean out any previously existent ids
         for (portIter = portList.begin(); portIter != portList.end(); ) {
@@ -210,10 +293,25 @@ Bus::recvStatusChange(Port::Status status, int id)
                 portIter++;
         }
 
+        for (snoopIter = portSnoopList.begin(); snoopIter != portSnoopList.end(); ) {
+            if (snoopIter->portId == id)
+                snoopIter = portSnoopList.erase(snoopIter);
+            else
+                snoopIter++;
+        }
+
         port->getPeerAddressRanges(ranges, snoops);
 
-        // not dealing with snooping yet either
-        assert(snoops.size() == 0);
+        for(iter = snoops.begin(); iter != snoops.end(); iter++) {
+            DevMap dm;
+            dm.portId = id;
+            dm.range = *iter;
+
+            DPRINTF(BusAddrRanges, "Adding snoop range %llx - %llx for id %d\n",
+                    dm.range.start, dm.range.end, id);
+            portSnoopList.push_back(dm);
+        }
+
         for(iter = ranges.begin(); iter != ranges.end(); iter++) {
             DevMap dm;
             dm.portId = id;
index cd25fab2c43c1bb7c36202a261717d3a617f446d..941389296d9680fe2b893c940b4d20cb9d57fab5 100644 (file)
@@ -60,6 +60,9 @@ class Bus : public MemObject
     };
     std::vector<DevMap> portList;
     AddrRangeList defaultRange;
+    std::vector<DevMap> portSnoopList;
+
+    std::vector<int> snoopCallbacks;
 
 
     /** Function called by the port when the bus is recieving a Timing
@@ -90,6 +93,29 @@ class Bus : public MemObject
      */
     Port *findPort(Addr addr, int id);
 
+    /** Find all ports with a matching snoop range, except src port.  Keep in mind
+     * that the ranges shouldn't overlap or you will get a double snoop to the same
+     * interface.and the cache will assert out.
+     * @param addr Address to find snoop prts for.
+     * @param id Id of the src port of the request to avoid calling snoop on src
+     * @return vector of IDs to snoop on
+     */
+    std::vector<int> findSnoopPorts(Addr addr, int id);
+
+    /** Snoop all relevant ports atomicly. */
+    void atomicSnoop(Packet *pkt);
+
+    /** Snoop for NACK and Blocked in phase 1
+     * @return True if succeds.
+     */
+    bool timingSnoopPhase1(Packet *pkt);
+
+    /** @todo Don't need to commit all snoops just those that need it
+     *(register somehow). */
+    /** Commit all snoops now that we know if any of them would have blocked.
+     */
+    void timingSnoopPhase2(Packet *pkt);
+
     /** Process address range request.
      * @param resp addresses that we can respond to
      * @param snoop addresses that we would like to snoop
index 5d8308df7715844378d6d432bc9c87113c9be5b0..c7d28010cb453e3a1c9d2d18ed34d1cd5c16ae5b 100644 (file)
@@ -56,6 +56,7 @@ typedef std::list<PacketPtr> PacketList;
 #define CACHE_LINE_FILL 1 << 3
 #define COMPRESSED 1 << 4
 #define NO_ALLOCATE 1 << 5
+#define SNOOP_COMMIT 1 << 6
 
 //For statistics we need max number of commands, hard code it at
 //20 for now.  @todo fix later
index 42e369205a94460870e3cea3724474132349911e..80c591f82923609db18f2b40a62cbbca558525ee 100644 (file)
@@ -106,7 +106,8 @@ class Port
     /** Holds the ports status.  Currently just that a range recomputation needs
      * to be done. */
     enum Status {
-        RangeChange
+        RangeChange,
+        SnoopSquash
     };
 
     void setName(const std::string &name)