snoop_filter.cc revision 14122
110399Sstephan.diestelhorst@arm.com/* 214005Stiago.muck@arm.com * Copyright (c) 2013-2017,2019 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 * 3711135Sandreas.hansson@arm.com * Authors: Stephan Diestelhorst 3810399Sstephan.diestelhorst@arm.com */ 3910399Sstephan.diestelhorst@arm.com 4010399Sstephan.diestelhorst@arm.com/** 4110399Sstephan.diestelhorst@arm.com * @file 4211135Sandreas.hansson@arm.com * Implementation of a snoop filter. 4310399Sstephan.diestelhorst@arm.com */ 4410399Sstephan.diestelhorst@arm.com 4511793Sbrandon.potter@amd.com#include "mem/snoop_filter.hh" 4611793Sbrandon.potter@amd.com 4712334Sgabeblack@google.com#include "base/logging.hh" 4810399Sstephan.diestelhorst@arm.com#include "base/trace.hh" 4910399Sstephan.diestelhorst@arm.com#include "debug/SnoopFilter.hh" 5010399Sstephan.diestelhorst@arm.com#include "sim/system.hh" 5110399Sstephan.diestelhorst@arm.com 5214005Stiago.muck@arm.comconst int SnoopFilter::SNOOP_MASK_SIZE; 5314005Stiago.muck@arm.com 5411129Sali.jafri@arm.comvoid 5511129Sali.jafri@arm.comSnoopFilter::eraseIfNullEntry(SnoopFilterCache::iterator& sf_it) 5611129Sali.jafri@arm.com{ 5711129Sali.jafri@arm.com SnoopItem& sf_item = sf_it->second; 5814005Stiago.muck@arm.com if ((sf_item.requested | sf_item.holder).none()) { 5911129Sali.jafri@arm.com cachedLocations.erase(sf_it); 6011129Sali.jafri@arm.com DPRINTF(SnoopFilter, "%s: Removed SF entry.\n", 6111129Sali.jafri@arm.com __func__); 6211129Sali.jafri@arm.com } 6311129Sali.jafri@arm.com} 6411129Sali.jafri@arm.com 6510399Sstephan.diestelhorst@arm.comstd::pair<SnoopFilter::SnoopList, Cycles> 6610399Sstephan.diestelhorst@arm.comSnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port) 6710399Sstephan.diestelhorst@arm.com{ 6811744Snikos.nikoleris@arm.com DPRINTF(SnoopFilter, "%s: src %s packet %s\n", __func__, 6911744Snikos.nikoleris@arm.com slave_port.name(), cpkt->print()); 7010399Sstephan.diestelhorst@arm.com 7111603Sandreas.hansson@arm.com // check if the packet came from a cache 7211603Sandreas.hansson@arm.com bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping() && 7311603Sandreas.hansson@arm.com cpkt->fromCache(); 7411128Sali.jafri@arm.com Addr line_addr = cpkt->getBlockAddr(linesize); 7511605Snikos.nikoleris@arm.com if (cpkt->isSecure()) { 7611605Snikos.nikoleris@arm.com line_addr |= LineSecure; 7711605Snikos.nikoleris@arm.com } 7810399Sstephan.diestelhorst@arm.com SnoopMask req_port = portToMask(slave_port); 7914122Sodanrc@yahoo.com.br reqLookupResult.it = cachedLocations.find(line_addr); 8014122Sodanrc@yahoo.com.br bool is_hit = (reqLookupResult.it != cachedLocations.end()); 8111128Sali.jafri@arm.com 8211128Sali.jafri@arm.com // If the snoop filter has no entry, and we should not allocate, 8311128Sali.jafri@arm.com // do not create a new snoop filter entry, simply return a NULL 8411128Sali.jafri@arm.com // portlist. 8511128Sali.jafri@arm.com if (!is_hit && !allocate) 8611128Sali.jafri@arm.com return snoopDown(lookupLatency); 8711128Sali.jafri@arm.com 8811131Sandreas.hansson@arm.com // If no hit in snoop filter create a new element and update iterator 8914122Sodanrc@yahoo.com.br if (!is_hit) { 9014122Sodanrc@yahoo.com.br reqLookupResult.it = 9114122Sodanrc@yahoo.com.br cachedLocations.emplace(line_addr, SnoopItem()).first; 9214122Sodanrc@yahoo.com.br } 9314122Sodanrc@yahoo.com.br SnoopItem& sf_item = reqLookupResult.it->second; 9410403Sstephan.diestelhorst@arm.com SnoopMask interested = sf_item.holder | sf_item.requested; 9510403Sstephan.diestelhorst@arm.com 9611129Sali.jafri@arm.com // Store unmodified value of snoop filter item in temp storage in 9711129Sali.jafri@arm.com // case we need to revert because of a send retry in 9811129Sali.jafri@arm.com // updateRequest. 9914122Sodanrc@yahoo.com.br reqLookupResult.retryItem = sf_item; 10011129Sali.jafri@arm.com 10110403Sstephan.diestelhorst@arm.com totRequests++; 10210403Sstephan.diestelhorst@arm.com if (is_hit) { 10314005Stiago.muck@arm.com if (interested.count() == 1) 10410403Sstephan.diestelhorst@arm.com hitSingleRequests++; 10510403Sstephan.diestelhorst@arm.com else 10610403Sstephan.diestelhorst@arm.com hitMultiRequests++; 10710403Sstephan.diestelhorst@arm.com } 10810399Sstephan.diestelhorst@arm.com 10910399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: SF value %x.%x\n", 11010399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 11110399Sstephan.diestelhorst@arm.com 11211129Sali.jafri@arm.com // If we are not allocating, we are done 11311129Sali.jafri@arm.com if (!allocate) 11411129Sali.jafri@arm.com return snoopSelected(maskToPortList(interested & ~req_port), 11511129Sali.jafri@arm.com lookupLatency); 11611129Sali.jafri@arm.com 11711129Sali.jafri@arm.com if (cpkt->needsResponse()) { 11811284Sandreas.hansson@arm.com if (!cpkt->cacheResponding()) { 11910399Sstephan.diestelhorst@arm.com // Max one request per address per port 12014005Stiago.muck@arm.com panic_if((sf_item.requested & req_port).any(), 12114005Stiago.muck@arm.com "double request :( SF value %x.%x\n", 12214005Stiago.muck@arm.com sf_item.requested, sf_item.holder); 12310399Sstephan.diestelhorst@arm.com 12410399Sstephan.diestelhorst@arm.com // Mark in-flight requests to distinguish later on 12510399Sstephan.diestelhorst@arm.com sf_item.requested |= req_port; 12611129Sali.jafri@arm.com DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n", 12711129Sali.jafri@arm.com __func__, sf_item.requested, sf_item.holder); 12810399Sstephan.diestelhorst@arm.com } else { 12910399Sstephan.diestelhorst@arm.com // NOTE: The memInhibit might have been asserted by a cache closer 13010399Sstephan.diestelhorst@arm.com // to the CPU, already -> the response will not be seen by this 13110399Sstephan.diestelhorst@arm.com // filter -> we do not need to keep the in-flight request, but make 13210399Sstephan.diestelhorst@arm.com // sure that we know that that cluster has a copy 13314005Stiago.muck@arm.com panic_if((sf_item.holder & req_port).none(), 13414005Stiago.muck@arm.com "Need to hold the value!"); 13511129Sali.jafri@arm.com DPRINTF(SnoopFilter, 13611129Sali.jafri@arm.com "%s: not marking request. SF value %x.%x\n", 13710399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 13810399Sstephan.diestelhorst@arm.com } 13911129Sali.jafri@arm.com } else { // if (!cpkt->needsResponse()) 14011199Sandreas.hansson@arm.com assert(cpkt->isEviction()); 14111129Sali.jafri@arm.com // make sure that the sender actually had the line 14214005Stiago.muck@arm.com panic_if((sf_item.holder & req_port).none(), "requester %x is not a " \ 14311129Sali.jafri@arm.com "holder :( SF value %x.%x\n", req_port, 14411129Sali.jafri@arm.com sf_item.requested, sf_item.holder); 14511129Sali.jafri@arm.com // CleanEvicts and Writebacks -> the sender and all caches above 14611129Sali.jafri@arm.com // it may not have the line anymore. 14711129Sali.jafri@arm.com if (!cpkt->isBlockCached()) { 14811129Sali.jafri@arm.com sf_item.holder &= ~req_port; 14911129Sali.jafri@arm.com DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n", 15011129Sali.jafri@arm.com __func__, sf_item.requested, sf_item.holder); 15111129Sali.jafri@arm.com } 15210399Sstephan.diestelhorst@arm.com } 15311129Sali.jafri@arm.com 15410403Sstephan.diestelhorst@arm.com return snoopSelected(maskToPortList(interested & ~req_port), lookupLatency); 15510399Sstephan.diestelhorst@arm.com} 15610399Sstephan.diestelhorst@arm.com 15710399Sstephan.diestelhorst@arm.comvoid 15811605Snikos.nikoleris@arm.comSnoopFilter::finishRequest(bool will_retry, Addr addr, bool is_secure) 15910399Sstephan.diestelhorst@arm.com{ 16014122Sodanrc@yahoo.com.br if (reqLookupResult.it != cachedLocations.end()) { 16111131Sandreas.hansson@arm.com // since we rely on the caller, do a basic check to ensure 16211131Sandreas.hansson@arm.com // that finishRequest is being called following lookupRequest 16311605Snikos.nikoleris@arm.com Addr line_addr = (addr & ~(Addr(linesize - 1))); 16411605Snikos.nikoleris@arm.com if (is_secure) { 16511605Snikos.nikoleris@arm.com line_addr |= LineSecure; 16611605Snikos.nikoleris@arm.com } 16714122Sodanrc@yahoo.com.br assert(reqLookupResult.it->first == line_addr); 16811131Sandreas.hansson@arm.com if (will_retry) { 16914122Sodanrc@yahoo.com.br SnoopItem retry_item = reqLookupResult.retryItem; 17011131Sandreas.hansson@arm.com // Undo any changes made in lookupRequest to the snoop filter 17111131Sandreas.hansson@arm.com // entry if the request will come again. retryItem holds 17211131Sandreas.hansson@arm.com // the previous value of the snoopfilter entry. 17314122Sodanrc@yahoo.com.br reqLookupResult.it->second = retry_item; 17410399Sstephan.diestelhorst@arm.com 17511131Sandreas.hansson@arm.com DPRINTF(SnoopFilter, "%s: restored SF value %x.%x\n", 17614122Sodanrc@yahoo.com.br __func__, retry_item.requested, retry_item.holder); 17711131Sandreas.hansson@arm.com } 17810821Sandreas.hansson@arm.com 17914122Sodanrc@yahoo.com.br eraseIfNullEntry(reqLookupResult.it); 18010399Sstephan.diestelhorst@arm.com } 18110399Sstephan.diestelhorst@arm.com} 18210399Sstephan.diestelhorst@arm.com 18310399Sstephan.diestelhorst@arm.comstd::pair<SnoopFilter::SnoopList, Cycles> 18410399Sstephan.diestelhorst@arm.comSnoopFilter::lookupSnoop(const Packet* cpkt) 18510399Sstephan.diestelhorst@arm.com{ 18611744Snikos.nikoleris@arm.com DPRINTF(SnoopFilter, "%s: packet %s\n", __func__, cpkt->print()); 18710399Sstephan.diestelhorst@arm.com 18810399Sstephan.diestelhorst@arm.com assert(cpkt->isRequest()); 18910399Sstephan.diestelhorst@arm.com 19011128Sali.jafri@arm.com Addr line_addr = cpkt->getBlockAddr(linesize); 19111605Snikos.nikoleris@arm.com if (cpkt->isSecure()) { 19211605Snikos.nikoleris@arm.com line_addr |= LineSecure; 19311605Snikos.nikoleris@arm.com } 19410403Sstephan.diestelhorst@arm.com auto sf_it = cachedLocations.find(line_addr); 19510403Sstephan.diestelhorst@arm.com bool is_hit = (sf_it != cachedLocations.end()); 19611129Sali.jafri@arm.com 19711132Sali.jafri@arm.com panic_if(!is_hit && (cachedLocations.size() >= maxEntryCount), 19811132Sali.jafri@arm.com "snoop filter exceeded capacity of %d cache blocks\n", 19911132Sali.jafri@arm.com maxEntryCount); 20011132Sali.jafri@arm.com 20111134Sandreas.hansson@arm.com // If the snoop filter has no entry, simply return a NULL 20211134Sandreas.hansson@arm.com // portlist, there is no point creating an entry only to remove it 20311134Sandreas.hansson@arm.com // later 20411134Sandreas.hansson@arm.com if (!is_hit) 20511129Sali.jafri@arm.com return snoopDown(lookupLatency); 20611129Sali.jafri@arm.com 20711129Sali.jafri@arm.com SnoopItem& sf_item = sf_it->second; 20810399Sstephan.diestelhorst@arm.com 20910399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n", 21010399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 21110399Sstephan.diestelhorst@arm.com 21210399Sstephan.diestelhorst@arm.com SnoopMask interested = (sf_item.holder | sf_item.requested); 21310403Sstephan.diestelhorst@arm.com 21410403Sstephan.diestelhorst@arm.com totSnoops++; 21514005Stiago.muck@arm.com 21614005Stiago.muck@arm.com if (interested.count() == 1) 21711134Sandreas.hansson@arm.com hitSingleSnoops++; 21811134Sandreas.hansson@arm.com else 21911134Sandreas.hansson@arm.com hitMultiSnoops++; 22011134Sandreas.hansson@arm.com 22110883Sali.jafri@arm.com // ReadEx and Writes require both invalidation and exlusivity, while reads 22210883Sali.jafri@arm.com // require neither. Writebacks on the other hand require exclusivity but 22310883Sali.jafri@arm.com // not the invalidation. Previously Writebacks did not generate upward 22412352Snikos.nikoleris@arm.com // snoops so this was never an issue. Now that Writebacks generate snoops 22512352Snikos.nikoleris@arm.com // we need a special case for Writebacks. Additionally cache maintenance 22612352Snikos.nikoleris@arm.com // operations can generate snoops as they clean and/or invalidate all 22712352Snikos.nikoleris@arm.com // caches down to the specified point of reference. 22811199Sandreas.hansson@arm.com assert(cpkt->isWriteback() || cpkt->req->isUncacheable() || 22912352Snikos.nikoleris@arm.com (cpkt->isInvalidate() == cpkt->needsWritable()) || 23012352Snikos.nikoleris@arm.com cpkt->req->isCacheMaintenance()); 23114005Stiago.muck@arm.com if (cpkt->isInvalidate() && sf_item.requested.none()) { 23210399Sstephan.diestelhorst@arm.com // Early clear of the holder, if no other request is currently going on 23310399Sstephan.diestelhorst@arm.com // @todo: This should possibly be updated even though we do not filter 23410399Sstephan.diestelhorst@arm.com // upward snoops 23510399Sstephan.diestelhorst@arm.com sf_item.holder = 0; 23610399Sstephan.diestelhorst@arm.com } 23710399Sstephan.diestelhorst@arm.com 23811129Sali.jafri@arm.com eraseIfNullEntry(sf_it); 23910399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: new SF value %x.%x interest: %x \n", 24010399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder, interested); 24110399Sstephan.diestelhorst@arm.com 24210399Sstephan.diestelhorst@arm.com return snoopSelected(maskToPortList(interested), lookupLatency); 24310399Sstephan.diestelhorst@arm.com} 24410399Sstephan.diestelhorst@arm.com 24510399Sstephan.diestelhorst@arm.comvoid 24610399Sstephan.diestelhorst@arm.comSnoopFilter::updateSnoopResponse(const Packet* cpkt, 24710399Sstephan.diestelhorst@arm.com const SlavePort& rsp_port, 24810399Sstephan.diestelhorst@arm.com const SlavePort& req_port) 24910399Sstephan.diestelhorst@arm.com{ 25011744Snikos.nikoleris@arm.com DPRINTF(SnoopFilter, "%s: rsp %s req %s packet %s\n", 25111744Snikos.nikoleris@arm.com __func__, rsp_port.name(), req_port.name(), cpkt->print()); 25210399Sstephan.diestelhorst@arm.com 25310821Sandreas.hansson@arm.com assert(cpkt->isResponse()); 25411284Sandreas.hansson@arm.com assert(cpkt->cacheResponding()); 25510821Sandreas.hansson@arm.com 25611603Sandreas.hansson@arm.com // if this snoop response is due to an uncacheable request, or is 25711603Sandreas.hansson@arm.com // being turned into a normal response, there is nothing more to 25811603Sandreas.hansson@arm.com // do 25911603Sandreas.hansson@arm.com if (cpkt->req->isUncacheable() || !req_port.isSnooping()) { 26010821Sandreas.hansson@arm.com return; 26111603Sandreas.hansson@arm.com } 26210821Sandreas.hansson@arm.com 26311128Sali.jafri@arm.com Addr line_addr = cpkt->getBlockAddr(linesize); 26411605Snikos.nikoleris@arm.com if (cpkt->isSecure()) { 26511605Snikos.nikoleris@arm.com line_addr |= LineSecure; 26611605Snikos.nikoleris@arm.com } 26710399Sstephan.diestelhorst@arm.com SnoopMask rsp_mask = portToMask(rsp_port); 26810399Sstephan.diestelhorst@arm.com SnoopMask req_mask = portToMask(req_port); 26910399Sstephan.diestelhorst@arm.com SnoopItem& sf_item = cachedLocations[line_addr]; 27010399Sstephan.diestelhorst@arm.com 27110399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n", 27210399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 27310399Sstephan.diestelhorst@arm.com 27410399Sstephan.diestelhorst@arm.com // The source should have the line 27514005Stiago.muck@arm.com panic_if((sf_item.holder & rsp_mask).none(), 27614005Stiago.muck@arm.com "SF value %x.%x does not have the line\n", 27714005Stiago.muck@arm.com sf_item.requested, sf_item.holder); 27810399Sstephan.diestelhorst@arm.com 27910399Sstephan.diestelhorst@arm.com // The destination should have had a request in 28014005Stiago.muck@arm.com panic_if((sf_item.requested & req_mask).none(), "SF value %x.%x missing "\ 28110399Sstephan.diestelhorst@arm.com "the original request\n", sf_item.requested, sf_item.holder); 28210399Sstephan.diestelhorst@arm.com 28311287Sandreas.hansson@arm.com // If the snoop response has no sharers the line is passed in 28411287Sandreas.hansson@arm.com // Modified state, and we know that there are no other copies, or 28511287Sandreas.hansson@arm.com // they will all be invalidated imminently 28611287Sandreas.hansson@arm.com if (!cpkt->hasSharers()) { 28711287Sandreas.hansson@arm.com DPRINTF(SnoopFilter, 28811287Sandreas.hansson@arm.com "%s: dropping %x because non-shared snoop " 28911287Sandreas.hansson@arm.com "response SF val: %x.%x\n", __func__, rsp_mask, 29010399Sstephan.diestelhorst@arm.com sf_item.requested, sf_item.holder); 29110399Sstephan.diestelhorst@arm.com sf_item.holder = 0; 29210399Sstephan.diestelhorst@arm.com } 29311199Sandreas.hansson@arm.com assert(!cpkt->isWriteback()); 29411603Sandreas.hansson@arm.com // @todo Deal with invalidating responses 29510399Sstephan.diestelhorst@arm.com sf_item.holder |= req_mask; 29610399Sstephan.diestelhorst@arm.com sf_item.requested &= ~req_mask; 29714005Stiago.muck@arm.com assert((sf_item.requested | sf_item.holder).any()); 29810399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n", 29910399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 30010399Sstephan.diestelhorst@arm.com} 30110399Sstephan.diestelhorst@arm.com 30210399Sstephan.diestelhorst@arm.comvoid 30310399Sstephan.diestelhorst@arm.comSnoopFilter::updateSnoopForward(const Packet* cpkt, 30410399Sstephan.diestelhorst@arm.com const SlavePort& rsp_port, const MasterPort& req_port) 30510399Sstephan.diestelhorst@arm.com{ 30611744Snikos.nikoleris@arm.com DPRINTF(SnoopFilter, "%s: rsp %s req %s packet %s\n", 30711744Snikos.nikoleris@arm.com __func__, rsp_port.name(), req_port.name(), cpkt->print()); 30810399Sstephan.diestelhorst@arm.com 30911134Sandreas.hansson@arm.com assert(cpkt->isResponse()); 31011284Sandreas.hansson@arm.com assert(cpkt->cacheResponding()); 31111134Sandreas.hansson@arm.com 31211128Sali.jafri@arm.com Addr line_addr = cpkt->getBlockAddr(linesize); 31311605Snikos.nikoleris@arm.com if (cpkt->isSecure()) { 31411605Snikos.nikoleris@arm.com line_addr |= LineSecure; 31511605Snikos.nikoleris@arm.com } 31611129Sali.jafri@arm.com auto sf_it = cachedLocations.find(line_addr); 31711134Sandreas.hansson@arm.com bool is_hit = sf_it != cachedLocations.end(); 31811134Sandreas.hansson@arm.com 31911134Sandreas.hansson@arm.com // Nothing to do if it is not a hit 32011134Sandreas.hansson@arm.com if (!is_hit) 32111134Sandreas.hansson@arm.com return; 32211134Sandreas.hansson@arm.com 32311129Sali.jafri@arm.com SnoopItem& sf_item = sf_it->second; 32410399Sstephan.diestelhorst@arm.com 32510399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n", 32610399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 32710399Sstephan.diestelhorst@arm.com 32811287Sandreas.hansson@arm.com // If the snoop response has no sharers the line is passed in 32911287Sandreas.hansson@arm.com // Modified state, and we know that there are no other copies, or 33011287Sandreas.hansson@arm.com // they will all be invalidated imminently 33111287Sandreas.hansson@arm.com if (!cpkt->hasSharers()) { 33210399Sstephan.diestelhorst@arm.com sf_item.holder = 0; 33310399Sstephan.diestelhorst@arm.com } 33410399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n", 33510399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 33611129Sali.jafri@arm.com eraseIfNullEntry(sf_it); 33711134Sandreas.hansson@arm.com 33810399Sstephan.diestelhorst@arm.com} 33910399Sstephan.diestelhorst@arm.com 34010399Sstephan.diestelhorst@arm.comvoid 34110399Sstephan.diestelhorst@arm.comSnoopFilter::updateResponse(const Packet* cpkt, const SlavePort& slave_port) 34210399Sstephan.diestelhorst@arm.com{ 34311744Snikos.nikoleris@arm.com DPRINTF(SnoopFilter, "%s: src %s packet %s\n", 34411744Snikos.nikoleris@arm.com __func__, slave_port.name(), cpkt->print()); 34510399Sstephan.diestelhorst@arm.com 34610821Sandreas.hansson@arm.com assert(cpkt->isResponse()); 34710821Sandreas.hansson@arm.com 34811603Sandreas.hansson@arm.com // we only allocate if the packet actually came from a cache, but 34911603Sandreas.hansson@arm.com // start by checking if the port is snooping 35011603Sandreas.hansson@arm.com if (cpkt->req->isUncacheable() || !slave_port.isSnooping()) 35110821Sandreas.hansson@arm.com return; 35210821Sandreas.hansson@arm.com 35311603Sandreas.hansson@arm.com // next check if we actually allocated an entry 35411128Sali.jafri@arm.com Addr line_addr = cpkt->getBlockAddr(linesize); 35511605Snikos.nikoleris@arm.com if (cpkt->isSecure()) { 35611605Snikos.nikoleris@arm.com line_addr |= LineSecure; 35711605Snikos.nikoleris@arm.com } 35811603Sandreas.hansson@arm.com auto sf_it = cachedLocations.find(line_addr); 35911603Sandreas.hansson@arm.com if (sf_it == cachedLocations.end()) 36011603Sandreas.hansson@arm.com return; 36111603Sandreas.hansson@arm.com 36210399Sstephan.diestelhorst@arm.com SnoopMask slave_mask = portToMask(slave_port); 36311603Sandreas.hansson@arm.com SnoopItem& sf_item = sf_it->second; 36410399Sstephan.diestelhorst@arm.com 36510399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n", 36610399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 36710399Sstephan.diestelhorst@arm.com 36810399Sstephan.diestelhorst@arm.com // Make sure we have seen the actual request, too 36914005Stiago.muck@arm.com panic_if((sf_item.requested & slave_mask).none(), 37014005Stiago.muck@arm.com "SF value %x.%x missing request bit\n", 37114005Stiago.muck@arm.com sf_item.requested, sf_item.holder); 37210399Sstephan.diestelhorst@arm.com 37312353Snikos.nikoleris@arm.com sf_item.requested &= ~slave_mask; 37411748Snikos.nikoleris@arm.com // Update the residency of the cache line. 37512353Snikos.nikoleris@arm.com 37612353Snikos.nikoleris@arm.com if (cpkt->req->isCacheMaintenance()) { 37712353Snikos.nikoleris@arm.com // A cache clean response does not carry any data so it 37812353Snikos.nikoleris@arm.com // shouldn't change the holders, unless it is invalidating. 37912353Snikos.nikoleris@arm.com if (cpkt->isInvalidate()) { 38012353Snikos.nikoleris@arm.com sf_item.holder &= ~slave_mask; 38112353Snikos.nikoleris@arm.com } 38212353Snikos.nikoleris@arm.com eraseIfNullEntry(sf_it); 38312353Snikos.nikoleris@arm.com } else { 38412353Snikos.nikoleris@arm.com // Any other response implies that a cache above will have the 38512353Snikos.nikoleris@arm.com // block. 38612353Snikos.nikoleris@arm.com sf_item.holder |= slave_mask; 38714005Stiago.muck@arm.com assert((sf_item.holder | sf_item.requested).any()); 38812353Snikos.nikoleris@arm.com } 38910399Sstephan.diestelhorst@arm.com DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n", 39010399Sstephan.diestelhorst@arm.com __func__, sf_item.requested, sf_item.holder); 39110399Sstephan.diestelhorst@arm.com} 39210399Sstephan.diestelhorst@arm.com 39310403Sstephan.diestelhorst@arm.comvoid 39410403Sstephan.diestelhorst@arm.comSnoopFilter::regStats() 39510403Sstephan.diestelhorst@arm.com{ 39611523Sdavid.guillen@arm.com SimObject::regStats(); 39711523Sdavid.guillen@arm.com 39810403Sstephan.diestelhorst@arm.com totRequests 39910403Sstephan.diestelhorst@arm.com .name(name() + ".tot_requests") 40010403Sstephan.diestelhorst@arm.com .desc("Total number of requests made to the snoop filter."); 40110403Sstephan.diestelhorst@arm.com 40210403Sstephan.diestelhorst@arm.com hitSingleRequests 40310403Sstephan.diestelhorst@arm.com .name(name() + ".hit_single_requests") 40410403Sstephan.diestelhorst@arm.com .desc("Number of requests hitting in the snoop filter with a single "\ 40510403Sstephan.diestelhorst@arm.com "holder of the requested data."); 40610403Sstephan.diestelhorst@arm.com 40710403Sstephan.diestelhorst@arm.com hitMultiRequests 40810403Sstephan.diestelhorst@arm.com .name(name() + ".hit_multi_requests") 40910403Sstephan.diestelhorst@arm.com .desc("Number of requests hitting in the snoop filter with multiple "\ 41010403Sstephan.diestelhorst@arm.com "(>1) holders of the requested data."); 41110403Sstephan.diestelhorst@arm.com 41210403Sstephan.diestelhorst@arm.com totSnoops 41310403Sstephan.diestelhorst@arm.com .name(name() + ".tot_snoops") 41410403Sstephan.diestelhorst@arm.com .desc("Total number of snoops made to the snoop filter."); 41510403Sstephan.diestelhorst@arm.com 41610403Sstephan.diestelhorst@arm.com hitSingleSnoops 41710403Sstephan.diestelhorst@arm.com .name(name() + ".hit_single_snoops") 41810403Sstephan.diestelhorst@arm.com .desc("Number of snoops hitting in the snoop filter with a single "\ 41910403Sstephan.diestelhorst@arm.com "holder of the requested data."); 42010403Sstephan.diestelhorst@arm.com 42110403Sstephan.diestelhorst@arm.com hitMultiSnoops 42210403Sstephan.diestelhorst@arm.com .name(name() + ".hit_multi_snoops") 42310403Sstephan.diestelhorst@arm.com .desc("Number of snoops hitting in the snoop filter with multiple "\ 42410403Sstephan.diestelhorst@arm.com "(>1) holders of the requested data."); 42510403Sstephan.diestelhorst@arm.com} 42610403Sstephan.diestelhorst@arm.com 42710399Sstephan.diestelhorst@arm.comSnoopFilter * 42810399Sstephan.diestelhorst@arm.comSnoopFilterParams::create() 42910399Sstephan.diestelhorst@arm.com{ 43010399Sstephan.diestelhorst@arm.com return new SnoopFilter(this); 43110399Sstephan.diestelhorst@arm.com} 432