ruby: slicc: remove nextLineHack from Type.py
[gem5.git] / src / mem / snoop_filter.cc
index 1acfbef6ce066b2b8550f4175f88f0a5ec6a7c08..48587c8ee6a3d149bc8d396b931a24b83b630221 100755 (executable)
@@ -56,12 +56,25 @@ SnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port)
 
     Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
     SnoopMask req_port = portToMask(slave_port);
-    SnoopItem& sf_item  = cachedLocations[line_addr];
+    auto sf_it = cachedLocations.find(line_addr);
+    bool is_hit = (sf_it != cachedLocations.end());
+    // Create a new element through operator[] and modify in-place
+    SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr];
+    SnoopMask interested = sf_item.holder | sf_item.requested;
+
+    totRequests++;
+    if (is_hit) {
+        // Single bit set -> value is a power of two
+        if (isPow2(interested))
+            hitSingleRequests++;
+        else
+            hitMultiRequests++;
+    }
 
     DPRINTF(SnoopFilter, "%s:   SF value %x.%x\n",
             __func__, sf_item.requested, sf_item.holder);
 
-    if (cpkt->needsResponse()) {
+    if (!cpkt->req->isUncacheable() && cpkt->needsResponse()) {
         if (!cpkt->memInhibitAsserted()) {
             // Max one request per address per port
             panic_if(sf_item.requested & req_port, "double request :( "\
@@ -81,8 +94,7 @@ SnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port)
         DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
                 __func__,  sf_item.requested, sf_item.holder);
     }
-    SnoopMask interested = (sf_item.holder | sf_item.requested) & ~req_port;
-    return snoopSelected(maskToPortList(interested), lookupLatency);
+    return snoopSelected(maskToPortList(interested & ~req_port), lookupLatency);
 }
 
 void
@@ -92,6 +104,9 @@ SnoopFilter::updateRequest(const Packet* cpkt, const SlavePort& slave_port,
     DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
             __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
 
+    if (cpkt->req->isUncacheable())
+        return;
+
     Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
     SnoopMask req_port = portToMask(slave_port);
     SnoopItem& sf_item  = cachedLocations[line_addr];
@@ -119,7 +134,8 @@ SnoopFilter::updateRequest(const Packet* cpkt, const SlavePort& slave_port,
             // Writebacks -> the sender does not have the line anymore
             sf_item.holder &= ~req_port;
         } else {
-            assert(0 == "Handle non-writeback, here");
+            // @todo Add CleanEvicts
+            assert(cpkt->cmd == MemCmd::CleanEvict);
         }
         DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
                 __func__,  sf_item.requested, sf_item.holder);
@@ -141,13 +157,31 @@ SnoopFilter::lookupSnoop(const Packet* cpkt)
         return snoopAll(lookupLatency);
 
     Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
-    SnoopItem& sf_item = cachedLocations[line_addr];
+    auto sf_it = cachedLocations.find(line_addr);
+    bool is_hit = (sf_it != cachedLocations.end());
+    // Create a new element through operator[] and modify in-place
+    SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr];
 
     DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
             __func__, sf_item.requested, sf_item.holder);
 
     SnoopMask interested = (sf_item.holder | sf_item.requested);
-    assert(cpkt->isInvalidate() == cpkt->needsExclusive());
+
+    totSnoops++;
+    if (is_hit) {
+        // Single bit set -> value is a power of two
+        if (isPow2(interested))
+            hitSingleSnoops++;
+        else
+            hitMultiSnoops++;
+    }
+    // ReadEx and Writes require both invalidation and exlusivity, while reads
+    // require neither. Writebacks on the other hand require exclusivity but
+    // not the invalidation. Previously Writebacks did not generate upward
+    // snoops so this was never an aissue. Now that Writebacks generate snoops
+    // we need to special case for Writebacks.
+    assert(cpkt->cmd == MemCmd::Writeback ||
+           (cpkt->isInvalidate() == cpkt->needsExclusive()));
     if (cpkt->isInvalidate() && !sf_item.requested) {
         // Early clear of the holder, if no other request is currently going on
         // @todo: This should possibly be updated even though we do not filter
@@ -170,14 +204,17 @@ SnoopFilter::updateSnoopResponse(const Packet* cpkt,
             __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
             cpkt->cmdString());
 
+    assert(cpkt->isResponse());
+    assert(cpkt->memInhibitAsserted());
+
+    if (cpkt->req->isUncacheable())
+        return;
+
     Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
     SnoopMask rsp_mask = portToMask(rsp_port);
     SnoopMask req_mask = portToMask(req_port);
     SnoopItem& sf_item = cachedLocations[line_addr];
 
-    assert(cpkt->isResponse());
-    assert(cpkt->memInhibitAsserted());
-
     DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
             __func__,  sf_item.requested, sf_item.holder);
 
@@ -245,12 +282,15 @@ SnoopFilter::updateResponse(const Packet* cpkt, const SlavePort& slave_port)
     DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
             __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
 
+    assert(cpkt->isResponse());
+
+    if (cpkt->req->isUncacheable())
+        return;
+
     Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
     SnoopMask slave_mask = portToMask(slave_port);
     SnoopItem& sf_item = cachedLocations[line_addr];
 
-    assert(cpkt->isResponse());
-
     DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
             __func__,  sf_item.requested, sf_item.holder);
 
@@ -267,6 +307,38 @@ SnoopFilter::updateResponse(const Packet* cpkt, const SlavePort& slave_port)
             __func__, sf_item.requested, sf_item.holder);
 }
 
+void
+SnoopFilter::regStats()
+{
+    totRequests
+        .name(name() + ".tot_requests")
+        .desc("Total number of requests made to the snoop filter.");
+
+    hitSingleRequests
+        .name(name() + ".hit_single_requests")
+        .desc("Number of requests hitting in the snoop filter with a single "\
+              "holder of the requested data.");
+
+    hitMultiRequests
+        .name(name() + ".hit_multi_requests")
+        .desc("Number of requests hitting in the snoop filter with multiple "\
+              "(>1) holders of the requested data.");
+
+    totSnoops
+        .name(name() + ".tot_snoops")
+        .desc("Total number of snoops made to the snoop filter.");
+
+    hitSingleSnoops
+        .name(name() + ".hit_single_snoops")
+        .desc("Number of snoops hitting in the snoop filter with a single "\
+              "holder of the requested data.");
+
+    hitMultiSnoops
+        .name(name() + ".hit_multi_snoops")
+        .desc("Number of snoops hitting in the snoop filter with multiple "\
+              "(>1) holders of the requested data.");
+}
+
 SnoopFilter *
 SnoopFilterParams::create()
 {