snoop_filter.cc revision 11128
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
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
5711128Sali.jafri@arm.com    // Ultimately we should check if the packet came from an
5811128Sali.jafri@arm.com    // allocating source, not just if the port is snooping
5911128Sali.jafri@arm.com    bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping();
6011128Sali.jafri@arm.com    Addr line_addr = cpkt->getBlockAddr(linesize);
6110399Sstephan.diestelhorst@arm.com    SnoopMask req_port = portToMask(slave_port);
6210403Sstephan.diestelhorst@arm.com    auto sf_it = cachedLocations.find(line_addr);
6310403Sstephan.diestelhorst@arm.com    bool is_hit = (sf_it != cachedLocations.end());
6411128Sali.jafri@arm.com
6511128Sali.jafri@arm.com    // If the snoop filter has no entry, and we should not allocate,
6611128Sali.jafri@arm.com    // do not create a new snoop filter entry, simply return a NULL
6711128Sali.jafri@arm.com    // portlist.
6811128Sali.jafri@arm.com    if (!is_hit && !allocate)
6911128Sali.jafri@arm.com        return snoopDown(lookupLatency);
7011128Sali.jafri@arm.com
7110403Sstephan.diestelhorst@arm.com    // Create a new element through operator[] and modify in-place
7210403Sstephan.diestelhorst@arm.com    SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr];
7310403Sstephan.diestelhorst@arm.com    SnoopMask interested = sf_item.holder | sf_item.requested;
7410403Sstephan.diestelhorst@arm.com
7510403Sstephan.diestelhorst@arm.com    totRequests++;
7610403Sstephan.diestelhorst@arm.com    if (is_hit) {
7710403Sstephan.diestelhorst@arm.com        // Single bit set -> value is a power of two
7810403Sstephan.diestelhorst@arm.com        if (isPow2(interested))
7910403Sstephan.diestelhorst@arm.com            hitSingleRequests++;
8010403Sstephan.diestelhorst@arm.com        else
8110403Sstephan.diestelhorst@arm.com            hitMultiRequests++;
8210403Sstephan.diestelhorst@arm.com    }
8310399Sstephan.diestelhorst@arm.com
8410399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   SF value %x.%x\n",
8510399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder);
8610399Sstephan.diestelhorst@arm.com
8711128Sali.jafri@arm.com    if (allocate && cpkt->needsResponse()) {
8810399Sstephan.diestelhorst@arm.com        if (!cpkt->memInhibitAsserted()) {
8910399Sstephan.diestelhorst@arm.com            // Max one request per address per port
9010399Sstephan.diestelhorst@arm.com            panic_if(sf_item.requested & req_port, "double request :( "\
9110399Sstephan.diestelhorst@arm.com                     "SF value %x.%x\n", sf_item.requested, sf_item.holder);
9210399Sstephan.diestelhorst@arm.com
9310399Sstephan.diestelhorst@arm.com            // Mark in-flight requests to distinguish later on
9410399Sstephan.diestelhorst@arm.com            sf_item.requested |= req_port;
9510399Sstephan.diestelhorst@arm.com        } else {
9610399Sstephan.diestelhorst@arm.com            // NOTE: The memInhibit might have been asserted by a cache closer
9710399Sstephan.diestelhorst@arm.com            // to the CPU, already -> the response will not be seen by this
9810399Sstephan.diestelhorst@arm.com            // filter -> we do not need to keep the in-flight request, but make
9910399Sstephan.diestelhorst@arm.com            // sure that we know that that cluster has a copy
10010399Sstephan.diestelhorst@arm.com            panic_if(!(sf_item.holder & req_port), "Need to hold the value!");
10110399Sstephan.diestelhorst@arm.com            DPRINTF(SnoopFilter, "%s:   not marking request. SF value %x.%x\n",
10210399Sstephan.diestelhorst@arm.com                    __func__,  sf_item.requested, sf_item.holder);
10310399Sstephan.diestelhorst@arm.com        }
10410399Sstephan.diestelhorst@arm.com        DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
10510399Sstephan.diestelhorst@arm.com                __func__,  sf_item.requested, sf_item.holder);
10610399Sstephan.diestelhorst@arm.com    }
10710403Sstephan.diestelhorst@arm.com    return snoopSelected(maskToPortList(interested & ~req_port), lookupLatency);
10810399Sstephan.diestelhorst@arm.com}
10910399Sstephan.diestelhorst@arm.com
11010399Sstephan.diestelhorst@arm.comvoid
11110399Sstephan.diestelhorst@arm.comSnoopFilter::updateRequest(const Packet* cpkt, const SlavePort& slave_port,
11210399Sstephan.diestelhorst@arm.com                           bool will_retry)
11310399Sstephan.diestelhorst@arm.com{
11410399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
11510399Sstephan.diestelhorst@arm.com            __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
11610399Sstephan.diestelhorst@arm.com
11711128Sali.jafri@arm.com    // Ultimately we should check if the packet came from an
11811128Sali.jafri@arm.com    // allocating source, not just if the port is snooping
11911128Sali.jafri@arm.com    bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping();
12011128Sali.jafri@arm.com    if (!allocate)
12110821Sandreas.hansson@arm.com        return;
12210821Sandreas.hansson@arm.com
12311128Sali.jafri@arm.com    Addr line_addr = cpkt->getBlockAddr(linesize);
12410399Sstephan.diestelhorst@arm.com    SnoopMask req_port = portToMask(slave_port);
12510399Sstephan.diestelhorst@arm.com    SnoopItem& sf_item  = cachedLocations[line_addr];
12610399Sstephan.diestelhorst@arm.com
12710399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x retry: %i\n",
12810399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder, will_retry);
12910399Sstephan.diestelhorst@arm.com
13010399Sstephan.diestelhorst@arm.com    if (will_retry) {
13110399Sstephan.diestelhorst@arm.com        // Unmark a request that will come again.
13210399Sstephan.diestelhorst@arm.com        sf_item.requested &= ~req_port;
13310399Sstephan.diestelhorst@arm.com        return;
13410399Sstephan.diestelhorst@arm.com    }
13510399Sstephan.diestelhorst@arm.com
13610399Sstephan.diestelhorst@arm.com    // will_retry == false
13710399Sstephan.diestelhorst@arm.com    if (!cpkt->needsResponse()) {
13810399Sstephan.diestelhorst@arm.com        // Packets that will not evoke a response but still need updates of the
13910399Sstephan.diestelhorst@arm.com        // snoop filter; WRITEBACKs for now only
14010399Sstephan.diestelhorst@arm.com        if (cpkt->cmd == MemCmd::Writeback) {
14110399Sstephan.diestelhorst@arm.com            // make sure that the sender actually had the line
14210399Sstephan.diestelhorst@arm.com            panic_if(sf_item.requested & req_port, "double request :( "\
14310399Sstephan.diestelhorst@arm.com                     "SF value %x.%x\n", sf_item.requested, sf_item.holder);
14410399Sstephan.diestelhorst@arm.com            panic_if(!(sf_item.holder & req_port), "requester %x is not a "\
14510399Sstephan.diestelhorst@arm.com                     "holder :( SF value %x.%x\n", req_port,
14610399Sstephan.diestelhorst@arm.com                     sf_item.requested, sf_item.holder);
14710399Sstephan.diestelhorst@arm.com            // Writebacks -> the sender does not have the line anymore
14810399Sstephan.diestelhorst@arm.com            sf_item.holder &= ~req_port;
14910399Sstephan.diestelhorst@arm.com        } else {
15010883Sali.jafri@arm.com            // @todo Add CleanEvicts
15110883Sali.jafri@arm.com            assert(cpkt->cmd == MemCmd::CleanEvict);
15210399Sstephan.diestelhorst@arm.com        }
15310399Sstephan.diestelhorst@arm.com        DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
15410399Sstephan.diestelhorst@arm.com                __func__,  sf_item.requested, sf_item.holder);
15510399Sstephan.diestelhorst@arm.com    }
15610399Sstephan.diestelhorst@arm.com}
15710399Sstephan.diestelhorst@arm.com
15810399Sstephan.diestelhorst@arm.comstd::pair<SnoopFilter::SnoopList, Cycles>
15910399Sstephan.diestelhorst@arm.comSnoopFilter::lookupSnoop(const Packet* cpkt)
16010399Sstephan.diestelhorst@arm.com{
16110399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s: packet addr 0x%x cmd %s\n",
16210399Sstephan.diestelhorst@arm.com            __func__, cpkt->getAddr(), cpkt->cmdString());
16310399Sstephan.diestelhorst@arm.com
16410399Sstephan.diestelhorst@arm.com    assert(cpkt->isRequest());
16510399Sstephan.diestelhorst@arm.com
16610399Sstephan.diestelhorst@arm.com    // Broadcast / filter upward snoops
16710399Sstephan.diestelhorst@arm.com    const bool filter_upward = true;  // @todo: Make configurable
16810399Sstephan.diestelhorst@arm.com
16910399Sstephan.diestelhorst@arm.com    if (!filter_upward)
17010399Sstephan.diestelhorst@arm.com        return snoopAll(lookupLatency);
17110399Sstephan.diestelhorst@arm.com
17211128Sali.jafri@arm.com    Addr line_addr = cpkt->getBlockAddr(linesize);
17310403Sstephan.diestelhorst@arm.com    auto sf_it = cachedLocations.find(line_addr);
17410403Sstephan.diestelhorst@arm.com    bool is_hit = (sf_it != cachedLocations.end());
17510403Sstephan.diestelhorst@arm.com    // Create a new element through operator[] and modify in-place
17610403Sstephan.diestelhorst@arm.com    SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr];
17710399Sstephan.diestelhorst@arm.com
17810399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
17910399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder);
18010399Sstephan.diestelhorst@arm.com
18110399Sstephan.diestelhorst@arm.com    SnoopMask interested = (sf_item.holder | sf_item.requested);
18210403Sstephan.diestelhorst@arm.com
18310403Sstephan.diestelhorst@arm.com    totSnoops++;
18410403Sstephan.diestelhorst@arm.com    if (is_hit) {
18510403Sstephan.diestelhorst@arm.com        // Single bit set -> value is a power of two
18610403Sstephan.diestelhorst@arm.com        if (isPow2(interested))
18710403Sstephan.diestelhorst@arm.com            hitSingleSnoops++;
18810403Sstephan.diestelhorst@arm.com        else
18910403Sstephan.diestelhorst@arm.com            hitMultiSnoops++;
19010403Sstephan.diestelhorst@arm.com    }
19110883Sali.jafri@arm.com    // ReadEx and Writes require both invalidation and exlusivity, while reads
19210883Sali.jafri@arm.com    // require neither. Writebacks on the other hand require exclusivity but
19310883Sali.jafri@arm.com    // not the invalidation. Previously Writebacks did not generate upward
19410883Sali.jafri@arm.com    // snoops so this was never an aissue. Now that Writebacks generate snoops
19510883Sali.jafri@arm.com    // we need to special case for Writebacks.
19610883Sali.jafri@arm.com    assert(cpkt->cmd == MemCmd::Writeback ||
19710883Sali.jafri@arm.com           (cpkt->isInvalidate() == cpkt->needsExclusive()));
19810399Sstephan.diestelhorst@arm.com    if (cpkt->isInvalidate() && !sf_item.requested) {
19910399Sstephan.diestelhorst@arm.com        // Early clear of the holder, if no other request is currently going on
20010399Sstephan.diestelhorst@arm.com        // @todo: This should possibly be updated even though we do not filter
20110399Sstephan.diestelhorst@arm.com        // upward snoops
20210399Sstephan.diestelhorst@arm.com        sf_item.holder = 0;
20310399Sstephan.diestelhorst@arm.com    }
20410399Sstephan.diestelhorst@arm.com
20510399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   new SF value %x.%x interest: %x \n",
20610399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder, interested);
20710399Sstephan.diestelhorst@arm.com
20810399Sstephan.diestelhorst@arm.com    return snoopSelected(maskToPortList(interested), lookupLatency);
20910399Sstephan.diestelhorst@arm.com}
21010399Sstephan.diestelhorst@arm.com
21110399Sstephan.diestelhorst@arm.comvoid
21210399Sstephan.diestelhorst@arm.comSnoopFilter::updateSnoopResponse(const Packet* cpkt,
21310399Sstephan.diestelhorst@arm.com                                 const SlavePort& rsp_port,
21410399Sstephan.diestelhorst@arm.com                                 const SlavePort& req_port)
21510399Sstephan.diestelhorst@arm.com{
21610399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n",
21710399Sstephan.diestelhorst@arm.com            __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
21810399Sstephan.diestelhorst@arm.com            cpkt->cmdString());
21910399Sstephan.diestelhorst@arm.com
22010821Sandreas.hansson@arm.com    assert(cpkt->isResponse());
22110821Sandreas.hansson@arm.com    assert(cpkt->memInhibitAsserted());
22210821Sandreas.hansson@arm.com
22311128Sali.jafri@arm.com    // Ultimately we should check if the packet came from an
22411128Sali.jafri@arm.com    // allocating source, not just if the port is snooping
22511128Sali.jafri@arm.com    bool allocate = !cpkt->req->isUncacheable() && req_port.isSnooping();
22611128Sali.jafri@arm.com    if (!allocate)
22710821Sandreas.hansson@arm.com        return;
22810821Sandreas.hansson@arm.com
22911128Sali.jafri@arm.com    Addr line_addr = cpkt->getBlockAddr(linesize);
23010399Sstephan.diestelhorst@arm.com    SnoopMask rsp_mask = portToMask(rsp_port);
23110399Sstephan.diestelhorst@arm.com    SnoopMask req_mask = portToMask(req_port);
23210399Sstephan.diestelhorst@arm.com    SnoopItem& sf_item = cachedLocations[line_addr];
23310399Sstephan.diestelhorst@arm.com
23410399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
23510399Sstephan.diestelhorst@arm.com            __func__,  sf_item.requested, sf_item.holder);
23610399Sstephan.diestelhorst@arm.com
23710399Sstephan.diestelhorst@arm.com    // The source should have the line
23810399Sstephan.diestelhorst@arm.com    panic_if(!(sf_item.holder & rsp_mask), "SF value %x.%x does not have "\
23910399Sstephan.diestelhorst@arm.com             "the line\n", sf_item.requested, sf_item.holder);
24010399Sstephan.diestelhorst@arm.com
24110399Sstephan.diestelhorst@arm.com    // The destination should have had a request in
24210399Sstephan.diestelhorst@arm.com    panic_if(!(sf_item.requested & req_mask), "SF value %x.%x missing "\
24310399Sstephan.diestelhorst@arm.com             "the original request\n",  sf_item.requested, sf_item.holder);
24410399Sstephan.diestelhorst@arm.com
24510399Sstephan.diestelhorst@arm.com    // Update the residency of the cache line.
24610399Sstephan.diestelhorst@arm.com    if (cpkt->needsExclusive() || !cpkt->sharedAsserted()) {
24710399Sstephan.diestelhorst@arm.com        DPRINTF(SnoopFilter, "%s:  dropping %x because needs: %i shared: %i "\
24810399Sstephan.diestelhorst@arm.com                "SF val: %x.%x\n", __func__,  rsp_mask,
24910399Sstephan.diestelhorst@arm.com                cpkt->needsExclusive(), cpkt->sharedAsserted(),
25010399Sstephan.diestelhorst@arm.com                sf_item.requested, sf_item.holder);
25110399Sstephan.diestelhorst@arm.com
25210399Sstephan.diestelhorst@arm.com        sf_item.holder &= ~rsp_mask;
25310399Sstephan.diestelhorst@arm.com        // The snoop filter does not see any ACKs from non-responding sharers
25410399Sstephan.diestelhorst@arm.com        // that have been invalidated :(  So below assert would be nice, but..
25510399Sstephan.diestelhorst@arm.com        //assert(sf_item.holder == 0);
25610399Sstephan.diestelhorst@arm.com        sf_item.holder = 0;
25710399Sstephan.diestelhorst@arm.com    }
25810399Sstephan.diestelhorst@arm.com    assert(cpkt->cmd != MemCmd::Writeback);
25910399Sstephan.diestelhorst@arm.com    sf_item.holder |=  req_mask;
26010399Sstephan.diestelhorst@arm.com    sf_item.requested &= ~req_mask;
26110399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
26210399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder);
26310399Sstephan.diestelhorst@arm.com}
26410399Sstephan.diestelhorst@arm.com
26510399Sstephan.diestelhorst@arm.comvoid
26610399Sstephan.diestelhorst@arm.comSnoopFilter::updateSnoopForward(const Packet* cpkt,
26710399Sstephan.diestelhorst@arm.com        const SlavePort& rsp_port, const MasterPort& req_port)
26810399Sstephan.diestelhorst@arm.com{
26910399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n",
27010399Sstephan.diestelhorst@arm.com            __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
27110399Sstephan.diestelhorst@arm.com            cpkt->cmdString());
27210399Sstephan.diestelhorst@arm.com
27311128Sali.jafri@arm.com    Addr line_addr = cpkt->getBlockAddr(linesize);
27410399Sstephan.diestelhorst@arm.com    SnoopItem& sf_item = cachedLocations[line_addr];
27510399Sstephan.diestelhorst@arm.com    SnoopMask rsp_mask M5_VAR_USED = portToMask(rsp_port);
27610399Sstephan.diestelhorst@arm.com
27710399Sstephan.diestelhorst@arm.com    assert(cpkt->isResponse());
27810399Sstephan.diestelhorst@arm.com    assert(cpkt->memInhibitAsserted());
27910399Sstephan.diestelhorst@arm.com
28010399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
28110399Sstephan.diestelhorst@arm.com            __func__,  sf_item.requested, sf_item.holder);
28210399Sstephan.diestelhorst@arm.com
28310399Sstephan.diestelhorst@arm.com    // Remote (to this snoop filter) snoops update the filter already when they
28410399Sstephan.diestelhorst@arm.com    // arrive from below, because we may not see any response.
28510399Sstephan.diestelhorst@arm.com    if (cpkt->needsExclusive()) {
28610399Sstephan.diestelhorst@arm.com        // If the request to this snoop response hit an in-flight transaction,
28710399Sstephan.diestelhorst@arm.com        // the holder was not reset -> no assertion & do that here, now!
28810399Sstephan.diestelhorst@arm.com        //assert(sf_item.holder == 0);
28910399Sstephan.diestelhorst@arm.com        sf_item.holder = 0;
29010399Sstephan.diestelhorst@arm.com    }
29110399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
29210399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder);
29310399Sstephan.diestelhorst@arm.com}
29410399Sstephan.diestelhorst@arm.com
29510399Sstephan.diestelhorst@arm.comvoid
29610399Sstephan.diestelhorst@arm.comSnoopFilter::updateResponse(const Packet* cpkt, const SlavePort& slave_port)
29710399Sstephan.diestelhorst@arm.com{
29810399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
29910399Sstephan.diestelhorst@arm.com            __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
30010399Sstephan.diestelhorst@arm.com
30110821Sandreas.hansson@arm.com    assert(cpkt->isResponse());
30210821Sandreas.hansson@arm.com
30311128Sali.jafri@arm.com    // Ultimately we should check if the packet came from an
30411128Sali.jafri@arm.com    // allocating source, not just if the port is snooping
30511128Sali.jafri@arm.com    bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping();
30611128Sali.jafri@arm.com    if (!allocate)
30710821Sandreas.hansson@arm.com        return;
30810821Sandreas.hansson@arm.com
30911128Sali.jafri@arm.com    Addr line_addr = cpkt->getBlockAddr(linesize);
31010399Sstephan.diestelhorst@arm.com    SnoopMask slave_mask = portToMask(slave_port);
31110399Sstephan.diestelhorst@arm.com    SnoopItem& sf_item = cachedLocations[line_addr];
31210399Sstephan.diestelhorst@arm.com
31310399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   old SF value %x.%x\n",
31410399Sstephan.diestelhorst@arm.com            __func__,  sf_item.requested, sf_item.holder);
31510399Sstephan.diestelhorst@arm.com
31610399Sstephan.diestelhorst@arm.com    // Make sure we have seen the actual request, too
31710399Sstephan.diestelhorst@arm.com    panic_if(!(sf_item.requested & slave_mask), "SF value %x.%x missing "\
31810399Sstephan.diestelhorst@arm.com             "request bit\n", sf_item.requested, sf_item.holder);
31910399Sstephan.diestelhorst@arm.com
32010399Sstephan.diestelhorst@arm.com    // Update the residency of the cache line.
32110399Sstephan.diestelhorst@arm.com    if (cpkt->needsExclusive() || !cpkt->sharedAsserted())
32210399Sstephan.diestelhorst@arm.com        sf_item.holder = 0;
32310399Sstephan.diestelhorst@arm.com    sf_item.holder |=  slave_mask;
32410399Sstephan.diestelhorst@arm.com    sf_item.requested &= ~slave_mask;
32510399Sstephan.diestelhorst@arm.com    DPRINTF(SnoopFilter, "%s:   new SF value %x.%x\n",
32610399Sstephan.diestelhorst@arm.com            __func__, sf_item.requested, sf_item.holder);
32710399Sstephan.diestelhorst@arm.com}
32810399Sstephan.diestelhorst@arm.com
32910403Sstephan.diestelhorst@arm.comvoid
33010403Sstephan.diestelhorst@arm.comSnoopFilter::regStats()
33110403Sstephan.diestelhorst@arm.com{
33210403Sstephan.diestelhorst@arm.com    totRequests
33310403Sstephan.diestelhorst@arm.com        .name(name() + ".tot_requests")
33410403Sstephan.diestelhorst@arm.com        .desc("Total number of requests made to the snoop filter.");
33510403Sstephan.diestelhorst@arm.com
33610403Sstephan.diestelhorst@arm.com    hitSingleRequests
33710403Sstephan.diestelhorst@arm.com        .name(name() + ".hit_single_requests")
33810403Sstephan.diestelhorst@arm.com        .desc("Number of requests hitting in the snoop filter with a single "\
33910403Sstephan.diestelhorst@arm.com              "holder of the requested data.");
34010403Sstephan.diestelhorst@arm.com
34110403Sstephan.diestelhorst@arm.com    hitMultiRequests
34210403Sstephan.diestelhorst@arm.com        .name(name() + ".hit_multi_requests")
34310403Sstephan.diestelhorst@arm.com        .desc("Number of requests hitting in the snoop filter with multiple "\
34410403Sstephan.diestelhorst@arm.com              "(>1) holders of the requested data.");
34510403Sstephan.diestelhorst@arm.com
34610403Sstephan.diestelhorst@arm.com    totSnoops
34710403Sstephan.diestelhorst@arm.com        .name(name() + ".tot_snoops")
34810403Sstephan.diestelhorst@arm.com        .desc("Total number of snoops made to the snoop filter.");
34910403Sstephan.diestelhorst@arm.com
35010403Sstephan.diestelhorst@arm.com    hitSingleSnoops
35110403Sstephan.diestelhorst@arm.com        .name(name() + ".hit_single_snoops")
35210403Sstephan.diestelhorst@arm.com        .desc("Number of snoops hitting in the snoop filter with a single "\
35310403Sstephan.diestelhorst@arm.com              "holder of the requested data.");
35410403Sstephan.diestelhorst@arm.com
35510403Sstephan.diestelhorst@arm.com    hitMultiSnoops
35610403Sstephan.diestelhorst@arm.com        .name(name() + ".hit_multi_snoops")
35710403Sstephan.diestelhorst@arm.com        .desc("Number of snoops hitting in the snoop filter with multiple "\
35810403Sstephan.diestelhorst@arm.com              "(>1) holders of the requested data.");
35910403Sstephan.diestelhorst@arm.com}
36010403Sstephan.diestelhorst@arm.com
36110399Sstephan.diestelhorst@arm.comSnoopFilter *
36210399Sstephan.diestelhorst@arm.comSnoopFilterParams::create()
36310399Sstephan.diestelhorst@arm.com{
36410399Sstephan.diestelhorst@arm.com    return new SnoopFilter(this);
36510399Sstephan.diestelhorst@arm.com}
366