snoop_filter.cc revision 11793:ef606668d247
17405SAli.Saidi@ARM.com/*
212667Schuan.zhu@arm.com * Copyright (c) 2013-2016 ARM Limited
37405SAli.Saidi@ARM.com * All rights reserved
47405SAli.Saidi@ARM.com *
57405SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall
67405SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual
77405SAli.Saidi@ARM.com * property including but not limited to intellectual property relating
87405SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software
97405SAli.Saidi@ARM.com * licensed hereunder.  You may use the software subject to the license
107405SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated
117405SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software,
127405SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form.
137405SAli.Saidi@ARM.com *
147405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
157405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
167405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
177405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
187405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
197405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
207405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
217405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
227405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
237405SAli.Saidi@ARM.com * this software without specific prior written permission.
247405SAli.Saidi@ARM.com *
257405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
267405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
277405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
287405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
297405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
307405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
317405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
327405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
337405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
347405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
357405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
367405SAli.Saidi@ARM.com *
377405SAli.Saidi@ARM.com * Authors: Stephan Diestelhorst
387405SAli.Saidi@ARM.com */
397405SAli.Saidi@ARM.com
407405SAli.Saidi@ARM.com/**
417405SAli.Saidi@ARM.com * @file
4210461SAndreas.Sandberg@ARM.com * Implementation of a snoop filter.
439050Schander.sudanthi@arm.com */
4412406Sgabeblack@google.com
4512605Sgiacomo.travaglini@arm.com#include "mem/snoop_filter.hh"
4611793Sbrandon.potter@amd.com
478887Sgeoffrey.blake@arm.com#include "base/misc.hh"
488232Snate@binkert.org#include "base/trace.hh"
498232Snate@binkert.org#include "debug/SnoopFilter.hh"
5010844Sandreas.sandberg@arm.com#include "sim/system.hh"
519384SAndreas.Sandberg@arm.com
527678Sgblack@eecs.umich.eduvoid
538059SAli.Saidi@ARM.comSnoopFilter::eraseIfNullEntry(SnoopFilterCache::iterator& sf_it)
548284SAli.Saidi@ARM.com{
557405SAli.Saidi@ARM.com    SnoopItem& sf_item = sf_it->second;
567405SAli.Saidi@ARM.com    if (!(sf_item.requested | sf_item.holder)) {
577405SAli.Saidi@ARM.com        cachedLocations.erase(sf_it);
587405SAli.Saidi@ARM.com        DPRINTF(SnoopFilter, "%s:   Removed SF entry.\n",
599384SAndreas.Sandberg@arm.com                __func__);
6010461SAndreas.Sandberg@ARM.com    }
6110461SAndreas.Sandberg@ARM.com}
6211165SRekai.GonzalezAlberquilla@arm.com
6312109SRekai.GonzalezAlberquilla@arm.comstd::pair<SnoopFilter::SnoopList, Cycles>
6412714Sgiacomo.travaglini@arm.comSnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port)
6512714Sgiacomo.travaglini@arm.com{
669384SAndreas.Sandberg@arm.com    DPRINTF(SnoopFilter, "%s: src %s packet %s\n", __func__,
6711770SCurtis.Dunham@arm.com            slave_port.name(), cpkt->print());
6810037SARM gem5 Developers
6910461SAndreas.Sandberg@ARM.com    // check if the packet came from a cache
7010461SAndreas.Sandberg@ARM.com    bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping() &&
7110461SAndreas.Sandberg@ARM.com        cpkt->fromCache();
7210461SAndreas.Sandberg@ARM.com    Addr line_addr = cpkt->getBlockAddr(linesize);
7310461SAndreas.Sandberg@ARM.com    if (cpkt->isSecure()) {
7410461SAndreas.Sandberg@ARM.com        line_addr |= LineSecure;
7510609Sandreas.sandberg@arm.com    }
7610609Sandreas.sandberg@arm.com    SnoopMask req_port = portToMask(slave_port);
7710609Sandreas.sandberg@arm.com    reqLookupResult = cachedLocations.find(line_addr);
7810037SARM gem5 Developers    bool is_hit = (reqLookupResult != cachedLocations.end());
7910037SARM gem5 Developers
8010037SARM gem5 Developers    // If the snoop filter has no entry, and we should not allocate,
8110037SARM gem5 Developers    // do not create a new snoop filter entry, simply return a NULL
8211771SCurtis.Dunham@arm.com    // portlist.
8310037SARM gem5 Developers    if (!is_hit && !allocate)
8410037SARM gem5 Developers        return snoopDown(lookupLatency);
8510037SARM gem5 Developers
8610037SARM gem5 Developers    // If no hit in snoop filter create a new element and update iterator
8710037SARM gem5 Developers    if (!is_hit)
8810037SARM gem5 Developers        reqLookupResult = cachedLocations.emplace(line_addr, SnoopItem()).first;
8911771SCurtis.Dunham@arm.com    SnoopItem& sf_item = reqLookupResult->second;
9010037SARM gem5 Developers    SnoopMask interested = sf_item.holder | sf_item.requested;
9110037SARM gem5 Developers
9210037SARM gem5 Developers    // Store unmodified value of snoop filter item in temp storage in
9310037SARM gem5 Developers    // case we need to revert because of a send retry in
9410037SARM gem5 Developers    // updateRequest.
9512477SCurtis.Dunham@arm.com    retryItem = sf_item;
9610037SARM gem5 Developers
9710037SARM gem5 Developers    totRequests++;
989384SAndreas.Sandberg@arm.com    if (is_hit) {
999384SAndreas.Sandberg@arm.com        // Single bit set -> value is a power of two
1009384SAndreas.Sandberg@arm.com        if (isPow2(interested))
10112479SCurtis.Dunham@arm.com            hitSingleRequests++;
10212479SCurtis.Dunham@arm.com        else
1039384SAndreas.Sandberg@arm.com            hitMultiRequests++;
1049384SAndreas.Sandberg@arm.com    }
1059384SAndreas.Sandberg@arm.com
1069384SAndreas.Sandberg@arm.com    DPRINTF(SnoopFilter, "%s:   SF value %x.%x\n",
1079384SAndreas.Sandberg@arm.com            __func__, sf_item.requested, sf_item.holder);
1089384SAndreas.Sandberg@arm.com
1097427Sgblack@eecs.umich.edu    // If we are not allocating, we are done
1107427Sgblack@eecs.umich.edu    if (!allocate)
1117427Sgblack@eecs.umich.edu        return snoopSelected(maskToPortList(interested & ~req_port),
1129385SAndreas.Sandberg@arm.com                             lookupLatency);
1139385SAndreas.Sandberg@arm.com
1147427Sgblack@eecs.umich.edu    if (cpkt->needsResponse()) {
1157427Sgblack@eecs.umich.edu        if (!cpkt->cacheResponding()) {
11610037SARM gem5 Developers            // Max one request per address per port
11710037SARM gem5 Developers            panic_if(sf_item.requested & req_port, "double request :( " \
11810037SARM gem5 Developers                     "SF value %x.%x\n", sf_item.requested, sf_item.holder);
11910037SARM gem5 Developers
12010037SARM gem5 Developers            // Mark in-flight requests to distinguish later on
12110037SARM gem5 Developers            sf_item.requested |= req_port;
12212690Sgiacomo.travaglini@arm.com            DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
12312690Sgiacomo.travaglini@arm.com                    __func__,  sf_item.requested, sf_item.holder);
12412690Sgiacomo.travaglini@arm.com        } else {
12512690Sgiacomo.travaglini@arm.com            // NOTE: The memInhibit might have been asserted by a cache closer
12612690Sgiacomo.travaglini@arm.com            // to the CPU, already -> the response will not be seen by this
12712690Sgiacomo.travaglini@arm.com            // filter -> we do not need to keep the in-flight request, but make
12812690Sgiacomo.travaglini@arm.com            // sure that we know that that cluster has a copy
12912690Sgiacomo.travaglini@arm.com            panic_if(!(sf_item.holder & req_port), "Need to hold the value!");
13012690Sgiacomo.travaglini@arm.com            DPRINTF(SnoopFilter,
13112690Sgiacomo.travaglini@arm.com                    "%s: not marking request. SF value %x.%x\n",
13212690Sgiacomo.travaglini@arm.com                    __func__,  sf_item.requested, sf_item.holder);
13312690Sgiacomo.travaglini@arm.com        }
13410037SARM gem5 Developers    } else { // if (!cpkt->needsResponse())
13510037SARM gem5 Developers        assert(cpkt->isEviction());
13610037SARM gem5 Developers        // make sure that the sender actually had the line
13710037SARM gem5 Developers        panic_if(!(sf_item.holder & req_port), "requester %x is not a " \
13810037SARM gem5 Developers                 "holder :( SF value %x.%x\n", req_port,
13910037SARM gem5 Developers                 sf_item.requested, sf_item.holder);
14010037SARM gem5 Developers        // CleanEvicts and Writebacks -> the sender and all caches above
14110037SARM gem5 Developers        // it may not have the line anymore.
1427427Sgblack@eecs.umich.edu        if (!cpkt->isBlockCached()) {
1437427Sgblack@eecs.umich.edu            sf_item.holder &= ~req_port;
1447427Sgblack@eecs.umich.edu            DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
1457427Sgblack@eecs.umich.edu                    __func__,  sf_item.requested, sf_item.holder);
1467427Sgblack@eecs.umich.edu        }
1477427Sgblack@eecs.umich.edu    }
14810037SARM gem5 Developers
14910037SARM gem5 Developers    return snoopSelected(maskToPortList(interested & ~req_port), lookupLatency);
15010037SARM gem5 Developers}
15110037SARM gem5 Developers
1527427Sgblack@eecs.umich.eduvoid
1537427Sgblack@eecs.umich.eduSnoopFilter::finishRequest(bool will_retry, Addr addr, bool is_secure)
1547427Sgblack@eecs.umich.edu{
15510037SARM gem5 Developers    if (reqLookupResult != cachedLocations.end()) {
15610204SAli.Saidi@ARM.com        // since we rely on the caller, do a basic check to ensure
15710204SAli.Saidi@ARM.com        // that finishRequest is being called following lookupRequest
15810037SARM gem5 Developers        Addr line_addr = (addr & ~(Addr(linesize - 1)));
1597427Sgblack@eecs.umich.edu        if (is_secure) {
16010037SARM gem5 Developers            line_addr |= LineSecure;
1617427Sgblack@eecs.umich.edu        }
16210037SARM gem5 Developers        assert(reqLookupResult->first == line_addr);
1637427Sgblack@eecs.umich.edu        if (will_retry) {
1647427Sgblack@eecs.umich.edu            // Undo any changes made in lookupRequest to the snoop filter
16510037SARM gem5 Developers            // entry if the request will come again. retryItem holds
1667427Sgblack@eecs.umich.edu            // the previous value of the snoopfilter entry.
1677427Sgblack@eecs.umich.edu            reqLookupResult->second = retryItem;
1687427Sgblack@eecs.umich.edu
1697427Sgblack@eecs.umich.edu            DPRINTF(SnoopFilter, "%s:   restored SF value %x.%x\n",
1707427Sgblack@eecs.umich.edu                    __func__,  retryItem.requested, retryItem.holder);
1717427Sgblack@eecs.umich.edu        }
1727427Sgblack@eecs.umich.edu
1737427Sgblack@eecs.umich.edu        eraseIfNullEntry(reqLookupResult);
1747427Sgblack@eecs.umich.edu    }
1757427Sgblack@eecs.umich.edu}
1767427Sgblack@eecs.umich.edu
1777427Sgblack@eecs.umich.edustd::pair<SnoopFilter::SnoopList, Cycles>
1787427Sgblack@eecs.umich.eduSnoopFilter::lookupSnoop(const Packet* cpkt)
1797427Sgblack@eecs.umich.edu{
1807427Sgblack@eecs.umich.edu    DPRINTF(SnoopFilter, "%s: packet %s\n", __func__, cpkt->print());
1817427Sgblack@eecs.umich.edu
1827427Sgblack@eecs.umich.edu    assert(cpkt->isRequest());
1837427Sgblack@eecs.umich.edu
1847427Sgblack@eecs.umich.edu    Addr line_addr = cpkt->getBlockAddr(linesize);
1857427Sgblack@eecs.umich.edu    if (cpkt->isSecure()) {
1867427Sgblack@eecs.umich.edu        line_addr |= LineSecure;
1877427Sgblack@eecs.umich.edu    }
1887427Sgblack@eecs.umich.edu    auto sf_it = cachedLocations.find(line_addr);
1897436Sdam.sunwoo@arm.com    bool is_hit = (sf_it != cachedLocations.end());
1907436Sdam.sunwoo@arm.com
19110037SARM gem5 Developers    panic_if(!is_hit && (cachedLocations.size() >= maxEntryCount),
19210037SARM gem5 Developers             "snoop filter exceeded capacity of %d cache blocks\n",
1937436Sdam.sunwoo@arm.com             maxEntryCount);
1947436Sdam.sunwoo@arm.com
1957436Sdam.sunwoo@arm.com    // If the snoop filter has no entry, simply return a NULL
1967436Sdam.sunwoo@arm.com    // portlist, there is no point creating an entry only to remove it
1977436Sdam.sunwoo@arm.com    // later
1987436Sdam.sunwoo@arm.com    if (!is_hit)
1997436Sdam.sunwoo@arm.com        return snoopDown(lookupLatency);
2007436Sdam.sunwoo@arm.com
2017436Sdam.sunwoo@arm.com    SnoopItem& sf_item = sf_it->second;
2027436Sdam.sunwoo@arm.com
2037436Sdam.sunwoo@arm.com    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
2047436Sdam.sunwoo@arm.com            __func__, sf_item.requested, sf_item.holder);
20510037SARM gem5 Developers
2067436Sdam.sunwoo@arm.com    SnoopMask interested = (sf_item.holder | sf_item.requested);
2077436Sdam.sunwoo@arm.com
2087436Sdam.sunwoo@arm.com    totSnoops++;
2097436Sdam.sunwoo@arm.com    // Single bit set -> value is a power of two
2107436Sdam.sunwoo@arm.com    if (isPow2(interested))
2117436Sdam.sunwoo@arm.com        hitSingleSnoops++;
2127436Sdam.sunwoo@arm.com    else
2137436Sdam.sunwoo@arm.com        hitMultiSnoops++;
2147436Sdam.sunwoo@arm.com
2157436Sdam.sunwoo@arm.com    // ReadEx and Writes require both invalidation and exlusivity, while reads
2167436Sdam.sunwoo@arm.com    // require neither. Writebacks on the other hand require exclusivity but
2177436Sdam.sunwoo@arm.com    // not the invalidation. Previously Writebacks did not generate upward
2187436Sdam.sunwoo@arm.com    // snoops so this was never an aissue. Now that Writebacks generate snoops
2197436Sdam.sunwoo@arm.com    // we need to special case for Writebacks.
2207436Sdam.sunwoo@arm.com    assert(cpkt->isWriteback() || cpkt->req->isUncacheable() ||
2217436Sdam.sunwoo@arm.com           (cpkt->isInvalidate() == cpkt->needsWritable()));
2227644Sali.saidi@arm.com    if (cpkt->isInvalidate() && !sf_item.requested) {
2238147SAli.Saidi@ARM.com        // Early clear of the holder, if no other request is currently going on
2249385SAndreas.Sandberg@arm.com        // @todo: This should possibly be updated even though we do not filter
2259385SAndreas.Sandberg@arm.com        // upward snoops
22610037SARM gem5 Developers        sf_item.holder = 0;
22710037SARM gem5 Developers    }
22810037SARM gem5 Developers
22910037SARM gem5 Developers    eraseIfNullEntry(sf_it);
23010037SARM gem5 Developers    DPRINTF(SnoopFilter, "%s:   new SF value %x.%x interest: %x \n",
23110037SARM gem5 Developers            __func__, sf_item.requested, sf_item.holder, interested);
23210037SARM gem5 Developers
23310037SARM gem5 Developers    return snoopSelected(maskToPortList(interested), lookupLatency);
23410037SARM gem5 Developers}
23510037SARM gem5 Developers
23610037SARM gem5 Developersvoid
23710037SARM gem5 DevelopersSnoopFilter::updateSnoopResponse(const Packet* cpkt,
23810037SARM gem5 Developers                                 const SlavePort& rsp_port,
23910037SARM gem5 Developers                                 const SlavePort& req_port)
24010037SARM gem5 Developers{
24110037SARM gem5 Developers    DPRINTF(SnoopFilter, "%s: rsp %s req %s packet %s\n",
2428147SAli.Saidi@ARM.com            __func__, rsp_port.name(), req_port.name(), cpkt->print());
2437427Sgblack@eecs.umich.edu
2447427Sgblack@eecs.umich.edu    assert(cpkt->isResponse());
2457427Sgblack@eecs.umich.edu    assert(cpkt->cacheResponding());
24610037SARM gem5 Developers
24710037SARM gem5 Developers    // if this snoop response is due to an uncacheable request, or is
24810037SARM gem5 Developers    // being turned into a normal response, there is nothing more to
24910037SARM gem5 Developers    // do
25010037SARM gem5 Developers    if (cpkt->req->isUncacheable() || !req_port.isSnooping()) {
25110037SARM gem5 Developers        return;
25210037SARM gem5 Developers    }
25310037SARM gem5 Developers
25410037SARM gem5 Developers    Addr line_addr = cpkt->getBlockAddr(linesize);
25510037SARM gem5 Developers    if (cpkt->isSecure()) {
25610037SARM gem5 Developers        line_addr |= LineSecure;
25710037SARM gem5 Developers    }
25810037SARM gem5 Developers    SnoopMask rsp_mask = portToMask(rsp_port);
25910037SARM gem5 Developers    SnoopMask req_mask = portToMask(req_port);
26010037SARM gem5 Developers    SnoopItem& sf_item = cachedLocations[line_addr];
26110037SARM gem5 Developers
26210037SARM gem5 Developers    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
26310037SARM gem5 Developers            __func__,  sf_item.requested, sf_item.holder);
26410037SARM gem5 Developers
26510037SARM gem5 Developers    // The source should have the line
26610037SARM gem5 Developers    panic_if(!(sf_item.holder & rsp_mask), "SF value %x.%x does not have "\
26710037SARM gem5 Developers             "the line\n", sf_item.requested, sf_item.holder);
26810037SARM gem5 Developers
26910037SARM gem5 Developers    // The destination should have had a request in
27010037SARM gem5 Developers    panic_if(!(sf_item.requested & req_mask), "SF value %x.%x missing "\
27110037SARM gem5 Developers             "the original request\n",  sf_item.requested, sf_item.holder);
27210037SARM gem5 Developers
27310037SARM gem5 Developers    // If the snoop response has no sharers the line is passed in
27410037SARM gem5 Developers    // Modified state, and we know that there are no other copies, or
27510037SARM gem5 Developers    // they will all be invalidated imminently
27610037SARM gem5 Developers    if (!cpkt->hasSharers()) {
27710037SARM gem5 Developers        DPRINTF(SnoopFilter,
27810037SARM gem5 Developers                "%s: dropping %x because non-shared snoop "
27910037SARM gem5 Developers                "response SF val: %x.%x\n", __func__,  rsp_mask,
28010037SARM gem5 Developers                sf_item.requested, sf_item.holder);
28110037SARM gem5 Developers        sf_item.holder = 0;
28211770SCurtis.Dunham@arm.com    }
28310037SARM gem5 Developers    assert(!cpkt->isWriteback());
28411574SCurtis.Dunham@arm.com    // @todo Deal with invalidating responses
28511770SCurtis.Dunham@arm.com    sf_item.holder |=  req_mask;
28611770SCurtis.Dunham@arm.com    sf_item.requested &= ~req_mask;
28710037SARM gem5 Developers    assert(sf_item.requested | sf_item.holder);
28811770SCurtis.Dunham@arm.com    DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
28911770SCurtis.Dunham@arm.com            __func__, sf_item.requested, sf_item.holder);
29010037SARM gem5 Developers}
29110037SARM gem5 Developers
29210037SARM gem5 Developersvoid
29310037SARM gem5 DevelopersSnoopFilter::updateSnoopForward(const Packet* cpkt,
29410037SARM gem5 Developers        const SlavePort& rsp_port, const MasterPort& req_port)
29510037SARM gem5 Developers{
29610037SARM gem5 Developers    DPRINTF(SnoopFilter, "%s: rsp %s req %s packet %s\n",
29710461SAndreas.Sandberg@ARM.com            __func__, rsp_port.name(), req_port.name(), cpkt->print());
29810461SAndreas.Sandberg@ARM.com
29910461SAndreas.Sandberg@ARM.com    assert(cpkt->isResponse());
30010461SAndreas.Sandberg@ARM.com    assert(cpkt->cacheResponding());
30110037SARM gem5 Developers
30210037SARM gem5 Developers    Addr line_addr = cpkt->getBlockAddr(linesize);
30310037SARM gem5 Developers    if (cpkt->isSecure()) {
30410037SARM gem5 Developers        line_addr |= LineSecure;
30510037SARM gem5 Developers    }
30610037SARM gem5 Developers    auto sf_it = cachedLocations.find(line_addr);
30710461SAndreas.Sandberg@ARM.com    bool is_hit = sf_it != cachedLocations.end();
30810461SAndreas.Sandberg@ARM.com
30910461SAndreas.Sandberg@ARM.com    // Nothing to do if it is not a hit
31010461SAndreas.Sandberg@ARM.com    if (!is_hit)
31110461SAndreas.Sandberg@ARM.com        return;
31210037SARM gem5 Developers
31310037SARM gem5 Developers    SnoopItem& sf_item = sf_it->second;
31410037SARM gem5 Developers
31510037SARM gem5 Developers    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
31610037SARM gem5 Developers            __func__,  sf_item.requested, sf_item.holder);
31711574SCurtis.Dunham@arm.com
31810037SARM gem5 Developers    // If the snoop response has no sharers the line is passed in
31910037SARM gem5 Developers    // Modified state, and we know that there are no other copies, or
32010037SARM gem5 Developers    // they will all be invalidated imminently
32111574SCurtis.Dunham@arm.com    if (!cpkt->hasSharers()) {
32210037SARM gem5 Developers        sf_item.holder = 0;
32310037SARM gem5 Developers    }
32410037SARM gem5 Developers    DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
32510037SARM gem5 Developers            __func__, sf_item.requested, sf_item.holder);
32610037SARM gem5 Developers    eraseIfNullEntry(sf_it);
32710037SARM gem5 Developers
32810037SARM gem5 Developers}
32910037SARM gem5 Developers
33010037SARM gem5 Developersvoid
33110037SARM gem5 DevelopersSnoopFilter::updateResponse(const Packet* cpkt, const SlavePort& slave_port)
3327405SAli.Saidi@ARM.com{
33310035Sandreas.hansson@arm.com    DPRINTF(SnoopFilter, "%s: src %s packet %s\n",
3347405SAli.Saidi@ARM.com            __func__, slave_port.name(), cpkt->print());
3357405SAli.Saidi@ARM.com
3367614Sminkyu.jeong@arm.com    assert(cpkt->isResponse());
33712478SCurtis.Dunham@arm.com
33812478SCurtis.Dunham@arm.com    // we only allocate if the packet actually came from a cache, but
33912478SCurtis.Dunham@arm.com    // start by checking if the port is snooping
34012478SCurtis.Dunham@arm.com    if (cpkt->req->isUncacheable() || !slave_port.isSnooping())
34112478SCurtis.Dunham@arm.com        return;
34212478SCurtis.Dunham@arm.com
34312478SCurtis.Dunham@arm.com    // next check if we actually allocated an entry
34412478SCurtis.Dunham@arm.com    Addr line_addr = cpkt->getBlockAddr(linesize);
34512478SCurtis.Dunham@arm.com    if (cpkt->isSecure()) {
34612478SCurtis.Dunham@arm.com        line_addr |= LineSecure;
34712478SCurtis.Dunham@arm.com    }
34812478SCurtis.Dunham@arm.com    auto sf_it = cachedLocations.find(line_addr);
34912478SCurtis.Dunham@arm.com    if (sf_it == cachedLocations.end())
35012478SCurtis.Dunham@arm.com        return;
35112478SCurtis.Dunham@arm.com
35212478SCurtis.Dunham@arm.com    SnoopMask slave_mask = portToMask(slave_port);
3537405SAli.Saidi@ARM.com    SnoopItem& sf_item = sf_it->second;
3547405SAli.Saidi@ARM.com
3557405SAli.Saidi@ARM.com    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
3567405SAli.Saidi@ARM.com            __func__,  sf_item.requested, sf_item.holder);
3577405SAli.Saidi@ARM.com
3587405SAli.Saidi@ARM.com    // Make sure we have seen the actual request, too
35910037SARM gem5 Developers    panic_if(!(sf_item.requested & slave_mask), "SF value %x.%x missing "\
36010037SARM gem5 Developers             "request bit\n", sf_item.requested, sf_item.holder);
36110037SARM gem5 Developers
3629050Schander.sudanthi@arm.com    // Update the residency of the cache line.
3637405SAli.Saidi@ARM.com    sf_item.holder |=  slave_mask;
36410037SARM gem5 Developers    sf_item.requested &= ~slave_mask;
36510037SARM gem5 Developers    assert(sf_item.holder | sf_item.requested);
3667720Sgblack@eecs.umich.edu    DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
3677720Sgblack@eecs.umich.edu            __func__, sf_item.requested, sf_item.holder);
3687405SAli.Saidi@ARM.com}
3697405SAli.Saidi@ARM.com
3707757SAli.Saidi@ARM.comvoid
37110037SARM gem5 DevelopersSnoopFilter::regStats()
37210037SARM gem5 Developers{
37310037SARM gem5 Developers    SimObject::regStats();
37410037SARM gem5 Developers
37510037SARM gem5 Developers    totRequests
37610037SARM gem5 Developers        .name(name() + ".tot_requests")
37710037SARM gem5 Developers        .desc("Total number of requests made to the snoop filter.");
37810037SARM gem5 Developers
37910037SARM gem5 Developers    hitSingleRequests
38010037SARM gem5 Developers        .name(name() + ".hit_single_requests")
38110037SARM gem5 Developers        .desc("Number of requests hitting in the snoop filter with a single "\
38210037SARM gem5 Developers              "holder of the requested data.");
38310037SARM gem5 Developers
38410037SARM gem5 Developers    hitMultiRequests
38510037SARM gem5 Developers        .name(name() + ".hit_multi_requests")
38610037SARM gem5 Developers        .desc("Number of requests hitting in the snoop filter with multiple "\
38710037SARM gem5 Developers              "(>1) holders of the requested data.");
38810037SARM gem5 Developers
38910037SARM gem5 Developers    totSnoops
39010037SARM gem5 Developers        .name(name() + ".tot_snoops")
39110037SARM gem5 Developers        .desc("Total number of snoops made to the snoop filter.");
39210037SARM gem5 Developers
39310037SARM gem5 Developers    hitSingleSnoops
39410037SARM gem5 Developers        .name(name() + ".hit_single_snoops")
39510037SARM gem5 Developers        .desc("Number of snoops hitting in the snoop filter with a single "\
39610037SARM gem5 Developers              "holder of the requested data.");
39710037SARM gem5 Developers
39810037SARM gem5 Developers    hitMultiSnoops
39910037SARM gem5 Developers        .name(name() + ".hit_multi_snoops")
40010037SARM gem5 Developers        .desc("Number of snoops hitting in the snoop filter with multiple "\
40110037SARM gem5 Developers              "(>1) holders of the requested data.");
40210037SARM gem5 Developers}
40310037SARM gem5 Developers
40412667Schuan.zhu@arm.comSnoopFilter *
40510037SARM gem5 DevelopersSnoopFilterParams::create()
40610037SARM gem5 Developers{
40710037SARM gem5 Developers    return new SnoopFilter(this);
40810037SARM gem5 Developers}
40910037SARM gem5 Developers