cache.cc revision 13945
112027Sjungma@eit.uni-kl.de/*
212027Sjungma@eit.uni-kl.de * Copyright (c) 2010-2019 ARM Limited
312027Sjungma@eit.uni-kl.de * All rights reserved.
412027Sjungma@eit.uni-kl.de *
512027Sjungma@eit.uni-kl.de * The license below extends only to copyright in the software and shall
612027Sjungma@eit.uni-kl.de * not be construed as granting a license to any other intellectual
712027Sjungma@eit.uni-kl.de * property including but not limited to intellectual property relating
812027Sjungma@eit.uni-kl.de * to a hardware implementation of the functionality of the software
912027Sjungma@eit.uni-kl.de * licensed hereunder.  You may use the software subject to the license
1012027Sjungma@eit.uni-kl.de * terms below provided that you ensure that this notice is replicated
1112027Sjungma@eit.uni-kl.de * unmodified and in its entirety in all distributions of the software,
1212027Sjungma@eit.uni-kl.de * modified or unmodified, in source code or in binary form.
1312027Sjungma@eit.uni-kl.de *
1412027Sjungma@eit.uni-kl.de * Copyright (c) 2002-2005 The Regents of The University of Michigan
1512027Sjungma@eit.uni-kl.de * Copyright (c) 2010,2015 Advanced Micro Devices, Inc.
1612027Sjungma@eit.uni-kl.de * All rights reserved.
1712027Sjungma@eit.uni-kl.de *
1812027Sjungma@eit.uni-kl.de * Redistribution and use in source and binary forms, with or without
1912027Sjungma@eit.uni-kl.de * modification, are permitted provided that the following conditions are
2012027Sjungma@eit.uni-kl.de * met: redistributions of source code must retain the above copyright
2112027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer;
2212027Sjungma@eit.uni-kl.de * redistributions in binary form must reproduce the above copyright
2312027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer in the
2412027Sjungma@eit.uni-kl.de * documentation and/or other materials provided with the distribution;
2512027Sjungma@eit.uni-kl.de * neither the name of the copyright holders nor the names of its
2612027Sjungma@eit.uni-kl.de * contributors may be used to endorse or promote products derived from
2712027Sjungma@eit.uni-kl.de * this software without specific prior written permission.
2812027Sjungma@eit.uni-kl.de *
2912027Sjungma@eit.uni-kl.de * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3012027Sjungma@eit.uni-kl.de * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3112027Sjungma@eit.uni-kl.de * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3212027Sjungma@eit.uni-kl.de * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3312027Sjungma@eit.uni-kl.de * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3412027Sjungma@eit.uni-kl.de * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3512027Sjungma@eit.uni-kl.de * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3612027Sjungma@eit.uni-kl.de * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3712027Sjungma@eit.uni-kl.de * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3812027Sjungma@eit.uni-kl.de * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3912027Sjungma@eit.uni-kl.de * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4012027Sjungma@eit.uni-kl.de *
4112027Sjungma@eit.uni-kl.de * Authors: Erik Hallnor
4212027Sjungma@eit.uni-kl.de *          Dave Greene
4312027Sjungma@eit.uni-kl.de *          Nathan Binkert
4412027Sjungma@eit.uni-kl.de *          Steve Reinhardt
4512027Sjungma@eit.uni-kl.de *          Ron Dreslinski
4612027Sjungma@eit.uni-kl.de *          Andreas Sandberg
4712027Sjungma@eit.uni-kl.de *          Nikos Nikoleris
4812027Sjungma@eit.uni-kl.de */
4912027Sjungma@eit.uni-kl.de
5012027Sjungma@eit.uni-kl.de/**
5112027Sjungma@eit.uni-kl.de * @file
5212027Sjungma@eit.uni-kl.de * Cache definitions.
5312027Sjungma@eit.uni-kl.de */
5412027Sjungma@eit.uni-kl.de
5512027Sjungma@eit.uni-kl.de#include "mem/cache/cache.hh"
5612027Sjungma@eit.uni-kl.de
5712027Sjungma@eit.uni-kl.de#include <cassert>
5812027Sjungma@eit.uni-kl.de
5912027Sjungma@eit.uni-kl.de#include "base/compiler.hh"
6012027Sjungma@eit.uni-kl.de#include "base/logging.hh"
6112027Sjungma@eit.uni-kl.de#include "base/trace.hh"
6212027Sjungma@eit.uni-kl.de#include "base/types.hh"
6312027Sjungma@eit.uni-kl.de#include "debug/Cache.hh"
6412027Sjungma@eit.uni-kl.de#include "debug/CacheTags.hh"
6512027Sjungma@eit.uni-kl.de#include "debug/CacheVerbose.hh"
6612027Sjungma@eit.uni-kl.de#include "enums/Clusivity.hh"
6712027Sjungma@eit.uni-kl.de#include "mem/cache/cache_blk.hh"
6812027Sjungma@eit.uni-kl.de#include "mem/cache/mshr.hh"
6912027Sjungma@eit.uni-kl.de#include "mem/cache/tags/base.hh"
7012027Sjungma@eit.uni-kl.de#include "mem/cache/write_queue_entry.hh"
7112027Sjungma@eit.uni-kl.de#include "mem/request.hh"
7212027Sjungma@eit.uni-kl.de#include "params/Cache.hh"
7312027Sjungma@eit.uni-kl.de
7412027Sjungma@eit.uni-kl.deCache::Cache(const CacheParams *p)
7512027Sjungma@eit.uni-kl.de    : BaseCache(p, p->system->cacheLineSize()),
7612027Sjungma@eit.uni-kl.de      doFastWrites(true)
7712027Sjungma@eit.uni-kl.de{
7812027Sjungma@eit.uni-kl.de}
7912027Sjungma@eit.uni-kl.de
8012027Sjungma@eit.uni-kl.devoid
8112027Sjungma@eit.uni-kl.deCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk,
8212027Sjungma@eit.uni-kl.de                      bool deferred_response, bool pending_downgrade)
8312027Sjungma@eit.uni-kl.de{
8412027Sjungma@eit.uni-kl.de    BaseCache::satisfyRequest(pkt, blk);
8512027Sjungma@eit.uni-kl.de
8612027Sjungma@eit.uni-kl.de    if (pkt->isRead()) {
8712027Sjungma@eit.uni-kl.de        // determine if this read is from a (coherent) cache or not
8812027Sjungma@eit.uni-kl.de        if (pkt->fromCache()) {
8912027Sjungma@eit.uni-kl.de            assert(pkt->getSize() == blkSize);
9012027Sjungma@eit.uni-kl.de            // special handling for coherent block requests from
9112027Sjungma@eit.uni-kl.de            // upper-level caches
9212027Sjungma@eit.uni-kl.de            if (pkt->needsWritable()) {
9312027Sjungma@eit.uni-kl.de                // sanity check
9412027Sjungma@eit.uni-kl.de                assert(pkt->cmd == MemCmd::ReadExReq ||
9512027Sjungma@eit.uni-kl.de                       pkt->cmd == MemCmd::SCUpgradeFailReq);
9612027Sjungma@eit.uni-kl.de                assert(!pkt->hasSharers());
9712027Sjungma@eit.uni-kl.de
9812027Sjungma@eit.uni-kl.de                // if we have a dirty copy, make sure the recipient
9912027Sjungma@eit.uni-kl.de                // keeps it marked dirty (in the modified state)
10012027Sjungma@eit.uni-kl.de                if (blk->isDirty()) {
10112027Sjungma@eit.uni-kl.de                    pkt->setCacheResponding();
10212027Sjungma@eit.uni-kl.de                    blk->status &= ~BlkDirty;
10312027Sjungma@eit.uni-kl.de                }
10412027Sjungma@eit.uni-kl.de            } else if (blk->isWritable() && !pending_downgrade &&
10512027Sjungma@eit.uni-kl.de                       !pkt->hasSharers() &&
10612027Sjungma@eit.uni-kl.de                       pkt->cmd != MemCmd::ReadCleanReq) {
10712027Sjungma@eit.uni-kl.de                // we can give the requester a writable copy on a read
10812027Sjungma@eit.uni-kl.de                // request if:
10912027Sjungma@eit.uni-kl.de                // - we have a writable copy at this level (& below)
11012027Sjungma@eit.uni-kl.de                // - we don't have a pending snoop from below
11112027Sjungma@eit.uni-kl.de                //   signaling another read request
11212027Sjungma@eit.uni-kl.de                // - no other cache above has a copy (otherwise it
11312027Sjungma@eit.uni-kl.de                //   would have set hasSharers flag when
11412027Sjungma@eit.uni-kl.de                //   snooping the packet)
11512027Sjungma@eit.uni-kl.de                // - the read has explicitly asked for a clean
11612027Sjungma@eit.uni-kl.de                //   copy of the line
11712027Sjungma@eit.uni-kl.de                if (blk->isDirty()) {
11812027Sjungma@eit.uni-kl.de                    // special considerations if we're owner:
11912027Sjungma@eit.uni-kl.de                    if (!deferred_response) {
12012027Sjungma@eit.uni-kl.de                        // respond with the line in Modified state
12112027Sjungma@eit.uni-kl.de                        // (cacheResponding set, hasSharers not set)
12212027Sjungma@eit.uni-kl.de                        pkt->setCacheResponding();
12312027Sjungma@eit.uni-kl.de
12412027Sjungma@eit.uni-kl.de                        // if this cache is mostly inclusive, we
12512027Sjungma@eit.uni-kl.de                        // keep the block in the Exclusive state,
12612027Sjungma@eit.uni-kl.de                        // and pass it upwards as Modified
12712027Sjungma@eit.uni-kl.de                        // (writable and dirty), hence we have
12812027Sjungma@eit.uni-kl.de                        // multiple caches, all on the same path
12912027Sjungma@eit.uni-kl.de                        // towards memory, all considering the
13012027Sjungma@eit.uni-kl.de                        // same block writable, but only one
13112027Sjungma@eit.uni-kl.de                        // considering it Modified
13212027Sjungma@eit.uni-kl.de
13312027Sjungma@eit.uni-kl.de                        // we get away with multiple caches (on
13412027Sjungma@eit.uni-kl.de                        // the same path to memory) considering
13512027Sjungma@eit.uni-kl.de                        // the block writeable as we always enter
13612027Sjungma@eit.uni-kl.de                        // the cache hierarchy through a cache,
13712027Sjungma@eit.uni-kl.de                        // and first snoop upwards in all other
13812027Sjungma@eit.uni-kl.de                        // branches
13912027Sjungma@eit.uni-kl.de                        blk->status &= ~BlkDirty;
14012027Sjungma@eit.uni-kl.de                    } else {
14112027Sjungma@eit.uni-kl.de                        // if we're responding after our own miss,
14212027Sjungma@eit.uni-kl.de                        // there's a window where the recipient didn't
14312027Sjungma@eit.uni-kl.de                        // know it was getting ownership and may not
14412027Sjungma@eit.uni-kl.de                        // have responded to snoops correctly, so we
14512027Sjungma@eit.uni-kl.de                        // have to respond with a shared line
14612027Sjungma@eit.uni-kl.de                        pkt->setHasSharers();
14712027Sjungma@eit.uni-kl.de                    }
14812027Sjungma@eit.uni-kl.de                }
14912027Sjungma@eit.uni-kl.de            } else {
15012027Sjungma@eit.uni-kl.de                // otherwise only respond with a shared copy
15112027Sjungma@eit.uni-kl.de                pkt->setHasSharers();
15212027Sjungma@eit.uni-kl.de            }
15312027Sjungma@eit.uni-kl.de        }
15412027Sjungma@eit.uni-kl.de    }
15512027Sjungma@eit.uni-kl.de}
15612027Sjungma@eit.uni-kl.de
15712027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////
15812027Sjungma@eit.uni-kl.de//
15912027Sjungma@eit.uni-kl.de// Access path: requests coming in from the CPU side
16012027Sjungma@eit.uni-kl.de//
16112027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////
16212027Sjungma@eit.uni-kl.de
16312027Sjungma@eit.uni-kl.debool
16412027Sjungma@eit.uni-kl.deCache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat,
16512027Sjungma@eit.uni-kl.de              PacketList &writebacks)
16612027Sjungma@eit.uni-kl.de{
16712027Sjungma@eit.uni-kl.de
16812027Sjungma@eit.uni-kl.de    if (pkt->req->isUncacheable()) {
16912027Sjungma@eit.uni-kl.de        assert(pkt->isRequest());
17012027Sjungma@eit.uni-kl.de
17112027Sjungma@eit.uni-kl.de        chatty_assert(!(isReadOnly && pkt->isWrite()),
17212027Sjungma@eit.uni-kl.de                      "Should never see a write in a read-only cache %s\n",
17312027Sjungma@eit.uni-kl.de                      name());
17412027Sjungma@eit.uni-kl.de
17512027Sjungma@eit.uni-kl.de        DPRINTF(Cache, "%s for %s\n", __func__, pkt->print());
17612027Sjungma@eit.uni-kl.de
17712027Sjungma@eit.uni-kl.de        // flush and invalidate any existing block
17812027Sjungma@eit.uni-kl.de        CacheBlk *old_blk(tags->findBlock(pkt->getAddr(), pkt->isSecure()));
17912027Sjungma@eit.uni-kl.de        if (old_blk && old_blk->isValid()) {
18012027Sjungma@eit.uni-kl.de            BaseCache::evictBlock(old_blk, writebacks);
18112027Sjungma@eit.uni-kl.de        }
18212027Sjungma@eit.uni-kl.de
18312027Sjungma@eit.uni-kl.de        blk = nullptr;
18412027Sjungma@eit.uni-kl.de        // lookupLatency is the latency in case the request is uncacheable.
18512027Sjungma@eit.uni-kl.de        lat = lookupLatency;
18612027Sjungma@eit.uni-kl.de        return false;
18712027Sjungma@eit.uni-kl.de    }
18812027Sjungma@eit.uni-kl.de
18912027Sjungma@eit.uni-kl.de    return BaseCache::access(pkt, blk, lat, writebacks);
19012027Sjungma@eit.uni-kl.de}
19112027Sjungma@eit.uni-kl.de
19212027Sjungma@eit.uni-kl.devoid
19312027Sjungma@eit.uni-kl.deCache::doWritebacks(PacketList& writebacks, Tick forward_time)
19412027Sjungma@eit.uni-kl.de{
19512027Sjungma@eit.uni-kl.de    while (!writebacks.empty()) {
19612027Sjungma@eit.uni-kl.de        PacketPtr wbPkt = writebacks.front();
19712027Sjungma@eit.uni-kl.de        // We use forwardLatency here because we are copying writebacks to
19812027Sjungma@eit.uni-kl.de        // write buffer.
19912027Sjungma@eit.uni-kl.de
20012027Sjungma@eit.uni-kl.de        // Call isCachedAbove for Writebacks, CleanEvicts and
20112027Sjungma@eit.uni-kl.de        // WriteCleans to discover if the block is cached above.
20212027Sjungma@eit.uni-kl.de        if (isCachedAbove(wbPkt)) {
20312027Sjungma@eit.uni-kl.de            if (wbPkt->cmd == MemCmd::CleanEvict) {
20412027Sjungma@eit.uni-kl.de                // Delete CleanEvict because cached copies exist above. The
20512027Sjungma@eit.uni-kl.de                // packet destructor will delete the request object because
20612027Sjungma@eit.uni-kl.de                // this is a non-snoop request packet which does not require a
20712027Sjungma@eit.uni-kl.de                // response.
20812027Sjungma@eit.uni-kl.de                delete wbPkt;
20912027Sjungma@eit.uni-kl.de            } else if (wbPkt->cmd == MemCmd::WritebackClean) {
21012027Sjungma@eit.uni-kl.de                // clean writeback, do not send since the block is
21112027Sjungma@eit.uni-kl.de                // still cached above
21212027Sjungma@eit.uni-kl.de                assert(writebackClean);
21312027Sjungma@eit.uni-kl.de                delete wbPkt;
21412027Sjungma@eit.uni-kl.de            } else {
21512027Sjungma@eit.uni-kl.de                assert(wbPkt->cmd == MemCmd::WritebackDirty ||
21612027Sjungma@eit.uni-kl.de                       wbPkt->cmd == MemCmd::WriteClean);
21712027Sjungma@eit.uni-kl.de                // Set BLOCK_CACHED flag in Writeback and send below, so that
21812027Sjungma@eit.uni-kl.de                // the Writeback does not reset the bit corresponding to this
21912027Sjungma@eit.uni-kl.de                // address in the snoop filter below.
22012027Sjungma@eit.uni-kl.de                wbPkt->setBlockCached();
22112027Sjungma@eit.uni-kl.de                allocateWriteBuffer(wbPkt, forward_time);
22212027Sjungma@eit.uni-kl.de            }
22312027Sjungma@eit.uni-kl.de        } else {
22412027Sjungma@eit.uni-kl.de            // If the block is not cached above, send packet below. Both
22512027Sjungma@eit.uni-kl.de            // CleanEvict and Writeback with BLOCK_CACHED flag cleared will
22612027Sjungma@eit.uni-kl.de            // reset the bit corresponding to this address in the snoop filter
22712027Sjungma@eit.uni-kl.de            // below.
22812027Sjungma@eit.uni-kl.de            allocateWriteBuffer(wbPkt, forward_time);
22912027Sjungma@eit.uni-kl.de        }
23012027Sjungma@eit.uni-kl.de        writebacks.pop_front();
23112027Sjungma@eit.uni-kl.de    }
23212027Sjungma@eit.uni-kl.de}
23312027Sjungma@eit.uni-kl.de
23412027Sjungma@eit.uni-kl.devoid
23512027Sjungma@eit.uni-kl.deCache::doWritebacksAtomic(PacketList& writebacks)
23612027Sjungma@eit.uni-kl.de{
23712027Sjungma@eit.uni-kl.de    while (!writebacks.empty()) {
23812027Sjungma@eit.uni-kl.de        PacketPtr wbPkt = writebacks.front();
23912027Sjungma@eit.uni-kl.de        // Call isCachedAbove for both Writebacks and CleanEvicts. If
24012027Sjungma@eit.uni-kl.de        // isCachedAbove returns true we set BLOCK_CACHED flag in Writebacks
24112027Sjungma@eit.uni-kl.de        // and discard CleanEvicts.
24212027Sjungma@eit.uni-kl.de        if (isCachedAbove(wbPkt, false)) {
24312027Sjungma@eit.uni-kl.de            if (wbPkt->cmd == MemCmd::WritebackDirty ||
24412027Sjungma@eit.uni-kl.de                wbPkt->cmd == MemCmd::WriteClean) {
24512027Sjungma@eit.uni-kl.de                // Set BLOCK_CACHED flag in Writeback and send below,
24612027Sjungma@eit.uni-kl.de                // so that the Writeback does not reset the bit
24712027Sjungma@eit.uni-kl.de                // corresponding to this address in the snoop filter
24812027Sjungma@eit.uni-kl.de                // below. We can discard CleanEvicts because cached
24912027Sjungma@eit.uni-kl.de                // copies exist above. Atomic mode isCachedAbove
25012027Sjungma@eit.uni-kl.de                // modifies packet to set BLOCK_CACHED flag
25112027Sjungma@eit.uni-kl.de                memSidePort.sendAtomic(wbPkt);
25212027Sjungma@eit.uni-kl.de            }
25312027Sjungma@eit.uni-kl.de        } else {
25412027Sjungma@eit.uni-kl.de            // If the block is not cached above, send packet below. Both
25512027Sjungma@eit.uni-kl.de            // CleanEvict and Writeback with BLOCK_CACHED flag cleared will
25612027Sjungma@eit.uni-kl.de            // reset the bit corresponding to this address in the snoop filter
25712027Sjungma@eit.uni-kl.de            // below.
25812027Sjungma@eit.uni-kl.de            memSidePort.sendAtomic(wbPkt);
25912027Sjungma@eit.uni-kl.de        }
26012027Sjungma@eit.uni-kl.de        writebacks.pop_front();
26112027Sjungma@eit.uni-kl.de        // In case of CleanEvicts, the packet destructor will delete the
26212027Sjungma@eit.uni-kl.de        // request object because this is a non-snoop request packet which
26312027Sjungma@eit.uni-kl.de        // does not require a response.
26412027Sjungma@eit.uni-kl.de        delete wbPkt;
26512027Sjungma@eit.uni-kl.de    }
26612027Sjungma@eit.uni-kl.de}
26712027Sjungma@eit.uni-kl.de
26812027Sjungma@eit.uni-kl.de
26912027Sjungma@eit.uni-kl.devoid
27012027Sjungma@eit.uni-kl.deCache::recvTimingSnoopResp(PacketPtr pkt)
27112027Sjungma@eit.uni-kl.de{
27212027Sjungma@eit.uni-kl.de    DPRINTF(Cache, "%s for %s\n", __func__, pkt->print());
27312027Sjungma@eit.uni-kl.de
27412027Sjungma@eit.uni-kl.de    // determine if the response is from a snoop request we created
27512027Sjungma@eit.uni-kl.de    // (in which case it should be in the outstandingSnoop), or if we
27612027Sjungma@eit.uni-kl.de    // merely forwarded someone else's snoop request
27712027Sjungma@eit.uni-kl.de    const bool forwardAsSnoop = outstandingSnoop.find(pkt->req) ==
27812027Sjungma@eit.uni-kl.de        outstandingSnoop.end();
27912027Sjungma@eit.uni-kl.de
28012027Sjungma@eit.uni-kl.de    if (!forwardAsSnoop) {
28112027Sjungma@eit.uni-kl.de        // the packet came from this cache, so sink it here and do not
28212027Sjungma@eit.uni-kl.de        // forward it
28312027Sjungma@eit.uni-kl.de        assert(pkt->cmd == MemCmd::HardPFResp);
28412027Sjungma@eit.uni-kl.de
28512027Sjungma@eit.uni-kl.de        outstandingSnoop.erase(pkt->req);
28612027Sjungma@eit.uni-kl.de
28712027Sjungma@eit.uni-kl.de        DPRINTF(Cache, "Got prefetch response from above for addr "
28812027Sjungma@eit.uni-kl.de                "%#llx (%s)\n", pkt->getAddr(), pkt->isSecure() ? "s" : "ns");
28912027Sjungma@eit.uni-kl.de        recvTimingResp(pkt);
29012027Sjungma@eit.uni-kl.de        return;
29112027Sjungma@eit.uni-kl.de    }
29212027Sjungma@eit.uni-kl.de
29312027Sjungma@eit.uni-kl.de    // forwardLatency is set here because there is a response from an
29412027Sjungma@eit.uni-kl.de    // upper level cache.
29512027Sjungma@eit.uni-kl.de    // To pay the delay that occurs if the packet comes from the bus,
29612027Sjungma@eit.uni-kl.de    // we charge also headerDelay.
29712027Sjungma@eit.uni-kl.de    Tick snoop_resp_time = clockEdge(forwardLatency) + pkt->headerDelay;
29812027Sjungma@eit.uni-kl.de    // Reset the timing of the packet.
29912027Sjungma@eit.uni-kl.de    pkt->headerDelay = pkt->payloadDelay = 0;
30012027Sjungma@eit.uni-kl.de    memSidePort.schedTimingSnoopResp(pkt, snoop_resp_time);
30112027Sjungma@eit.uni-kl.de}
30212027Sjungma@eit.uni-kl.de
30312027Sjungma@eit.uni-kl.devoid
30412027Sjungma@eit.uni-kl.deCache::promoteWholeLineWrites(PacketPtr pkt)
30512027Sjungma@eit.uni-kl.de{
30612027Sjungma@eit.uni-kl.de    // Cache line clearing instructions
30712027Sjungma@eit.uni-kl.de    if (doFastWrites && (pkt->cmd == MemCmd::WriteReq) &&
30812027Sjungma@eit.uni-kl.de        (pkt->getSize() == blkSize) && (pkt->getOffset(blkSize) == 0)) {
30912027Sjungma@eit.uni-kl.de        pkt->cmd = MemCmd::WriteLineReq;
31012027Sjungma@eit.uni-kl.de        DPRINTF(Cache, "packet promoted from Write to WriteLineReq\n");
31112027Sjungma@eit.uni-kl.de    }
31212027Sjungma@eit.uni-kl.de}
31312027Sjungma@eit.uni-kl.de
31412027Sjungma@eit.uni-kl.devoid
31512027Sjungma@eit.uni-kl.deCache::handleTimingReqHit(PacketPtr pkt, CacheBlk *blk, Tick request_time)
31612027Sjungma@eit.uni-kl.de{
31712027Sjungma@eit.uni-kl.de    // should never be satisfying an uncacheable access as we
31812027Sjungma@eit.uni-kl.de    // flush and invalidate any existing block as part of the
31912027Sjungma@eit.uni-kl.de    // lookup
32012027Sjungma@eit.uni-kl.de    assert(!pkt->req->isUncacheable());
32112027Sjungma@eit.uni-kl.de
32212027Sjungma@eit.uni-kl.de    BaseCache::handleTimingReqHit(pkt, blk, request_time);
32312027Sjungma@eit.uni-kl.de}
32412027Sjungma@eit.uni-kl.de
32512027Sjungma@eit.uni-kl.devoid
32612027Sjungma@eit.uni-kl.deCache::handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time,
32712027Sjungma@eit.uni-kl.de                           Tick request_time)
32812027Sjungma@eit.uni-kl.de{
32912027Sjungma@eit.uni-kl.de    if (pkt->req->isUncacheable()) {
33012027Sjungma@eit.uni-kl.de        // ignore any existing MSHR if we are dealing with an
33112027Sjungma@eit.uni-kl.de        // uncacheable request
33212027Sjungma@eit.uni-kl.de
33312027Sjungma@eit.uni-kl.de        // should have flushed and have no valid block
33412027Sjungma@eit.uni-kl.de        assert(!blk || !blk->isValid());
33512027Sjungma@eit.uni-kl.de
33612027Sjungma@eit.uni-kl.de        mshr_uncacheable[pkt->cmdToIndex()][pkt->req->masterId()]++;
33712027Sjungma@eit.uni-kl.de
33812027Sjungma@eit.uni-kl.de        if (pkt->isWrite()) {
33912027Sjungma@eit.uni-kl.de            allocateWriteBuffer(pkt, forward_time);
34012027Sjungma@eit.uni-kl.de        } else {
34112027Sjungma@eit.uni-kl.de            assert(pkt->isRead());
34212027Sjungma@eit.uni-kl.de
34312027Sjungma@eit.uni-kl.de            // uncacheable accesses always allocate a new MSHR
34412027Sjungma@eit.uni-kl.de
34512027Sjungma@eit.uni-kl.de            // Here we are using forward_time, modelling the latency of
34612027Sjungma@eit.uni-kl.de            // a miss (outbound) just as forwardLatency, neglecting the
34712027Sjungma@eit.uni-kl.de            // lookupLatency component.
34812027Sjungma@eit.uni-kl.de            allocateMissBuffer(pkt, forward_time);
34912027Sjungma@eit.uni-kl.de        }
35012027Sjungma@eit.uni-kl.de
35112027Sjungma@eit.uni-kl.de        return;
35212027Sjungma@eit.uni-kl.de    }
35312027Sjungma@eit.uni-kl.de
35412027Sjungma@eit.uni-kl.de    Addr blk_addr = pkt->getBlockAddr(blkSize);
35512027Sjungma@eit.uni-kl.de
35612027Sjungma@eit.uni-kl.de    MSHR *mshr = mshrQueue.findMatch(blk_addr, pkt->isSecure());
35712027Sjungma@eit.uni-kl.de
35812027Sjungma@eit.uni-kl.de    // Software prefetch handling:
35912027Sjungma@eit.uni-kl.de    // To keep the core from waiting on data it won't look at
36012027Sjungma@eit.uni-kl.de    // anyway, send back a response with dummy data. Miss handling
36112027Sjungma@eit.uni-kl.de    // will continue asynchronously. Unfortunately, the core will
36212027Sjungma@eit.uni-kl.de    // insist upon freeing original Packet/Request, so we have to
36312027Sjungma@eit.uni-kl.de    // create a new pair with a different lifecycle. Note that this
36412027Sjungma@eit.uni-kl.de    // processing happens before any MSHR munging on the behalf of
36512027Sjungma@eit.uni-kl.de    // this request because this new Request will be the one stored
36612027Sjungma@eit.uni-kl.de    // into the MSHRs, not the original.
36712027Sjungma@eit.uni-kl.de    if (pkt->cmd.isSWPrefetch()) {
36812027Sjungma@eit.uni-kl.de        assert(pkt->needsResponse());
36912027Sjungma@eit.uni-kl.de        assert(pkt->req->hasPaddr());
37012027Sjungma@eit.uni-kl.de        assert(!pkt->req->isUncacheable());
37112027Sjungma@eit.uni-kl.de
37212027Sjungma@eit.uni-kl.de        // There's no reason to add a prefetch as an additional target
37312027Sjungma@eit.uni-kl.de        // to an existing MSHR. If an outstanding request is already
37412027Sjungma@eit.uni-kl.de        // in progress, there is nothing for the prefetch to do.
37512027Sjungma@eit.uni-kl.de        // If this is the case, we don't even create a request at all.
37612027Sjungma@eit.uni-kl.de        PacketPtr pf = nullptr;
37712027Sjungma@eit.uni-kl.de
37812027Sjungma@eit.uni-kl.de        if (!mshr) {
37912027Sjungma@eit.uni-kl.de            // copy the request and create a new SoftPFReq packet
38012027Sjungma@eit.uni-kl.de            RequestPtr req = std::make_shared<Request>(pkt->req->getPaddr(),
38112027Sjungma@eit.uni-kl.de                                                       pkt->req->getSize(),
38212027Sjungma@eit.uni-kl.de                                                       pkt->req->getFlags(),
38312027Sjungma@eit.uni-kl.de                                                       pkt->req->masterId());
38412027Sjungma@eit.uni-kl.de            pf = new Packet(req, pkt->cmd);
38512027Sjungma@eit.uni-kl.de            pf->allocate();
38612027Sjungma@eit.uni-kl.de            assert(pf->matchAddr(pkt));
38712027Sjungma@eit.uni-kl.de            assert(pf->getSize() == pkt->getSize());
38812027Sjungma@eit.uni-kl.de        }
38912027Sjungma@eit.uni-kl.de
39012027Sjungma@eit.uni-kl.de        pkt->makeTimingResponse();
39112027Sjungma@eit.uni-kl.de
39212027Sjungma@eit.uni-kl.de        // request_time is used here, taking into account lat and the delay
39312027Sjungma@eit.uni-kl.de        // charged if the packet comes from the xbar.
39412027Sjungma@eit.uni-kl.de        cpuSidePort.schedTimingResp(pkt, request_time);
39512027Sjungma@eit.uni-kl.de
39612027Sjungma@eit.uni-kl.de        // If an outstanding request is in progress (we found an
39712027Sjungma@eit.uni-kl.de        // MSHR) this is set to null
39812027Sjungma@eit.uni-kl.de        pkt = pf;
39912027Sjungma@eit.uni-kl.de    }
40012027Sjungma@eit.uni-kl.de
40112027Sjungma@eit.uni-kl.de    BaseCache::handleTimingReqMiss(pkt, mshr, blk, forward_time, request_time);
40212027Sjungma@eit.uni-kl.de}
40312027Sjungma@eit.uni-kl.de
40412027Sjungma@eit.uni-kl.devoid
40512027Sjungma@eit.uni-kl.deCache::recvTimingReq(PacketPtr pkt)
40612027Sjungma@eit.uni-kl.de{
40712027Sjungma@eit.uni-kl.de    DPRINTF(CacheTags, "%s tags:\n%s\n", __func__, tags->print());
40812027Sjungma@eit.uni-kl.de
40912027Sjungma@eit.uni-kl.de    promoteWholeLineWrites(pkt);
41012027Sjungma@eit.uni-kl.de
41112027Sjungma@eit.uni-kl.de    if (pkt->cacheResponding()) {
41212027Sjungma@eit.uni-kl.de        // a cache above us (but not where the packet came from) is
41312027Sjungma@eit.uni-kl.de        // responding to the request, in other words it has the line
41412027Sjungma@eit.uni-kl.de        // in Modified or Owned state
41512027Sjungma@eit.uni-kl.de        DPRINTF(Cache, "Cache above responding to %s: not responding\n",
41612027Sjungma@eit.uni-kl.de                pkt->print());
41712027Sjungma@eit.uni-kl.de
41812027Sjungma@eit.uni-kl.de        // if the packet needs the block to be writable, and the cache
41912027Sjungma@eit.uni-kl.de        // that has promised to respond (setting the cache responding
42012027Sjungma@eit.uni-kl.de        // flag) is not providing writable (it is in Owned rather than
42112027Sjungma@eit.uni-kl.de        // the Modified state), we know that there may be other Shared
42212027Sjungma@eit.uni-kl.de        // copies in the system; go out and invalidate them all
42312027Sjungma@eit.uni-kl.de        assert(pkt->needsWritable() && !pkt->responderHadWritable());
42412027Sjungma@eit.uni-kl.de
42512027Sjungma@eit.uni-kl.de        // an upstream cache that had the line in Owned state
42612027Sjungma@eit.uni-kl.de        // (dirty, but not writable), is responding and thus
42712027Sjungma@eit.uni-kl.de        // transferring the dirty line from one branch of the
42812027Sjungma@eit.uni-kl.de        // cache hierarchy to another
42912027Sjungma@eit.uni-kl.de
43012027Sjungma@eit.uni-kl.de        // send out an express snoop and invalidate all other
43112027Sjungma@eit.uni-kl.de        // copies (snooping a packet that needs writable is the
43212027Sjungma@eit.uni-kl.de        // same as an invalidation), thus turning the Owned line
43312027Sjungma@eit.uni-kl.de        // into a Modified line, note that we don't invalidate the
43412027Sjungma@eit.uni-kl.de        // block in the current cache or any other cache on the
43512027Sjungma@eit.uni-kl.de        // path to memory
43612027Sjungma@eit.uni-kl.de
43712027Sjungma@eit.uni-kl.de        // create a downstream express snoop with cleared packet
43812027Sjungma@eit.uni-kl.de        // flags, there is no need to allocate any data as the
43912027Sjungma@eit.uni-kl.de        // packet is merely used to co-ordinate state transitions
44012027Sjungma@eit.uni-kl.de        Packet *snoop_pkt = new Packet(pkt, true, false);
44112027Sjungma@eit.uni-kl.de
44212027Sjungma@eit.uni-kl.de        // also reset the bus time that the original packet has
44312027Sjungma@eit.uni-kl.de        // not yet paid for
44412027Sjungma@eit.uni-kl.de        snoop_pkt->headerDelay = snoop_pkt->payloadDelay = 0;
44512027Sjungma@eit.uni-kl.de
44612027Sjungma@eit.uni-kl.de        // make this an instantaneous express snoop, and let the
44712027Sjungma@eit.uni-kl.de        // other caches in the system know that the another cache
44812027Sjungma@eit.uni-kl.de        // is responding, because we have found the authorative
44912027Sjungma@eit.uni-kl.de        // copy (Modified or Owned) that will supply the right
45012027Sjungma@eit.uni-kl.de        // data
45112027Sjungma@eit.uni-kl.de        snoop_pkt->setExpressSnoop();
45212027Sjungma@eit.uni-kl.de        snoop_pkt->setCacheResponding();
45312027Sjungma@eit.uni-kl.de
45412027Sjungma@eit.uni-kl.de        // this express snoop travels towards the memory, and at
45512027Sjungma@eit.uni-kl.de        // every crossbar it is snooped upwards thus reaching
45612027Sjungma@eit.uni-kl.de        // every cache in the system
45712027Sjungma@eit.uni-kl.de        bool M5_VAR_USED success = memSidePort.sendTimingReq(snoop_pkt);
45812027Sjungma@eit.uni-kl.de        // express snoops always succeed
45912027Sjungma@eit.uni-kl.de        assert(success);
46012027Sjungma@eit.uni-kl.de
46112027Sjungma@eit.uni-kl.de        // main memory will delete the snoop packet
46212027Sjungma@eit.uni-kl.de
46312027Sjungma@eit.uni-kl.de        // queue for deletion, as opposed to immediate deletion, as
46412027Sjungma@eit.uni-kl.de        // the sending cache is still relying on the packet
46512027Sjungma@eit.uni-kl.de        pendingDelete.reset(pkt);
46612027Sjungma@eit.uni-kl.de
46712027Sjungma@eit.uni-kl.de        // no need to take any further action in this particular cache
46812027Sjungma@eit.uni-kl.de        // as an upstram cache has already committed to responding,
46912027Sjungma@eit.uni-kl.de        // and we have already sent out any express snoops in the
47012027Sjungma@eit.uni-kl.de        // section above to ensure all other copies in the system are
47112027Sjungma@eit.uni-kl.de        // invalidated
47212027Sjungma@eit.uni-kl.de        return;
47312027Sjungma@eit.uni-kl.de    }
47412027Sjungma@eit.uni-kl.de
47512027Sjungma@eit.uni-kl.de    BaseCache::recvTimingReq(pkt);
47612027Sjungma@eit.uni-kl.de}
47712027Sjungma@eit.uni-kl.de
47812027Sjungma@eit.uni-kl.dePacketPtr
47912027Sjungma@eit.uni-kl.deCache::createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk,
48012027Sjungma@eit.uni-kl.de                        bool needsWritable,
48112027Sjungma@eit.uni-kl.de                        bool is_whole_line_write) const
48212027Sjungma@eit.uni-kl.de{
48312027Sjungma@eit.uni-kl.de    // should never see evictions here
48412027Sjungma@eit.uni-kl.de    assert(!cpu_pkt->isEviction());
48512027Sjungma@eit.uni-kl.de
48612027Sjungma@eit.uni-kl.de    bool blkValid = blk && blk->isValid();
48712027Sjungma@eit.uni-kl.de
48812027Sjungma@eit.uni-kl.de    if (cpu_pkt->req->isUncacheable() ||
48912027Sjungma@eit.uni-kl.de        (!blkValid && cpu_pkt->isUpgrade()) ||
49012027Sjungma@eit.uni-kl.de        cpu_pkt->cmd == MemCmd::InvalidateReq || cpu_pkt->isClean()) {
49112027Sjungma@eit.uni-kl.de        // uncacheable requests and upgrades from upper-level caches
49212027Sjungma@eit.uni-kl.de        // that missed completely just go through as is
49312027Sjungma@eit.uni-kl.de        return nullptr;
49412027Sjungma@eit.uni-kl.de    }
49512027Sjungma@eit.uni-kl.de
49612027Sjungma@eit.uni-kl.de    assert(cpu_pkt->needsResponse());
49712027Sjungma@eit.uni-kl.de
49812027Sjungma@eit.uni-kl.de    MemCmd cmd;
49912027Sjungma@eit.uni-kl.de    // @TODO make useUpgrades a parameter.
50012027Sjungma@eit.uni-kl.de    // Note that ownership protocols require upgrade, otherwise a
50112027Sjungma@eit.uni-kl.de    // write miss on a shared owned block will generate a ReadExcl,
50212027Sjungma@eit.uni-kl.de    // which will clobber the owned copy.
50312027Sjungma@eit.uni-kl.de    const bool useUpgrades = true;
50412027Sjungma@eit.uni-kl.de    assert(cpu_pkt->cmd != MemCmd::WriteLineReq || is_whole_line_write);
50512027Sjungma@eit.uni-kl.de    if (is_whole_line_write) {
50612027Sjungma@eit.uni-kl.de        assert(!blkValid || !blk->isWritable());
50712027Sjungma@eit.uni-kl.de        // forward as invalidate to all other caches, this gives us
50812027Sjungma@eit.uni-kl.de        // the line in Exclusive state, and invalidates all other
50912027Sjungma@eit.uni-kl.de        // copies
51012027Sjungma@eit.uni-kl.de        cmd = MemCmd::InvalidateReq;
51112027Sjungma@eit.uni-kl.de    } else if (blkValid && useUpgrades) {
51212027Sjungma@eit.uni-kl.de        // only reason to be here is that blk is read only and we need
51312027Sjungma@eit.uni-kl.de        // it to be writable
51412027Sjungma@eit.uni-kl.de        assert(needsWritable);
51512027Sjungma@eit.uni-kl.de        assert(!blk->isWritable());
51612027Sjungma@eit.uni-kl.de        cmd = cpu_pkt->isLLSC() ? MemCmd::SCUpgradeReq : MemCmd::UpgradeReq;
51712027Sjungma@eit.uni-kl.de    } else if (cpu_pkt->cmd == MemCmd::SCUpgradeFailReq ||
51812027Sjungma@eit.uni-kl.de               cpu_pkt->cmd == MemCmd::StoreCondFailReq) {
51912027Sjungma@eit.uni-kl.de        // Even though this SC will fail, we still need to send out the
52012027Sjungma@eit.uni-kl.de        // request and get the data to supply it to other snoopers in the case
52112027Sjungma@eit.uni-kl.de        // where the determination the StoreCond fails is delayed due to
52212027Sjungma@eit.uni-kl.de        // all caches not being on the same local bus.
52312027Sjungma@eit.uni-kl.de        cmd = MemCmd::SCUpgradeFailReq;
52412027Sjungma@eit.uni-kl.de    } else {
52512027Sjungma@eit.uni-kl.de        // block is invalid
52612027Sjungma@eit.uni-kl.de
52712027Sjungma@eit.uni-kl.de        // If the request does not need a writable there are two cases
52812027Sjungma@eit.uni-kl.de        // where we need to ensure the response will not fetch the
52912027Sjungma@eit.uni-kl.de        // block in dirty state:
53012027Sjungma@eit.uni-kl.de        // * this cache is read only and it does not perform
53112027Sjungma@eit.uni-kl.de        //   writebacks,
53212027Sjungma@eit.uni-kl.de        // * this cache is mostly exclusive and will not fill (since
53312027Sjungma@eit.uni-kl.de        //   it does not fill it will have to writeback the dirty data
53412027Sjungma@eit.uni-kl.de        //   immediately which generates uneccesary writebacks).
53512027Sjungma@eit.uni-kl.de        bool force_clean_rsp = isReadOnly || clusivity == Enums::mostly_excl;
53612027Sjungma@eit.uni-kl.de        cmd = needsWritable ? MemCmd::ReadExReq :
53712027Sjungma@eit.uni-kl.de            (force_clean_rsp ? MemCmd::ReadCleanReq : MemCmd::ReadSharedReq);
53812027Sjungma@eit.uni-kl.de    }
53912027Sjungma@eit.uni-kl.de    PacketPtr pkt = new Packet(cpu_pkt->req, cmd, blkSize);
54012027Sjungma@eit.uni-kl.de
54112027Sjungma@eit.uni-kl.de    // if there are upstream caches that have already marked the
54212027Sjungma@eit.uni-kl.de    // packet as having sharers (not passing writable), pass that info
54312027Sjungma@eit.uni-kl.de    // downstream
54412027Sjungma@eit.uni-kl.de    if (cpu_pkt->hasSharers() && !needsWritable) {
54512027Sjungma@eit.uni-kl.de        // note that cpu_pkt may have spent a considerable time in the
54612027Sjungma@eit.uni-kl.de        // MSHR queue and that the information could possibly be out
54712027Sjungma@eit.uni-kl.de        // of date, however, there is no harm in conservatively
54812027Sjungma@eit.uni-kl.de        // assuming the block has sharers
54912027Sjungma@eit.uni-kl.de        pkt->setHasSharers();
55012027Sjungma@eit.uni-kl.de        DPRINTF(Cache, "%s: passing hasSharers from %s to %s\n",
55112027Sjungma@eit.uni-kl.de                __func__, cpu_pkt->print(), pkt->print());
55212027Sjungma@eit.uni-kl.de    }
55312027Sjungma@eit.uni-kl.de
55412027Sjungma@eit.uni-kl.de    // the packet should be block aligned
55512027Sjungma@eit.uni-kl.de    assert(pkt->getAddr() == pkt->getBlockAddr(blkSize));
55612027Sjungma@eit.uni-kl.de
55712027Sjungma@eit.uni-kl.de    pkt->allocate();
55812027Sjungma@eit.uni-kl.de    DPRINTF(Cache, "%s: created %s from %s\n", __func__, pkt->print(),
55912027Sjungma@eit.uni-kl.de            cpu_pkt->print());
56012027Sjungma@eit.uni-kl.de    return pkt;
56112027Sjungma@eit.uni-kl.de}
56212027Sjungma@eit.uni-kl.de
56312027Sjungma@eit.uni-kl.de
56412027Sjungma@eit.uni-kl.deCycles
56512027Sjungma@eit.uni-kl.deCache::handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk,
56612027Sjungma@eit.uni-kl.de                           PacketList &writebacks)
56712027Sjungma@eit.uni-kl.de{
56812027Sjungma@eit.uni-kl.de    // deal with the packets that go through the write path of
56912027Sjungma@eit.uni-kl.de    // the cache, i.e. any evictions and writes
57012027Sjungma@eit.uni-kl.de    if (pkt->isEviction() || pkt->cmd == MemCmd::WriteClean ||
57112027Sjungma@eit.uni-kl.de        (pkt->req->isUncacheable() && pkt->isWrite())) {
57212027Sjungma@eit.uni-kl.de        Cycles latency = ticksToCycles(memSidePort.sendAtomic(pkt));
57312027Sjungma@eit.uni-kl.de
57412027Sjungma@eit.uni-kl.de        // at this point, if the request was an uncacheable write
57512027Sjungma@eit.uni-kl.de        // request, it has been satisfied by a memory below and the
57612027Sjungma@eit.uni-kl.de        // packet carries the response back
57712027Sjungma@eit.uni-kl.de        assert(!(pkt->req->isUncacheable() && pkt->isWrite()) ||
57812027Sjungma@eit.uni-kl.de               pkt->isResponse());
57912027Sjungma@eit.uni-kl.de
58012027Sjungma@eit.uni-kl.de        return latency;
58112027Sjungma@eit.uni-kl.de    }
58212027Sjungma@eit.uni-kl.de
58312027Sjungma@eit.uni-kl.de    // only misses left
58412027Sjungma@eit.uni-kl.de
58512027Sjungma@eit.uni-kl.de    PacketPtr bus_pkt = createMissPacket(pkt, blk, pkt->needsWritable(),
58612027Sjungma@eit.uni-kl.de                                         pkt->isWholeLineWrite(blkSize));
58712027Sjungma@eit.uni-kl.de
58812027Sjungma@eit.uni-kl.de    bool is_forward = (bus_pkt == nullptr);
58912027Sjungma@eit.uni-kl.de
59012027Sjungma@eit.uni-kl.de    if (is_forward) {
59112027Sjungma@eit.uni-kl.de        // just forwarding the same request to the next level
59212027Sjungma@eit.uni-kl.de        // no local cache operation involved
59312027Sjungma@eit.uni-kl.de        bus_pkt = pkt;
59412027Sjungma@eit.uni-kl.de    }
59512027Sjungma@eit.uni-kl.de
59612027Sjungma@eit.uni-kl.de    DPRINTF(Cache, "%s: Sending an atomic %s\n", __func__,
59712027Sjungma@eit.uni-kl.de            bus_pkt->print());
59812027Sjungma@eit.uni-kl.de
59912027Sjungma@eit.uni-kl.de#if TRACING_ON
60012027Sjungma@eit.uni-kl.de    CacheBlk::State old_state = blk ? blk->status : 0;
60112027Sjungma@eit.uni-kl.de#endif
60212027Sjungma@eit.uni-kl.de
60312027Sjungma@eit.uni-kl.de    Cycles latency = ticksToCycles(memSidePort.sendAtomic(bus_pkt));
60412027Sjungma@eit.uni-kl.de
60512027Sjungma@eit.uni-kl.de    bool is_invalidate = bus_pkt->isInvalidate();
60612027Sjungma@eit.uni-kl.de
60712027Sjungma@eit.uni-kl.de    // We are now dealing with the response handling
60812027Sjungma@eit.uni-kl.de    DPRINTF(Cache, "%s: Receive response: %s in state %i\n", __func__,
60912027Sjungma@eit.uni-kl.de            bus_pkt->print(), old_state);
61012027Sjungma@eit.uni-kl.de
61112027Sjungma@eit.uni-kl.de    // If packet was a forward, the response (if any) is already
61212027Sjungma@eit.uni-kl.de    // in place in the bus_pkt == pkt structure, so we don't need
61312027Sjungma@eit.uni-kl.de    // to do anything.  Otherwise, use the separate bus_pkt to
61412027Sjungma@eit.uni-kl.de    // generate response to pkt and then delete it.
61512027Sjungma@eit.uni-kl.de    if (!is_forward) {
61612027Sjungma@eit.uni-kl.de        if (pkt->needsResponse()) {
61712027Sjungma@eit.uni-kl.de            assert(bus_pkt->isResponse());
61812027Sjungma@eit.uni-kl.de            if (bus_pkt->isError()) {
61912027Sjungma@eit.uni-kl.de                pkt->makeAtomicResponse();
62012027Sjungma@eit.uni-kl.de                pkt->copyError(bus_pkt);
62112027Sjungma@eit.uni-kl.de            } else if (pkt->isWholeLineWrite(blkSize)) {
62212027Sjungma@eit.uni-kl.de                // note the use of pkt, not bus_pkt here.
62312027Sjungma@eit.uni-kl.de
62412027Sjungma@eit.uni-kl.de                // write-line request to the cache that promoted
62512027Sjungma@eit.uni-kl.de                // the write to a whole line
62612027Sjungma@eit.uni-kl.de                const bool allocate = allocOnFill(pkt->cmd) &&
62712027Sjungma@eit.uni-kl.de                    (!writeAllocator || writeAllocator->allocate());
62812027Sjungma@eit.uni-kl.de                blk = handleFill(bus_pkt, blk, writebacks, allocate);
62912027Sjungma@eit.uni-kl.de                assert(blk != NULL);
63012027Sjungma@eit.uni-kl.de                is_invalidate = false;
63112027Sjungma@eit.uni-kl.de                satisfyRequest(pkt, blk);
63212027Sjungma@eit.uni-kl.de            } else if (bus_pkt->isRead() ||
63312027Sjungma@eit.uni-kl.de                       bus_pkt->cmd == MemCmd::UpgradeResp) {
63412027Sjungma@eit.uni-kl.de                // we're updating cache state to allow us to
63512027Sjungma@eit.uni-kl.de                // satisfy the upstream request from the cache
63612027Sjungma@eit.uni-kl.de                blk = handleFill(bus_pkt, blk, writebacks,
63712027Sjungma@eit.uni-kl.de                                 allocOnFill(pkt->cmd));
63812027Sjungma@eit.uni-kl.de                satisfyRequest(pkt, blk);
63912027Sjungma@eit.uni-kl.de                maintainClusivity(pkt->fromCache(), blk);
64012027Sjungma@eit.uni-kl.de            } else {
64112027Sjungma@eit.uni-kl.de                // we're satisfying the upstream request without
64212027Sjungma@eit.uni-kl.de                // modifying cache state, e.g., a write-through
64312027Sjungma@eit.uni-kl.de                pkt->makeAtomicResponse();
64412027Sjungma@eit.uni-kl.de            }
64512027Sjungma@eit.uni-kl.de        }
64612027Sjungma@eit.uni-kl.de        delete bus_pkt;
64712027Sjungma@eit.uni-kl.de    }
64812027Sjungma@eit.uni-kl.de
64912027Sjungma@eit.uni-kl.de    if (is_invalidate && blk && blk->isValid()) {
65012027Sjungma@eit.uni-kl.de        invalidateBlock(blk);
65112027Sjungma@eit.uni-kl.de    }
65212027Sjungma@eit.uni-kl.de
65312027Sjungma@eit.uni-kl.de    return latency;
65412027Sjungma@eit.uni-kl.de}
65512027Sjungma@eit.uni-kl.de
65612027Sjungma@eit.uni-kl.deTick
65712027Sjungma@eit.uni-kl.deCache::recvAtomic(PacketPtr pkt)
65812027Sjungma@eit.uni-kl.de{
65912027Sjungma@eit.uni-kl.de    promoteWholeLineWrites(pkt);
66012027Sjungma@eit.uni-kl.de
66112027Sjungma@eit.uni-kl.de    // follow the same flow as in recvTimingReq, and check if a cache
66212027Sjungma@eit.uni-kl.de    // above us is responding
66312027Sjungma@eit.uni-kl.de    if (pkt->cacheResponding()) {
66412027Sjungma@eit.uni-kl.de        assert(!pkt->req->isCacheInvalidate());
66512027Sjungma@eit.uni-kl.de        DPRINTF(Cache, "Cache above responding to %s: not responding\n",
66612027Sjungma@eit.uni-kl.de                pkt->print());
66712027Sjungma@eit.uni-kl.de
66812027Sjungma@eit.uni-kl.de        // if a cache is responding, and it had the line in Owned
66912027Sjungma@eit.uni-kl.de        // rather than Modified state, we need to invalidate any
67012027Sjungma@eit.uni-kl.de        // copies that are not on the same path to memory
67112027Sjungma@eit.uni-kl.de        assert(pkt->needsWritable() && !pkt->responderHadWritable());
67212027Sjungma@eit.uni-kl.de
67312027Sjungma@eit.uni-kl.de        return memSidePort.sendAtomic(pkt);
67412027Sjungma@eit.uni-kl.de    }
67512027Sjungma@eit.uni-kl.de
67612027Sjungma@eit.uni-kl.de    return BaseCache::recvAtomic(pkt);
67712027Sjungma@eit.uni-kl.de}
67812027Sjungma@eit.uni-kl.de
67912027Sjungma@eit.uni-kl.de
68012027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////
68112027Sjungma@eit.uni-kl.de//
68212027Sjungma@eit.uni-kl.de// Response handling: responses from the memory side
68312027Sjungma@eit.uni-kl.de//
68412027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////
68512027Sjungma@eit.uni-kl.de
68612027Sjungma@eit.uni-kl.de
68712027Sjungma@eit.uni-kl.devoid
68812027Sjungma@eit.uni-kl.deCache::serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt, CacheBlk *blk)
68912027Sjungma@eit.uni-kl.de{
69012027Sjungma@eit.uni-kl.de    QueueEntry::Target *initial_tgt = mshr->getTarget();
69112027Sjungma@eit.uni-kl.de    // First offset for critical word first calculations
69212027Sjungma@eit.uni-kl.de    const int initial_offset = initial_tgt->pkt->getOffset(blkSize);
69312027Sjungma@eit.uni-kl.de
69412027Sjungma@eit.uni-kl.de    const bool is_error = pkt->isError();
69512027Sjungma@eit.uni-kl.de    // allow invalidation responses originating from write-line
69612027Sjungma@eit.uni-kl.de    // requests to be discarded
69712027Sjungma@eit.uni-kl.de    bool is_invalidate = pkt->isInvalidate() &&
69812027Sjungma@eit.uni-kl.de        !mshr->wasWholeLineWrite;
69912027Sjungma@eit.uni-kl.de
70012027Sjungma@eit.uni-kl.de    MSHR::TargetList targets = mshr->extractServiceableTargets(pkt);
70112027Sjungma@eit.uni-kl.de    for (auto &target: targets) {
70212027Sjungma@eit.uni-kl.de        Packet *tgt_pkt = target.pkt;
70312027Sjungma@eit.uni-kl.de        switch (target.source) {
70412027Sjungma@eit.uni-kl.de          case MSHR::Target::FromCPU:
70512027Sjungma@eit.uni-kl.de            Tick completion_time;
70612027Sjungma@eit.uni-kl.de            // Here we charge on completion_time the delay of the xbar if the
70712027Sjungma@eit.uni-kl.de            // packet comes from it, charged on headerDelay.
70812027Sjungma@eit.uni-kl.de            completion_time = pkt->headerDelay;
70912027Sjungma@eit.uni-kl.de
71012027Sjungma@eit.uni-kl.de            // Software prefetch handling for cache closest to core
71112027Sjungma@eit.uni-kl.de            if (tgt_pkt->cmd.isSWPrefetch()) {
71212027Sjungma@eit.uni-kl.de                // a software prefetch would have already been ack'd
71312027Sjungma@eit.uni-kl.de                // immediately with dummy data so the core would be able to
71412027Sjungma@eit.uni-kl.de                // retire it. This request completes right here, so we
71512027Sjungma@eit.uni-kl.de                // deallocate it.
71612027Sjungma@eit.uni-kl.de                delete tgt_pkt;
71712027Sjungma@eit.uni-kl.de                break; // skip response
71812027Sjungma@eit.uni-kl.de            }
71912027Sjungma@eit.uni-kl.de
72012027Sjungma@eit.uni-kl.de            // unlike the other packet flows, where data is found in other
72112027Sjungma@eit.uni-kl.de            // caches or memory and brought back, write-line requests always
72212027Sjungma@eit.uni-kl.de            // have the data right away, so the above check for "is fill?"
72312027Sjungma@eit.uni-kl.de            // cannot actually be determined until examining the stored MSHR
72412027Sjungma@eit.uni-kl.de            // state. We "catch up" with that logic here, which is duplicated
72512027Sjungma@eit.uni-kl.de            // from above.
72612027Sjungma@eit.uni-kl.de            if (tgt_pkt->cmd == MemCmd::WriteLineReq) {
72712027Sjungma@eit.uni-kl.de                assert(!is_error);
72812027Sjungma@eit.uni-kl.de                assert(blk);
72912027Sjungma@eit.uni-kl.de                assert(blk->isWritable());
73012027Sjungma@eit.uni-kl.de            }
73112027Sjungma@eit.uni-kl.de
73212027Sjungma@eit.uni-kl.de            if (blk && blk->isValid() && !mshr->isForward) {
73312027Sjungma@eit.uni-kl.de                satisfyRequest(tgt_pkt, blk, true, mshr->hasPostDowngrade());
73412027Sjungma@eit.uni-kl.de
73512027Sjungma@eit.uni-kl.de                // How many bytes past the first request is this one
73612027Sjungma@eit.uni-kl.de                int transfer_offset =
73712027Sjungma@eit.uni-kl.de                    tgt_pkt->getOffset(blkSize) - initial_offset;
73812027Sjungma@eit.uni-kl.de                if (transfer_offset < 0) {
73912027Sjungma@eit.uni-kl.de                    transfer_offset += blkSize;
74012027Sjungma@eit.uni-kl.de                }
74112027Sjungma@eit.uni-kl.de
74212027Sjungma@eit.uni-kl.de                // If not critical word (offset) return payloadDelay.
74312027Sjungma@eit.uni-kl.de                // responseLatency is the latency of the return path
74412027Sjungma@eit.uni-kl.de                // from lower level caches/memory to an upper level cache or
74512027Sjungma@eit.uni-kl.de                // the core.
74612027Sjungma@eit.uni-kl.de                completion_time += clockEdge(responseLatency) +
74712027Sjungma@eit.uni-kl.de                    (transfer_offset ? pkt->payloadDelay : 0);
74812027Sjungma@eit.uni-kl.de
74912027Sjungma@eit.uni-kl.de                assert(!tgt_pkt->req->isUncacheable());
75012027Sjungma@eit.uni-kl.de
75112027Sjungma@eit.uni-kl.de                assert(tgt_pkt->req->masterId() < system->maxMasters());
75212027Sjungma@eit.uni-kl.de                missLatency[tgt_pkt->cmdToIndex()][tgt_pkt->req->masterId()] +=
75312027Sjungma@eit.uni-kl.de                    completion_time - target.recvTime;
75412027Sjungma@eit.uni-kl.de            } else if (pkt->cmd == MemCmd::UpgradeFailResp) {
75512027Sjungma@eit.uni-kl.de                // failed StoreCond upgrade
75612027Sjungma@eit.uni-kl.de                assert(tgt_pkt->cmd == MemCmd::StoreCondReq ||
75712027Sjungma@eit.uni-kl.de                       tgt_pkt->cmd == MemCmd::StoreCondFailReq ||
75812027Sjungma@eit.uni-kl.de                       tgt_pkt->cmd == MemCmd::SCUpgradeFailReq);
75912027Sjungma@eit.uni-kl.de                // responseLatency is the latency of the return path
76012027Sjungma@eit.uni-kl.de                // from lower level caches/memory to an upper level cache or
76112027Sjungma@eit.uni-kl.de                // the core.
76212027Sjungma@eit.uni-kl.de                completion_time += clockEdge(responseLatency) +
76312027Sjungma@eit.uni-kl.de                    pkt->payloadDelay;
76412027Sjungma@eit.uni-kl.de                tgt_pkt->req->setExtraData(0);
76512027Sjungma@eit.uni-kl.de            } else {
76612027Sjungma@eit.uni-kl.de                // We are about to send a response to a cache above
76712027Sjungma@eit.uni-kl.de                // that asked for an invalidation; we need to
76812027Sjungma@eit.uni-kl.de                // invalidate our copy immediately as the most
76912027Sjungma@eit.uni-kl.de                // up-to-date copy of the block will now be in the
77012027Sjungma@eit.uni-kl.de                // cache above. It will also prevent this cache from
77112027Sjungma@eit.uni-kl.de                // responding (if the block was previously dirty) to
77212027Sjungma@eit.uni-kl.de                // snoops as they should snoop the caches above where
77312027Sjungma@eit.uni-kl.de                // they will get the response from.
77412027Sjungma@eit.uni-kl.de                if (is_invalidate && blk && blk->isValid()) {
77512027Sjungma@eit.uni-kl.de                    invalidateBlock(blk);
77612027Sjungma@eit.uni-kl.de                }
77712027Sjungma@eit.uni-kl.de                // not a cache fill, just forwarding response
77812027Sjungma@eit.uni-kl.de                // responseLatency is the latency of the return path
77912027Sjungma@eit.uni-kl.de                // from lower level cahces/memory to the core.
78012027Sjungma@eit.uni-kl.de                completion_time += clockEdge(responseLatency) +
78112027Sjungma@eit.uni-kl.de                    pkt->payloadDelay;
78212027Sjungma@eit.uni-kl.de                if (pkt->isRead() && !is_error) {
78312027Sjungma@eit.uni-kl.de                    // sanity check
78412027Sjungma@eit.uni-kl.de                    assert(pkt->matchAddr(tgt_pkt));
78512027Sjungma@eit.uni-kl.de                    assert(pkt->getSize() >= tgt_pkt->getSize());
78612027Sjungma@eit.uni-kl.de
78712027Sjungma@eit.uni-kl.de                    tgt_pkt->setData(pkt->getConstPtr<uint8_t>());
78812027Sjungma@eit.uni-kl.de                }
78912027Sjungma@eit.uni-kl.de
79012027Sjungma@eit.uni-kl.de                // this response did not allocate here and therefore
79112027Sjungma@eit.uni-kl.de                // it was not consumed, make sure that any flags are
79212027Sjungma@eit.uni-kl.de                // carried over to cache above
79312027Sjungma@eit.uni-kl.de                tgt_pkt->copyResponderFlags(pkt);
79412027Sjungma@eit.uni-kl.de            }
79512027Sjungma@eit.uni-kl.de            tgt_pkt->makeTimingResponse();
79612027Sjungma@eit.uni-kl.de            // if this packet is an error copy that to the new packet
79712027Sjungma@eit.uni-kl.de            if (is_error)
79812027Sjungma@eit.uni-kl.de                tgt_pkt->copyError(pkt);
79912027Sjungma@eit.uni-kl.de            if (tgt_pkt->cmd == MemCmd::ReadResp &&
80012027Sjungma@eit.uni-kl.de                (is_invalidate || mshr->hasPostInvalidate())) {
80112027Sjungma@eit.uni-kl.de                // If intermediate cache got ReadRespWithInvalidate,
80212027Sjungma@eit.uni-kl.de                // propagate that.  Response should not have
80312027Sjungma@eit.uni-kl.de                // isInvalidate() set otherwise.
80412027Sjungma@eit.uni-kl.de                tgt_pkt->cmd = MemCmd::ReadRespWithInvalidate;
80512027Sjungma@eit.uni-kl.de                DPRINTF(Cache, "%s: updated cmd to %s\n", __func__,
80612027Sjungma@eit.uni-kl.de                        tgt_pkt->print());
80712027Sjungma@eit.uni-kl.de            }
80812027Sjungma@eit.uni-kl.de            // Reset the bus additional time as it is now accounted for
80912027Sjungma@eit.uni-kl.de            tgt_pkt->headerDelay = tgt_pkt->payloadDelay = 0;
81012027Sjungma@eit.uni-kl.de            cpuSidePort.schedTimingResp(tgt_pkt, completion_time);
81112027Sjungma@eit.uni-kl.de            break;
81212027Sjungma@eit.uni-kl.de
81312027Sjungma@eit.uni-kl.de          case MSHR::Target::FromPrefetcher:
81412027Sjungma@eit.uni-kl.de            assert(tgt_pkt->cmd == MemCmd::HardPFReq);
81512027Sjungma@eit.uni-kl.de            if (blk)
81612027Sjungma@eit.uni-kl.de                blk->status |= BlkHWPrefetched;
81712027Sjungma@eit.uni-kl.de            delete tgt_pkt;
81812027Sjungma@eit.uni-kl.de            break;
81912027Sjungma@eit.uni-kl.de
82012027Sjungma@eit.uni-kl.de          case MSHR::Target::FromSnoop:
82112027Sjungma@eit.uni-kl.de            // I don't believe that a snoop can be in an error state
82212027Sjungma@eit.uni-kl.de            assert(!is_error);
82312027Sjungma@eit.uni-kl.de            // response to snoop request
82412027Sjungma@eit.uni-kl.de            DPRINTF(Cache, "processing deferred snoop...\n");
82512027Sjungma@eit.uni-kl.de            // If the response is invalidating, a snooping target can
82612027Sjungma@eit.uni-kl.de            // be satisfied if it is also invalidating. If the reponse is, not
82712027Sjungma@eit.uni-kl.de            // only invalidating, but more specifically an InvalidateResp and
82812027Sjungma@eit.uni-kl.de            // the MSHR was created due to an InvalidateReq then a cache above
82912027Sjungma@eit.uni-kl.de            // is waiting to satisfy a WriteLineReq. In this case even an
83012027Sjungma@eit.uni-kl.de            // non-invalidating snoop is added as a target here since this is
83112027Sjungma@eit.uni-kl.de            // the ordering point. When the InvalidateResp reaches this cache,
83212027Sjungma@eit.uni-kl.de            // the snooping target will snoop further the cache above with the
83312027Sjungma@eit.uni-kl.de            // WriteLineReq.
83412027Sjungma@eit.uni-kl.de            assert(!is_invalidate || pkt->cmd == MemCmd::InvalidateResp ||
83512027Sjungma@eit.uni-kl.de                   pkt->req->isCacheMaintenance() ||
83612027Sjungma@eit.uni-kl.de                   mshr->hasPostInvalidate());
83712027Sjungma@eit.uni-kl.de            handleSnoop(tgt_pkt, blk, true, true, mshr->hasPostInvalidate());
83812027Sjungma@eit.uni-kl.de            break;
83912027Sjungma@eit.uni-kl.de
84012027Sjungma@eit.uni-kl.de          default:
84112027Sjungma@eit.uni-kl.de            panic("Illegal target->source enum %d\n", target.source);
84212027Sjungma@eit.uni-kl.de        }
84312027Sjungma@eit.uni-kl.de    }
84412027Sjungma@eit.uni-kl.de
84512027Sjungma@eit.uni-kl.de    maintainClusivity(targets.hasFromCache, blk);
84612027Sjungma@eit.uni-kl.de
84712027Sjungma@eit.uni-kl.de    if (blk && blk->isValid()) {
84812027Sjungma@eit.uni-kl.de        // an invalidate response stemming from a write line request
84912027Sjungma@eit.uni-kl.de        // should not invalidate the block, so check if the
85012027Sjungma@eit.uni-kl.de        // invalidation should be discarded
85112027Sjungma@eit.uni-kl.de        if (is_invalidate || mshr->hasPostInvalidate()) {
85212027Sjungma@eit.uni-kl.de            invalidateBlock(blk);
85312027Sjungma@eit.uni-kl.de        } else if (mshr->hasPostDowngrade()) {
85412027Sjungma@eit.uni-kl.de            blk->status &= ~BlkWritable;
85512027Sjungma@eit.uni-kl.de        }
85612027Sjungma@eit.uni-kl.de    }
85712027Sjungma@eit.uni-kl.de}
85812027Sjungma@eit.uni-kl.de
85912027Sjungma@eit.uni-kl.dePacketPtr
86012027Sjungma@eit.uni-kl.deCache::evictBlock(CacheBlk *blk)
86112027Sjungma@eit.uni-kl.de{
86212027Sjungma@eit.uni-kl.de    PacketPtr pkt = (blk->isDirty() || writebackClean) ?
86312027Sjungma@eit.uni-kl.de        writebackBlk(blk) : cleanEvictBlk(blk);
86412027Sjungma@eit.uni-kl.de
86512027Sjungma@eit.uni-kl.de    invalidateBlock(blk);
86612027Sjungma@eit.uni-kl.de
86712027Sjungma@eit.uni-kl.de    return pkt;
86812027Sjungma@eit.uni-kl.de}
86912027Sjungma@eit.uni-kl.de
87012027Sjungma@eit.uni-kl.dePacketPtr
87112027Sjungma@eit.uni-kl.deCache::cleanEvictBlk(CacheBlk *blk)
87212027Sjungma@eit.uni-kl.de{
87312027Sjungma@eit.uni-kl.de    assert(!writebackClean);
87412027Sjungma@eit.uni-kl.de    assert(blk && blk->isValid() && !blk->isDirty());
87512027Sjungma@eit.uni-kl.de
87612027Sjungma@eit.uni-kl.de    // Creating a zero sized write, a message to the snoop filter
87712027Sjungma@eit.uni-kl.de    RequestPtr req = std::make_shared<Request>(
87812027Sjungma@eit.uni-kl.de        regenerateBlkAddr(blk), blkSize, 0, Request::wbMasterId);
87912027Sjungma@eit.uni-kl.de
88012027Sjungma@eit.uni-kl.de    if (blk->isSecure())
88112027Sjungma@eit.uni-kl.de        req->setFlags(Request::SECURE);
88212027Sjungma@eit.uni-kl.de
88312027Sjungma@eit.uni-kl.de    req->taskId(blk->task_id);
88412027Sjungma@eit.uni-kl.de
88512027Sjungma@eit.uni-kl.de    PacketPtr pkt = new Packet(req, MemCmd::CleanEvict);
88612027Sjungma@eit.uni-kl.de    pkt->allocate();
88712027Sjungma@eit.uni-kl.de    DPRINTF(Cache, "Create CleanEvict %s\n", pkt->print());
88812027Sjungma@eit.uni-kl.de
88912027Sjungma@eit.uni-kl.de    return pkt;
89012027Sjungma@eit.uni-kl.de}
89112027Sjungma@eit.uni-kl.de
89212027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////
89312027Sjungma@eit.uni-kl.de//
89412027Sjungma@eit.uni-kl.de// Snoop path: requests coming in from the memory side
89512027Sjungma@eit.uni-kl.de//
89612027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////
89712027Sjungma@eit.uni-kl.de
89812027Sjungma@eit.uni-kl.devoid
89912027Sjungma@eit.uni-kl.deCache::doTimingSupplyResponse(PacketPtr req_pkt, const uint8_t *blk_data,
90012027Sjungma@eit.uni-kl.de                              bool already_copied, bool pending_inval)
90112027Sjungma@eit.uni-kl.de{
90212027Sjungma@eit.uni-kl.de    // sanity check
90312027Sjungma@eit.uni-kl.de    assert(req_pkt->isRequest());
90412027Sjungma@eit.uni-kl.de    assert(req_pkt->needsResponse());
90512027Sjungma@eit.uni-kl.de
90612027Sjungma@eit.uni-kl.de    DPRINTF(Cache, "%s: for %s\n", __func__, req_pkt->print());
90712027Sjungma@eit.uni-kl.de    // timing-mode snoop responses require a new packet, unless we
90812027Sjungma@eit.uni-kl.de    // already made a copy...
90912027Sjungma@eit.uni-kl.de    PacketPtr pkt = req_pkt;
91012027Sjungma@eit.uni-kl.de    if (!already_copied)
91112027Sjungma@eit.uni-kl.de        // do not clear flags, and allocate space for data if the
91212027Sjungma@eit.uni-kl.de        // packet needs it (the only packets that carry data are read
91312027Sjungma@eit.uni-kl.de        // responses)
91412027Sjungma@eit.uni-kl.de        pkt = new Packet(req_pkt, false, req_pkt->isRead());
91512027Sjungma@eit.uni-kl.de
91612027Sjungma@eit.uni-kl.de    assert(req_pkt->req->isUncacheable() || req_pkt->isInvalidate() ||
91712027Sjungma@eit.uni-kl.de           pkt->hasSharers());
91812027Sjungma@eit.uni-kl.de    pkt->makeTimingResponse();
91912027Sjungma@eit.uni-kl.de    if (pkt->isRead()) {
92012027Sjungma@eit.uni-kl.de        pkt->setDataFromBlock(blk_data, blkSize);
92112027Sjungma@eit.uni-kl.de    }
92212027Sjungma@eit.uni-kl.de    if (pkt->cmd == MemCmd::ReadResp && pending_inval) {
92312027Sjungma@eit.uni-kl.de        // Assume we defer a response to a read from a far-away cache
92412027Sjungma@eit.uni-kl.de        // A, then later defer a ReadExcl from a cache B on the same
92512027Sjungma@eit.uni-kl.de        // bus as us. We'll assert cacheResponding in both cases, but
92612027Sjungma@eit.uni-kl.de        // in the latter case cacheResponding will keep the
92712027Sjungma@eit.uni-kl.de        // invalidation from reaching cache A. This special response
92812027Sjungma@eit.uni-kl.de        // tells cache A that it gets the block to satisfy its read,
92912027Sjungma@eit.uni-kl.de        // but must immediately invalidate it.
93012027Sjungma@eit.uni-kl.de        pkt->cmd = MemCmd::ReadRespWithInvalidate;
93112027Sjungma@eit.uni-kl.de    }
93212027Sjungma@eit.uni-kl.de    // Here we consider forward_time, paying for just forward latency and
93312027Sjungma@eit.uni-kl.de    // also charging the delay provided by the xbar.
93412027Sjungma@eit.uni-kl.de    // forward_time is used as send_time in next allocateWriteBuffer().
93512027Sjungma@eit.uni-kl.de    Tick forward_time = clockEdge(forwardLatency) + pkt->headerDelay;
93612027Sjungma@eit.uni-kl.de    // Here we reset the timing of the packet.
93712027Sjungma@eit.uni-kl.de    pkt->headerDelay = pkt->payloadDelay = 0;
93812027Sjungma@eit.uni-kl.de    DPRINTF(CacheVerbose, "%s: created response: %s tick: %lu\n", __func__,
93912027Sjungma@eit.uni-kl.de            pkt->print(), forward_time);
94012027Sjungma@eit.uni-kl.de    memSidePort.schedTimingSnoopResp(pkt, forward_time);
94112027Sjungma@eit.uni-kl.de}
94212027Sjungma@eit.uni-kl.de
94312027Sjungma@eit.uni-kl.deuint32_t
94412027Sjungma@eit.uni-kl.deCache::handleSnoop(PacketPtr pkt, CacheBlk *blk, bool is_timing,
94512027Sjungma@eit.uni-kl.de                   bool is_deferred, bool pending_inval)
94612027Sjungma@eit.uni-kl.de{
94712027Sjungma@eit.uni-kl.de    DPRINTF(CacheVerbose, "%s: for %s\n", __func__, pkt->print());
94812027Sjungma@eit.uni-kl.de    // deferred snoops can only happen in timing mode
94912027Sjungma@eit.uni-kl.de    assert(!(is_deferred && !is_timing));
95012027Sjungma@eit.uni-kl.de    // pending_inval only makes sense on deferred snoops
95112027Sjungma@eit.uni-kl.de    assert(!(pending_inval && !is_deferred));
95212027Sjungma@eit.uni-kl.de    assert(pkt->isRequest());
95312027Sjungma@eit.uni-kl.de
95412027Sjungma@eit.uni-kl.de    // the packet may get modified if we or a forwarded snooper
95512027Sjungma@eit.uni-kl.de    // responds in atomic mode, so remember a few things about the
95612027Sjungma@eit.uni-kl.de    // original packet up front
95712027Sjungma@eit.uni-kl.de    bool invalidate = pkt->isInvalidate();
95812027Sjungma@eit.uni-kl.de    bool M5_VAR_USED needs_writable = pkt->needsWritable();
95912027Sjungma@eit.uni-kl.de
960    // at the moment we could get an uncacheable write which does not
961    // have the invalidate flag, and we need a suitable way of dealing
962    // with this case
963    panic_if(invalidate && pkt->req->isUncacheable(),
964             "%s got an invalidating uncacheable snoop request %s",
965             name(), pkt->print());
966
967    uint32_t snoop_delay = 0;
968
969    if (forwardSnoops) {
970        // first propagate snoop upward to see if anyone above us wants to
971        // handle it.  save & restore packet src since it will get
972        // rewritten to be relative to cpu-side bus (if any)
973        if (is_timing) {
974            // copy the packet so that we can clear any flags before
975            // forwarding it upwards, we also allocate data (passing
976            // the pointer along in case of static data), in case
977            // there is a snoop hit in upper levels
978            Packet snoopPkt(pkt, true, true);
979            snoopPkt.setExpressSnoop();
980            // the snoop packet does not need to wait any additional
981            // time
982            snoopPkt.headerDelay = snoopPkt.payloadDelay = 0;
983            cpuSidePort.sendTimingSnoopReq(&snoopPkt);
984
985            // add the header delay (including crossbar and snoop
986            // delays) of the upward snoop to the snoop delay for this
987            // cache
988            snoop_delay += snoopPkt.headerDelay;
989
990            // If this request is a prefetch or clean evict and an upper level
991            // signals block present, make sure to propagate the block
992            // presence to the requester.
993            if (snoopPkt.isBlockCached()) {
994                pkt->setBlockCached();
995            }
996            // If the request was satisfied by snooping the cache
997            // above, mark the original packet as satisfied too.
998            if (snoopPkt.satisfied()) {
999                pkt->setSatisfied();
1000            }
1001
1002            // Copy over flags from the snoop response to make sure we
1003            // inform the final destination
1004            pkt->copyResponderFlags(&snoopPkt);
1005        } else {
1006            bool already_responded = pkt->cacheResponding();
1007            cpuSidePort.sendAtomicSnoop(pkt);
1008            if (!already_responded && pkt->cacheResponding()) {
1009                // cache-to-cache response from some upper cache:
1010                // forward response to original requester
1011                assert(pkt->isResponse());
1012            }
1013        }
1014    }
1015
1016    bool respond = false;
1017    bool blk_valid = blk && blk->isValid();
1018    if (pkt->isClean()) {
1019        if (blk_valid && blk->isDirty()) {
1020            DPRINTF(CacheVerbose, "%s: packet (snoop) %s found block: %s\n",
1021                    __func__, pkt->print(), blk->print());
1022            PacketPtr wb_pkt = writecleanBlk(blk, pkt->req->getDest(), pkt->id);
1023            PacketList writebacks;
1024            writebacks.push_back(wb_pkt);
1025
1026            if (is_timing) {
1027                // anything that is merely forwarded pays for the forward
1028                // latency and the delay provided by the crossbar
1029                Tick forward_time = clockEdge(forwardLatency) +
1030                    pkt->headerDelay;
1031                doWritebacks(writebacks, forward_time);
1032            } else {
1033                doWritebacksAtomic(writebacks);
1034            }
1035            pkt->setSatisfied();
1036        }
1037    } else if (!blk_valid) {
1038        DPRINTF(CacheVerbose, "%s: snoop miss for %s\n", __func__,
1039                pkt->print());
1040        if (is_deferred) {
1041            // we no longer have the block, and will not respond, but a
1042            // packet was allocated in MSHR::handleSnoop and we have
1043            // to delete it
1044            assert(pkt->needsResponse());
1045
1046            // we have passed the block to a cache upstream, that
1047            // cache should be responding
1048            assert(pkt->cacheResponding());
1049
1050            delete pkt;
1051        }
1052        return snoop_delay;
1053    } else {
1054        DPRINTF(Cache, "%s: snoop hit for %s, old state is %s\n", __func__,
1055                pkt->print(), blk->print());
1056
1057        // We may end up modifying both the block state and the packet (if
1058        // we respond in atomic mode), so just figure out what to do now
1059        // and then do it later. We respond to all snoops that need
1060        // responses provided we have the block in dirty state. The
1061        // invalidation itself is taken care of below. We don't respond to
1062        // cache maintenance operations as this is done by the destination
1063        // xbar.
1064        respond = blk->isDirty() && pkt->needsResponse();
1065
1066        chatty_assert(!(isReadOnly && blk->isDirty()), "Should never have "
1067                      "a dirty block in a read-only cache %s\n", name());
1068    }
1069
1070    // Invalidate any prefetch's from below that would strip write permissions
1071    // MemCmd::HardPFReq is only observed by upstream caches.  After missing
1072    // above and in it's own cache, a new MemCmd::ReadReq is created that
1073    // downstream caches observe.
1074    if (pkt->mustCheckAbove()) {
1075        DPRINTF(Cache, "Found addr %#llx in upper level cache for snoop %s "
1076                "from lower cache\n", pkt->getAddr(), pkt->print());
1077        pkt->setBlockCached();
1078        return snoop_delay;
1079    }
1080
1081    if (pkt->isRead() && !invalidate) {
1082        // reading without requiring the line in a writable state
1083        assert(!needs_writable);
1084        pkt->setHasSharers();
1085
1086        // if the requesting packet is uncacheable, retain the line in
1087        // the current state, otherwhise unset the writable flag,
1088        // which means we go from Modified to Owned (and will respond
1089        // below), remain in Owned (and will respond below), from
1090        // Exclusive to Shared, or remain in Shared
1091        if (!pkt->req->isUncacheable())
1092            blk->status &= ~BlkWritable;
1093        DPRINTF(Cache, "new state is %s\n", blk->print());
1094    }
1095
1096    if (respond) {
1097        // prevent anyone else from responding, cache as well as
1098        // memory, and also prevent any memory from even seeing the
1099        // request
1100        pkt->setCacheResponding();
1101        if (!pkt->isClean() && blk->isWritable()) {
1102            // inform the cache hierarchy that this cache had the line
1103            // in the Modified state so that we avoid unnecessary
1104            // invalidations (see Packet::setResponderHadWritable)
1105            pkt->setResponderHadWritable();
1106
1107            // in the case of an uncacheable request there is no point
1108            // in setting the responderHadWritable flag, but since the
1109            // recipient does not care there is no harm in doing so
1110        } else {
1111            // if the packet has needsWritable set we invalidate our
1112            // copy below and all other copies will be invalidates
1113            // through express snoops, and if needsWritable is not set
1114            // we already called setHasSharers above
1115        }
1116
1117        // if we are returning a writable and dirty (Modified) line,
1118        // we should be invalidating the line
1119        panic_if(!invalidate && !pkt->hasSharers(),
1120                 "%s is passing a Modified line through %s, "
1121                 "but keeping the block", name(), pkt->print());
1122
1123        if (is_timing) {
1124            doTimingSupplyResponse(pkt, blk->data, is_deferred, pending_inval);
1125        } else {
1126            pkt->makeAtomicResponse();
1127            // packets such as upgrades do not actually have any data
1128            // payload
1129            if (pkt->hasData())
1130                pkt->setDataFromBlock(blk->data, blkSize);
1131        }
1132
1133        // When a block is compressed, it must first be decompressed before
1134        // being read, and this increases the snoop delay.
1135        if (compressor && pkt->isRead()) {
1136            snoop_delay += compressor->getDecompressionLatency(blk);
1137        }
1138    }
1139
1140    if (!respond && is_deferred) {
1141        assert(pkt->needsResponse());
1142        delete pkt;
1143    }
1144
1145    // Do this last in case it deallocates block data or something
1146    // like that
1147    if (blk_valid && invalidate) {
1148        invalidateBlock(blk);
1149        DPRINTF(Cache, "new state is %s\n", blk->print());
1150    }
1151
1152    return snoop_delay;
1153}
1154
1155
1156void
1157Cache::recvTimingSnoopReq(PacketPtr pkt)
1158{
1159    DPRINTF(CacheVerbose, "%s: for %s\n", __func__, pkt->print());
1160
1161    // no need to snoop requests that are not in range
1162    if (!inRange(pkt->getAddr())) {
1163        return;
1164    }
1165
1166    bool is_secure = pkt->isSecure();
1167    CacheBlk *blk = tags->findBlock(pkt->getAddr(), is_secure);
1168
1169    Addr blk_addr = pkt->getBlockAddr(blkSize);
1170    MSHR *mshr = mshrQueue.findMatch(blk_addr, is_secure);
1171
1172    // Update the latency cost of the snoop so that the crossbar can
1173    // account for it. Do not overwrite what other neighbouring caches
1174    // have already done, rather take the maximum. The update is
1175    // tentative, for cases where we return before an upward snoop
1176    // happens below.
1177    pkt->snoopDelay = std::max<uint32_t>(pkt->snoopDelay,
1178                                         lookupLatency * clockPeriod());
1179
1180    // Inform request(Prefetch, CleanEvict or Writeback) from below of
1181    // MSHR hit, set setBlockCached.
1182    if (mshr && pkt->mustCheckAbove()) {
1183        DPRINTF(Cache, "Setting block cached for %s from lower cache on "
1184                "mshr hit\n", pkt->print());
1185        pkt->setBlockCached();
1186        return;
1187    }
1188
1189    // Let the MSHR itself track the snoop and decide whether we want
1190    // to go ahead and do the regular cache snoop
1191    if (mshr && mshr->handleSnoop(pkt, order++)) {
1192        DPRINTF(Cache, "Deferring snoop on in-service MSHR to blk %#llx (%s)."
1193                "mshrs: %s\n", blk_addr, is_secure ? "s" : "ns",
1194                mshr->print());
1195
1196        if (mshr->getNumTargets() > numTarget)
1197            warn("allocating bonus target for snoop"); //handle later
1198        return;
1199    }
1200
1201    //We also need to check the writeback buffers and handle those
1202    WriteQueueEntry *wb_entry = writeBuffer.findMatch(blk_addr, is_secure);
1203    if (wb_entry) {
1204        DPRINTF(Cache, "Snoop hit in writeback to addr %#llx (%s)\n",
1205                pkt->getAddr(), is_secure ? "s" : "ns");
1206        // Expect to see only Writebacks and/or CleanEvicts here, both of
1207        // which should not be generated for uncacheable data.
1208        assert(!wb_entry->isUncacheable());
1209        // There should only be a single request responsible for generating
1210        // Writebacks/CleanEvicts.
1211        assert(wb_entry->getNumTargets() == 1);
1212        PacketPtr wb_pkt = wb_entry->getTarget()->pkt;
1213        assert(wb_pkt->isEviction() || wb_pkt->cmd == MemCmd::WriteClean);
1214
1215        if (pkt->isEviction()) {
1216            // if the block is found in the write queue, set the BLOCK_CACHED
1217            // flag for Writeback/CleanEvict snoop. On return the snoop will
1218            // propagate the BLOCK_CACHED flag in Writeback packets and prevent
1219            // any CleanEvicts from travelling down the memory hierarchy.
1220            pkt->setBlockCached();
1221            DPRINTF(Cache, "%s: Squashing %s from lower cache on writequeue "
1222                    "hit\n", __func__, pkt->print());
1223            return;
1224        }
1225
1226        // conceptually writebacks are no different to other blocks in
1227        // this cache, so the behaviour is modelled after handleSnoop,
1228        // the difference being that instead of querying the block
1229        // state to determine if it is dirty and writable, we use the
1230        // command and fields of the writeback packet
1231        bool respond = wb_pkt->cmd == MemCmd::WritebackDirty &&
1232            pkt->needsResponse();
1233        bool have_writable = !wb_pkt->hasSharers();
1234        bool invalidate = pkt->isInvalidate();
1235
1236        if (!pkt->req->isUncacheable() && pkt->isRead() && !invalidate) {
1237            assert(!pkt->needsWritable());
1238            pkt->setHasSharers();
1239            wb_pkt->setHasSharers();
1240        }
1241
1242        if (respond) {
1243            pkt->setCacheResponding();
1244
1245            if (have_writable) {
1246                pkt->setResponderHadWritable();
1247            }
1248
1249            doTimingSupplyResponse(pkt, wb_pkt->getConstPtr<uint8_t>(),
1250                                   false, false);
1251        }
1252
1253        if (invalidate && wb_pkt->cmd != MemCmd::WriteClean) {
1254            // Invalidation trumps our writeback... discard here
1255            // Note: markInService will remove entry from writeback buffer.
1256            markInService(wb_entry);
1257            delete wb_pkt;
1258        }
1259    }
1260
1261    // If this was a shared writeback, there may still be
1262    // other shared copies above that require invalidation.
1263    // We could be more selective and return here if the
1264    // request is non-exclusive or if the writeback is
1265    // exclusive.
1266    uint32_t snoop_delay = handleSnoop(pkt, blk, true, false, false);
1267
1268    // Override what we did when we first saw the snoop, as we now
1269    // also have the cost of the upwards snoops to account for
1270    pkt->snoopDelay = std::max<uint32_t>(pkt->snoopDelay, snoop_delay +
1271                                         lookupLatency * clockPeriod());
1272}
1273
1274Tick
1275Cache::recvAtomicSnoop(PacketPtr pkt)
1276{
1277    // no need to snoop requests that are not in range.
1278    if (!inRange(pkt->getAddr())) {
1279        return 0;
1280    }
1281
1282    CacheBlk *blk = tags->findBlock(pkt->getAddr(), pkt->isSecure());
1283    uint32_t snoop_delay = handleSnoop(pkt, blk, false, false, false);
1284    return snoop_delay + lookupLatency * clockPeriod();
1285}
1286
1287bool
1288Cache::isCachedAbove(PacketPtr pkt, bool is_timing)
1289{
1290    if (!forwardSnoops)
1291        return false;
1292    // Mirroring the flow of HardPFReqs, the cache sends CleanEvict and
1293    // Writeback snoops into upper level caches to check for copies of the
1294    // same block. Using the BLOCK_CACHED flag with the Writeback/CleanEvict
1295    // packet, the cache can inform the crossbar below of presence or absence
1296    // of the block.
1297    if (is_timing) {
1298        Packet snoop_pkt(pkt, true, false);
1299        snoop_pkt.setExpressSnoop();
1300        // Assert that packet is either Writeback or CleanEvict and not a
1301        // prefetch request because prefetch requests need an MSHR and may
1302        // generate a snoop response.
1303        assert(pkt->isEviction() || pkt->cmd == MemCmd::WriteClean);
1304        snoop_pkt.senderState = nullptr;
1305        cpuSidePort.sendTimingSnoopReq(&snoop_pkt);
1306        // Writeback/CleanEvict snoops do not generate a snoop response.
1307        assert(!(snoop_pkt.cacheResponding()));
1308        return snoop_pkt.isBlockCached();
1309    } else {
1310        cpuSidePort.sendAtomicSnoop(pkt);
1311        return pkt->isBlockCached();
1312    }
1313}
1314
1315bool
1316Cache::sendMSHRQueuePacket(MSHR* mshr)
1317{
1318    assert(mshr);
1319
1320    // use request from 1st target
1321    PacketPtr tgt_pkt = mshr->getTarget()->pkt;
1322
1323    if (tgt_pkt->cmd == MemCmd::HardPFReq && forwardSnoops) {
1324        DPRINTF(Cache, "%s: MSHR %s\n", __func__, tgt_pkt->print());
1325
1326        // we should never have hardware prefetches to allocated
1327        // blocks
1328        assert(!tags->findBlock(mshr->blkAddr, mshr->isSecure));
1329
1330        // We need to check the caches above us to verify that
1331        // they don't have a copy of this block in the dirty state
1332        // at the moment. Without this check we could get a stale
1333        // copy from memory that might get used in place of the
1334        // dirty one.
1335        Packet snoop_pkt(tgt_pkt, true, false);
1336        snoop_pkt.setExpressSnoop();
1337        // We are sending this packet upwards, but if it hits we will
1338        // get a snoop response that we end up treating just like a
1339        // normal response, hence it needs the MSHR as its sender
1340        // state
1341        snoop_pkt.senderState = mshr;
1342        cpuSidePort.sendTimingSnoopReq(&snoop_pkt);
1343
1344        // Check to see if the prefetch was squashed by an upper cache (to
1345        // prevent us from grabbing the line) or if a Check to see if a
1346        // writeback arrived between the time the prefetch was placed in
1347        // the MSHRs and when it was selected to be sent or if the
1348        // prefetch was squashed by an upper cache.
1349
1350        // It is important to check cacheResponding before
1351        // prefetchSquashed. If another cache has committed to
1352        // responding, it will be sending a dirty response which will
1353        // arrive at the MSHR allocated for this request. Checking the
1354        // prefetchSquash first may result in the MSHR being
1355        // prematurely deallocated.
1356        if (snoop_pkt.cacheResponding()) {
1357            auto M5_VAR_USED r = outstandingSnoop.insert(snoop_pkt.req);
1358            assert(r.second);
1359
1360            // if we are getting a snoop response with no sharers it
1361            // will be allocated as Modified
1362            bool pending_modified_resp = !snoop_pkt.hasSharers();
1363            markInService(mshr, pending_modified_resp);
1364
1365            DPRINTF(Cache, "Upward snoop of prefetch for addr"
1366                    " %#x (%s) hit\n",
1367                    tgt_pkt->getAddr(), tgt_pkt->isSecure()? "s": "ns");
1368            return false;
1369        }
1370
1371        if (snoop_pkt.isBlockCached()) {
1372            DPRINTF(Cache, "Block present, prefetch squashed by cache.  "
1373                    "Deallocating mshr target %#x.\n",
1374                    mshr->blkAddr);
1375
1376            // Deallocate the mshr target
1377            if (mshrQueue.forceDeallocateTarget(mshr)) {
1378                // Clear block if this deallocation resulted freed an
1379                // mshr when all had previously been utilized
1380                clearBlocked(Blocked_NoMSHRs);
1381            }
1382
1383            // given that no response is expected, delete Request and Packet
1384            delete tgt_pkt;
1385
1386            return false;
1387        }
1388    }
1389
1390    return BaseCache::sendMSHRQueuePacket(mshr);
1391}
1392
1393Cache*
1394CacheParams::create()
1395{
1396    assert(tags);
1397    assert(replacement_policy);
1398
1399    return new Cache(this);
1400}
1401