snoop_filter.cc revision 10883
110399Sstephan.diestelhorst@arm.com/*
210399Sstephan.diestelhorst@arm.com * Copyright (c) 2013 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
5110399Sstephan.diestelhorst@arm.comstd::pair<SnoopFilter::SnoopList, Cycles>
5210399Sstephan.diestelhorst@arm.comSnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port)
5310399Sstephan.diestelhorst@arm.com{
5410399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
5510399Sstephan.diestelhorst@arm.com            __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
5610399Sstephan.diestelhorst@arm.com
5710399Sstephan.diestelhorst@arm.com    Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
5810399Sstephan.diestelhorst@arm.com    SnoopMask req_port = portToMask(slave_port);
5910403Sstephan.diestelhorst@arm.com    auto sf_it = cachedLocations.find(line_addr);
6010403Sstephan.diestelhorst@arm.com    bool is_hit = (sf_it != cachedLocations.end());
6110403Sstephan.diestelhorst@arm.com    // Create a new element through operator[] and modify in-place
6210403Sstephan.diestelhorst@arm.com    SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr];
6310403Sstephan.diestelhorst@arm.com    SnoopMask interested = sf_item.holder | sf_item.requested;
6410403Sstephan.diestelhorst@arm.com
6510403Sstephan.diestelhorst@arm.com    totRequests++;
6610403Sstephan.diestelhorst@arm.com    if (is_hit) {
6710403Sstephan.diestelhorst@arm.com        // Single bit set -> value is a power of two
6810403Sstephan.diestelhorst@arm.com        if (isPow2(interested))
6910403Sstephan.diestelhorst@arm.com            hitSingleRequests++;
7010403Sstephan.diestelhorst@arm.com        else
7110403Sstephan.diestelhorst@arm.com            hitMultiRequests++;
7210403Sstephan.diestelhorst@arm.com    }
7310399Sstephan.diestelhorst@arm.com
7410399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   SF value %x.%x\n",
7510399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder);
7610399Sstephan.diestelhorst@arm.com
7710821Sandreas.hansson@arm.com    if (!cpkt->req->isUncacheable() && cpkt->needsResponse()) {
7810399Sstephan.diestelhorst@arm.com        if (!cpkt->memInhibitAsserted()) {
7910399Sstephan.diestelhorst@arm.com            // Max one request per address per port
8010399Sstephan.diestelhorst@arm.com            panic_if(sf_item.requested & req_port, "double request :( "\
8110399Sstephan.diestelhorst@arm.com                     "SF value %x.%x\n", sf_item.requested, sf_item.holder);
8210399Sstephan.diestelhorst@arm.com
8310399Sstephan.diestelhorst@arm.com            // Mark in-flight requests to distinguish later on
8410399Sstephan.diestelhorst@arm.com            sf_item.requested |= req_port;
8510399Sstephan.diestelhorst@arm.com        } else {
8610399Sstephan.diestelhorst@arm.com            // NOTE: The memInhibit might have been asserted by a cache closer
8710399Sstephan.diestelhorst@arm.com            // to the CPU, already -> the response will not be seen by this
8810399Sstephan.diestelhorst@arm.com            // filter -> we do not need to keep the in-flight request, but make
8910399Sstephan.diestelhorst@arm.com            // sure that we know that that cluster has a copy
9010399Sstephan.diestelhorst@arm.com            panic_if(!(sf_item.holder & req_port), "Need to hold the value!");
9110399Sstephan.diestelhorst@arm.com            DPRINTF(SnoopFilter, "%s:   not marking request. SF value %x.%x\n",
9210399Sstephan.diestelhorst@arm.com                    __func__,  sf_item.requested, sf_item.holder);
9310399Sstephan.diestelhorst@arm.com        }
9410399Sstephan.diestelhorst@arm.com        DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
9510399Sstephan.diestelhorst@arm.com                __func__,  sf_item.requested, sf_item.holder);
9610399Sstephan.diestelhorst@arm.com    }
9710403Sstephan.diestelhorst@arm.com    return snoopSelected(maskToPortList(interested & ~req_port), lookupLatency);
9810399Sstephan.diestelhorst@arm.com}
9910399Sstephan.diestelhorst@arm.com
10010399Sstephan.diestelhorst@arm.comvoid
10110399Sstephan.diestelhorst@arm.comSnoopFilter::updateRequest(const Packet* cpkt, const SlavePort& slave_port,
10210399Sstephan.diestelhorst@arm.com                           bool will_retry)
10310399Sstephan.diestelhorst@arm.com{
10410399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
10510399Sstephan.diestelhorst@arm.com            __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
10610399Sstephan.diestelhorst@arm.com
10710821Sandreas.hansson@arm.com    if (cpkt->req->isUncacheable())
10810821Sandreas.hansson@arm.com        return;
10910821Sandreas.hansson@arm.com
11010399Sstephan.diestelhorst@arm.com    Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
11110399Sstephan.diestelhorst@arm.com    SnoopMask req_port = portToMask(slave_port);
11210399Sstephan.diestelhorst@arm.com    SnoopItem& sf_item  = cachedLocations[line_addr];
11310399Sstephan.diestelhorst@arm.com
11410399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x retry: %i\n",
11510399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder, will_retry);
11610399Sstephan.diestelhorst@arm.com
11710399Sstephan.diestelhorst@arm.com    if (will_retry) {
11810399Sstephan.diestelhorst@arm.com        // Unmark a request that will come again.
11910399Sstephan.diestelhorst@arm.com        sf_item.requested &= ~req_port;
12010399Sstephan.diestelhorst@arm.com        return;
12110399Sstephan.diestelhorst@arm.com    }
12210399Sstephan.diestelhorst@arm.com
12310399Sstephan.diestelhorst@arm.com    // will_retry == false
12410399Sstephan.diestelhorst@arm.com    if (!cpkt->needsResponse()) {
12510399Sstephan.diestelhorst@arm.com        // Packets that will not evoke a response but still need updates of the
12610399Sstephan.diestelhorst@arm.com        // snoop filter; WRITEBACKs for now only
12710399Sstephan.diestelhorst@arm.com        if (cpkt->cmd == MemCmd::Writeback) {
12810399Sstephan.diestelhorst@arm.com            // make sure that the sender actually had the line
12910399Sstephan.diestelhorst@arm.com            panic_if(sf_item.requested & req_port, "double request :( "\
13010399Sstephan.diestelhorst@arm.com                     "SF value %x.%x\n", sf_item.requested, sf_item.holder);
13110399Sstephan.diestelhorst@arm.com            panic_if(!(sf_item.holder & req_port), "requester %x is not a "\
13210399Sstephan.diestelhorst@arm.com                     "holder :( SF value %x.%x\n", req_port,
13310399Sstephan.diestelhorst@arm.com                     sf_item.requested, sf_item.holder);
13410399Sstephan.diestelhorst@arm.com            // Writebacks -> the sender does not have the line anymore
13510399Sstephan.diestelhorst@arm.com            sf_item.holder &= ~req_port;
13610399Sstephan.diestelhorst@arm.com        } else {
13710883Sali.jafri@arm.com            // @todo Add CleanEvicts
13810883Sali.jafri@arm.com            assert(cpkt->cmd == MemCmd::CleanEvict);
13910399Sstephan.diestelhorst@arm.com        }
14010399Sstephan.diestelhorst@arm.com        DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
14110399Sstephan.diestelhorst@arm.com                __func__,  sf_item.requested, sf_item.holder);
14210399Sstephan.diestelhorst@arm.com    }
14310399Sstephan.diestelhorst@arm.com}
14410399Sstephan.diestelhorst@arm.com
14510399Sstephan.diestelhorst@arm.comstd::pair<SnoopFilter::SnoopList, Cycles>
14610399Sstephan.diestelhorst@arm.comSnoopFilter::lookupSnoop(const Packet* cpkt)
14710399Sstephan.diestelhorst@arm.com{
14810399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s: packet addr 0x%x cmd %s\n",
14910399Sstephan.diestelhorst@arm.com            __func__, cpkt->getAddr(), cpkt->cmdString());
15010399Sstephan.diestelhorst@arm.com
15110399Sstephan.diestelhorst@arm.com    assert(cpkt->isRequest());
15210399Sstephan.diestelhorst@arm.com
15310399Sstephan.diestelhorst@arm.com    // Broadcast / filter upward snoops
15410399Sstephan.diestelhorst@arm.com    const bool filter_upward = true;  // @todo: Make configurable
15510399Sstephan.diestelhorst@arm.com
15610399Sstephan.diestelhorst@arm.com    if (!filter_upward)
15710399Sstephan.diestelhorst@arm.com        return snoopAll(lookupLatency);
15810399Sstephan.diestelhorst@arm.com
15910399Sstephan.diestelhorst@arm.com    Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
16010403Sstephan.diestelhorst@arm.com    auto sf_it = cachedLocations.find(line_addr);
16110403Sstephan.diestelhorst@arm.com    bool is_hit = (sf_it != cachedLocations.end());
16210403Sstephan.diestelhorst@arm.com    // Create a new element through operator[] and modify in-place
16310403Sstephan.diestelhorst@arm.com    SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr];
16410399Sstephan.diestelhorst@arm.com
16510399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
16610399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder);
16710399Sstephan.diestelhorst@arm.com
16810399Sstephan.diestelhorst@arm.com    SnoopMask interested = (sf_item.holder | sf_item.requested);
16910403Sstephan.diestelhorst@arm.com
17010403Sstephan.diestelhorst@arm.com    totSnoops++;
17110403Sstephan.diestelhorst@arm.com    if (is_hit) {
17210403Sstephan.diestelhorst@arm.com        // Single bit set -> value is a power of two
17310403Sstephan.diestelhorst@arm.com        if (isPow2(interested))
17410403Sstephan.diestelhorst@arm.com            hitSingleSnoops++;
17510403Sstephan.diestelhorst@arm.com        else
17610403Sstephan.diestelhorst@arm.com            hitMultiSnoops++;
17710403Sstephan.diestelhorst@arm.com    }
17810883Sali.jafri@arm.com    // ReadEx and Writes require both invalidation and exlusivity, while reads
17910883Sali.jafri@arm.com    // require neither. Writebacks on the other hand require exclusivity but
18010883Sali.jafri@arm.com    // not the invalidation. Previously Writebacks did not generate upward
18110883Sali.jafri@arm.com    // snoops so this was never an aissue. Now that Writebacks generate snoops
18210883Sali.jafri@arm.com    // we need to special case for Writebacks.
18310883Sali.jafri@arm.com    assert(cpkt->cmd == MemCmd::Writeback ||
18410883Sali.jafri@arm.com           (cpkt->isInvalidate() == cpkt->needsExclusive()));
18510399Sstephan.diestelhorst@arm.com    if (cpkt->isInvalidate() && !sf_item.requested) {
18610399Sstephan.diestelhorst@arm.com        // Early clear of the holder, if no other request is currently going on
18710399Sstephan.diestelhorst@arm.com        // @todo: This should possibly be updated even though we do not filter
18810399Sstephan.diestelhorst@arm.com        // upward snoops
18910399Sstephan.diestelhorst@arm.com        sf_item.holder = 0;
19010399Sstephan.diestelhorst@arm.com    }
19110399Sstephan.diestelhorst@arm.com
19210399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   new SF value %x.%x interest: %x \n",
19310399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder, interested);
19410399Sstephan.diestelhorst@arm.com
19510399Sstephan.diestelhorst@arm.com    return snoopSelected(maskToPortList(interested), lookupLatency);
19610399Sstephan.diestelhorst@arm.com}
19710399Sstephan.diestelhorst@arm.com
19810399Sstephan.diestelhorst@arm.comvoid
19910399Sstephan.diestelhorst@arm.comSnoopFilter::updateSnoopResponse(const Packet* cpkt,
20010399Sstephan.diestelhorst@arm.com                                 const SlavePort& rsp_port,
20110399Sstephan.diestelhorst@arm.com                                 const SlavePort& req_port)
20210399Sstephan.diestelhorst@arm.com{
20310399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n",
20410399Sstephan.diestelhorst@arm.com            __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
20510399Sstephan.diestelhorst@arm.com            cpkt->cmdString());
20610399Sstephan.diestelhorst@arm.com
20710821Sandreas.hansson@arm.com    assert(cpkt->isResponse());
20810821Sandreas.hansson@arm.com    assert(cpkt->memInhibitAsserted());
20910821Sandreas.hansson@arm.com
21010821Sandreas.hansson@arm.com    if (cpkt->req->isUncacheable())
21110821Sandreas.hansson@arm.com        return;
21210821Sandreas.hansson@arm.com
21310399Sstephan.diestelhorst@arm.com    Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
21410399Sstephan.diestelhorst@arm.com    SnoopMask rsp_mask = portToMask(rsp_port);
21510399Sstephan.diestelhorst@arm.com    SnoopMask req_mask = portToMask(req_port);
21610399Sstephan.diestelhorst@arm.com    SnoopItem& sf_item = cachedLocations[line_addr];
21710399Sstephan.diestelhorst@arm.com
21810399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
21910399Sstephan.diestelhorst@arm.com            __func__,  sf_item.requested, sf_item.holder);
22010399Sstephan.diestelhorst@arm.com
22110399Sstephan.diestelhorst@arm.com    // The source should have the line
22210399Sstephan.diestelhorst@arm.com    panic_if(!(sf_item.holder & rsp_mask), "SF value %x.%x does not have "\
22310399Sstephan.diestelhorst@arm.com             "the line\n", sf_item.requested, sf_item.holder);
22410399Sstephan.diestelhorst@arm.com
22510399Sstephan.diestelhorst@arm.com    // The destination should have had a request in
22610399Sstephan.diestelhorst@arm.com    panic_if(!(sf_item.requested & req_mask), "SF value %x.%x missing "\
22710399Sstephan.diestelhorst@arm.com             "the original request\n",  sf_item.requested, sf_item.holder);
22810399Sstephan.diestelhorst@arm.com
22910399Sstephan.diestelhorst@arm.com    // Update the residency of the cache line.
23010399Sstephan.diestelhorst@arm.com    if (cpkt->needsExclusive() || !cpkt->sharedAsserted()) {
23110399Sstephan.diestelhorst@arm.com        DPRINTF(SnoopFilter, "%s:  dropping %x because needs: %i shared: %i "\
23210399Sstephan.diestelhorst@arm.com                "SF val: %x.%x\n", __func__,  rsp_mask,
23310399Sstephan.diestelhorst@arm.com                cpkt->needsExclusive(), cpkt->sharedAsserted(),
23410399Sstephan.diestelhorst@arm.com                sf_item.requested, sf_item.holder);
23510399Sstephan.diestelhorst@arm.com
23610399Sstephan.diestelhorst@arm.com        sf_item.holder &= ~rsp_mask;
23710399Sstephan.diestelhorst@arm.com        // The snoop filter does not see any ACKs from non-responding sharers
23810399Sstephan.diestelhorst@arm.com        // that have been invalidated :(  So below assert would be nice, but..
23910399Sstephan.diestelhorst@arm.com        //assert(sf_item.holder == 0);
24010399Sstephan.diestelhorst@arm.com        sf_item.holder = 0;
24110399Sstephan.diestelhorst@arm.com    }
24210399Sstephan.diestelhorst@arm.com    assert(cpkt->cmd != MemCmd::Writeback);
24310399Sstephan.diestelhorst@arm.com    sf_item.holder |=  req_mask;
24410399Sstephan.diestelhorst@arm.com    sf_item.requested &= ~req_mask;
24510399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
24610399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder);
24710399Sstephan.diestelhorst@arm.com}
24810399Sstephan.diestelhorst@arm.com
24910399Sstephan.diestelhorst@arm.comvoid
25010399Sstephan.diestelhorst@arm.comSnoopFilter::updateSnoopForward(const Packet* cpkt,
25110399Sstephan.diestelhorst@arm.com        const SlavePort& rsp_port, const MasterPort& req_port)
25210399Sstephan.diestelhorst@arm.com{
25310399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n",
25410399Sstephan.diestelhorst@arm.com            __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
25510399Sstephan.diestelhorst@arm.com            cpkt->cmdString());
25610399Sstephan.diestelhorst@arm.com
25710399Sstephan.diestelhorst@arm.com    Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
25810399Sstephan.diestelhorst@arm.com    SnoopItem& sf_item = cachedLocations[line_addr];
25910399Sstephan.diestelhorst@arm.com    SnoopMask rsp_mask M5_VAR_USED = portToMask(rsp_port);
26010399Sstephan.diestelhorst@arm.com
26110399Sstephan.diestelhorst@arm.com    assert(cpkt->isResponse());
26210399Sstephan.diestelhorst@arm.com    assert(cpkt->memInhibitAsserted());
26310399Sstephan.diestelhorst@arm.com
26410399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
26510399Sstephan.diestelhorst@arm.com            __func__,  sf_item.requested, sf_item.holder);
26610399Sstephan.diestelhorst@arm.com
26710399Sstephan.diestelhorst@arm.com    // Remote (to this snoop filter) snoops update the filter already when they
26810399Sstephan.diestelhorst@arm.com    // arrive from below, because we may not see any response.
26910399Sstephan.diestelhorst@arm.com    if (cpkt->needsExclusive()) {
27010399Sstephan.diestelhorst@arm.com        // If the request to this snoop response hit an in-flight transaction,
27110399Sstephan.diestelhorst@arm.com        // the holder was not reset -> no assertion & do that here, now!
27210399Sstephan.diestelhorst@arm.com        //assert(sf_item.holder == 0);
27310399Sstephan.diestelhorst@arm.com        sf_item.holder = 0;
27410399Sstephan.diestelhorst@arm.com    }
27510399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
27610399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder);
27710399Sstephan.diestelhorst@arm.com}
27810399Sstephan.diestelhorst@arm.com
27910399Sstephan.diestelhorst@arm.comvoid
28010399Sstephan.diestelhorst@arm.comSnoopFilter::updateResponse(const Packet* cpkt, const SlavePort& slave_port)
28110399Sstephan.diestelhorst@arm.com{
28210399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
28310399Sstephan.diestelhorst@arm.com            __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
28410399Sstephan.diestelhorst@arm.com
28510821Sandreas.hansson@arm.com    assert(cpkt->isResponse());
28610821Sandreas.hansson@arm.com
28710821Sandreas.hansson@arm.com    if (cpkt->req->isUncacheable())
28810821Sandreas.hansson@arm.com        return;
28910821Sandreas.hansson@arm.com
29010399Sstephan.diestelhorst@arm.com    Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
29110399Sstephan.diestelhorst@arm.com    SnoopMask slave_mask = portToMask(slave_port);
29210399Sstephan.diestelhorst@arm.com    SnoopItem& sf_item = cachedLocations[line_addr];
29310399Sstephan.diestelhorst@arm.com
29410399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
29510399Sstephan.diestelhorst@arm.com            __func__,  sf_item.requested, sf_item.holder);
29610399Sstephan.diestelhorst@arm.com
29710399Sstephan.diestelhorst@arm.com    // Make sure we have seen the actual request, too
29810399Sstephan.diestelhorst@arm.com    panic_if(!(sf_item.requested & slave_mask), "SF value %x.%x missing "\
29910399Sstephan.diestelhorst@arm.com             "request bit\n", sf_item.requested, sf_item.holder);
30010399Sstephan.diestelhorst@arm.com
30110399Sstephan.diestelhorst@arm.com    // Update the residency of the cache line.
30210399Sstephan.diestelhorst@arm.com    if (cpkt->needsExclusive() || !cpkt->sharedAsserted())
30310399Sstephan.diestelhorst@arm.com        sf_item.holder = 0;
30410399Sstephan.diestelhorst@arm.com    sf_item.holder |=  slave_mask;
30510399Sstephan.diestelhorst@arm.com    sf_item.requested &= ~slave_mask;
30610399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
30710399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder);
30810399Sstephan.diestelhorst@arm.com}
30910399Sstephan.diestelhorst@arm.com
31010403Sstephan.diestelhorst@arm.comvoid
31110403Sstephan.diestelhorst@arm.comSnoopFilter::regStats()
31210403Sstephan.diestelhorst@arm.com{
31310403Sstephan.diestelhorst@arm.com    totRequests
31410403Sstephan.diestelhorst@arm.com        .name(name() + ".tot_requests")
31510403Sstephan.diestelhorst@arm.com        .desc("Total number of requests made to the snoop filter.");
31610403Sstephan.diestelhorst@arm.com
31710403Sstephan.diestelhorst@arm.com    hitSingleRequests
31810403Sstephan.diestelhorst@arm.com        .name(name() + ".hit_single_requests")
31910403Sstephan.diestelhorst@arm.com        .desc("Number of requests hitting in the snoop filter with a single "\
32010403Sstephan.diestelhorst@arm.com              "holder of the requested data.");
32110403Sstephan.diestelhorst@arm.com
32210403Sstephan.diestelhorst@arm.com    hitMultiRequests
32310403Sstephan.diestelhorst@arm.com        .name(name() + ".hit_multi_requests")
32410403Sstephan.diestelhorst@arm.com        .desc("Number of requests hitting in the snoop filter with multiple "\
32510403Sstephan.diestelhorst@arm.com              "(>1) holders of the requested data.");
32610403Sstephan.diestelhorst@arm.com
32710403Sstephan.diestelhorst@arm.com    totSnoops
32810403Sstephan.diestelhorst@arm.com        .name(name() + ".tot_snoops")
32910403Sstephan.diestelhorst@arm.com        .desc("Total number of snoops made to the snoop filter.");
33010403Sstephan.diestelhorst@arm.com
33110403Sstephan.diestelhorst@arm.com    hitSingleSnoops
33210403Sstephan.diestelhorst@arm.com        .name(name() + ".hit_single_snoops")
33310403Sstephan.diestelhorst@arm.com        .desc("Number of snoops hitting in the snoop filter with a single "\
33410403Sstephan.diestelhorst@arm.com              "holder of the requested data.");
33510403Sstephan.diestelhorst@arm.com
33610403Sstephan.diestelhorst@arm.com    hitMultiSnoops
33710403Sstephan.diestelhorst@arm.com        .name(name() + ".hit_multi_snoops")
33810403Sstephan.diestelhorst@arm.com        .desc("Number of snoops hitting in the snoop filter with multiple "\
33910403Sstephan.diestelhorst@arm.com              "(>1) holders of the requested data.");
34010403Sstephan.diestelhorst@arm.com}
34110403Sstephan.diestelhorst@arm.com
34210399Sstephan.diestelhorst@arm.comSnoopFilter *
34310399Sstephan.diestelhorst@arm.comSnoopFilterParams::create()
34410399Sstephan.diestelhorst@arm.com{
34510399Sstephan.diestelhorst@arm.com    return new SnoopFilter(this);
34610399Sstephan.diestelhorst@arm.com}
347