snoop_filter.cc revision 11134
110399Sstephan.diestelhorst@arm.com/* 211128Sali.jafri@arm.com * Copyright (c) 2013-2015 ARM Limited 310399Sstephan.diestelhorst@arm.com * All rights reserved 410399Sstephan.diestelhorst@arm.com * 510399Sstephan.diestelhorst@arm.com * The license below extends only to copyright in the software and shall 610399Sstephan.diestelhorst@arm.com * not be construed as granting a license to any other intellectual 710399Sstephan.diestelhorst@arm.com * property including but not limited to intellectual property relating 810399Sstephan.diestelhorst@arm.com * to a hardware implementation of the functionality of the software 910399Sstephan.diestelhorst@arm.com * licensed hereunder. You may use the software subject to the license 1010399Sstephan.diestelhorst@arm.com * terms below provided that you ensure that this notice is replicated 1110399Sstephan.diestelhorst@arm.com * unmodified and in its entirety in all distributions of the software, 1210399Sstephan.diestelhorst@arm.com * modified or unmodified, in source code or in binary form. 1310399Sstephan.diestelhorst@arm.com * 1410399Sstephan.diestelhorst@arm.com * Redistribution and use in source and binary forms, with or without 1510399Sstephan.diestelhorst@arm.com * modification, are permitted provided that the following conditions are 1610399Sstephan.diestelhorst@arm.com * met: redistributions of source code must retain the above copyright 1710399Sstephan.diestelhorst@arm.com * notice, this list of conditions and the following disclaimer; 1810399Sstephan.diestelhorst@arm.com * redistributions in binary form must reproduce the above copyright 1910399Sstephan.diestelhorst@arm.com * notice, this list of conditions and the following disclaimer in the 2010399Sstephan.diestelhorst@arm.com * documentation and/or other materials provided with the distribution; 2110399Sstephan.diestelhorst@arm.com * neither the name of the copyright holders nor the names of its 2210399Sstephan.diestelhorst@arm.com * contributors may be used to endorse or promote products derived from 2310399Sstephan.diestelhorst@arm.com * this software without specific prior written permission. 2410399Sstephan.diestelhorst@arm.com * 2510399Sstephan.diestelhorst@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2610399Sstephan.diestelhorst@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2710399Sstephan.diestelhorst@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810399Sstephan.diestelhorst@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2910399Sstephan.diestelhorst@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3010399Sstephan.diestelhorst@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3110399Sstephan.diestelhorst@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3210399Sstephan.diestelhorst@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3310399Sstephan.diestelhorst@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3410399Sstephan.diestelhorst@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3510399Sstephan.diestelhorst@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3610399Sstephan.diestelhorst@arm.com * 3710399Sstephan.diestelhorst@arm.com * Authors: Stephan Diestelhorst <stephan.diestelhorst@arm.com> 3810399Sstephan.diestelhorst@arm.com */ 3910399Sstephan.diestelhorst@arm.com 4010399Sstephan.diestelhorst@arm.com/** 4110399Sstephan.diestelhorst@arm.com * @file 4210399Sstephan.diestelhorst@arm.com * Definition of a snoop filter. 4310399Sstephan.diestelhorst@arm.com */ 4410399Sstephan.diestelhorst@arm.com 4510399Sstephan.diestelhorst@arm.com#include "base/misc.hh" 4610399Sstephan.diestelhorst@arm.com#include "base/trace.hh" 4710399Sstephan.diestelhorst@arm.com#include "debug/SnoopFilter.hh" 4810399Sstephan.diestelhorst@arm.com#include "mem/snoop_filter.hh" 4910399Sstephan.diestelhorst@arm.com#include "sim/system.hh" 5010399Sstephan.diestelhorst@arm.com 5111129Sali.jafri@arm.comvoid 5211129Sali.jafri@arm.comSnoopFilter::eraseIfNullEntry(SnoopFilterCache::iterator& sf_it) 5311129Sali.jafri@arm.com{ 5411129Sali.jafri@arm.com SnoopItem& sf_item = sf_it->second; 5511129Sali.jafri@arm.com if (!(sf_item.requested | sf_item.holder)) { 5611129Sali.jafri@arm.com cachedLocations.erase(sf_it); 5711129Sali.jafri@arm.com DPRINTF(SnoopFilter, "%s: Removed SF entry.\n", 5811129Sali.jafri@arm.com __func__); 5911129Sali.jafri@arm.com } 6011129Sali.jafri@arm.com} 6111129Sali.jafri@arm.com 6210399Sstephan.diestelhorst@arm.comstd::pair<SnoopFilter::SnoopList, Cycles> 6310399Sstephan.diestelhorst@arm.comSnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port) 6410399Sstephan.diestelhorst@arm.com{ 6510399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n", 6610399Sstephan.diestelhorst@arm.com __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString()); 6710399Sstephan.diestelhorst@arm.com 6811128Sali.jafri@arm.com // Ultimately we should check if the packet came from an 6911128Sali.jafri@arm.com // allocating source, not just if the port is snooping 7011128Sali.jafri@arm.com bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping(); 7111128Sali.jafri@arm.com Addr line_addr = cpkt->getBlockAddr(linesize); 7210399Sstephan.diestelhorst@arm.com SnoopMask req_port = portToMask(slave_port); 7311131Sandreas.hansson@arm.com reqLookupResult = cachedLocations.find(line_addr); 7411131Sandreas.hansson@arm.com bool is_hit = (reqLookupResult != cachedLocations.end()); 7511128Sali.jafri@arm.com 7611128Sali.jafri@arm.com // If the snoop filter has no entry, and we should not allocate, 7711128Sali.jafri@arm.com // do not create a new snoop filter entry, simply return a NULL 7811128Sali.jafri@arm.com // portlist. 7911128Sali.jafri@arm.com if (!is_hit && !allocate) 8011128Sali.jafri@arm.com return snoopDown(lookupLatency); 8111128Sali.jafri@arm.com 8211131Sandreas.hansson@arm.com // If no hit in snoop filter create a new element and update iterator 8311131Sandreas.hansson@arm.com if (!is_hit) 8411131Sandreas.hansson@arm.com reqLookupResult = cachedLocations.emplace(line_addr, SnoopItem()).first; 8511131Sandreas.hansson@arm.com SnoopItem& sf_item = reqLookupResult->second; 8610403Sstephan.diestelhorst@arm.com SnoopMask interested = sf_item.holder | sf_item.requested; 8710403Sstephan.diestelhorst@arm.com 8811129Sali.jafri@arm.com // Store unmodified value of snoop filter item in temp storage in 8911129Sali.jafri@arm.com // case we need to revert because of a send retry in 9011129Sali.jafri@arm.com // updateRequest. 9111129Sali.jafri@arm.com retryItem = sf_item; 9211129Sali.jafri@arm.com 9310403Sstephan.diestelhorst@arm.com totRequests++; 9410403Sstephan.diestelhorst@arm.com if (is_hit) { 9510403Sstephan.diestelhorst@arm.com // Single bit set -> value is a power of two 9610403Sstephan.diestelhorst@arm.com if (isPow2(interested)) 9710403Sstephan.diestelhorst@arm.com hitSingleRequests++; 9810403Sstephan.diestelhorst@arm.com else 9910403Sstephan.diestelhorst@arm.com hitMultiRequests++; 10010403Sstephan.diestelhorst@arm.com } 10110399Sstephan.diestelhorst@arm.com 10210399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: SF value %x.%x\n", 10310399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 10410399Sstephan.diestelhorst@arm.com 10511129Sali.jafri@arm.com // If we are not allocating, we are done 10611129Sali.jafri@arm.com if (!allocate) 10711129Sali.jafri@arm.com return snoopSelected(maskToPortList(interested & ~req_port), 10811129Sali.jafri@arm.com lookupLatency); 10911129Sali.jafri@arm.com 11011129Sali.jafri@arm.com if (cpkt->needsResponse()) { 11110399Sstephan.diestelhorst@arm.com if (!cpkt->memInhibitAsserted()) { 11210399Sstephan.diestelhorst@arm.com // Max one request per address per port 11311129Sali.jafri@arm.com panic_if(sf_item.requested & req_port, "double request :( " \ 11410399Sstephan.diestelhorst@arm.com "SF value %x.%x\n", sf_item.requested, sf_item.holder); 11510399Sstephan.diestelhorst@arm.com 11610399Sstephan.diestelhorst@arm.com // Mark in-flight requests to distinguish later on 11710399Sstephan.diestelhorst@arm.com sf_item.requested |= req_port; 11811129Sali.jafri@arm.com DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n", 11911129Sali.jafri@arm.com __func__, sf_item.requested, sf_item.holder); 12010399Sstephan.diestelhorst@arm.com } else { 12110399Sstephan.diestelhorst@arm.com // NOTE: The memInhibit might have been asserted by a cache closer 12210399Sstephan.diestelhorst@arm.com // to the CPU, already -> the response will not be seen by this 12310399Sstephan.diestelhorst@arm.com // filter -> we do not need to keep the in-flight request, but make 12410399Sstephan.diestelhorst@arm.com // sure that we know that that cluster has a copy 12510399Sstephan.diestelhorst@arm.com panic_if(!(sf_item.holder & req_port), "Need to hold the value!"); 12611129Sali.jafri@arm.com DPRINTF(SnoopFilter, 12711129Sali.jafri@arm.com "%s: not marking request. SF value %x.%x\n", 12810399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 12910399Sstephan.diestelhorst@arm.com } 13011129Sali.jafri@arm.com } else { // if (!cpkt->needsResponse()) 13111129Sali.jafri@arm.com assert(cpkt->evictingBlock()); 13211129Sali.jafri@arm.com // make sure that the sender actually had the line 13311129Sali.jafri@arm.com panic_if(!(sf_item.holder & req_port), "requester %x is not a " \ 13411129Sali.jafri@arm.com "holder :( SF value %x.%x\n", req_port, 13511129Sali.jafri@arm.com sf_item.requested, sf_item.holder); 13611129Sali.jafri@arm.com // CleanEvicts and Writebacks -> the sender and all caches above 13711129Sali.jafri@arm.com // it may not have the line anymore. 13811129Sali.jafri@arm.com if (!cpkt->isBlockCached()) { 13911129Sali.jafri@arm.com sf_item.holder &= ~req_port; 14011129Sali.jafri@arm.com DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n", 14111129Sali.jafri@arm.com __func__, sf_item.requested, sf_item.holder); 14211129Sali.jafri@arm.com } 14310399Sstephan.diestelhorst@arm.com } 14411129Sali.jafri@arm.com 14510403Sstephan.diestelhorst@arm.com return snoopSelected(maskToPortList(interested & ~req_port), lookupLatency); 14610399Sstephan.diestelhorst@arm.com} 14710399Sstephan.diestelhorst@arm.com 14810399Sstephan.diestelhorst@arm.comvoid 14911131Sandreas.hansson@arm.comSnoopFilter::finishRequest(bool will_retry, const Packet* cpkt) 15010399Sstephan.diestelhorst@arm.com{ 15111131Sandreas.hansson@arm.com if (reqLookupResult != cachedLocations.end()) { 15211131Sandreas.hansson@arm.com // since we rely on the caller, do a basic check to ensure 15311131Sandreas.hansson@arm.com // that finishRequest is being called following lookupRequest 15411131Sandreas.hansson@arm.com assert(reqLookupResult->first == cpkt->getBlockAddr(linesize)); 15511131Sandreas.hansson@arm.com if (will_retry) { 15611131Sandreas.hansson@arm.com // Undo any changes made in lookupRequest to the snoop filter 15711131Sandreas.hansson@arm.com // entry if the request will come again. retryItem holds 15811131Sandreas.hansson@arm.com // the previous value of the snoopfilter entry. 15911131Sandreas.hansson@arm.com reqLookupResult->second = retryItem; 16010399Sstephan.diestelhorst@arm.com 16111131Sandreas.hansson@arm.com DPRINTF(SnoopFilter, "%s: restored SF value %x.%x\n", 16211131Sandreas.hansson@arm.com __func__, retryItem.requested, retryItem.holder); 16311131Sandreas.hansson@arm.com } 16410821Sandreas.hansson@arm.com 16511131Sandreas.hansson@arm.com eraseIfNullEntry(reqLookupResult); 16610399Sstephan.diestelhorst@arm.com } 16710399Sstephan.diestelhorst@arm.com} 16810399Sstephan.diestelhorst@arm.com 16910399Sstephan.diestelhorst@arm.comstd::pair<SnoopFilter::SnoopList, Cycles> 17010399Sstephan.diestelhorst@arm.comSnoopFilter::lookupSnoop(const Packet* cpkt) 17110399Sstephan.diestelhorst@arm.com{ 17210399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: packet addr 0x%x cmd %s\n", 17310399Sstephan.diestelhorst@arm.com __func__, cpkt->getAddr(), cpkt->cmdString()); 17410399Sstephan.diestelhorst@arm.com 17510399Sstephan.diestelhorst@arm.com assert(cpkt->isRequest()); 17610399Sstephan.diestelhorst@arm.com 17711128Sali.jafri@arm.com Addr line_addr = cpkt->getBlockAddr(linesize); 17810403Sstephan.diestelhorst@arm.com auto sf_it = cachedLocations.find(line_addr); 17910403Sstephan.diestelhorst@arm.com bool is_hit = (sf_it != cachedLocations.end()); 18011129Sali.jafri@arm.com 18111132Sali.jafri@arm.com panic_if(!is_hit && (cachedLocations.size() >= maxEntryCount), 18211132Sali.jafri@arm.com "snoop filter exceeded capacity of %d cache blocks\n", 18311132Sali.jafri@arm.com maxEntryCount); 18411132Sali.jafri@arm.com 18511134Sandreas.hansson@arm.com // If the snoop filter has no entry, simply return a NULL 18611134Sandreas.hansson@arm.com // portlist, there is no point creating an entry only to remove it 18711134Sandreas.hansson@arm.com // later 18811134Sandreas.hansson@arm.com if (!is_hit) 18911129Sali.jafri@arm.com return snoopDown(lookupLatency); 19011129Sali.jafri@arm.com 19111129Sali.jafri@arm.com SnoopItem& sf_item = sf_it->second; 19210399Sstephan.diestelhorst@arm.com 19310399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n", 19410399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 19510399Sstephan.diestelhorst@arm.com 19610399Sstephan.diestelhorst@arm.com SnoopMask interested = (sf_item.holder | sf_item.requested); 19710403Sstephan.diestelhorst@arm.com 19810403Sstephan.diestelhorst@arm.com totSnoops++; 19911134Sandreas.hansson@arm.com // Single bit set -> value is a power of two 20011134Sandreas.hansson@arm.com if (isPow2(interested)) 20111134Sandreas.hansson@arm.com hitSingleSnoops++; 20211134Sandreas.hansson@arm.com else 20311134Sandreas.hansson@arm.com hitMultiSnoops++; 20411134Sandreas.hansson@arm.com 20510883Sali.jafri@arm.com // ReadEx and Writes require both invalidation and exlusivity, while reads 20610883Sali.jafri@arm.com // require neither. Writebacks on the other hand require exclusivity but 20710883Sali.jafri@arm.com // not the invalidation. Previously Writebacks did not generate upward 20810883Sali.jafri@arm.com // snoops so this was never an aissue. Now that Writebacks generate snoops 20910883Sali.jafri@arm.com // we need to special case for Writebacks. 21011129Sali.jafri@arm.com assert(cpkt->cmd == MemCmd::Writeback || cpkt->req->isUncacheable() || 21110883Sali.jafri@arm.com (cpkt->isInvalidate() == cpkt->needsExclusive())); 21210399Sstephan.diestelhorst@arm.com if (cpkt->isInvalidate() && !sf_item.requested) { 21310399Sstephan.diestelhorst@arm.com // Early clear of the holder, if no other request is currently going on 21410399Sstephan.diestelhorst@arm.com // @todo: This should possibly be updated even though we do not filter 21510399Sstephan.diestelhorst@arm.com // upward snoops 21610399Sstephan.diestelhorst@arm.com sf_item.holder = 0; 21710399Sstephan.diestelhorst@arm.com } 21810399Sstephan.diestelhorst@arm.com 21911129Sali.jafri@arm.com eraseIfNullEntry(sf_it); 22010399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: new SF value %x.%x interest: %x \n", 22110399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder, interested); 22210399Sstephan.diestelhorst@arm.com 22310399Sstephan.diestelhorst@arm.com return snoopSelected(maskToPortList(interested), lookupLatency); 22410399Sstephan.diestelhorst@arm.com} 22510399Sstephan.diestelhorst@arm.com 22610399Sstephan.diestelhorst@arm.comvoid 22710399Sstephan.diestelhorst@arm.comSnoopFilter::updateSnoopResponse(const Packet* cpkt, 22810399Sstephan.diestelhorst@arm.com const SlavePort& rsp_port, 22910399Sstephan.diestelhorst@arm.com const SlavePort& req_port) 23010399Sstephan.diestelhorst@arm.com{ 23110399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n", 23210399Sstephan.diestelhorst@arm.com __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(), 23310399Sstephan.diestelhorst@arm.com cpkt->cmdString()); 23410399Sstephan.diestelhorst@arm.com 23510821Sandreas.hansson@arm.com assert(cpkt->isResponse()); 23610821Sandreas.hansson@arm.com assert(cpkt->memInhibitAsserted()); 23710821Sandreas.hansson@arm.com 23811128Sali.jafri@arm.com // Ultimately we should check if the packet came from an 23911128Sali.jafri@arm.com // allocating source, not just if the port is snooping 24011128Sali.jafri@arm.com bool allocate = !cpkt->req->isUncacheable() && req_port.isSnooping(); 24111128Sali.jafri@arm.com if (!allocate) 24210821Sandreas.hansson@arm.com return; 24310821Sandreas.hansson@arm.com 24411128Sali.jafri@arm.com Addr line_addr = cpkt->getBlockAddr(linesize); 24510399Sstephan.diestelhorst@arm.com SnoopMask rsp_mask = portToMask(rsp_port); 24610399Sstephan.diestelhorst@arm.com SnoopMask req_mask = portToMask(req_port); 24710399Sstephan.diestelhorst@arm.com SnoopItem& sf_item = cachedLocations[line_addr]; 24810399Sstephan.diestelhorst@arm.com 24910399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n", 25010399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 25110399Sstephan.diestelhorst@arm.com 25210399Sstephan.diestelhorst@arm.com // The source should have the line 25310399Sstephan.diestelhorst@arm.com panic_if(!(sf_item.holder & rsp_mask), "SF value %x.%x does not have "\ 25410399Sstephan.diestelhorst@arm.com "the line\n", sf_item.requested, sf_item.holder); 25510399Sstephan.diestelhorst@arm.com 25610399Sstephan.diestelhorst@arm.com // The destination should have had a request in 25710399Sstephan.diestelhorst@arm.com panic_if(!(sf_item.requested & req_mask), "SF value %x.%x missing "\ 25810399Sstephan.diestelhorst@arm.com "the original request\n", sf_item.requested, sf_item.holder); 25910399Sstephan.diestelhorst@arm.com 26010399Sstephan.diestelhorst@arm.com // Update the residency of the cache line. 26110399Sstephan.diestelhorst@arm.com if (cpkt->needsExclusive() || !cpkt->sharedAsserted()) { 26210399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: dropping %x because needs: %i shared: %i "\ 26310399Sstephan.diestelhorst@arm.com "SF val: %x.%x\n", __func__, rsp_mask, 26410399Sstephan.diestelhorst@arm.com cpkt->needsExclusive(), cpkt->sharedAsserted(), 26510399Sstephan.diestelhorst@arm.com sf_item.requested, sf_item.holder); 26610399Sstephan.diestelhorst@arm.com 26710399Sstephan.diestelhorst@arm.com sf_item.holder &= ~rsp_mask; 26810399Sstephan.diestelhorst@arm.com // The snoop filter does not see any ACKs from non-responding sharers 26910399Sstephan.diestelhorst@arm.com // that have been invalidated :( So below assert would be nice, but.. 27010399Sstephan.diestelhorst@arm.com //assert(sf_item.holder == 0); 27110399Sstephan.diestelhorst@arm.com sf_item.holder = 0; 27210399Sstephan.diestelhorst@arm.com } 27310399Sstephan.diestelhorst@arm.com assert(cpkt->cmd != MemCmd::Writeback); 27410399Sstephan.diestelhorst@arm.com sf_item.holder |= req_mask; 27510399Sstephan.diestelhorst@arm.com sf_item.requested &= ~req_mask; 27611129Sali.jafri@arm.com assert(sf_item.requested | sf_item.holder); 27710399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n", 27810399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 27910399Sstephan.diestelhorst@arm.com} 28010399Sstephan.diestelhorst@arm.com 28110399Sstephan.diestelhorst@arm.comvoid 28210399Sstephan.diestelhorst@arm.comSnoopFilter::updateSnoopForward(const Packet* cpkt, 28310399Sstephan.diestelhorst@arm.com const SlavePort& rsp_port, const MasterPort& req_port) 28410399Sstephan.diestelhorst@arm.com{ 28510399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n", 28610399Sstephan.diestelhorst@arm.com __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(), 28710399Sstephan.diestelhorst@arm.com cpkt->cmdString()); 28810399Sstephan.diestelhorst@arm.com 28911134Sandreas.hansson@arm.com assert(cpkt->isResponse()); 29011134Sandreas.hansson@arm.com assert(cpkt->memInhibitAsserted()); 29111134Sandreas.hansson@arm.com 29211128Sali.jafri@arm.com Addr line_addr = cpkt->getBlockAddr(linesize); 29311129Sali.jafri@arm.com auto sf_it = cachedLocations.find(line_addr); 29411134Sandreas.hansson@arm.com bool is_hit = sf_it != cachedLocations.end(); 29511134Sandreas.hansson@arm.com 29611134Sandreas.hansson@arm.com // Nothing to do if it is not a hit 29711134Sandreas.hansson@arm.com if (!is_hit) 29811134Sandreas.hansson@arm.com return; 29911134Sandreas.hansson@arm.com 30011129Sali.jafri@arm.com SnoopItem& sf_item = sf_it->second; 30110399Sstephan.diestelhorst@arm.com 30210399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n", 30310399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 30410399Sstephan.diestelhorst@arm.com 30511134Sandreas.hansson@arm.com // Remote (to this snoop filter) snoops update the filter 30611134Sandreas.hansson@arm.com // already when they arrive from below, because we may not see 30711134Sandreas.hansson@arm.com // any response. 30810399Sstephan.diestelhorst@arm.com if (cpkt->needsExclusive()) { 30911134Sandreas.hansson@arm.com // If the request to this snoop response hit an in-flight 31011134Sandreas.hansson@arm.com // transaction, 31110399Sstephan.diestelhorst@arm.com // the holder was not reset -> no assertion & do that here, now! 31210399Sstephan.diestelhorst@arm.com //assert(sf_item.holder == 0); 31310399Sstephan.diestelhorst@arm.com sf_item.holder = 0; 31410399Sstephan.diestelhorst@arm.com } 31510399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n", 31610399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 31711129Sali.jafri@arm.com eraseIfNullEntry(sf_it); 31811134Sandreas.hansson@arm.com 31910399Sstephan.diestelhorst@arm.com} 32010399Sstephan.diestelhorst@arm.com 32110399Sstephan.diestelhorst@arm.comvoid 32210399Sstephan.diestelhorst@arm.comSnoopFilter::updateResponse(const Packet* cpkt, const SlavePort& slave_port) 32310399Sstephan.diestelhorst@arm.com{ 32410399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n", 32510399Sstephan.diestelhorst@arm.com __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString()); 32610399Sstephan.diestelhorst@arm.com 32710821Sandreas.hansson@arm.com assert(cpkt->isResponse()); 32810821Sandreas.hansson@arm.com 32911128Sali.jafri@arm.com // Ultimately we should check if the packet came from an 33011128Sali.jafri@arm.com // allocating source, not just if the port is snooping 33111128Sali.jafri@arm.com bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping(); 33211128Sali.jafri@arm.com if (!allocate) 33310821Sandreas.hansson@arm.com return; 33410821Sandreas.hansson@arm.com 33511128Sali.jafri@arm.com Addr line_addr = cpkt->getBlockAddr(linesize); 33610399Sstephan.diestelhorst@arm.com SnoopMask slave_mask = portToMask(slave_port); 33710399Sstephan.diestelhorst@arm.com SnoopItem& sf_item = cachedLocations[line_addr]; 33810399Sstephan.diestelhorst@arm.com 33910399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n", 34010399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 34110399Sstephan.diestelhorst@arm.com 34210399Sstephan.diestelhorst@arm.com // Make sure we have seen the actual request, too 34310399Sstephan.diestelhorst@arm.com panic_if(!(sf_item.requested & slave_mask), "SF value %x.%x missing "\ 34410399Sstephan.diestelhorst@arm.com "request bit\n", sf_item.requested, sf_item.holder); 34510399Sstephan.diestelhorst@arm.com 34611129Sali.jafri@arm.com // Update the residency of the cache line. Here we assume that the 34711129Sali.jafri@arm.com // line has been zapped in all caches that are not the responder. 34811129Sali.jafri@arm.com if (cpkt->needsExclusive() || !cpkt->sharedAsserted()) 34910399Sstephan.diestelhorst@arm.com sf_item.holder = 0; 35010399Sstephan.diestelhorst@arm.com sf_item.holder |= slave_mask; 35110399Sstephan.diestelhorst@arm.com sf_item.requested &= ~slave_mask; 35211129Sali.jafri@arm.com assert(sf_item.holder | sf_item.requested); 35310399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n", 35410399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 35510399Sstephan.diestelhorst@arm.com} 35610399Sstephan.diestelhorst@arm.com 35710403Sstephan.diestelhorst@arm.comvoid 35810403Sstephan.diestelhorst@arm.comSnoopFilter::regStats() 35910403Sstephan.diestelhorst@arm.com{ 36010403Sstephan.diestelhorst@arm.com totRequests 36110403Sstephan.diestelhorst@arm.com .name(name() + ".tot_requests") 36210403Sstephan.diestelhorst@arm.com .desc("Total number of requests made to the snoop filter."); 36310403Sstephan.diestelhorst@arm.com 36410403Sstephan.diestelhorst@arm.com hitSingleRequests 36510403Sstephan.diestelhorst@arm.com .name(name() + ".hit_single_requests") 36610403Sstephan.diestelhorst@arm.com .desc("Number of requests hitting in the snoop filter with a single "\ 36710403Sstephan.diestelhorst@arm.com "holder of the requested data."); 36810403Sstephan.diestelhorst@arm.com 36910403Sstephan.diestelhorst@arm.com hitMultiRequests 37010403Sstephan.diestelhorst@arm.com .name(name() + ".hit_multi_requests") 37110403Sstephan.diestelhorst@arm.com .desc("Number of requests hitting in the snoop filter with multiple "\ 37210403Sstephan.diestelhorst@arm.com "(>1) holders of the requested data."); 37310403Sstephan.diestelhorst@arm.com 37410403Sstephan.diestelhorst@arm.com totSnoops 37510403Sstephan.diestelhorst@arm.com .name(name() + ".tot_snoops") 37610403Sstephan.diestelhorst@arm.com .desc("Total number of snoops made to the snoop filter."); 37710403Sstephan.diestelhorst@arm.com 37810403Sstephan.diestelhorst@arm.com hitSingleSnoops 37910403Sstephan.diestelhorst@arm.com .name(name() + ".hit_single_snoops") 38010403Sstephan.diestelhorst@arm.com .desc("Number of snoops hitting in the snoop filter with a single "\ 38110403Sstephan.diestelhorst@arm.com "holder of the requested data."); 38210403Sstephan.diestelhorst@arm.com 38310403Sstephan.diestelhorst@arm.com hitMultiSnoops 38410403Sstephan.diestelhorst@arm.com .name(name() + ".hit_multi_snoops") 38510403Sstephan.diestelhorst@arm.com .desc("Number of snoops hitting in the snoop filter with multiple "\ 38610403Sstephan.diestelhorst@arm.com "(>1) holders of the requested data."); 38710403Sstephan.diestelhorst@arm.com} 38810403Sstephan.diestelhorst@arm.com 38910399Sstephan.diestelhorst@arm.comSnoopFilter * 39010399Sstephan.diestelhorst@arm.comSnoopFilterParams::create() 39110399Sstephan.diestelhorst@arm.com{ 39210399Sstephan.diestelhorst@arm.com return new SnoopFilter(this); 39310399Sstephan.diestelhorst@arm.com} 394