cache.cc revision 11333
12632Sstever@eecs.umich.edu/*
22632Sstever@eecs.umich.edu * Copyright (c) 2010-2015 ARM Limited
32632Sstever@eecs.umich.edu * All rights reserved.
42632Sstever@eecs.umich.edu *
52632Sstever@eecs.umich.edu * The license below extends only to copyright in the software and shall
62632Sstever@eecs.umich.edu * not be construed as granting a license to any other intellectual
72632Sstever@eecs.umich.edu * property including but not limited to intellectual property relating
82632Sstever@eecs.umich.edu * to a hardware implementation of the functionality of the software
92632Sstever@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
102632Sstever@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
112632Sstever@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
122632Sstever@eecs.umich.edu * modified or unmodified, in source code or in binary form.
132632Sstever@eecs.umich.edu *
142632Sstever@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan
152632Sstever@eecs.umich.edu * Copyright (c) 2010,2015 Advanced Micro Devices, Inc.
162632Sstever@eecs.umich.edu * All rights reserved.
172632Sstever@eecs.umich.edu *
182632Sstever@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
192632Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are
202632Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright
212632Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
222632Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
232632Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
242632Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution;
252632Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its
262632Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from
272632Sstever@eecs.umich.edu * this software without specific prior written permission.
282632Sstever@eecs.umich.edu *
292632Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
302632Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312022SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
322022SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
332022SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342022SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
352022SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362469SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372469SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
382469SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
392469SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402516SN/A *
412516SN/A * Authors: Erik Hallnor
422944Sgblack@eecs.umich.edu *          Dave Greene
432482SN/A *          Nathan Binkert
443598Sgblack@eecs.umich.edu *          Steve Reinhardt
453056Sgblack@eecs.umich.edu *          Ron Dreslinski
462469SN/A *          Andreas Sandberg
473056Sgblack@eecs.umich.edu */
483056Sgblack@eecs.umich.edu
493056Sgblack@eecs.umich.edu/**
503598Sgblack@eecs.umich.edu * @file
512516SN/A * Cache definitions.
523056Sgblack@eecs.umich.edu */
533598Sgblack@eecs.umich.edu
543056Sgblack@eecs.umich.edu#include "mem/cache/cache.hh"
553056Sgblack@eecs.umich.edu
563056Sgblack@eecs.umich.edu#include "base/misc.hh"
573056Sgblack@eecs.umich.edu#include "base/types.hh"
583056Sgblack@eecs.umich.edu#include "debug/Cache.hh"
593056Sgblack@eecs.umich.edu#include "debug/CachePort.hh"
603056Sgblack@eecs.umich.edu#include "debug/CacheTags.hh"
613598Sgblack@eecs.umich.edu#include "debug/CacheVerbose.hh"
623056Sgblack@eecs.umich.edu#include "mem/cache/blk.hh"
633056Sgblack@eecs.umich.edu#include "mem/cache/mshr.hh"
643598Sgblack@eecs.umich.edu#include "mem/cache/prefetch/base.hh"
653056Sgblack@eecs.umich.edu#include "sim/sim_exit.hh"
663056Sgblack@eecs.umich.edu
673056Sgblack@eecs.umich.eduCache::Cache(const CacheParams *p)
683056Sgblack@eecs.umich.edu    : BaseCache(p, p->system->cacheLineSize()),
693056Sgblack@eecs.umich.edu      tags(p->tags),
703056Sgblack@eecs.umich.edu      prefetcher(p->prefetcher),
713056Sgblack@eecs.umich.edu      doFastWrites(true),
723056Sgblack@eecs.umich.edu      prefetchOnAccess(p->prefetch_on_access),
733056Sgblack@eecs.umich.edu      clusivity(p->clusivity),
743056Sgblack@eecs.umich.edu      writebackClean(p->writeback_clean),
753056Sgblack@eecs.umich.edu      tempBlockWriteback(nullptr),
763056Sgblack@eecs.umich.edu      writebackTempBlockAtomicEvent(this, false,
773056Sgblack@eecs.umich.edu                                    EventBase::Delayed_Writeback_Pri)
783056Sgblack@eecs.umich.edu{
793056Sgblack@eecs.umich.edu    tempBlock = new CacheBlk();
803056Sgblack@eecs.umich.edu    tempBlock->data = new uint8_t[blkSize];
813056Sgblack@eecs.umich.edu
823056Sgblack@eecs.umich.edu    cpuSidePort = new CpuSidePort(p->name + ".cpu_side", this,
833056Sgblack@eecs.umich.edu                                  "CpuSidePort");
842482SN/A    memSidePort = new MemSidePort(p->name + ".mem_side", this,
853598Sgblack@eecs.umich.edu                                  "MemSidePort");
863598Sgblack@eecs.umich.edu
873598Sgblack@eecs.umich.edu    tags->setCache(this);
883598Sgblack@eecs.umich.edu    if (prefetcher)
893598Sgblack@eecs.umich.edu        prefetcher->setCache(this);
903598Sgblack@eecs.umich.edu}
913598Sgblack@eecs.umich.edu
923598Sgblack@eecs.umich.eduCache::~Cache()
933598Sgblack@eecs.umich.edu{
943598Sgblack@eecs.umich.edu    delete [] tempBlock->data;
953598Sgblack@eecs.umich.edu    delete tempBlock;
963598Sgblack@eecs.umich.edu
973598Sgblack@eecs.umich.edu    delete cpuSidePort;
983598Sgblack@eecs.umich.edu    delete memSidePort;
993598Sgblack@eecs.umich.edu}
1003598Sgblack@eecs.umich.edu
1013598Sgblack@eecs.umich.eduvoid
1023598Sgblack@eecs.umich.eduCache::regStats()
1033598Sgblack@eecs.umich.edu{
1043598Sgblack@eecs.umich.edu    BaseCache::regStats();
1053598Sgblack@eecs.umich.edu}
1063598Sgblack@eecs.umich.edu
1073598Sgblack@eecs.umich.eduvoid
1083598Sgblack@eecs.umich.eduCache::cmpAndSwap(CacheBlk *blk, PacketPtr pkt)
1093598Sgblack@eecs.umich.edu{
1103598Sgblack@eecs.umich.edu    assert(pkt->isRequest());
1113598Sgblack@eecs.umich.edu
1123598Sgblack@eecs.umich.edu    uint64_t overwrite_val;
1133598Sgblack@eecs.umich.edu    bool overwrite_mem;
1143598Sgblack@eecs.umich.edu    uint64_t condition_val64;
1153598Sgblack@eecs.umich.edu    uint32_t condition_val32;
1163598Sgblack@eecs.umich.edu
1172516SN/A    int offset = tags->extractBlkOffset(pkt->getAddr());
1182516SN/A    uint8_t *blk_data = blk->data + offset;
1192516SN/A
1202516SN/A    assert(sizeof(uint64_t) >= pkt->getSize());
1212482SN/A
1222482SN/A    overwrite_mem = true;
1232591SN/A    // keep a copy of our possible write value, and copy what is at the
1242516SN/A    // memory address into the packet
1252580SN/A    pkt->writeData((uint8_t *)&overwrite_val);
1262580SN/A    pkt->setData(blk_data);
1272482SN/A
1282482SN/A    if (pkt->req->isCondSwap()) {
1292591SN/A        if (pkt->getSize() == sizeof(uint64_t)) {
1302516SN/A            condition_val64 = pkt->req->getExtraData();
1312580SN/A            overwrite_mem = !std::memcmp(&condition_val64, blk_data,
1322580SN/A                                         sizeof(uint64_t));
1332482SN/A        } else if (pkt->getSize() == sizeof(uint32_t)) {
1342482SN/A            condition_val32 = (uint32_t)pkt->req->getExtraData();
1352591SN/A            overwrite_mem = !std::memcmp(&condition_val32, blk_data,
1362516SN/A                                         sizeof(uint32_t));
1372580SN/A        } else
1382580SN/A            panic("Invalid size for conditional read/write\n");
1392482SN/A    }
1402482SN/A
1412591SN/A    if (overwrite_mem) {
1422516SN/A        std::memcpy(blk_data, &overwrite_val, pkt->getSize());
1432580SN/A        blk->status |= BlkDirty;
1442580SN/A    }
1452482SN/A}
1462482SN/A
1472591SN/A
1482516SN/Avoid
1492580SN/ACache::satisfyCpuSideRequest(PacketPtr pkt, CacheBlk *blk,
1502580SN/A                             bool deferred_response, bool pending_downgrade)
1512482SN/A{
1522482SN/A    assert(pkt->isRequest());
1532591SN/A
1542516SN/A    assert(blk && blk->isValid());
1552580SN/A    // Occasionally this is not true... if we are a lower-level cache
1562580SN/A    // satisfying a string of Read and ReadEx requests from
1572482SN/A    // upper-level caches, a Read will mark the block as shared but we
1582469SN/A    // can satisfy a following ReadEx anyway since we can rely on the
1592482SN/A    // Read requester(s) to have buffered the ReadEx snoop and to
1602516SN/A    // invalidate their blocks after receiving them.
1613042Sgblack@eecs.umich.edu    // assert(!pkt->needsWritable() || blk->isWritable());
1622516SN/A    assert(pkt->getOffset(blkSize) + pkt->getSize() <= blkSize);
1632516SN/A
1642469SN/A    // Check RMW operations first since both isRead() and
1652944Sgblack@eecs.umich.edu    // isWrite() will be true for them
1662516SN/A    if (pkt->cmd == MemCmd::SwapReq) {
1672516SN/A        cmpAndSwap(blk, pkt);
1682469SN/A    } else if (pkt->isWrite()) {
1692469SN/A        // we have the block in a writable state and can go ahead,
1702482SN/A        // note that the line may be also be considered writable in
1712482SN/A        // downstream caches along the path to memory, but always
1722974Sgblack@eecs.umich.edu        // Exclusive, and never Modified
1732974Sgblack@eecs.umich.edu        assert(blk->isWritable());
1742974Sgblack@eecs.umich.edu        // Write or WriteLine at the first cache with block in writable state
1752526SN/A        if (blk->checkWrite(pkt)) {
1762974Sgblack@eecs.umich.edu            pkt->writeDataToBlock(blk->data, blkSize);
1772974Sgblack@eecs.umich.edu        }
1782974Sgblack@eecs.umich.edu        // Always mark the line as dirty (and thus transition to the
1792646Ssaidi@eecs.umich.edu        // Modified state) even if we are a failed StoreCond so we
1802974Sgblack@eecs.umich.edu        // supply data to any snoops that have appended themselves to
1812469SN/A        // this cache before knowing the store will fail.
1822516SN/A        blk->status |= BlkDirty;
1832646Ssaidi@eecs.umich.edu        DPRINTF(CacheVerbose, "%s for %s addr %#llx size %d (write)\n",
1842482SN/A                __func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize());
1852469SN/A    } else if (pkt->isRead()) {
1862516SN/A        if (pkt->isLLSC()) {
1872646Ssaidi@eecs.umich.edu            blk->trackLoadLocked(pkt);
1882482SN/A        }
1892954Sgblack@eecs.umich.edu
1902469SN/A        // all read responses have a data payload
1912516SN/A        assert(pkt->hasRespData());
1922516SN/A        pkt->setDataFromBlock(blk->data, blkSize);
1932482SN/A
1942469SN/A        // determine if this read is from a (coherent) cache, or not
1952516SN/A        // by looking at the command type; we could potentially add a
1962482SN/A        // packet attribute such as 'FromCache' to make this check a
1972482SN/A        // bit cleaner
1982646Ssaidi@eecs.umich.edu        if (pkt->cmd == MemCmd::ReadExReq ||
1992482SN/A            pkt->cmd == MemCmd::ReadSharedReq ||
2002482SN/A            pkt->cmd == MemCmd::ReadCleanReq ||
2012482SN/A            pkt->cmd == MemCmd::SCUpgradeFailReq) {
2022482SN/A            assert(pkt->getSize() == blkSize);
2032482SN/A            // special handling for coherent block requests from
2042615SN/A            // upper-level caches
2052469SN/A            if (pkt->needsWritable()) {
2062469SN/A                // sanity check
2072482SN/A                assert(pkt->cmd == MemCmd::ReadExReq ||
2082646Ssaidi@eecs.umich.edu                       pkt->cmd == MemCmd::SCUpgradeFailReq);
2092482SN/A
2102482SN/A                // if we have a dirty copy, make sure the recipient
2112482SN/A                // keeps it marked dirty (in the modified state)
2122588SN/A                if (blk->isDirty()) {
2132482SN/A                    pkt->setCacheResponding();
2142526SN/A                }
2152469SN/A                // on ReadExReq we give up our copy unconditionally,
2162482SN/A                // even if this cache is mostly inclusive, we may want
2172469SN/A                // to revisit this
2182516SN/A                invalidateBlock(blk);
2192469SN/A            } else if (blk->isWritable() && !pending_downgrade &&
2202580SN/A                       !pkt->hasSharers() &&
2212469SN/A                       pkt->cmd != MemCmd::ReadCleanReq) {
2222580SN/A                // we can give the requester a writable copy on a read
2232469SN/A                // request if:
2242526SN/A                // - we have a writable copy at this level (& below)
2252482SN/A                // - we don't have a pending snoop from below
2262482SN/A                //   signaling another read request
2272482SN/A                // - no other cache above has a copy (otherwise it
2282469SN/A                //   would have set hasSharers flag when
2292580SN/A                //   snooping the packet)
2302580SN/A                // - the read has explicitly asked for a clean
2312580SN/A                //   copy of the line
2322580SN/A                if (blk->isDirty()) {
2332580SN/A                    // special considerations if we're owner:
2342580SN/A                    if (!deferred_response) {
2352580SN/A                        // respond with the line in Modified state
2362526SN/A                        // (cacheResponding set, hasSharers not set)
2372482SN/A                        pkt->setCacheResponding();
2382482SN/A
2392482SN/A                        if (clusivity == Enums::mostly_excl) {
2402469SN/A                            // if this cache is mostly exclusive with
2412516SN/A                            // respect to the cache above, drop the
2422646Ssaidi@eecs.umich.edu                            // block, no need to first unset the dirty
2432469SN/A                            // bit
2442580SN/A                            invalidateBlock(blk);
2452469SN/A                        } else {
2462580SN/A                            // if this cache is mostly inclusive, we
2472580SN/A                            // keep the block in the Exclusive state,
2482469SN/A                            // and pass it upwards as Modified
2492526SN/A                            // (writable and dirty), hence we have
2502469SN/A                            // multiple caches, all on the same path
2512615SN/A                            // towards memory, all considering the
2522615SN/A                            // same block writable, but only one
2532646Ssaidi@eecs.umich.edu                            // considering it Modified
2542526SN/A
2552469SN/A                            // we get away with multiple caches (on
2562615SN/A                            // the same path to memory) considering
2572615SN/A                            // the block writeable as we always enter
2582646Ssaidi@eecs.umich.edu                            // the cache hierarchy through a cache,
2592526SN/A                            // and first snoop upwards in all other
2602469SN/A                            // branches
2612516SN/A                            blk->status &= ~BlkDirty;
2622646Ssaidi@eecs.umich.edu                        }
2632954Sgblack@eecs.umich.edu                    } else {
2642580SN/A                        // if we're responding after our own miss,
2652469SN/A                        // there's a window where the recipient didn't
2662580SN/A                        // know it was getting ownership and may not
2672469SN/A                        // have responded to snoops correctly, so we
2682526SN/A                        // have to respond with a shared line
2692469SN/A                        pkt->setHasSharers();
2702615SN/A                    }
2712615SN/A                }
2722526SN/A            } else {
2732469SN/A                // otherwise only respond with a shared copy
2742615SN/A                pkt->setHasSharers();
2752989Ssaidi@eecs.umich.edu            }
2762469SN/A        }
2772469SN/A    } else {
2782224SN/A        // Upgrade or Invalidate
2792646Ssaidi@eecs.umich.edu        assert(pkt->isUpgrade() || pkt->isInvalidate());
2802516SN/A
2812516SN/A        // for invalidations we could be looking at the temp block
2822516SN/A        // (for upgrades we always allocate)
2832469SN/A        invalidateBlock(blk);
2842469SN/A        DPRINTF(CacheVerbose, "%s for %s addr %#llx size %d (invalidation)\n",
2852469SN/A                __func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize());
2862469SN/A    }
2872469SN/A}
2882526SN/A
2892469SN/A
2902996Sgblack@eecs.umich.edu/////////////////////////////////////////////////////
2912996Sgblack@eecs.umich.edu//
2922469SN/A// MSHR helper functions
2932469SN/A//
2942469SN/A/////////////////////////////////////////////////////
2952996Sgblack@eecs.umich.edu
2962996Sgblack@eecs.umich.edu
2972996Sgblack@eecs.umich.eduvoid
2982996Sgblack@eecs.umich.eduCache::markInService(MSHR *mshr, bool pending_modified_resp)
2992996Sgblack@eecs.umich.edu{
3002469SN/A    markInServiceInternal(mshr, pending_modified_resp);
3012469SN/A}
3022469SN/A
3032469SN/A/////////////////////////////////////////////////////
3042469SN/A//
3052526SN/A// Access path: requests coming in from the CPU side
3062469SN/A//
3072516SN/A/////////////////////////////////////////////////////
3082469SN/A
3092469SN/Abool
3103753Sgblack@eecs.umich.eduCache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat,
3112469SN/A              PacketList &writebacks)
3122469SN/A{
3132469SN/A    // sanity check
3142526SN/A    assert(pkt->isRequest());
3152469SN/A
3162516SN/A    chatty_assert(!(isReadOnly && pkt->isWrite()),
3172469SN/A                  "Should never see a write in a read-only cache %s\n",
3182469SN/A                  name());
3193753Sgblack@eecs.umich.edu
3202469SN/A    DPRINTF(CacheVerbose, "%s for %s addr %#llx size %d\n", __func__,
3212469SN/A            pkt->cmdString(), pkt->getAddr(), pkt->getSize());
3222469SN/A
3232526SN/A    if (pkt->req->isUncacheable()) {
3242469SN/A        DPRINTF(Cache, "%s%s addr %#llx uncacheable\n", pkt->cmdString(),
3252996Sgblack@eecs.umich.edu                pkt->req->isInstFetch() ? " (ifetch)" : "",
3262996Sgblack@eecs.umich.edu                pkt->getAddr());
3272954Sgblack@eecs.umich.edu
3282954Sgblack@eecs.umich.edu        // flush and invalidate any existing block
3292469SN/A        CacheBlk *old_blk(tags->findBlock(pkt->getAddr(), pkt->isSecure()));
3303753Sgblack@eecs.umich.edu        if (old_blk && old_blk->isValid()) {
3312469SN/A            if (old_blk->isDirty() || writebackClean)
3322469SN/A                writebacks.push_back(writebackBlk(old_blk));
3332996Sgblack@eecs.umich.edu            else
3342526SN/A                writebacks.push_back(cleanEvictBlk(old_blk));
3352469SN/A            tags->invalidate(old_blk);
3362516SN/A            old_blk->invalidate();
3372469SN/A        }
3382469SN/A
3392469SN/A        blk = NULL;
3403753Sgblack@eecs.umich.edu        // lookupLatency is the latency in case the request is uncacheable.
3412469SN/A        lat = lookupLatency;
3422469SN/A        return false;
3432469SN/A    }
3442526SN/A
3452469SN/A    ContextID id = pkt->req->hasContextId() ?
3462516SN/A        pkt->req->contextId() : InvalidContextID;
3472469SN/A    // Here lat is the value passed as parameter to accessBlock() function
3482469SN/A    // that can modify its value.
3492516SN/A    blk = tags->accessBlock(pkt->getAddr(), pkt->isSecure(), lat, id);
3503753Sgblack@eecs.umich.edu
3512646Ssaidi@eecs.umich.edu    DPRINTF(Cache, "%s%s addr %#llx size %d (%s) %s\n", pkt->cmdString(),
3522469SN/A            pkt->req->isInstFetch() ? " (ifetch)" : "",
3532469SN/A            pkt->getAddr(), pkt->getSize(), pkt->isSecure() ? "s" : "ns",
3542646Ssaidi@eecs.umich.edu            blk ? "hit " + blk->print() : "miss");
3553753Sgblack@eecs.umich.edu
3562469SN/A
3572469SN/A    if (pkt->isEviction()) {
3582469SN/A        // We check for presence of block in above caches before issuing
3592526SN/A        // Writeback or CleanEvict to write buffer. Therefore the only
3602526SN/A        // possible cases can be of a CleanEvict packet coming from above
3612526SN/A        // encountering a Writeback generated in this cache peer cache and
3622526SN/A        // waiting in the write buffer. Cases of upper level peer caches
3632526SN/A        // generating CleanEvict and Writeback or simply CleanEvict and
3642526SN/A        // CleanEvict almost simultaneously will be caught by snoops sent out
3652526SN/A        // by crossbar.
3662469SN/A        std::vector<MSHR *> outgoing;
3672526SN/A        if (writeBuffer.findMatches(pkt->getAddr(), pkt->isSecure(),
3682526SN/A                                   outgoing)) {
3692526SN/A            assert(outgoing.size() == 1);
3702526SN/A            MSHR *wb_entry = outgoing[0];
3712526SN/A            assert(wb_entry->getNumTargets() == 1);
3722526SN/A            PacketPtr wbPkt = wb_entry->getTarget()->pkt;
3732526SN/A            assert(wbPkt->isWriteback());
3742526SN/A
3752954Sgblack@eecs.umich.edu            if (pkt->isCleanEviction()) {
3763587Sgblack@eecs.umich.edu                // The CleanEvict and WritebackClean snoops into other
3773587Sgblack@eecs.umich.edu                // peer caches of the same level while traversing the
3783587Sgblack@eecs.umich.edu                // crossbar. If a copy of the block is found, the
3793587Sgblack@eecs.umich.edu                // packet is deleted in the crossbar. Hence, none of
3803823Ssaidi@eecs.umich.edu                // the other upper level caches connected to this
3813587Sgblack@eecs.umich.edu                // cache have the block, so we can clear the
3823587Sgblack@eecs.umich.edu                // BLOCK_CACHED flag in the Writeback if set and
3833587Sgblack@eecs.umich.edu                // discard the CleanEvict by returning true.
3843587Sgblack@eecs.umich.edu                wbPkt->clearBlockCached();
3853587Sgblack@eecs.umich.edu                return true;
3863587Sgblack@eecs.umich.edu            } else {
3873587Sgblack@eecs.umich.edu                assert(pkt->cmd == MemCmd::WritebackDirty);
3883587Sgblack@eecs.umich.edu                // Dirty writeback from above trumps our clean
3893587Sgblack@eecs.umich.edu                // writeback... discard here
3903587Sgblack@eecs.umich.edu                // Note: markInService will remove entry from writeback buffer.
3913587Sgblack@eecs.umich.edu                markInService(wb_entry, false);
3922954Sgblack@eecs.umich.edu                delete wbPkt;
3932954Sgblack@eecs.umich.edu            }
3942954Sgblack@eecs.umich.edu        }
3953587Sgblack@eecs.umich.edu    }
3963587Sgblack@eecs.umich.edu
3973587Sgblack@eecs.umich.edu    // Writeback handling is special case.  We can write the block into
3983587Sgblack@eecs.umich.edu    // the cache without having a writeable copy (or any copy at all).
3993587Sgblack@eecs.umich.edu    if (pkt->isWriteback()) {
4003587Sgblack@eecs.umich.edu        assert(blkSize == pkt->getSize());
4013587Sgblack@eecs.umich.edu
4023587Sgblack@eecs.umich.edu        // we could get a clean writeback while we are having
4032954Sgblack@eecs.umich.edu        // outstanding accesses to a block, do the simple thing for
4043587Sgblack@eecs.umich.edu        // now and drop the clean writeback so that we do not upset
4053587Sgblack@eecs.umich.edu        // any ordering/decisions about ownership already taken
4063823Ssaidi@eecs.umich.edu        if (pkt->cmd == MemCmd::WritebackClean &&
4073823Ssaidi@eecs.umich.edu            mshrQueue.findMatch(pkt->getAddr(), pkt->isSecure())) {
4083823Ssaidi@eecs.umich.edu            DPRINTF(Cache, "Clean writeback %#llx to block with MSHR, "
4093598Sgblack@eecs.umich.edu                    "dropping\n", pkt->getAddr());
4103598Sgblack@eecs.umich.edu            return true;
4113598Sgblack@eecs.umich.edu        }
4123598Sgblack@eecs.umich.edu
4133598Sgblack@eecs.umich.edu        if (blk == NULL) {
4143598Sgblack@eecs.umich.edu            // need to do a replacement
4153598Sgblack@eecs.umich.edu            blk = allocateBlock(pkt->getAddr(), pkt->isSecure(), writebacks);
4163598Sgblack@eecs.umich.edu            if (blk == NULL) {
4173598Sgblack@eecs.umich.edu                // no replaceable block available: give up, fwd to next level.
4182954Sgblack@eecs.umich.edu                incMissCount(pkt);
4193587Sgblack@eecs.umich.edu                return false;
4203587Sgblack@eecs.umich.edu            }
4213587Sgblack@eecs.umich.edu            tags->insertBlock(pkt, blk);
4223587Sgblack@eecs.umich.edu
4233587Sgblack@eecs.umich.edu            blk->status = (BlkValid | BlkReadable);
4243587Sgblack@eecs.umich.edu            if (pkt->isSecure()) {
4253587Sgblack@eecs.umich.edu                blk->status |= BlkSecure;
4263587Sgblack@eecs.umich.edu            }
4273587Sgblack@eecs.umich.edu        }
4283587Sgblack@eecs.umich.edu        // only mark the block dirty if we got a writeback command,
4293587Sgblack@eecs.umich.edu        // and leave it as is for a clean writeback
4303587Sgblack@eecs.umich.edu        if (pkt->cmd == MemCmd::WritebackDirty) {
4313587Sgblack@eecs.umich.edu            blk->status |= BlkDirty;
4323823Ssaidi@eecs.umich.edu        }
4333587Sgblack@eecs.umich.edu        // if the packet does not have sharers, it is passing
4343587Sgblack@eecs.umich.edu        // writable, and we got the writeback in Modified or Exclusive
4353587Sgblack@eecs.umich.edu        // state, if not we are in the Owned or Shared state
4363587Sgblack@eecs.umich.edu        if (!pkt->hasSharers()) {
4373587Sgblack@eecs.umich.edu            blk->status |= BlkWritable;
4383587Sgblack@eecs.umich.edu        }
4393587Sgblack@eecs.umich.edu        // nothing else to do; writeback doesn't expect response
4403587Sgblack@eecs.umich.edu        assert(!pkt->needsResponse());
4413587Sgblack@eecs.umich.edu        std::memcpy(blk->data, pkt->getConstPtr<uint8_t>(), blkSize);
4423587Sgblack@eecs.umich.edu        DPRINTF(Cache, "%s new state is %s\n", __func__, blk->print());
4433587Sgblack@eecs.umich.edu        incHitCount(pkt);
4443587Sgblack@eecs.umich.edu        return true;
4453587Sgblack@eecs.umich.edu    } else if (pkt->cmd == MemCmd::CleanEvict) {
4463587Sgblack@eecs.umich.edu        if (blk != NULL) {
4473587Sgblack@eecs.umich.edu            // Found the block in the tags, need to stop CleanEvict from
4483587Sgblack@eecs.umich.edu            // propagating further down the hierarchy. Returning true will
4493587Sgblack@eecs.umich.edu            // treat the CleanEvict like a satisfied write request and delete
4503587Sgblack@eecs.umich.edu            // it.
4513587Sgblack@eecs.umich.edu            return true;
4523587Sgblack@eecs.umich.edu        }
4533587Sgblack@eecs.umich.edu        // We didn't find the block here, propagate the CleanEvict further
4543587Sgblack@eecs.umich.edu        // down the memory hierarchy. Returning false will treat the CleanEvict
4553823Ssaidi@eecs.umich.edu        // like a Writeback which could not find a replaceable block so has to
4563587Sgblack@eecs.umich.edu        // go to next level.
4573587Sgblack@eecs.umich.edu        return false;
4583587Sgblack@eecs.umich.edu    } else if ((blk != NULL) &&
4593587Sgblack@eecs.umich.edu               (pkt->needsWritable() ? blk->isWritable() : blk->isReadable())) {
4603587Sgblack@eecs.umich.edu        // OK to satisfy access
4613587Sgblack@eecs.umich.edu        incHitCount(pkt);
4623587Sgblack@eecs.umich.edu        satisfyCpuSideRequest(pkt, blk);
4633587Sgblack@eecs.umich.edu        return true;
4643587Sgblack@eecs.umich.edu    }
4653587Sgblack@eecs.umich.edu
4663587Sgblack@eecs.umich.edu    // Can't satisfy access normally... either no block (blk == NULL)
4673587Sgblack@eecs.umich.edu    // or have block but need writable
4683587Sgblack@eecs.umich.edu
4693587Sgblack@eecs.umich.edu    incMissCount(pkt);
4702526SN/A
4712526SN/A    if (blk == NULL && pkt->isLLSC() && pkt->isWrite()) {
4722526SN/A        // complete miss on store conditional... just give up now
4732526SN/A        pkt->req->setExtraData(0);
4742646Ssaidi@eecs.umich.edu        return true;
4752526SN/A    }
4762646Ssaidi@eecs.umich.edu
4772526SN/A    return false;
4782526SN/A}
4792526SN/A
4802469SN/Avoid
4812526SN/ACache::doWritebacks(PacketList& writebacks, Tick forward_time)
4822526SN/A{
4832526SN/A    while (!writebacks.empty()) {
4842526SN/A        PacketPtr wbPkt = writebacks.front();
4852646Ssaidi@eecs.umich.edu        // We use forwardLatency here because we are copying writebacks to
4862591SN/A        // write buffer.  Call isCachedAbove for both Writebacks and
4872591SN/A        // CleanEvicts. If isCachedAbove returns true we set BLOCK_CACHED flag
4882591SN/A        // in Writebacks and discard CleanEvicts.
4892526SN/A        if (isCachedAbove(wbPkt)) {
4902526SN/A            if (wbPkt->cmd == MemCmd::CleanEvict) {
4912646Ssaidi@eecs.umich.edu                // Delete CleanEvict because cached copies exist above. The
4922591SN/A                // packet destructor will delete the request object because
4932591SN/A                // this is a non-snoop request packet which does not require a
4942591SN/A                // response.
4952526SN/A                delete wbPkt;
4962224SN/A            } else if (wbPkt->cmd == MemCmd::WritebackClean) {
4972526SN/A                // clean writeback, do not send since the block is
4982526SN/A                // still cached above
4992615SN/A                assert(writebackClean);
5002615SN/A                delete wbPkt;
5012526SN/A            } else {
5022526SN/A                assert(wbPkt->cmd == MemCmd::WritebackDirty);
5032526SN/A                // Set BLOCK_CACHED flag in Writeback and send below, so that
5042526SN/A                // the Writeback does not reset the bit corresponding to this
5052526SN/A                // address in the snoop filter below.
5062526SN/A                wbPkt->setBlockCached();
5072526SN/A                allocateWriteBuffer(wbPkt, forward_time);
5082526SN/A            }
5092469SN/A        } else {
5102526SN/A            // If the block is not cached above, send packet below. Both
5112526SN/A            // CleanEvict and Writeback with BLOCK_CACHED flag cleared will
5122516SN/A            // reset the bit corresponding to this address in the snoop filter
5132591SN/A            // below.
5142516SN/A            allocateWriteBuffer(wbPkt, forward_time);
5152526SN/A        }
5162526SN/A        writebacks.pop_front();
5172526SN/A    }
5182615SN/A}
5192615SN/A
5202615SN/Avoid
5212615SN/ACache::doWritebacksAtomic(PacketList& writebacks)
5222615SN/A{
5232615SN/A    while (!writebacks.empty()) {
5242526SN/A        PacketPtr wbPkt = writebacks.front();
5253587Sgblack@eecs.umich.edu        // Call isCachedAbove for both Writebacks and CleanEvicts. If
5263587Sgblack@eecs.umich.edu        // isCachedAbove returns true we set BLOCK_CACHED flag in Writebacks
5273587Sgblack@eecs.umich.edu        // and discard CleanEvicts.
5283587Sgblack@eecs.umich.edu        if (isCachedAbove(wbPkt, false)) {
5293587Sgblack@eecs.umich.edu            if (wbPkt->cmd == MemCmd::WritebackDirty) {
5303587Sgblack@eecs.umich.edu                // Set BLOCK_CACHED flag in Writeback and send below,
5313587Sgblack@eecs.umich.edu                // so that the Writeback does not reset the bit
5323587Sgblack@eecs.umich.edu                // corresponding to this address in the snoop filter
5333587Sgblack@eecs.umich.edu                // below. We can discard CleanEvicts because cached
5343587Sgblack@eecs.umich.edu                // copies exist above. Atomic mode isCachedAbove
5353587Sgblack@eecs.umich.edu                // modifies packet to set BLOCK_CACHED flag
5363587Sgblack@eecs.umich.edu                memSidePort->sendAtomic(wbPkt);
5373587Sgblack@eecs.umich.edu            }
5383587Sgblack@eecs.umich.edu        } else {
5393587Sgblack@eecs.umich.edu            // If the block is not cached above, send packet below. Both
5403587Sgblack@eecs.umich.edu            // CleanEvict and Writeback with BLOCK_CACHED flag cleared will
5413587Sgblack@eecs.umich.edu            // reset the bit corresponding to this address in the snoop filter
5423587Sgblack@eecs.umich.edu            // below.
5433587Sgblack@eecs.umich.edu            memSidePort->sendAtomic(wbPkt);
5443587Sgblack@eecs.umich.edu        }
5453823Ssaidi@eecs.umich.edu        writebacks.pop_front();
5463587Sgblack@eecs.umich.edu        // In case of CleanEvicts, the packet destructor will delete the
5473587Sgblack@eecs.umich.edu        // request object because this is a non-snoop request packet which
5483587Sgblack@eecs.umich.edu        // does not require a response.
5493823Ssaidi@eecs.umich.edu        delete wbPkt;
5503587Sgblack@eecs.umich.edu    }
5513823Ssaidi@eecs.umich.edu}
5523598Sgblack@eecs.umich.edu
5533598Sgblack@eecs.umich.edu
5543598Sgblack@eecs.umich.eduvoid
5553598Sgblack@eecs.umich.eduCache::recvTimingSnoopResp(PacketPtr pkt)
5563598Sgblack@eecs.umich.edu{
5573598Sgblack@eecs.umich.edu    DPRINTF(Cache, "%s for %s addr %#llx size %d\n", __func__,
5583598Sgblack@eecs.umich.edu            pkt->cmdString(), pkt->getAddr(), pkt->getSize());
5593598Sgblack@eecs.umich.edu
5603598Sgblack@eecs.umich.edu    assert(pkt->isResponse());
5613598Sgblack@eecs.umich.edu    assert(!system->bypassCaches());
5623587Sgblack@eecs.umich.edu
5632526SN/A    // determine if the response is from a snoop request we created
5643417Sgblack@eecs.umich.edu    // (in which case it should be in the outstandingSnoop), or if we
5653417Sgblack@eecs.umich.edu    // merely forwarded someone else's snoop request
5663417Sgblack@eecs.umich.edu    const bool forwardAsSnoop = outstandingSnoop.find(pkt->req) ==
5673417Sgblack@eecs.umich.edu        outstandingSnoop.end();
5683417Sgblack@eecs.umich.edu
5693417Sgblack@eecs.umich.edu    if (!forwardAsSnoop) {
5703417Sgblack@eecs.umich.edu        // the packet came from this cache, so sink it here and do not
5713417Sgblack@eecs.umich.edu        // forward it
5723417Sgblack@eecs.umich.edu        assert(pkt->cmd == MemCmd::HardPFResp);
5733598Sgblack@eecs.umich.edu
5743417Sgblack@eecs.umich.edu        outstandingSnoop.erase(pkt->req);
5753417Sgblack@eecs.umich.edu
5763417Sgblack@eecs.umich.edu        DPRINTF(Cache, "Got prefetch response from above for addr "
5773417Sgblack@eecs.umich.edu                "%#llx (%s)\n", pkt->getAddr(), pkt->isSecure() ? "s" : "ns");
5783417Sgblack@eecs.umich.edu        recvTimingResp(pkt);
5793417Sgblack@eecs.umich.edu        return;
5803417Sgblack@eecs.umich.edu    }
5813417Sgblack@eecs.umich.edu
5822526SN/A    // forwardLatency is set here because there is a response from an
5833587Sgblack@eecs.umich.edu    // upper level cache.
5843587Sgblack@eecs.umich.edu    // To pay the delay that occurs if the packet comes from the bus,
5853587Sgblack@eecs.umich.edu    // we charge also headerDelay.
5863587Sgblack@eecs.umich.edu    Tick snoop_resp_time = clockEdge(forwardLatency) + pkt->headerDelay;
5873587Sgblack@eecs.umich.edu    // Reset the timing of the packet.
5883587Sgblack@eecs.umich.edu    pkt->headerDelay = pkt->payloadDelay = 0;
5893587Sgblack@eecs.umich.edu    memSidePort->schedTimingSnoopResp(pkt, snoop_resp_time);
5903587Sgblack@eecs.umich.edu}
5913587Sgblack@eecs.umich.edu
5923587Sgblack@eecs.umich.eduvoid
5933587Sgblack@eecs.umich.eduCache::promoteWholeLineWrites(PacketPtr pkt)
5943587Sgblack@eecs.umich.edu{
5953587Sgblack@eecs.umich.edu    // Cache line clearing instructions
5963587Sgblack@eecs.umich.edu    if (doFastWrites && (pkt->cmd == MemCmd::WriteReq) &&
5973587Sgblack@eecs.umich.edu        (pkt->getSize() == blkSize) && (pkt->getOffset(blkSize) == 0)) {
5983587Sgblack@eecs.umich.edu        pkt->cmd = MemCmd::WriteLineReq;
5993587Sgblack@eecs.umich.edu        DPRINTF(Cache, "packet promoted from Write to WriteLineReq\n");
6003587Sgblack@eecs.umich.edu    }
6013587Sgblack@eecs.umich.edu}
6023587Sgblack@eecs.umich.edu
6033587Sgblack@eecs.umich.edubool
6043587Sgblack@eecs.umich.eduCache::recvTimingReq(PacketPtr pkt)
6053587Sgblack@eecs.umich.edu{
6063587Sgblack@eecs.umich.edu    DPRINTF(CacheTags, "%s tags: %s\n", __func__, tags->print());
6073587Sgblack@eecs.umich.edu
6083823Ssaidi@eecs.umich.edu    assert(pkt->isRequest());
6093587Sgblack@eecs.umich.edu
6103587Sgblack@eecs.umich.edu    // Just forward the packet if caches are disabled.
6113587Sgblack@eecs.umich.edu    if (system->bypassCaches()) {
6123587Sgblack@eecs.umich.edu        // @todo This should really enqueue the packet rather
6133587Sgblack@eecs.umich.edu        bool M5_VAR_USED success = memSidePort->sendTimingReq(pkt);
6143587Sgblack@eecs.umich.edu        assert(success);
6153587Sgblack@eecs.umich.edu        return true;
6163587Sgblack@eecs.umich.edu    }
6173587Sgblack@eecs.umich.edu
6183587Sgblack@eecs.umich.edu    promoteWholeLineWrites(pkt);
6193587Sgblack@eecs.umich.edu
6203587Sgblack@eecs.umich.edu    if (pkt->cacheResponding()) {
6213587Sgblack@eecs.umich.edu        // a cache above us (but not where the packet came from) is
6223587Sgblack@eecs.umich.edu        // responding to the request, in other words it has the line
6233587Sgblack@eecs.umich.edu        // in Modified or Owned state
6243587Sgblack@eecs.umich.edu        DPRINTF(Cache, "Cache above responding to %#llx (%s): "
6253587Sgblack@eecs.umich.edu                "not responding\n",
6263587Sgblack@eecs.umich.edu                pkt->getAddr(), pkt->isSecure() ? "s" : "ns");
6273587Sgblack@eecs.umich.edu
6283587Sgblack@eecs.umich.edu        // if the packet needs the block to be writable, and the cache
6293587Sgblack@eecs.umich.edu        // that has promised to respond (setting the cache responding
6303587Sgblack@eecs.umich.edu        // flag) is not providing writable (it is in Owned rather than
6313587Sgblack@eecs.umich.edu        // the Modified state), we know that there may be other Shared
6323587Sgblack@eecs.umich.edu        // copies in the system; go out and invalidate them all
6333587Sgblack@eecs.umich.edu        if (pkt->needsWritable() && !pkt->responderHadWritable()) {
6343587Sgblack@eecs.umich.edu            // an upstream cache that had the line in Owned state
6353587Sgblack@eecs.umich.edu            // (dirty, but not writable), is responding and thus
6363587Sgblack@eecs.umich.edu            // transferring the dirty line from one branch of the
6373587Sgblack@eecs.umich.edu            // cache hierarchy to another
6383587Sgblack@eecs.umich.edu
6393587Sgblack@eecs.umich.edu            // send out an express snoop and invalidate all other
6403587Sgblack@eecs.umich.edu            // copies (snooping a packet that needs writable is the
6413587Sgblack@eecs.umich.edu            // same as an invalidation), thus turning the Owned line
6423587Sgblack@eecs.umich.edu            // into a Modified line, note that we don't invalidate the
6433587Sgblack@eecs.umich.edu            // block in the current cache or any other cache on the
6443587Sgblack@eecs.umich.edu            // path to memory
6453823Ssaidi@eecs.umich.edu
6463587Sgblack@eecs.umich.edu            // create a downstream express snoop with cleared packet
6472954Sgblack@eecs.umich.edu            // flags, there is no need to allocate any data as the
6482963Sgblack@eecs.umich.edu            // packet is merely used to co-ordinate state transitions
6492963Sgblack@eecs.umich.edu            Packet *snoop_pkt = new Packet(pkt, true, false);
6503279Sgblack@eecs.umich.edu
6512963Sgblack@eecs.umich.edu            // also reset the bus time that the original packet has
6522963Sgblack@eecs.umich.edu            // not yet paid for
6532963Sgblack@eecs.umich.edu            snoop_pkt->headerDelay = snoop_pkt->payloadDelay = 0;
6542963Sgblack@eecs.umich.edu
6552963Sgblack@eecs.umich.edu            // make this an instantaneous express snoop, and let the
6563057Sgblack@eecs.umich.edu            // other caches in the system know that the another cache
6572963Sgblack@eecs.umich.edu            // is responding, because we have found the authorative
6582963Sgblack@eecs.umich.edu            // copy (Modified or Owned) that will supply the right
6592963Sgblack@eecs.umich.edu            // data
6602963Sgblack@eecs.umich.edu            snoop_pkt->setExpressSnoop();
6612963Sgblack@eecs.umich.edu            snoop_pkt->setCacheResponding();
6622963Sgblack@eecs.umich.edu
6633279Sgblack@eecs.umich.edu            // this express snoop travels towards the memory, and at
6642963Sgblack@eecs.umich.edu            // every crossbar it is snooped upwards thus reaching
6652963Sgblack@eecs.umich.edu            // every cache in the system
6662963Sgblack@eecs.umich.edu            bool M5_VAR_USED success = memSidePort->sendTimingReq(snoop_pkt);
6672963Sgblack@eecs.umich.edu            // express snoops always succeed
6682963Sgblack@eecs.umich.edu            assert(success);
6693057Sgblack@eecs.umich.edu
6702963Sgblack@eecs.umich.edu            // main memory will delete the snoop packet
6712963Sgblack@eecs.umich.edu        }
6722963Sgblack@eecs.umich.edu
6732963Sgblack@eecs.umich.edu        // queue for deletion, as opposed to immediate deletion, as
6742963Sgblack@eecs.umich.edu        // the sending cache is still relying on the packet
6752963Sgblack@eecs.umich.edu        pendingDelete.reset(pkt);
6763279Sgblack@eecs.umich.edu
6772963Sgblack@eecs.umich.edu        // no need to take any action in this particular cache as an
6782963Sgblack@eecs.umich.edu        // upstream cache has already committed to responding, and
6792963Sgblack@eecs.umich.edu        // either the packet does not need writable (and we can let
6802963Sgblack@eecs.umich.edu        // the cache that set the cache responding flag pass on the
6812963Sgblack@eecs.umich.edu        // line without any need for intervention), or if the packet
6823057Sgblack@eecs.umich.edu        // needs writable it is provided, or we have already sent out
6832963Sgblack@eecs.umich.edu        // any express snoops in the section above
6842963Sgblack@eecs.umich.edu        return true;
6852963Sgblack@eecs.umich.edu    }
6862963Sgblack@eecs.umich.edu
6872963Sgblack@eecs.umich.edu    // anything that is merely forwarded pays for the forward latency and
6883279Sgblack@eecs.umich.edu    // the delay provided by the crossbar
6892963Sgblack@eecs.umich.edu    Tick forward_time = clockEdge(forwardLatency) + pkt->headerDelay;
6902963Sgblack@eecs.umich.edu
6913279Sgblack@eecs.umich.edu    // We use lookupLatency here because it is used to specify the latency
6922963Sgblack@eecs.umich.edu    // to access.
6932963Sgblack@eecs.umich.edu    Cycles lat = lookupLatency;
6943279Sgblack@eecs.umich.edu    CacheBlk *blk = NULL;
6952963Sgblack@eecs.umich.edu    bool satisfied = false;
6962963Sgblack@eecs.umich.edu    {
6973279Sgblack@eecs.umich.edu        PacketList writebacks;
6982963Sgblack@eecs.umich.edu        // Note that lat is passed by reference here. The function
6992963Sgblack@eecs.umich.edu        // access() calls accessBlock() which can modify lat value.
7003279Sgblack@eecs.umich.edu        satisfied = access(pkt, blk, lat, writebacks);
7012963Sgblack@eecs.umich.edu
7022963Sgblack@eecs.umich.edu        // copy writebacks to write buffer here to ensure they logically
7033279Sgblack@eecs.umich.edu        // proceed anything happening below
7042963Sgblack@eecs.umich.edu        doWritebacks(writebacks, forward_time);
7052963Sgblack@eecs.umich.edu    }
7063279Sgblack@eecs.umich.edu
7072963Sgblack@eecs.umich.edu    // Here we charge the headerDelay that takes into account the latencies
7082963Sgblack@eecs.umich.edu    // of the bus, if the packet comes from it.
7092963Sgblack@eecs.umich.edu    // The latency charged it is just lat that is the value of lookupLatency
7102963Sgblack@eecs.umich.edu    // modified by access() function, or if not just lookupLatency.
7112963Sgblack@eecs.umich.edu    // In case of a hit we are neglecting response latency.
7122963Sgblack@eecs.umich.edu    // In case of a miss we are neglecting forward latency.
7133279Sgblack@eecs.umich.edu    Tick request_time = clockEdge(lat) + pkt->headerDelay;
7142963Sgblack@eecs.umich.edu    // Here we reset the timing of the packet.
7152963Sgblack@eecs.umich.edu    pkt->headerDelay = pkt->payloadDelay = 0;
7162963Sgblack@eecs.umich.edu
7172963Sgblack@eecs.umich.edu    // track time of availability of next prefetch, if any
7182963Sgblack@eecs.umich.edu    Tick next_pf_time = MaxTick;
7192963Sgblack@eecs.umich.edu
7203279Sgblack@eecs.umich.edu    bool needsResponse = pkt->needsResponse();
7212963Sgblack@eecs.umich.edu
7223279Sgblack@eecs.umich.edu    if (satisfied) {
7232963Sgblack@eecs.umich.edu        // should never be satisfying an uncacheable access as we
7242963Sgblack@eecs.umich.edu        // flush and invalidate any existing block as part of the
7253279Sgblack@eecs.umich.edu        // lookup
7262963Sgblack@eecs.umich.edu        assert(!pkt->req->isUncacheable());
7273279Sgblack@eecs.umich.edu
7282963Sgblack@eecs.umich.edu        // hit (for all other request types)
7292963Sgblack@eecs.umich.edu
7302963Sgblack@eecs.umich.edu        if (prefetcher && (prefetchOnAccess || (blk && blk->wasPrefetched()))) {
7312963Sgblack@eecs.umich.edu            if (blk)
7322963Sgblack@eecs.umich.edu                blk->status &= ~BlkHWPrefetched;
7333279Sgblack@eecs.umich.edu
7342963Sgblack@eecs.umich.edu            // Don't notify on SWPrefetch
7352963Sgblack@eecs.umich.edu            if (!pkt->cmd.isSWPrefetch())
7363279Sgblack@eecs.umich.edu                next_pf_time = prefetcher->notify(pkt);
7372963Sgblack@eecs.umich.edu        }
7382963Sgblack@eecs.umich.edu
7392963Sgblack@eecs.umich.edu        if (needsResponse) {
7402963Sgblack@eecs.umich.edu            pkt->makeTimingResponse();
7412954Sgblack@eecs.umich.edu            // @todo: Make someone pay for this
7422526SN/A            pkt->headerDelay = pkt->payloadDelay = 0;
7432954Sgblack@eecs.umich.edu
7442954Sgblack@eecs.umich.edu            // In this case we are considering request_time that takes
7452954Sgblack@eecs.umich.edu            // into account the delay of the xbar, if any, and just
7462954Sgblack@eecs.umich.edu            // lat, neglecting responseLatency, modelling hit latency
7472954Sgblack@eecs.umich.edu            // just as lookupLatency or or the value of lat overriden
7482954Sgblack@eecs.umich.edu            // by access(), that calls accessBlock() function.
7492954Sgblack@eecs.umich.edu            cpuSidePort->schedTimingResp(pkt, request_time, true);
7502954Sgblack@eecs.umich.edu        } else {
7512954Sgblack@eecs.umich.edu            DPRINTF(Cache, "%s satisfied %s addr %#llx, no response needed\n",
7522954Sgblack@eecs.umich.edu                    __func__, pkt->cmdString(), pkt->getAddr(),
7532954Sgblack@eecs.umich.edu                    pkt->getSize());
7542954Sgblack@eecs.umich.edu
7552954Sgblack@eecs.umich.edu            // queue the packet for deletion, as the sending cache is
7562954Sgblack@eecs.umich.edu            // still relying on it; if the block is found in access(),
7572954Sgblack@eecs.umich.edu            // CleanEvict and Writeback messages will be deleted
7582954Sgblack@eecs.umich.edu            // here as well
7592954Sgblack@eecs.umich.edu            pendingDelete.reset(pkt);
7602954Sgblack@eecs.umich.edu        }
7613042Sgblack@eecs.umich.edu    } else {
7622963Sgblack@eecs.umich.edu        // miss
7633042Sgblack@eecs.umich.edu
7642963Sgblack@eecs.umich.edu        Addr blk_addr = blockAlign(pkt->getAddr());
7652963Sgblack@eecs.umich.edu
7662954Sgblack@eecs.umich.edu        // ignore any existing MSHR if we are dealing with an
7672963Sgblack@eecs.umich.edu        // uncacheable request
7682963Sgblack@eecs.umich.edu        MSHR *mshr = pkt->req->isUncacheable() ? nullptr :
7693042Sgblack@eecs.umich.edu            mshrQueue.findMatch(blk_addr, pkt->isSecure());
7702963Sgblack@eecs.umich.edu
7712963Sgblack@eecs.umich.edu        // Software prefetch handling:
7722954Sgblack@eecs.umich.edu        // To keep the core from waiting on data it won't look at
7732954Sgblack@eecs.umich.edu        // anyway, send back a response with dummy data. Miss handling
7742954Sgblack@eecs.umich.edu        // will continue asynchronously. Unfortunately, the core will
7752954Sgblack@eecs.umich.edu        // insist upon freeing original Packet/Request, so we have to
7762954Sgblack@eecs.umich.edu        // create a new pair with a different lifecycle. Note that this
7772954Sgblack@eecs.umich.edu        // processing happens before any MSHR munging on the behalf of
7782954Sgblack@eecs.umich.edu        // this request because this new Request will be the one stored
7792954Sgblack@eecs.umich.edu        // into the MSHRs, not the original.
7802954Sgblack@eecs.umich.edu        if (pkt->cmd.isSWPrefetch()) {
7812954Sgblack@eecs.umich.edu            assert(needsResponse);
7822954Sgblack@eecs.umich.edu            assert(pkt->req->hasPaddr());
7832954Sgblack@eecs.umich.edu            assert(!pkt->req->isUncacheable());
7842954Sgblack@eecs.umich.edu
7852954Sgblack@eecs.umich.edu            // There's no reason to add a prefetch as an additional target
7862954Sgblack@eecs.umich.edu            // to an existing MSHR. If an outstanding request is already
7872954Sgblack@eecs.umich.edu            // in progress, there is nothing for the prefetch to do.
7882954Sgblack@eecs.umich.edu            // If this is the case, we don't even create a request at all.
7892954Sgblack@eecs.umich.edu            PacketPtr pf = nullptr;
7902954Sgblack@eecs.umich.edu
7912963Sgblack@eecs.umich.edu            if (!mshr) {
7923057Sgblack@eecs.umich.edu                // copy the request and create a new SoftPFReq packet
7933057Sgblack@eecs.umich.edu                RequestPtr req = new Request(pkt->req->getPaddr(),
7943057Sgblack@eecs.umich.edu                                             pkt->req->getSize(),
7953057Sgblack@eecs.umich.edu                                             pkt->req->getFlags(),
7963057Sgblack@eecs.umich.edu                                             pkt->req->masterId());
7973057Sgblack@eecs.umich.edu                pf = new Packet(req, pkt->cmd);
7983057Sgblack@eecs.umich.edu                pf->allocate();
7993057Sgblack@eecs.umich.edu                assert(pf->getAddr() == pkt->getAddr());
8003057Sgblack@eecs.umich.edu                assert(pf->getSize() == pkt->getSize());
8013057Sgblack@eecs.umich.edu            }
8023057Sgblack@eecs.umich.edu
8033057Sgblack@eecs.umich.edu            pkt->makeTimingResponse();
8043057Sgblack@eecs.umich.edu
8053057Sgblack@eecs.umich.edu            // request_time is used here, taking into account lat and the delay
8063057Sgblack@eecs.umich.edu            // charged if the packet comes from the xbar.
8073057Sgblack@eecs.umich.edu            cpuSidePort->schedTimingResp(pkt, request_time, true);
8083057Sgblack@eecs.umich.edu
8093057Sgblack@eecs.umich.edu            // If an outstanding request is in progress (we found an
8103057Sgblack@eecs.umich.edu            // MSHR) this is set to null
8113057Sgblack@eecs.umich.edu            pkt = pf;
8123057Sgblack@eecs.umich.edu        }
8133057Sgblack@eecs.umich.edu
8143057Sgblack@eecs.umich.edu        if (mshr) {
8153057Sgblack@eecs.umich.edu            /// MSHR hit
8162963Sgblack@eecs.umich.edu            /// @note writebacks will be checked in getNextMSHR()
8172954Sgblack@eecs.umich.edu            /// for any conflicting requests to the same block
8182954Sgblack@eecs.umich.edu
8192954Sgblack@eecs.umich.edu            //@todo remove hw_pf here
8202954Sgblack@eecs.umich.edu
8212954Sgblack@eecs.umich.edu            // Coalesce unless it was a software prefetch (see above).
8222954Sgblack@eecs.umich.edu            if (pkt) {
8232954Sgblack@eecs.umich.edu                assert(!pkt->isWriteback());
8242954Sgblack@eecs.umich.edu                // CleanEvicts corresponding to blocks which have
8252954Sgblack@eecs.umich.edu                // outstanding requests in MSHRs are simply sunk here
8262954Sgblack@eecs.umich.edu                if (pkt->cmd == MemCmd::CleanEvict) {
8272954Sgblack@eecs.umich.edu                    pendingDelete.reset(pkt);
8282963Sgblack@eecs.umich.edu                } else {
8293279Sgblack@eecs.umich.edu                    DPRINTF(Cache, "%s coalescing MSHR for %s addr %#llx size %d\n",
8302954Sgblack@eecs.umich.edu                            __func__, pkt->cmdString(), pkt->getAddr(),
8312954Sgblack@eecs.umich.edu                            pkt->getSize());
8322954Sgblack@eecs.umich.edu
8332954Sgblack@eecs.umich.edu                    assert(pkt->req->masterId() < system->maxMasters());
8342963Sgblack@eecs.umich.edu                    mshr_hits[pkt->cmdToIndex()][pkt->req->masterId()]++;
8352963Sgblack@eecs.umich.edu                    // We use forward_time here because it is the same
8362963Sgblack@eecs.umich.edu                    // considering new targets. We have multiple
8372963Sgblack@eecs.umich.edu                    // requests for the same address here. It
8383279Sgblack@eecs.umich.edu                    // specifies the latency to allocate an internal
8392963Sgblack@eecs.umich.edu                    // buffer and to schedule an event to the queued
8402954Sgblack@eecs.umich.edu                    // port and also takes into account the additional
8412954Sgblack@eecs.umich.edu                    // delay of the xbar.
8422963Sgblack@eecs.umich.edu                    mshr->allocateTarget(pkt, forward_time, order++,
8432963Sgblack@eecs.umich.edu                                         allocOnFill(pkt->cmd));
8442963Sgblack@eecs.umich.edu                    if (mshr->getNumTargets() == numTarget) {
8452963Sgblack@eecs.umich.edu                        noTargetMSHR = mshr;
8463279Sgblack@eecs.umich.edu                        setBlocked(Blocked_NoTargets);
8472963Sgblack@eecs.umich.edu                        // need to be careful with this... if this mshr isn't
8482954Sgblack@eecs.umich.edu                        // ready yet (i.e. time > curTick()), we don't want to
8492954Sgblack@eecs.umich.edu                        // move it ahead of mshrs that are ready
8502954Sgblack@eecs.umich.edu                        // mshrQueue.moveToFront(mshr);
8512954Sgblack@eecs.umich.edu                    }
8522954Sgblack@eecs.umich.edu                }
8532954Sgblack@eecs.umich.edu                // We should call the prefetcher reguardless if the request is
8542954Sgblack@eecs.umich.edu                // satisfied or not, reguardless if the request is in the MSHR or
8552954Sgblack@eecs.umich.edu                // not.  The request could be a ReadReq hit, but still not
8563057Sgblack@eecs.umich.edu                // satisfied (potentially because of a prior write to the same
8573057Sgblack@eecs.umich.edu                // cache line.  So, even when not satisfied, tehre is an MSHR
8582954Sgblack@eecs.umich.edu                // already allocated for this, we need to let the prefetcher know
8592954Sgblack@eecs.umich.edu                // about the request
8603057Sgblack@eecs.umich.edu                if (prefetcher) {
8613057Sgblack@eecs.umich.edu                    // Don't notify on SWPrefetch
8622954Sgblack@eecs.umich.edu                    if (!pkt->cmd.isSWPrefetch())
8632954Sgblack@eecs.umich.edu                        next_pf_time = prefetcher->notify(pkt);
8642954Sgblack@eecs.umich.edu                }
8652954Sgblack@eecs.umich.edu            }
8662954Sgblack@eecs.umich.edu        } else {
8672954Sgblack@eecs.umich.edu            // no MSHR
8682954Sgblack@eecs.umich.edu            assert(pkt->req->masterId() < system->maxMasters());
8692954Sgblack@eecs.umich.edu            if (pkt->req->isUncacheable()) {
8702954Sgblack@eecs.umich.edu                mshr_uncacheable[pkt->cmdToIndex()][pkt->req->masterId()]++;
8712954Sgblack@eecs.umich.edu            } else {
8722526SN/A                mshr_misses[pkt->cmdToIndex()][pkt->req->masterId()]++;
8732526SN/A            }
8742526SN/A
8752526SN/A            if (pkt->isEviction() ||
8762526SN/A                (pkt->req->isUncacheable() && pkt->isWrite())) {
8772526SN/A                // We use forward_time here because there is an
8782526SN/A                // uncached memory write, forwarded to WriteBuffer.
8792526SN/A                allocateWriteBuffer(pkt, forward_time);
8802526SN/A            } else {
8812526SN/A                if (blk && blk->isValid()) {
8822526SN/A                    // should have flushed and have no valid block
8832561SN/A                    assert(!pkt->req->isUncacheable());
8842561SN/A
8852561SN/A                    // If we have a write miss to a valid block, we
8862526SN/A                    // need to mark the block non-readable.  Otherwise
8872526SN/A                    // if we allow reads while there's an outstanding
8882526SN/A                    // write miss, the read could return stale data
8892526SN/A                    // out of the cache block... a more aggressive
8902526SN/A                    // system could detect the overlap (if any) and
8912561SN/A                    // forward data out of the MSHRs, but we don't do
8922561SN/A                    // that yet.  Note that we do need to leave the
8932561SN/A                    // block valid so that it stays in the cache, in
8942561SN/A                    // case we get an upgrade response (and hence no
8952561SN/A                    // new data) when the write miss completes.
8962646Ssaidi@eecs.umich.edu                    // As long as CPUs do proper store/load forwarding
8972561SN/A                    // internally, and have a sufficiently weak memory
8982646Ssaidi@eecs.umich.edu                    // model, this is probably unnecessary, but at some
8992561SN/A                    // point it must have seemed like we needed it...
9002561SN/A                    assert(pkt->needsWritable());
9012561SN/A                    assert(!blk->isWritable());
9023417Sgblack@eecs.umich.edu                    blk->status &= ~BlkReadable;
9033417Sgblack@eecs.umich.edu                }
9043417Sgblack@eecs.umich.edu                // Here we are using forward_time, modelling the latency of
9053417Sgblack@eecs.umich.edu                // a miss (outbound) just as forwardLatency, neglecting the
9062561SN/A                // lookupLatency component.
9072561SN/A                allocateMissBuffer(pkt, forward_time);
9083417Sgblack@eecs.umich.edu            }
9093417Sgblack@eecs.umich.edu
9103417Sgblack@eecs.umich.edu            if (prefetcher) {
9113417Sgblack@eecs.umich.edu                // Don't notify on SWPrefetch
9122561SN/A                if (!pkt->cmd.isSWPrefetch())
9132561SN/A                    next_pf_time = prefetcher->notify(pkt);
9142526SN/A            }
9152526SN/A        }
9162526SN/A    }
9172526SN/A
9182646Ssaidi@eecs.umich.edu    if (next_pf_time != MaxTick)
9192561SN/A        schedMemSideSendEvent(next_pf_time);
9203039Sstever@eecs.umich.edu
9212561SN/A    return true;
9222561SN/A}
9233531Sgblack@eecs.umich.edu
9242526SN/A
9252561SN/A// See comment in cache.hh.
9262561SN/APacketPtr
9272561SN/ACache::getBusPacket(PacketPtr cpu_pkt, CacheBlk *blk,
9282561SN/A                    bool needsWritable) const
9292526SN/A{
9302526SN/A    bool blkValid = blk && blk->isValid();
9312646Ssaidi@eecs.umich.edu
9322561SN/A    if (cpu_pkt->req->isUncacheable()) {
9333039Sstever@eecs.umich.edu        // note that at the point we see the uncacheable request we
9342561SN/A        // flush any block, but there could be an outstanding MSHR,
9352561SN/A        // and the cache could have filled again before we actually
9363531Sgblack@eecs.umich.edu        // send out the forwarded uncacheable request (blk could thus
9372526SN/A        // be non-null)
9382561SN/A        return NULL;
9392561SN/A    }
9402561SN/A
9412526SN/A    if (!blkValid &&
9422526SN/A        (cpu_pkt->isUpgrade() ||
9432526SN/A         cpu_pkt->isEviction())) {
9442526SN/A        // Writebacks that weren't allocated in access() and upgrades
9452526SN/A        // from upper-level caches that missed completely just go
9462526SN/A        // through.
9472526SN/A        return NULL;
9482526SN/A    }
9492526SN/A
9502526SN/A    assert(cpu_pkt->needsResponse());
9512526SN/A
9522646Ssaidi@eecs.umich.edu    MemCmd cmd;
9532526SN/A    // @TODO make useUpgrades a parameter.
9542646Ssaidi@eecs.umich.edu    // Note that ownership protocols require upgrade, otherwise a
9553417Sgblack@eecs.umich.edu    // write miss on a shared owned block will generate a ReadExcl,
9562526SN/A    // which will clobber the owned copy.
9572526SN/A    const bool useUpgrades = true;
9582526SN/A    if (blkValid && useUpgrades) {
9593417Sgblack@eecs.umich.edu        // only reason to be here is that blk is read only and we need
9602526SN/A        // it to be writable
9612526SN/A        assert(needsWritable);
9622526SN/A        assert(!blk->isWritable());
9632526SN/A        cmd = cpu_pkt->isLLSC() ? MemCmd::SCUpgradeReq : MemCmd::UpgradeReq;
9642526SN/A    } else if (cpu_pkt->cmd == MemCmd::SCUpgradeFailReq ||
9652526SN/A               cpu_pkt->cmd == MemCmd::StoreCondFailReq) {
9662561SN/A        // Even though this SC will fail, we still need to send out the
9672561SN/A        // request and get the data to supply it to other snoopers in the case
9683417Sgblack@eecs.umich.edu        // where the determination the StoreCond fails is delayed due to
9693417Sgblack@eecs.umich.edu        // all caches not being on the same local bus.
9703417Sgblack@eecs.umich.edu        cmd = MemCmd::SCUpgradeFailReq;
9713417Sgblack@eecs.umich.edu    } else if (cpu_pkt->cmd == MemCmd::WriteLineReq) {
9722526SN/A        // forward as invalidate to all other caches, this gives us
9732526SN/A        // the line in Exclusive state, and invalidates all other
9742526SN/A        // copies
9752526SN/A        cmd = MemCmd::InvalidateReq;
9762526SN/A    } else {
9772526SN/A        // block is invalid
9782646Ssaidi@eecs.umich.edu        cmd = needsWritable ? MemCmd::ReadExReq :
9792526SN/A            (isReadOnly ? MemCmd::ReadCleanReq : MemCmd::ReadSharedReq);
9802646Ssaidi@eecs.umich.edu    }
9812526SN/A    PacketPtr pkt = new Packet(cpu_pkt->req, cmd, blkSize);
9822526SN/A
9832526SN/A    // if there are upstream caches that have already marked the
9843417Sgblack@eecs.umich.edu    // packet as having sharers (not passing writable), pass that info
9853417Sgblack@eecs.umich.edu    // downstream
9863417Sgblack@eecs.umich.edu    if (cpu_pkt->hasSharers()) {
9873417Sgblack@eecs.umich.edu        // note that cpu_pkt may have spent a considerable time in the
9882526SN/A        // MSHR queue and that the information could possibly be out
9892561SN/A        // of date, however, there is no harm in conservatively
9902561SN/A        // assuming the block has sharers
9913417Sgblack@eecs.umich.edu        pkt->setHasSharers();
9923417Sgblack@eecs.umich.edu        DPRINTF(Cache, "%s passing hasSharers from %s to %s addr %#llx "
9933417Sgblack@eecs.umich.edu                "size %d\n",
9943417Sgblack@eecs.umich.edu                __func__, cpu_pkt->cmdString(), pkt->cmdString(),
9952526SN/A                pkt->getAddr(), pkt->getSize());
9962526SN/A    }
9972526SN/A
9982526SN/A    // the packet should be block aligned
9992526SN/A    assert(pkt->getAddr() == blockAlign(pkt->getAddr()));
10002526SN/A
10012646Ssaidi@eecs.umich.edu    pkt->allocate();
10022646Ssaidi@eecs.umich.edu    DPRINTF(Cache, "%s created %s from %s for  addr %#llx size %d\n",
10032646Ssaidi@eecs.umich.edu            __func__, pkt->cmdString(), cpu_pkt->cmdString(), pkt->getAddr(),
10042646Ssaidi@eecs.umich.edu            pkt->getSize());
10052646Ssaidi@eecs.umich.edu    return pkt;
10062646Ssaidi@eecs.umich.edu}
10072646Ssaidi@eecs.umich.edu
10082646Ssaidi@eecs.umich.edu
10092526SN/ATick
10102526SN/ACache::recvAtomic(PacketPtr pkt)
10112938Sgblack@eecs.umich.edu{
10122526SN/A    // We are in atomic mode so we pay just for lookupLatency here.
10132526SN/A    Cycles lat = lookupLatency;
10142646Ssaidi@eecs.umich.edu
10152646Ssaidi@eecs.umich.edu    // Forward the request if the system is in cache bypass mode.
10162646Ssaidi@eecs.umich.edu    if (system->bypassCaches())
10172646Ssaidi@eecs.umich.edu        return ticksToCycles(memSidePort->sendAtomic(pkt));
10182646Ssaidi@eecs.umich.edu
10192646Ssaidi@eecs.umich.edu    promoteWholeLineWrites(pkt);
10203417Sgblack@eecs.umich.edu
10212526SN/A    // follow the same flow as in recvTimingReq, and check if a cache
10222526SN/A    // above us is responding
10232526SN/A    if (pkt->cacheResponding()) {
10242526SN/A        DPRINTF(Cache, "Cache above responding to %#llx (%s): "
10252469SN/A                "not responding\n",
10262469SN/A                pkt->getAddr(), pkt->isSecure() ? "s" : "ns");
10272526SN/A
10283272Sgblack@eecs.umich.edu        // if a cache is responding, and it had the line in Owned
10293272Sgblack@eecs.umich.edu        // rather than Modified state, we need to invalidate any
10303272Sgblack@eecs.umich.edu        // copies that are not on the same path to memory
10312526SN/A        if (pkt->needsWritable() && !pkt->responderHadWritable()) {
10323272Sgblack@eecs.umich.edu            lat += ticksToCycles(memSidePort->sendAtomic(pkt));
10332526SN/A        }
10342526SN/A
10353272Sgblack@eecs.umich.edu        return lat * clockPeriod();
10362526SN/A    }
10372526SN/A
10383272Sgblack@eecs.umich.edu    // should assert here that there are no outstanding MSHRs or
10393272Sgblack@eecs.umich.edu    // writebacks... that would mean that someone used an atomic
10403272Sgblack@eecs.umich.edu    // access in timing mode
10413272Sgblack@eecs.umich.edu
10422526SN/A    CacheBlk *blk = NULL;
10432526SN/A    PacketList writebacks;
10443272Sgblack@eecs.umich.edu    bool satisfied = access(pkt, blk, lat, writebacks);
10453272Sgblack@eecs.umich.edu
10463272Sgblack@eecs.umich.edu    // handle writebacks resulting from the access here to ensure they
10473272Sgblack@eecs.umich.edu    // logically proceed anything happening below
10482526SN/A    doWritebacksAtomic(writebacks);
10493438Sgblack@eecs.umich.edu
10503438Sgblack@eecs.umich.edu    if (!satisfied) {
10513438Sgblack@eecs.umich.edu        // MISS
10523272Sgblack@eecs.umich.edu
10533388Sgblack@eecs.umich.edu        PacketPtr bus_pkt = getBusPacket(pkt, blk, pkt->needsWritable());
10543438Sgblack@eecs.umich.edu
10553388Sgblack@eecs.umich.edu        bool is_forward = (bus_pkt == NULL);
10563438Sgblack@eecs.umich.edu
10573810Sgblack@eecs.umich.edu        if (is_forward) {
10583810Sgblack@eecs.umich.edu            // just forwarding the same request to the next level
10593810Sgblack@eecs.umich.edu            // no local cache operation involved
10603810Sgblack@eecs.umich.edu            bus_pkt = pkt;
10612526SN/A        }
10623272Sgblack@eecs.umich.edu
10632526SN/A        DPRINTF(Cache, "Sending an atomic %s for %#llx (%s)\n",
10642526SN/A                bus_pkt->cmdString(), bus_pkt->getAddr(),
10653810Sgblack@eecs.umich.edu                bus_pkt->isSecure() ? "s" : "ns");
10662526SN/A
10673810Sgblack@eecs.umich.edu#if TRACING_ON
10683810Sgblack@eecs.umich.edu        CacheBlk::State old_state = blk ? blk->status : 0;
10693810Sgblack@eecs.umich.edu#endif
10703810Sgblack@eecs.umich.edu
10713810Sgblack@eecs.umich.edu        lat += ticksToCycles(memSidePort->sendAtomic(bus_pkt));
10722526SN/A
10733810Sgblack@eecs.umich.edu        // We are now dealing with the response handling
10743810Sgblack@eecs.umich.edu        DPRINTF(Cache, "Receive response: %s for addr %#llx (%s) in state %i\n",
10753810Sgblack@eecs.umich.edu                bus_pkt->cmdString(), bus_pkt->getAddr(),
10763810Sgblack@eecs.umich.edu                bus_pkt->isSecure() ? "s" : "ns",
10773810Sgblack@eecs.umich.edu                old_state);
10782526SN/A
10793810Sgblack@eecs.umich.edu        // If packet was a forward, the response (if any) is already
10803388Sgblack@eecs.umich.edu        // in place in the bus_pkt == pkt structure, so we don't need
10813810Sgblack@eecs.umich.edu        // to do anything.  Otherwise, use the separate bus_pkt to
10823810Sgblack@eecs.umich.edu        // generate response to pkt and then delete it.
10833810Sgblack@eecs.umich.edu        if (!is_forward) {
10843438Sgblack@eecs.umich.edu            if (pkt->needsResponse()) {
10853388Sgblack@eecs.umich.edu                assert(bus_pkt->isResponse());
10863810Sgblack@eecs.umich.edu                if (bus_pkt->isError()) {
10872526SN/A                    pkt->makeAtomicResponse();
10883272Sgblack@eecs.umich.edu                    pkt->copyError(bus_pkt);
10892526SN/A                } else if (pkt->cmd == MemCmd::InvalidateReq) {
10903272Sgblack@eecs.umich.edu                    if (blk) {
10913272Sgblack@eecs.umich.edu                        // invalidate response to a cache that received
10922469SN/A                        // an invalidate request
10932526SN/A                        satisfyCpuSideRequest(pkt, blk);
10943272Sgblack@eecs.umich.edu                    }
10953272Sgblack@eecs.umich.edu                } else if (pkt->cmd == MemCmd::WriteLineReq) {
10962526SN/A                    // note the use of pkt, not bus_pkt here.
10973272Sgblack@eecs.umich.edu
10983272Sgblack@eecs.umich.edu                    // write-line request to the cache that promoted
10992526SN/A                    // the write to a whole line
11002526SN/A                    blk = handleFill(pkt, blk, writebacks,
11013272Sgblack@eecs.umich.edu                                     allocOnFill(pkt->cmd));
11022526SN/A                    satisfyCpuSideRequest(pkt, blk);
11033810Sgblack@eecs.umich.edu                } else if (bus_pkt->isRead() ||
11042526SN/A                           bus_pkt->cmd == MemCmd::UpgradeResp) {
11053272Sgblack@eecs.umich.edu                    // we're updating cache state to allow us to
11063272Sgblack@eecs.umich.edu                    // satisfy the upstream request from the cache
11073272Sgblack@eecs.umich.edu                    blk = handleFill(bus_pkt, blk, writebacks,
11083272Sgblack@eecs.umich.edu                                     allocOnFill(pkt->cmd));
11093272Sgblack@eecs.umich.edu                    satisfyCpuSideRequest(pkt, blk);
11103272Sgblack@eecs.umich.edu                } else {
11113272Sgblack@eecs.umich.edu                    // we're satisfying the upstream request without
11123272Sgblack@eecs.umich.edu                    // modifying cache state, e.g., a write-through
11133272Sgblack@eecs.umich.edu                    pkt->makeAtomicResponse();
11143272Sgblack@eecs.umich.edu                }
11153272Sgblack@eecs.umich.edu            }
11163272Sgblack@eecs.umich.edu            delete bus_pkt;
11173272Sgblack@eecs.umich.edu        }
11183272Sgblack@eecs.umich.edu    }
11193272Sgblack@eecs.umich.edu
11203272Sgblack@eecs.umich.edu    // Note that we don't invoke the prefetcher at all in atomic mode.
11213272Sgblack@eecs.umich.edu    // It's not clear how to do it properly, particularly for
11223272Sgblack@eecs.umich.edu    // prefetchers that aggressively generate prefetch candidates and
11233272Sgblack@eecs.umich.edu    // rely on bandwidth contention to throttle them; these will tend
11243272Sgblack@eecs.umich.edu    // to pollute the cache in atomic mode since there is no bandwidth
11253272Sgblack@eecs.umich.edu    // contention.  If we ever do want to enable prefetching in atomic
11263272Sgblack@eecs.umich.edu    // mode, though, this is the place to do it... see timingAccess()
11273272Sgblack@eecs.umich.edu    // for an example (though we'd want to issue the prefetch(es)
11283272Sgblack@eecs.umich.edu    // immediately rather than calling requestMemSideBus() as we do
11293272Sgblack@eecs.umich.edu    // there).
11303272Sgblack@eecs.umich.edu
11313272Sgblack@eecs.umich.edu    // do any writebacks resulting from the response handling
11323272Sgblack@eecs.umich.edu    doWritebacksAtomic(writebacks);
11333272Sgblack@eecs.umich.edu
11343272Sgblack@eecs.umich.edu    // if we used temp block, check to see if its valid and if so
11353272Sgblack@eecs.umich.edu    // clear it out, but only do so after the call to recvAtomic is
11363272Sgblack@eecs.umich.edu    // finished so that any downstream observers (such as a snoop
11373272Sgblack@eecs.umich.edu    // filter), first see the fill, and only then see the eviction
11383272Sgblack@eecs.umich.edu    if (blk == tempBlock && tempBlock->isValid()) {
11393272Sgblack@eecs.umich.edu        // the atomic CPU calls recvAtomic for fetch and load/store
11403272Sgblack@eecs.umich.edu        // sequentuially, and we may already have a tempBlock
11413272Sgblack@eecs.umich.edu        // writeback from the fetch that we have not yet sent
11423272Sgblack@eecs.umich.edu        if (tempBlockWriteback) {
11433272Sgblack@eecs.umich.edu            // if that is the case, write the prevoius one back, and
11443272Sgblack@eecs.umich.edu            // do not schedule any new event
11453272Sgblack@eecs.umich.edu            writebackTempBlockAtomic();
11463272Sgblack@eecs.umich.edu        } else {
11473272Sgblack@eecs.umich.edu            // the writeback/clean eviction happens after the call to
11483272Sgblack@eecs.umich.edu            // recvAtomic has finished (but before any successive
11493272Sgblack@eecs.umich.edu            // calls), so that the response handling from the fill is
11503272Sgblack@eecs.umich.edu            // allowed to happen first
11513272Sgblack@eecs.umich.edu            schedule(writebackTempBlockAtomicEvent, curTick());
11523272Sgblack@eecs.umich.edu        }
11533272Sgblack@eecs.umich.edu
11543272Sgblack@eecs.umich.edu        tempBlockWriteback = (blk->isDirty() || writebackClean) ?
11553810Sgblack@eecs.umich.edu            writebackBlk(blk) : cleanEvictBlk(blk);
11563272Sgblack@eecs.umich.edu        blk->invalidate();
11573272Sgblack@eecs.umich.edu    }
11583272Sgblack@eecs.umich.edu
11593272Sgblack@eecs.umich.edu    if (pkt->needsResponse()) {
11603272Sgblack@eecs.umich.edu        pkt->makeAtomicResponse();
11613272Sgblack@eecs.umich.edu    }
11623272Sgblack@eecs.umich.edu
11633272Sgblack@eecs.umich.edu    return lat * clockPeriod();
11643272Sgblack@eecs.umich.edu}
11653272Sgblack@eecs.umich.edu
11663272Sgblack@eecs.umich.edu
11673272Sgblack@eecs.umich.eduvoid
11683272Sgblack@eecs.umich.eduCache::functionalAccess(PacketPtr pkt, bool fromCpuSide)
11693272Sgblack@eecs.umich.edu{
11703272Sgblack@eecs.umich.edu    if (system->bypassCaches()) {
11713272Sgblack@eecs.umich.edu        // Packets from the memory side are snoop request and
11723272Sgblack@eecs.umich.edu        // shouldn't happen in bypass mode.
11733272Sgblack@eecs.umich.edu        assert(fromCpuSide);
11743272Sgblack@eecs.umich.edu
11753272Sgblack@eecs.umich.edu        // The cache should be flushed if we are in cache bypass mode,
11763272Sgblack@eecs.umich.edu        // so we don't need to check if we need to update anything.
11773272Sgblack@eecs.umich.edu        memSidePort->sendFunctional(pkt);
11783272Sgblack@eecs.umich.edu        return;
11793272Sgblack@eecs.umich.edu    }
11803272Sgblack@eecs.umich.edu
11813272Sgblack@eecs.umich.edu    Addr blk_addr = blockAlign(pkt->getAddr());
11823378Sgblack@eecs.umich.edu    bool is_secure = pkt->isSecure();
11833378Sgblack@eecs.umich.edu    CacheBlk *blk = tags->findBlock(pkt->getAddr(), is_secure);
11843272Sgblack@eecs.umich.edu    MSHR *mshr = mshrQueue.findMatch(blk_addr, is_secure);
11853272Sgblack@eecs.umich.edu
11863272Sgblack@eecs.umich.edu    pkt->pushLabel(name());
11872954Sgblack@eecs.umich.edu
11883378Sgblack@eecs.umich.edu    CacheBlkPrintWrapper cbpw(blk);
11893378Sgblack@eecs.umich.edu
11903378Sgblack@eecs.umich.edu    // Note that just because an L2/L3 has valid data doesn't mean an
11913378Sgblack@eecs.umich.edu    // L1 doesn't have a more up-to-date modified copy that still
11923378Sgblack@eecs.umich.edu    // needs to be found.  As a result we always update the request if
11933378Sgblack@eecs.umich.edu    // we have it, but only declare it satisfied if we are the owner.
11943378Sgblack@eecs.umich.edu
11953378Sgblack@eecs.umich.edu    // see if we have data at all (owned or otherwise)
11963378Sgblack@eecs.umich.edu    bool have_data = blk && blk->isValid()
11973378Sgblack@eecs.umich.edu        && pkt->checkFunctional(&cbpw, blk_addr, is_secure, blkSize,
11983378Sgblack@eecs.umich.edu                                blk->data);
11993378Sgblack@eecs.umich.edu
12003378Sgblack@eecs.umich.edu    // data we have is dirty if marked as such or if we have an
12013378Sgblack@eecs.umich.edu    // in-service MSHR that is pending a modified line
12023378Sgblack@eecs.umich.edu    bool have_dirty =
12033378Sgblack@eecs.umich.edu        have_data && (blk->isDirty() ||
12043378Sgblack@eecs.umich.edu                      (mshr && mshr->inService && mshr->isPendingModified()));
12053378Sgblack@eecs.umich.edu
12063378Sgblack@eecs.umich.edu    bool done = have_dirty
12073378Sgblack@eecs.umich.edu        || cpuSidePort->checkFunctional(pkt)
12083378Sgblack@eecs.umich.edu        || mshrQueue.checkFunctional(pkt, blk_addr)
12093378Sgblack@eecs.umich.edu        || writeBuffer.checkFunctional(pkt, blk_addr)
12103378Sgblack@eecs.umich.edu        || memSidePort->checkFunctional(pkt);
12113378Sgblack@eecs.umich.edu
12123378Sgblack@eecs.umich.edu    DPRINTF(CacheVerbose, "functional %s %#llx (%s) %s%s%s\n",
12133378Sgblack@eecs.umich.edu            pkt->cmdString(), pkt->getAddr(), is_secure ? "s" : "ns",
12143378Sgblack@eecs.umich.edu            (blk && blk->isValid()) ? "valid " : "",
12153378Sgblack@eecs.umich.edu            have_data ? "data " : "", done ? "done " : "");
12163378Sgblack@eecs.umich.edu
12173378Sgblack@eecs.umich.edu    // We're leaving the cache, so pop cache->name() label
12183378Sgblack@eecs.umich.edu    pkt->popLabel();
12193378Sgblack@eecs.umich.edu
12203378Sgblack@eecs.umich.edu    if (done) {
12213378Sgblack@eecs.umich.edu        pkt->makeResponse();
12223378Sgblack@eecs.umich.edu    } else {
12233378Sgblack@eecs.umich.edu        // if it came as a request from the CPU side then make sure it
12243378Sgblack@eecs.umich.edu        // continues towards the memory side
12253378Sgblack@eecs.umich.edu        if (fromCpuSide) {
12263378Sgblack@eecs.umich.edu            memSidePort->sendFunctional(pkt);
12273378Sgblack@eecs.umich.edu        } else if (forwardSnoops && cpuSidePort->isSnooping()) {
12283378Sgblack@eecs.umich.edu            // if it came from the memory side, it must be a snoop request
12293378Sgblack@eecs.umich.edu            // and we should only forward it if we are forwarding snoops
12303378Sgblack@eecs.umich.edu            cpuSidePort->sendFunctionalSnoop(pkt);
12313378Sgblack@eecs.umich.edu        }
12323378Sgblack@eecs.umich.edu    }
12333378Sgblack@eecs.umich.edu}
12343378Sgblack@eecs.umich.edu
12353378Sgblack@eecs.umich.edu
12363378Sgblack@eecs.umich.edu/////////////////////////////////////////////////////
12373378Sgblack@eecs.umich.edu//
12383810Sgblack@eecs.umich.edu// Response handling: responses from the memory side
12393378Sgblack@eecs.umich.edu//
12403378Sgblack@eecs.umich.edu/////////////////////////////////////////////////////
12413378Sgblack@eecs.umich.edu
12423378Sgblack@eecs.umich.edu
12433378Sgblack@eecs.umich.eduvoid
12443378Sgblack@eecs.umich.eduCache::recvTimingResp(PacketPtr pkt)
12453378Sgblack@eecs.umich.edu{
12463378Sgblack@eecs.umich.edu    assert(pkt->isResponse());
12473378Sgblack@eecs.umich.edu
12483378Sgblack@eecs.umich.edu    // all header delay should be paid for by the crossbar, unless
12493378Sgblack@eecs.umich.edu    // this is a prefetch response from above
12503378Sgblack@eecs.umich.edu    panic_if(pkt->headerDelay != 0 && pkt->cmd != MemCmd::HardPFResp,
12513378Sgblack@eecs.umich.edu             "%s saw a non-zero packet delay\n", name());
12523378Sgblack@eecs.umich.edu
12533378Sgblack@eecs.umich.edu    MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
12543378Sgblack@eecs.umich.edu    bool is_error = pkt->isError();
12553378Sgblack@eecs.umich.edu
12563378Sgblack@eecs.umich.edu    assert(mshr);
12573378Sgblack@eecs.umich.edu
12583378Sgblack@eecs.umich.edu    if (is_error) {
12593378Sgblack@eecs.umich.edu        DPRINTF(Cache, "Cache received packet with error for addr %#llx (%s), "
12603378Sgblack@eecs.umich.edu                "cmd: %s\n", pkt->getAddr(), pkt->isSecure() ? "s" : "ns",
12613378Sgblack@eecs.umich.edu                pkt->cmdString());
12623378Sgblack@eecs.umich.edu    }
12633378Sgblack@eecs.umich.edu
12643378Sgblack@eecs.umich.edu    DPRINTF(Cache, "Handling response %s for addr %#llx size %d (%s)\n",
12653378Sgblack@eecs.umich.edu            pkt->cmdString(), pkt->getAddr(), pkt->getSize(),
12663378Sgblack@eecs.umich.edu            pkt->isSecure() ? "s" : "ns");
12673378Sgblack@eecs.umich.edu
12683378Sgblack@eecs.umich.edu    MSHRQueue *mq = mshr->queue;
12693439Sgblack@eecs.umich.edu    bool wasFull = mq->isFull();
12703439Sgblack@eecs.umich.edu
12713439Sgblack@eecs.umich.edu    if (mshr == noTargetMSHR) {
12722526SN/A        // we always clear at least one target
12733439Sgblack@eecs.umich.edu        clearBlocked(Blocked_NoTargets);
12743439Sgblack@eecs.umich.edu        noTargetMSHR = NULL;
12753810Sgblack@eecs.umich.edu    }
12762526SN/A
12773439Sgblack@eecs.umich.edu    // Initial target is used just for stats
12783439Sgblack@eecs.umich.edu    MSHR::Target *initial_tgt = mshr->getTarget();
12793439Sgblack@eecs.umich.edu    int stats_cmd_idx = initial_tgt->pkt->cmdToIndex();
12802526SN/A    Tick miss_latency = curTick() - initial_tgt->recvTime;
12813439Sgblack@eecs.umich.edu    PacketList writebacks;
12823439Sgblack@eecs.umich.edu    // We need forward_time here because we have a call of
12833810Sgblack@eecs.umich.edu    // allocateWriteBuffer() that need this parameter to specify the
12842526SN/A    // time to request the bus.  In this case we use forward latency
12852469SN/A    // because there is a writeback.  We pay also here for headerDelay
12862022SN/A    // that is charged of bus latencies if the packet comes from the
1287    // bus.
1288    Tick forward_time = clockEdge(forwardLatency) + pkt->headerDelay;
1289
1290    if (pkt->req->isUncacheable()) {
1291        assert(pkt->req->masterId() < system->maxMasters());
1292        mshr_uncacheable_lat[stats_cmd_idx][pkt->req->masterId()] +=
1293            miss_latency;
1294    } else {
1295        assert(pkt->req->masterId() < system->maxMasters());
1296        mshr_miss_latency[stats_cmd_idx][pkt->req->masterId()] +=
1297            miss_latency;
1298    }
1299
1300    // upgrade deferred targets if the response has no sharers, and is
1301    // thus passing writable
1302    if (!pkt->hasSharers()) {
1303        mshr->promoteWritable();
1304    }
1305
1306    bool is_fill = !mshr->isForward &&
1307        (pkt->isRead() || pkt->cmd == MemCmd::UpgradeResp);
1308
1309    CacheBlk *blk = tags->findBlock(pkt->getAddr(), pkt->isSecure());
1310
1311    if (is_fill && !is_error) {
1312        DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n",
1313                pkt->getAddr());
1314
1315        blk = handleFill(pkt, blk, writebacks, mshr->allocOnFill);
1316        assert(blk != NULL);
1317    }
1318
1319    // allow invalidation responses originating from write-line
1320    // requests to be discarded
1321    bool is_invalidate = pkt->isInvalidate();
1322
1323    // First offset for critical word first calculations
1324    int initial_offset = initial_tgt->pkt->getOffset(blkSize);
1325
1326    while (mshr->hasTargets()) {
1327        MSHR::Target *target = mshr->getTarget();
1328        Packet *tgt_pkt = target->pkt;
1329
1330        switch (target->source) {
1331          case MSHR::Target::FromCPU:
1332            Tick completion_time;
1333            // Here we charge on completion_time the delay of the xbar if the
1334            // packet comes from it, charged on headerDelay.
1335            completion_time = pkt->headerDelay;
1336
1337            // Software prefetch handling for cache closest to core
1338            if (tgt_pkt->cmd.isSWPrefetch()) {
1339                // a software prefetch would have already been ack'd immediately
1340                // with dummy data so the core would be able to retire it.
1341                // this request completes right here, so we deallocate it.
1342                delete tgt_pkt->req;
1343                delete tgt_pkt;
1344                break; // skip response
1345            }
1346
1347            // unlike the other packet flows, where data is found in other
1348            // caches or memory and brought back, write-line requests always
1349            // have the data right away, so the above check for "is fill?"
1350            // cannot actually be determined until examining the stored MSHR
1351            // state. We "catch up" with that logic here, which is duplicated
1352            // from above.
1353            if (tgt_pkt->cmd == MemCmd::WriteLineReq) {
1354                assert(!is_error);
1355                // we got the block in a writable state, so promote
1356                // any deferred targets if possible
1357                mshr->promoteWritable();
1358                // NB: we use the original packet here and not the response!
1359                blk = handleFill(tgt_pkt, blk, writebacks, mshr->allocOnFill);
1360                assert(blk != NULL);
1361
1362                // treat as a fill, and discard the invalidation
1363                // response
1364                is_fill = true;
1365                is_invalidate = false;
1366            }
1367
1368            if (is_fill) {
1369                satisfyCpuSideRequest(tgt_pkt, blk,
1370                                      true, mshr->hasPostDowngrade());
1371
1372                // How many bytes past the first request is this one
1373                int transfer_offset =
1374                    tgt_pkt->getOffset(blkSize) - initial_offset;
1375                if (transfer_offset < 0) {
1376                    transfer_offset += blkSize;
1377                }
1378
1379                // If not critical word (offset) return payloadDelay.
1380                // responseLatency is the latency of the return path
1381                // from lower level caches/memory to an upper level cache or
1382                // the core.
1383                completion_time += clockEdge(responseLatency) +
1384                    (transfer_offset ? pkt->payloadDelay : 0);
1385
1386                assert(!tgt_pkt->req->isUncacheable());
1387
1388                assert(tgt_pkt->req->masterId() < system->maxMasters());
1389                missLatency[tgt_pkt->cmdToIndex()][tgt_pkt->req->masterId()] +=
1390                    completion_time - target->recvTime;
1391            } else if (pkt->cmd == MemCmd::UpgradeFailResp) {
1392                // failed StoreCond upgrade
1393                assert(tgt_pkt->cmd == MemCmd::StoreCondReq ||
1394                       tgt_pkt->cmd == MemCmd::StoreCondFailReq ||
1395                       tgt_pkt->cmd == MemCmd::SCUpgradeFailReq);
1396                // responseLatency is the latency of the return path
1397                // from lower level caches/memory to an upper level cache or
1398                // the core.
1399                completion_time += clockEdge(responseLatency) +
1400                    pkt->payloadDelay;
1401                tgt_pkt->req->setExtraData(0);
1402            } else {
1403                // not a cache fill, just forwarding response
1404                // responseLatency is the latency of the return path
1405                // from lower level cahces/memory to the core.
1406                completion_time += clockEdge(responseLatency) +
1407                    pkt->payloadDelay;
1408                if (pkt->isRead() && !is_error) {
1409                    // sanity check
1410                    assert(pkt->getAddr() == tgt_pkt->getAddr());
1411                    assert(pkt->getSize() >= tgt_pkt->getSize());
1412
1413                    tgt_pkt->setData(pkt->getConstPtr<uint8_t>());
1414                }
1415            }
1416            tgt_pkt->makeTimingResponse();
1417            // if this packet is an error copy that to the new packet
1418            if (is_error)
1419                tgt_pkt->copyError(pkt);
1420            if (tgt_pkt->cmd == MemCmd::ReadResp &&
1421                (is_invalidate || mshr->hasPostInvalidate())) {
1422                // If intermediate cache got ReadRespWithInvalidate,
1423                // propagate that.  Response should not have
1424                // isInvalidate() set otherwise.
1425                tgt_pkt->cmd = MemCmd::ReadRespWithInvalidate;
1426                DPRINTF(Cache, "%s updated cmd to %s for addr %#llx\n",
1427                        __func__, tgt_pkt->cmdString(), tgt_pkt->getAddr());
1428            }
1429            // Reset the bus additional time as it is now accounted for
1430            tgt_pkt->headerDelay = tgt_pkt->payloadDelay = 0;
1431            cpuSidePort->schedTimingResp(tgt_pkt, completion_time, true);
1432            break;
1433
1434          case MSHR::Target::FromPrefetcher:
1435            assert(tgt_pkt->cmd == MemCmd::HardPFReq);
1436            if (blk)
1437                blk->status |= BlkHWPrefetched;
1438            delete tgt_pkt->req;
1439            delete tgt_pkt;
1440            break;
1441
1442          case MSHR::Target::FromSnoop:
1443            // I don't believe that a snoop can be in an error state
1444            assert(!is_error);
1445            // response to snoop request
1446            DPRINTF(Cache, "processing deferred snoop...\n");
1447            assert(!(is_invalidate && !mshr->hasPostInvalidate()));
1448            handleSnoop(tgt_pkt, blk, true, true, mshr->hasPostInvalidate());
1449            break;
1450
1451          default:
1452            panic("Illegal target->source enum %d\n", target->source);
1453        }
1454
1455        mshr->popTarget();
1456    }
1457
1458    if (blk && blk->isValid()) {
1459        // an invalidate response stemming from a write line request
1460        // should not invalidate the block, so check if the
1461        // invalidation should be discarded
1462        if (is_invalidate || mshr->hasPostInvalidate()) {
1463            invalidateBlock(blk);
1464        } else if (mshr->hasPostDowngrade()) {
1465            blk->status &= ~BlkWritable;
1466        }
1467    }
1468
1469    if (mshr->promoteDeferredTargets()) {
1470        // avoid later read getting stale data while write miss is
1471        // outstanding.. see comment in timingAccess()
1472        if (blk) {
1473            blk->status &= ~BlkReadable;
1474        }
1475        mq = mshr->queue;
1476        mq->markPending(mshr);
1477        schedMemSideSendEvent(clockEdge() + pkt->payloadDelay);
1478    } else {
1479        mq->deallocate(mshr);
1480        if (wasFull && !mq->isFull()) {
1481            clearBlocked((BlockedCause)mq->index);
1482        }
1483
1484        // Request the bus for a prefetch if this deallocation freed enough
1485        // MSHRs for a prefetch to take place
1486        if (prefetcher && mq == &mshrQueue && mshrQueue.canPrefetch()) {
1487            Tick next_pf_time = std::max(prefetcher->nextPrefetchReadyTime(),
1488                                         clockEdge());
1489            if (next_pf_time != MaxTick)
1490                schedMemSideSendEvent(next_pf_time);
1491        }
1492    }
1493    // reset the xbar additional timinig  as it is now accounted for
1494    pkt->headerDelay = pkt->payloadDelay = 0;
1495
1496    // copy writebacks to write buffer
1497    doWritebacks(writebacks, forward_time);
1498
1499    // if we used temp block, check to see if its valid and then clear it out
1500    if (blk == tempBlock && tempBlock->isValid()) {
1501        // We use forwardLatency here because we are copying
1502        // Writebacks/CleanEvicts to write buffer. It specifies the latency to
1503        // allocate an internal buffer and to schedule an event to the
1504        // queued port.
1505        if (blk->isDirty() || writebackClean) {
1506            PacketPtr wbPkt = writebackBlk(blk);
1507            allocateWriteBuffer(wbPkt, forward_time);
1508            // Set BLOCK_CACHED flag if cached above.
1509            if (isCachedAbove(wbPkt))
1510                wbPkt->setBlockCached();
1511        } else {
1512            PacketPtr wcPkt = cleanEvictBlk(blk);
1513            // Check to see if block is cached above. If not allocate
1514            // write buffer
1515            if (isCachedAbove(wcPkt))
1516                delete wcPkt;
1517            else
1518                allocateWriteBuffer(wcPkt, forward_time);
1519        }
1520        blk->invalidate();
1521    }
1522
1523    DPRINTF(CacheVerbose, "Leaving %s with %s for addr %#llx\n", __func__,
1524            pkt->cmdString(), pkt->getAddr());
1525    delete pkt;
1526}
1527
1528PacketPtr
1529Cache::writebackBlk(CacheBlk *blk)
1530{
1531    chatty_assert(!isReadOnly || writebackClean,
1532                  "Writeback from read-only cache");
1533    assert(blk && blk->isValid() && (blk->isDirty() || writebackClean));
1534
1535    writebacks[Request::wbMasterId]++;
1536
1537    Request *req = new Request(tags->regenerateBlkAddr(blk->tag, blk->set),
1538                               blkSize, 0, Request::wbMasterId);
1539    if (blk->isSecure())
1540        req->setFlags(Request::SECURE);
1541
1542    req->taskId(blk->task_id);
1543    blk->task_id= ContextSwitchTaskId::Unknown;
1544    blk->tickInserted = curTick();
1545
1546    PacketPtr pkt =
1547        new Packet(req, blk->isDirty() ?
1548                   MemCmd::WritebackDirty : MemCmd::WritebackClean);
1549
1550    DPRINTF(Cache, "Create Writeback %#llx writable: %d, dirty: %d\n",
1551            pkt->getAddr(), blk->isWritable(), blk->isDirty());
1552
1553    if (blk->isWritable()) {
1554        // not asserting shared means we pass the block in modified
1555        // state, mark our own block non-writeable
1556        blk->status &= ~BlkWritable;
1557    } else {
1558        // we are in the Owned state, tell the receiver
1559        pkt->setHasSharers();
1560    }
1561
1562    // make sure the block is not marked dirty
1563    blk->status &= ~BlkDirty;
1564
1565    pkt->allocate();
1566    std::memcpy(pkt->getPtr<uint8_t>(), blk->data, blkSize);
1567
1568    return pkt;
1569}
1570
1571PacketPtr
1572Cache::cleanEvictBlk(CacheBlk *blk)
1573{
1574    assert(!writebackClean);
1575    assert(blk && blk->isValid() && !blk->isDirty());
1576    // Creating a zero sized write, a message to the snoop filter
1577    Request *req =
1578        new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0,
1579                    Request::wbMasterId);
1580    if (blk->isSecure())
1581        req->setFlags(Request::SECURE);
1582
1583    req->taskId(blk->task_id);
1584    blk->task_id = ContextSwitchTaskId::Unknown;
1585    blk->tickInserted = curTick();
1586
1587    PacketPtr pkt = new Packet(req, MemCmd::CleanEvict);
1588    pkt->allocate();
1589    DPRINTF(Cache, "%s%s %x Create CleanEvict\n", pkt->cmdString(),
1590            pkt->req->isInstFetch() ? " (ifetch)" : "",
1591            pkt->getAddr());
1592
1593    return pkt;
1594}
1595
1596void
1597Cache::memWriteback()
1598{
1599    CacheBlkVisitorWrapper visitor(*this, &Cache::writebackVisitor);
1600    tags->forEachBlk(visitor);
1601}
1602
1603void
1604Cache::memInvalidate()
1605{
1606    CacheBlkVisitorWrapper visitor(*this, &Cache::invalidateVisitor);
1607    tags->forEachBlk(visitor);
1608}
1609
1610bool
1611Cache::isDirty() const
1612{
1613    CacheBlkIsDirtyVisitor visitor;
1614    tags->forEachBlk(visitor);
1615
1616    return visitor.isDirty();
1617}
1618
1619bool
1620Cache::writebackVisitor(CacheBlk &blk)
1621{
1622    if (blk.isDirty()) {
1623        assert(blk.isValid());
1624
1625        Request request(tags->regenerateBlkAddr(blk.tag, blk.set),
1626                        blkSize, 0, Request::funcMasterId);
1627        request.taskId(blk.task_id);
1628
1629        Packet packet(&request, MemCmd::WriteReq);
1630        packet.dataStatic(blk.data);
1631
1632        memSidePort->sendFunctional(&packet);
1633
1634        blk.status &= ~BlkDirty;
1635    }
1636
1637    return true;
1638}
1639
1640bool
1641Cache::invalidateVisitor(CacheBlk &blk)
1642{
1643
1644    if (blk.isDirty())
1645        warn_once("Invalidating dirty cache lines. Expect things to break.\n");
1646
1647    if (blk.isValid()) {
1648        assert(!blk.isDirty());
1649        tags->invalidate(&blk);
1650        blk.invalidate();
1651    }
1652
1653    return true;
1654}
1655
1656CacheBlk*
1657Cache::allocateBlock(Addr addr, bool is_secure, PacketList &writebacks)
1658{
1659    CacheBlk *blk = tags->findVictim(addr);
1660
1661    // It is valid to return NULL if there is no victim
1662    if (!blk)
1663        return nullptr;
1664
1665    if (blk->isValid()) {
1666        Addr repl_addr = tags->regenerateBlkAddr(blk->tag, blk->set);
1667        MSHR *repl_mshr = mshrQueue.findMatch(repl_addr, blk->isSecure());
1668        if (repl_mshr) {
1669            // must be an outstanding upgrade request
1670            // on a block we're about to replace...
1671            assert(!blk->isWritable() || blk->isDirty());
1672            assert(repl_mshr->needsWritable());
1673            // too hard to replace block with transient state
1674            // allocation failed, block not inserted
1675            return NULL;
1676        } else {
1677            DPRINTF(Cache, "replacement: replacing %#llx (%s) with %#llx (%s): %s\n",
1678                    repl_addr, blk->isSecure() ? "s" : "ns",
1679                    addr, is_secure ? "s" : "ns",
1680                    blk->isDirty() ? "writeback" : "clean");
1681
1682            // Will send up Writeback/CleanEvict snoops via isCachedAbove
1683            // when pushing this writeback list into the write buffer.
1684            if (blk->isDirty() || writebackClean) {
1685                // Save writeback packet for handling by caller
1686                writebacks.push_back(writebackBlk(blk));
1687            } else {
1688                writebacks.push_back(cleanEvictBlk(blk));
1689            }
1690        }
1691    }
1692
1693    return blk;
1694}
1695
1696void
1697Cache::invalidateBlock(CacheBlk *blk)
1698{
1699    if (blk != tempBlock)
1700        tags->invalidate(blk);
1701    blk->invalidate();
1702}
1703
1704// Note that the reason we return a list of writebacks rather than
1705// inserting them directly in the write buffer is that this function
1706// is called by both atomic and timing-mode accesses, and in atomic
1707// mode we don't mess with the write buffer (we just perform the
1708// writebacks atomically once the original request is complete).
1709CacheBlk*
1710Cache::handleFill(PacketPtr pkt, CacheBlk *blk, PacketList &writebacks,
1711                  bool allocate)
1712{
1713    assert(pkt->isResponse() || pkt->cmd == MemCmd::WriteLineReq);
1714    Addr addr = pkt->getAddr();
1715    bool is_secure = pkt->isSecure();
1716#if TRACING_ON
1717    CacheBlk::State old_state = blk ? blk->status : 0;
1718#endif
1719
1720    // When handling a fill, discard any CleanEvicts for the
1721    // same address in write buffer.
1722    Addr M5_VAR_USED blk_addr = blockAlign(pkt->getAddr());
1723    std::vector<MSHR *> M5_VAR_USED wbs;
1724    assert (!writeBuffer.findMatches(blk_addr, is_secure, wbs));
1725
1726    if (blk == NULL) {
1727        // better have read new data...
1728        assert(pkt->hasData());
1729
1730        // only read responses and write-line requests have data;
1731        // note that we don't write the data here for write-line - that
1732        // happens in the subsequent satisfyCpuSideRequest.
1733        assert(pkt->isRead() || pkt->cmd == MemCmd::WriteLineReq);
1734
1735        // need to do a replacement if allocating, otherwise we stick
1736        // with the temporary storage
1737        blk = allocate ? allocateBlock(addr, is_secure, writebacks) : NULL;
1738
1739        if (blk == NULL) {
1740            // No replaceable block or a mostly exclusive
1741            // cache... just use temporary storage to complete the
1742            // current request and then get rid of it
1743            assert(!tempBlock->isValid());
1744            blk = tempBlock;
1745            tempBlock->set = tags->extractSet(addr);
1746            tempBlock->tag = tags->extractTag(addr);
1747            // @todo: set security state as well...
1748            DPRINTF(Cache, "using temp block for %#llx (%s)\n", addr,
1749                    is_secure ? "s" : "ns");
1750        } else {
1751            tags->insertBlock(pkt, blk);
1752        }
1753
1754        // we should never be overwriting a valid block
1755        assert(!blk->isValid());
1756    } else {
1757        // existing block... probably an upgrade
1758        assert(blk->tag == tags->extractTag(addr));
1759        // either we're getting new data or the block should already be valid
1760        assert(pkt->hasData() || blk->isValid());
1761        // don't clear block status... if block is already dirty we
1762        // don't want to lose that
1763    }
1764
1765    if (is_secure)
1766        blk->status |= BlkSecure;
1767    blk->status |= BlkValid | BlkReadable;
1768
1769    // sanity check for whole-line writes, which should always be
1770    // marked as writable as part of the fill, and then later marked
1771    // dirty as part of satisfyCpuSideRequest
1772    if (pkt->cmd == MemCmd::WriteLineReq) {
1773        assert(!pkt->hasSharers());
1774        // at the moment other caches do not respond to the
1775        // invalidation requests corresponding to a whole-line write
1776        assert(!pkt->cacheResponding());
1777    }
1778
1779    // here we deal with setting the appropriate state of the line,
1780    // and we start by looking at the hasSharers flag, and ignore the
1781    // cacheResponding flag (normally signalling dirty data) if the
1782    // packet has sharers, thus the line is never allocated as Owned
1783    // (dirty but not writable), and always ends up being either
1784    // Shared, Exclusive or Modified, see Packet::setCacheResponding
1785    // for more details
1786    if (!pkt->hasSharers()) {
1787        // we could get a writable line from memory (rather than a
1788        // cache) even in a read-only cache, note that we set this bit
1789        // even for a read-only cache, possibly revisit this decision
1790        blk->status |= BlkWritable;
1791
1792        // check if we got this via cache-to-cache transfer (i.e., from a
1793        // cache that had the block in Modified or Owned state)
1794        if (pkt->cacheResponding()) {
1795            // we got the block in Modified state, and invalidated the
1796            // owners copy
1797            blk->status |= BlkDirty;
1798
1799            chatty_assert(!isReadOnly, "Should never see dirty snoop response "
1800                          "in read-only cache %s\n", name());
1801        }
1802    }
1803
1804    DPRINTF(Cache, "Block addr %#llx (%s) moving from state %x to %s\n",
1805            addr, is_secure ? "s" : "ns", old_state, blk->print());
1806
1807    // if we got new data, copy it in (checking for a read response
1808    // and a response that has data is the same in the end)
1809    if (pkt->isRead()) {
1810        // sanity checks
1811        assert(pkt->hasData());
1812        assert(pkt->getSize() == blkSize);
1813
1814        std::memcpy(blk->data, pkt->getConstPtr<uint8_t>(), blkSize);
1815    }
1816    // We pay for fillLatency here.
1817    blk->whenReady = clockEdge() + fillLatency * clockPeriod() +
1818        pkt->payloadDelay;
1819
1820    return blk;
1821}
1822
1823
1824/////////////////////////////////////////////////////
1825//
1826// Snoop path: requests coming in from the memory side
1827//
1828/////////////////////////////////////////////////////
1829
1830void
1831Cache::doTimingSupplyResponse(PacketPtr req_pkt, const uint8_t *blk_data,
1832                              bool already_copied, bool pending_inval)
1833{
1834    // sanity check
1835    assert(req_pkt->isRequest());
1836    assert(req_pkt->needsResponse());
1837
1838    DPRINTF(Cache, "%s for %s addr %#llx size %d\n", __func__,
1839            req_pkt->cmdString(), req_pkt->getAddr(), req_pkt->getSize());
1840    // timing-mode snoop responses require a new packet, unless we
1841    // already made a copy...
1842    PacketPtr pkt = req_pkt;
1843    if (!already_copied)
1844        // do not clear flags, and allocate space for data if the
1845        // packet needs it (the only packets that carry data are read
1846        // responses)
1847        pkt = new Packet(req_pkt, false, req_pkt->isRead());
1848
1849    assert(req_pkt->req->isUncacheable() || req_pkt->isInvalidate() ||
1850           pkt->hasSharers());
1851    pkt->makeTimingResponse();
1852    if (pkt->isRead()) {
1853        pkt->setDataFromBlock(blk_data, blkSize);
1854    }
1855    if (pkt->cmd == MemCmd::ReadResp && pending_inval) {
1856        // Assume we defer a response to a read from a far-away cache
1857        // A, then later defer a ReadExcl from a cache B on the same
1858        // bus as us. We'll assert cacheResponding in both cases, but
1859        // in the latter case cacheResponding will keep the
1860        // invalidation from reaching cache A. This special response
1861        // tells cache A that it gets the block to satisfy its read,
1862        // but must immediately invalidate it.
1863        pkt->cmd = MemCmd::ReadRespWithInvalidate;
1864    }
1865    // Here we consider forward_time, paying for just forward latency and
1866    // also charging the delay provided by the xbar.
1867    // forward_time is used as send_time in next allocateWriteBuffer().
1868    Tick forward_time = clockEdge(forwardLatency) + pkt->headerDelay;
1869    // Here we reset the timing of the packet.
1870    pkt->headerDelay = pkt->payloadDelay = 0;
1871    DPRINTF(CacheVerbose,
1872            "%s created response: %s addr %#llx size %d tick: %lu\n",
1873            __func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize(),
1874            forward_time);
1875    memSidePort->schedTimingSnoopResp(pkt, forward_time, true);
1876}
1877
1878uint32_t
1879Cache::handleSnoop(PacketPtr pkt, CacheBlk *blk, bool is_timing,
1880                   bool is_deferred, bool pending_inval)
1881{
1882    DPRINTF(CacheVerbose, "%s for %s addr %#llx size %d\n", __func__,
1883            pkt->cmdString(), pkt->getAddr(), pkt->getSize());
1884    // deferred snoops can only happen in timing mode
1885    assert(!(is_deferred && !is_timing));
1886    // pending_inval only makes sense on deferred snoops
1887    assert(!(pending_inval && !is_deferred));
1888    assert(pkt->isRequest());
1889
1890    // the packet may get modified if we or a forwarded snooper
1891    // responds in atomic mode, so remember a few things about the
1892    // original packet up front
1893    bool invalidate = pkt->isInvalidate();
1894    bool M5_VAR_USED needs_writable = pkt->needsWritable();
1895
1896    // at the moment we could get an uncacheable write which does not
1897    // have the invalidate flag, and we need a suitable way of dealing
1898    // with this case
1899    panic_if(invalidate && pkt->req->isUncacheable(),
1900             "%s got an invalidating uncacheable snoop request %s to %#llx",
1901             name(), pkt->cmdString(), pkt->getAddr());
1902
1903    uint32_t snoop_delay = 0;
1904
1905    if (forwardSnoops) {
1906        // first propagate snoop upward to see if anyone above us wants to
1907        // handle it.  save & restore packet src since it will get
1908        // rewritten to be relative to cpu-side bus (if any)
1909        bool alreadyResponded = pkt->cacheResponding();
1910        if (is_timing) {
1911            // copy the packet so that we can clear any flags before
1912            // forwarding it upwards, we also allocate data (passing
1913            // the pointer along in case of static data), in case
1914            // there is a snoop hit in upper levels
1915            Packet snoopPkt(pkt, true, true);
1916            snoopPkt.setExpressSnoop();
1917            // the snoop packet does not need to wait any additional
1918            // time
1919            snoopPkt.headerDelay = snoopPkt.payloadDelay = 0;
1920            cpuSidePort->sendTimingSnoopReq(&snoopPkt);
1921
1922            // add the header delay (including crossbar and snoop
1923            // delays) of the upward snoop to the snoop delay for this
1924            // cache
1925            snoop_delay += snoopPkt.headerDelay;
1926
1927            if (snoopPkt.cacheResponding()) {
1928                // cache-to-cache response from some upper cache
1929                assert(!alreadyResponded);
1930                pkt->setCacheResponding();
1931            }
1932            // upstream cache has the block, or has an outstanding
1933            // MSHR, pass the flag on
1934            if (snoopPkt.hasSharers()) {
1935                pkt->setHasSharers();
1936            }
1937            // If this request is a prefetch or clean evict and an upper level
1938            // signals block present, make sure to propagate the block
1939            // presence to the requester.
1940            if (snoopPkt.isBlockCached()) {
1941                pkt->setBlockCached();
1942            }
1943        } else {
1944            cpuSidePort->sendAtomicSnoop(pkt);
1945            if (!alreadyResponded && pkt->cacheResponding()) {
1946                // cache-to-cache response from some upper cache:
1947                // forward response to original requester
1948                assert(pkt->isResponse());
1949            }
1950        }
1951    }
1952
1953    if (!blk || !blk->isValid()) {
1954        DPRINTF(CacheVerbose, "%s snoop miss for %s addr %#llx size %d\n",
1955                __func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize());
1956        return snoop_delay;
1957    } else {
1958        DPRINTF(Cache, "%s snoop hit for %s addr %#llx size %d, "
1959                "old state is %s\n", __func__, pkt->cmdString(),
1960                pkt->getAddr(), pkt->getSize(), blk->print());
1961    }
1962
1963    chatty_assert(!(isReadOnly && blk->isDirty()),
1964                  "Should never have a dirty block in a read-only cache %s\n",
1965                  name());
1966
1967    // We may end up modifying both the block state and the packet (if
1968    // we respond in atomic mode), so just figure out what to do now
1969    // and then do it later. If we find dirty data while snooping for
1970    // an invalidate, we don't need to send a response. The
1971    // invalidation itself is taken care of below.
1972    bool respond = blk->isDirty() && pkt->needsResponse() &&
1973        pkt->cmd != MemCmd::InvalidateReq;
1974    bool have_writable = blk->isWritable();
1975
1976    // Invalidate any prefetch's from below that would strip write permissions
1977    // MemCmd::HardPFReq is only observed by upstream caches.  After missing
1978    // above and in it's own cache, a new MemCmd::ReadReq is created that
1979    // downstream caches observe.
1980    if (pkt->mustCheckAbove()) {
1981        DPRINTF(Cache, "Found addr %#llx in upper level cache for snoop %s from"
1982                " lower cache\n", pkt->getAddr(), pkt->cmdString());
1983        pkt->setBlockCached();
1984        return snoop_delay;
1985    }
1986
1987    if (pkt->isRead() && !invalidate) {
1988        // reading without requiring the line in a writable state
1989        assert(!needs_writable);
1990        pkt->setHasSharers();
1991
1992        // if the requesting packet is uncacheable, retain the line in
1993        // the current state, otherwhise unset the writable flag,
1994        // which means we go from Modified to Owned (and will respond
1995        // below), remain in Owned (and will respond below), from
1996        // Exclusive to Shared, or remain in Shared
1997        if (!pkt->req->isUncacheable())
1998            blk->status &= ~BlkWritable;
1999    }
2000
2001    if (respond) {
2002        // prevent anyone else from responding, cache as well as
2003        // memory, and also prevent any memory from even seeing the
2004        // request
2005        pkt->setCacheResponding();
2006        if (have_writable) {
2007            // inform the cache hierarchy that this cache had the line
2008            // in the Modified state so that we avoid unnecessary
2009            // invalidations (see Packet::setResponderHadWritable)
2010            pkt->setResponderHadWritable();
2011
2012            // in the case of an uncacheable request there is no point
2013            // in setting the responderHadWritable flag, but since the
2014            // recipient does not care there is no harm in doing so
2015        } else {
2016            // if the packet has needsWritable set we invalidate our
2017            // copy below and all other copies will be invalidates
2018            // through express snoops, and if needsWritable is not set
2019            // we already called setHasSharers above
2020        }
2021
2022        // if we are returning a writable and dirty (Modified) line,
2023        // we should be invalidating the line
2024        panic_if(!invalidate && !pkt->hasSharers(),
2025                 "%s is passing a Modified line through %s to %#llx, "
2026                 "but keeping the block",
2027                 name(), pkt->cmdString(), pkt->getAddr());
2028
2029        if (is_timing) {
2030            doTimingSupplyResponse(pkt, blk->data, is_deferred, pending_inval);
2031        } else {
2032            pkt->makeAtomicResponse();
2033            // packets such as upgrades do not actually have any data
2034            // payload
2035            if (pkt->hasData())
2036                pkt->setDataFromBlock(blk->data, blkSize);
2037        }
2038    }
2039
2040    if (!respond && is_timing && is_deferred) {
2041        // if it's a deferred timing snoop to which we are not
2042        // responding, then we've made a copy of both the request and
2043        // the packet, delete them here
2044        assert(pkt->needsResponse());
2045        delete pkt->req;
2046        delete pkt;
2047    }
2048
2049    // Do this last in case it deallocates block data or something
2050    // like that
2051    if (invalidate) {
2052        invalidateBlock(blk);
2053    }
2054
2055    DPRINTF(Cache, "new state is %s\n", blk->print());
2056
2057    return snoop_delay;
2058}
2059
2060
2061void
2062Cache::recvTimingSnoopReq(PacketPtr pkt)
2063{
2064    DPRINTF(CacheVerbose, "%s for %s addr %#llx size %d\n", __func__,
2065            pkt->cmdString(), pkt->getAddr(), pkt->getSize());
2066
2067    // Snoops shouldn't happen when bypassing caches
2068    assert(!system->bypassCaches());
2069
2070    // no need to snoop requests that are not in range
2071    if (!inRange(pkt->getAddr())) {
2072        return;
2073    }
2074
2075    bool is_secure = pkt->isSecure();
2076    CacheBlk *blk = tags->findBlock(pkt->getAddr(), is_secure);
2077
2078    Addr blk_addr = blockAlign(pkt->getAddr());
2079    MSHR *mshr = mshrQueue.findMatch(blk_addr, is_secure);
2080
2081    // Update the latency cost of the snoop so that the crossbar can
2082    // account for it. Do not overwrite what other neighbouring caches
2083    // have already done, rather take the maximum. The update is
2084    // tentative, for cases where we return before an upward snoop
2085    // happens below.
2086    pkt->snoopDelay = std::max<uint32_t>(pkt->snoopDelay,
2087                                         lookupLatency * clockPeriod());
2088
2089    // Inform request(Prefetch, CleanEvict or Writeback) from below of
2090    // MSHR hit, set setBlockCached.
2091    if (mshr && pkt->mustCheckAbove()) {
2092        DPRINTF(Cache, "Setting block cached for %s from"
2093                "lower cache on mshr hit %#x\n",
2094                pkt->cmdString(), pkt->getAddr());
2095        pkt->setBlockCached();
2096        return;
2097    }
2098
2099    // Let the MSHR itself track the snoop and decide whether we want
2100    // to go ahead and do the regular cache snoop
2101    if (mshr && mshr->handleSnoop(pkt, order++)) {
2102        DPRINTF(Cache, "Deferring snoop on in-service MSHR to blk %#llx (%s)."
2103                "mshrs: %s\n", blk_addr, is_secure ? "s" : "ns",
2104                mshr->print());
2105
2106        if (mshr->getNumTargets() > numTarget)
2107            warn("allocating bonus target for snoop"); //handle later
2108        return;
2109    }
2110
2111    //We also need to check the writeback buffers and handle those
2112    std::vector<MSHR *> writebacks;
2113    if (writeBuffer.findMatches(blk_addr, is_secure, writebacks)) {
2114        DPRINTF(Cache, "Snoop hit in writeback to addr %#llx (%s)\n",
2115                pkt->getAddr(), is_secure ? "s" : "ns");
2116
2117        // Look through writebacks for any cachable writes.
2118        // We should only ever find a single match
2119        assert(writebacks.size() == 1);
2120        MSHR *wb_entry = writebacks[0];
2121        // Expect to see only Writebacks and/or CleanEvicts here, both of
2122        // which should not be generated for uncacheable data.
2123        assert(!wb_entry->isUncacheable());
2124        // There should only be a single request responsible for generating
2125        // Writebacks/CleanEvicts.
2126        assert(wb_entry->getNumTargets() == 1);
2127        PacketPtr wb_pkt = wb_entry->getTarget()->pkt;
2128        assert(wb_pkt->isEviction());
2129
2130        if (pkt->isEviction()) {
2131            // if the block is found in the write queue, set the BLOCK_CACHED
2132            // flag for Writeback/CleanEvict snoop. On return the snoop will
2133            // propagate the BLOCK_CACHED flag in Writeback packets and prevent
2134            // any CleanEvicts from travelling down the memory hierarchy.
2135            pkt->setBlockCached();
2136            DPRINTF(Cache, "Squashing %s from lower cache on writequeue hit"
2137                    " %#x\n", pkt->cmdString(), pkt->getAddr());
2138            return;
2139        }
2140
2141        // conceptually writebacks are no different to other blocks in
2142        // this cache, so the behaviour is modelled after handleSnoop,
2143        // the difference being that instead of querying the block
2144        // state to determine if it is dirty and writable, we use the
2145        // command and fields of the writeback packet
2146        bool respond = wb_pkt->cmd == MemCmd::WritebackDirty &&
2147            pkt->needsResponse() && pkt->cmd != MemCmd::InvalidateReq;
2148        bool have_writable = !wb_pkt->hasSharers();
2149        bool invalidate = pkt->isInvalidate();
2150
2151        if (!pkt->req->isUncacheable() && pkt->isRead() && !invalidate) {
2152            assert(!pkt->needsWritable());
2153            pkt->setHasSharers();
2154            wb_pkt->setHasSharers();
2155        }
2156
2157        if (respond) {
2158            pkt->setCacheResponding();
2159
2160            if (have_writable) {
2161                pkt->setResponderHadWritable();
2162            }
2163
2164            doTimingSupplyResponse(pkt, wb_pkt->getConstPtr<uint8_t>(),
2165                                   false, false);
2166        }
2167
2168        if (invalidate) {
2169            // Invalidation trumps our writeback... discard here
2170            // Note: markInService will remove entry from writeback buffer.
2171            markInService(wb_entry, false);
2172            delete wb_pkt;
2173        }
2174    }
2175
2176    // If this was a shared writeback, there may still be
2177    // other shared copies above that require invalidation.
2178    // We could be more selective and return here if the
2179    // request is non-exclusive or if the writeback is
2180    // exclusive.
2181    uint32_t snoop_delay = handleSnoop(pkt, blk, true, false, false);
2182
2183    // Override what we did when we first saw the snoop, as we now
2184    // also have the cost of the upwards snoops to account for
2185    pkt->snoopDelay = std::max<uint32_t>(pkt->snoopDelay, snoop_delay +
2186                                         lookupLatency * clockPeriod());
2187}
2188
2189bool
2190Cache::CpuSidePort::recvTimingSnoopResp(PacketPtr pkt)
2191{
2192    // Express snoop responses from master to slave, e.g., from L1 to L2
2193    cache->recvTimingSnoopResp(pkt);
2194    return true;
2195}
2196
2197Tick
2198Cache::recvAtomicSnoop(PacketPtr pkt)
2199{
2200    // Snoops shouldn't happen when bypassing caches
2201    assert(!system->bypassCaches());
2202
2203    // no need to snoop requests that are not in range.
2204    if (!inRange(pkt->getAddr())) {
2205        return 0;
2206    }
2207
2208    CacheBlk *blk = tags->findBlock(pkt->getAddr(), pkt->isSecure());
2209    uint32_t snoop_delay = handleSnoop(pkt, blk, false, false, false);
2210    return snoop_delay + lookupLatency * clockPeriod();
2211}
2212
2213
2214MSHR *
2215Cache::getNextMSHR()
2216{
2217    // Check both MSHR queue and write buffer for potential requests,
2218    // note that null does not mean there is no request, it could
2219    // simply be that it is not ready
2220    MSHR *miss_mshr  = mshrQueue.getNextMSHR();
2221    MSHR *write_mshr = writeBuffer.getNextMSHR();
2222
2223    // If we got a write buffer request ready, first priority is a
2224    // full write buffer, otherwhise we favour the miss requests
2225    if (write_mshr &&
2226        ((writeBuffer.isFull() && writeBuffer.inServiceEntries == 0) ||
2227         !miss_mshr)) {
2228        // need to search MSHR queue for conflicting earlier miss.
2229        MSHR *conflict_mshr =
2230            mshrQueue.findPending(write_mshr->blkAddr,
2231                                  write_mshr->isSecure);
2232
2233        if (conflict_mshr && conflict_mshr->order < write_mshr->order) {
2234            // Service misses in order until conflict is cleared.
2235            return conflict_mshr;
2236
2237            // @todo Note that we ignore the ready time of the conflict here
2238        }
2239
2240        // No conflicts; issue write
2241        return write_mshr;
2242    } else if (miss_mshr) {
2243        // need to check for conflicting earlier writeback
2244        MSHR *conflict_mshr =
2245            writeBuffer.findPending(miss_mshr->blkAddr,
2246                                    miss_mshr->isSecure);
2247        if (conflict_mshr) {
2248            // not sure why we don't check order here... it was in the
2249            // original code but commented out.
2250
2251            // The only way this happens is if we are
2252            // doing a write and we didn't have permissions
2253            // then subsequently saw a writeback (owned got evicted)
2254            // We need to make sure to perform the writeback first
2255            // To preserve the dirty data, then we can issue the write
2256
2257            // should we return write_mshr here instead?  I.e. do we
2258            // have to flush writes in order?  I don't think so... not
2259            // for Alpha anyway.  Maybe for x86?
2260            return conflict_mshr;
2261
2262            // @todo Note that we ignore the ready time of the conflict here
2263        }
2264
2265        // No conflicts; issue read
2266        return miss_mshr;
2267    }
2268
2269    // fall through... no pending requests.  Try a prefetch.
2270    assert(!miss_mshr && !write_mshr);
2271    if (prefetcher && mshrQueue.canPrefetch()) {
2272        // If we have a miss queue slot, we can try a prefetch
2273        PacketPtr pkt = prefetcher->getPacket();
2274        if (pkt) {
2275            Addr pf_addr = blockAlign(pkt->getAddr());
2276            if (!tags->findBlock(pf_addr, pkt->isSecure()) &&
2277                !mshrQueue.findMatch(pf_addr, pkt->isSecure()) &&
2278                !writeBuffer.findMatch(pf_addr, pkt->isSecure())) {
2279                // Update statistic on number of prefetches issued
2280                // (hwpf_mshr_misses)
2281                assert(pkt->req->masterId() < system->maxMasters());
2282                mshr_misses[pkt->cmdToIndex()][pkt->req->masterId()]++;
2283
2284                // allocate an MSHR and return it, note
2285                // that we send the packet straight away, so do not
2286                // schedule the send
2287                return allocateMissBuffer(pkt, curTick(), false);
2288            } else {
2289                // free the request and packet
2290                delete pkt->req;
2291                delete pkt;
2292            }
2293        }
2294    }
2295
2296    return NULL;
2297}
2298
2299bool
2300Cache::isCachedAbove(PacketPtr pkt, bool is_timing) const
2301{
2302    if (!forwardSnoops)
2303        return false;
2304    // Mirroring the flow of HardPFReqs, the cache sends CleanEvict and
2305    // Writeback snoops into upper level caches to check for copies of the
2306    // same block. Using the BLOCK_CACHED flag with the Writeback/CleanEvict
2307    // packet, the cache can inform the crossbar below of presence or absence
2308    // of the block.
2309    if (is_timing) {
2310        Packet snoop_pkt(pkt, true, false);
2311        snoop_pkt.setExpressSnoop();
2312        // Assert that packet is either Writeback or CleanEvict and not a
2313        // prefetch request because prefetch requests need an MSHR and may
2314        // generate a snoop response.
2315        assert(pkt->isEviction());
2316        snoop_pkt.senderState = NULL;
2317        cpuSidePort->sendTimingSnoopReq(&snoop_pkt);
2318        // Writeback/CleanEvict snoops do not generate a snoop response.
2319        assert(!(snoop_pkt.cacheResponding()));
2320        return snoop_pkt.isBlockCached();
2321    } else {
2322        cpuSidePort->sendAtomicSnoop(pkt);
2323        return pkt->isBlockCached();
2324    }
2325}
2326
2327PacketPtr
2328Cache::getTimingPacket()
2329{
2330    MSHR *mshr = getNextMSHR();
2331
2332    if (mshr == NULL) {
2333        return NULL;
2334    }
2335
2336    // use request from 1st target
2337    PacketPtr tgt_pkt = mshr->getTarget()->pkt;
2338    PacketPtr pkt = NULL;
2339
2340    DPRINTF(CachePort, "%s %s for addr %#llx size %d\n", __func__,
2341            tgt_pkt->cmdString(), tgt_pkt->getAddr(), tgt_pkt->getSize());
2342
2343    CacheBlk *blk = tags->findBlock(mshr->blkAddr, mshr->isSecure);
2344
2345    if (tgt_pkt->cmd == MemCmd::HardPFReq && forwardSnoops) {
2346        // We need to check the caches above us to verify that
2347        // they don't have a copy of this block in the dirty state
2348        // at the moment. Without this check we could get a stale
2349        // copy from memory that might get used in place of the
2350        // dirty one.
2351        Packet snoop_pkt(tgt_pkt, true, false);
2352        snoop_pkt.setExpressSnoop();
2353        // We are sending this packet upwards, but if it hits we will
2354        // get a snoop response that we end up treating just like a
2355        // normal response, hence it needs the MSHR as its sender
2356        // state
2357        snoop_pkt.senderState = mshr;
2358        cpuSidePort->sendTimingSnoopReq(&snoop_pkt);
2359
2360        // Check to see if the prefetch was squashed by an upper cache (to
2361        // prevent us from grabbing the line) or if a Check to see if a
2362        // writeback arrived between the time the prefetch was placed in
2363        // the MSHRs and when it was selected to be sent or if the
2364        // prefetch was squashed by an upper cache.
2365
2366        // It is important to check cacheResponding before
2367        // prefetchSquashed. If another cache has committed to
2368        // responding, it will be sending a dirty response which will
2369        // arrive at the MSHR allocated for this request. Checking the
2370        // prefetchSquash first may result in the MSHR being
2371        // prematurely deallocated.
2372        if (snoop_pkt.cacheResponding()) {
2373            auto M5_VAR_USED r = outstandingSnoop.insert(snoop_pkt.req);
2374            assert(r.second);
2375
2376            // if we are getting a snoop response with no sharers it
2377            // will be allocated as Modified
2378            bool pending_modified_resp = !snoop_pkt.hasSharers();
2379            markInService(mshr, pending_modified_resp);
2380
2381            DPRINTF(Cache, "Upward snoop of prefetch for addr"
2382                    " %#x (%s) hit\n",
2383                    tgt_pkt->getAddr(), tgt_pkt->isSecure()? "s": "ns");
2384            return NULL;
2385        }
2386
2387        if (snoop_pkt.isBlockCached() || blk != NULL) {
2388            DPRINTF(Cache, "Block present, prefetch squashed by cache.  "
2389                    "Deallocating mshr target %#x.\n",
2390                    mshr->blkAddr);
2391            // Deallocate the mshr target
2392            if (mshr->queue->forceDeallocateTarget(mshr)) {
2393                // Clear block if this deallocation resulted freed an
2394                // mshr when all had previously been utilized
2395                clearBlocked((BlockedCause)(mshr->queue->index));
2396            }
2397            return NULL;
2398        }
2399    }
2400
2401    if (mshr->isForwardNoResponse()) {
2402        // no response expected, just forward packet as it is
2403        assert(tags->findBlock(mshr->blkAddr, mshr->isSecure) == NULL);
2404        pkt = tgt_pkt;
2405    } else {
2406        pkt = getBusPacket(tgt_pkt, blk, mshr->needsWritable());
2407
2408        mshr->isForward = (pkt == NULL);
2409
2410        if (mshr->isForward) {
2411            // not a cache block request, but a response is expected
2412            // make copy of current packet to forward, keep current
2413            // copy for response handling
2414            pkt = new Packet(tgt_pkt, false, true);
2415            if (pkt->isWrite()) {
2416                pkt->setData(tgt_pkt->getConstPtr<uint8_t>());
2417            }
2418        }
2419    }
2420
2421    assert(pkt != NULL);
2422    // play it safe and append (rather than set) the sender state, as
2423    // forwarded packets may already have existing state
2424    pkt->pushSenderState(mshr);
2425    return pkt;
2426}
2427
2428
2429Tick
2430Cache::nextMSHRReadyTime() const
2431{
2432    Tick nextReady = std::min(mshrQueue.nextMSHRReadyTime(),
2433                              writeBuffer.nextMSHRReadyTime());
2434
2435    // Don't signal prefetch ready time if no MSHRs available
2436    // Will signal once enoguh MSHRs are deallocated
2437    if (prefetcher && mshrQueue.canPrefetch()) {
2438        nextReady = std::min(nextReady,
2439                             prefetcher->nextPrefetchReadyTime());
2440    }
2441
2442    return nextReady;
2443}
2444
2445void
2446Cache::serialize(CheckpointOut &cp) const
2447{
2448    bool dirty(isDirty());
2449
2450    if (dirty) {
2451        warn("*** The cache still contains dirty data. ***\n");
2452        warn("    Make sure to drain the system using the correct flags.\n");
2453        warn("    This checkpoint will not restore correctly and dirty data in "
2454             "the cache will be lost!\n");
2455    }
2456
2457    // Since we don't checkpoint the data in the cache, any dirty data
2458    // will be lost when restoring from a checkpoint of a system that
2459    // wasn't drained properly. Flag the checkpoint as invalid if the
2460    // cache contains dirty data.
2461    bool bad_checkpoint(dirty);
2462    SERIALIZE_SCALAR(bad_checkpoint);
2463}
2464
2465void
2466Cache::unserialize(CheckpointIn &cp)
2467{
2468    bool bad_checkpoint;
2469    UNSERIALIZE_SCALAR(bad_checkpoint);
2470    if (bad_checkpoint) {
2471        fatal("Restoring from checkpoints with dirty caches is not supported "
2472              "in the classic memory system. Please remove any caches or "
2473              " drain them properly before taking checkpoints.\n");
2474    }
2475}
2476
2477///////////////
2478//
2479// CpuSidePort
2480//
2481///////////////
2482
2483AddrRangeList
2484Cache::CpuSidePort::getAddrRanges() const
2485{
2486    return cache->getAddrRanges();
2487}
2488
2489bool
2490Cache::CpuSidePort::recvTimingReq(PacketPtr pkt)
2491{
2492    assert(!cache->system->bypassCaches());
2493
2494    bool success = false;
2495
2496    // always let packets through if an upstream cache has committed
2497    // to responding, even if blocked (we should technically look at
2498    // the isExpressSnoop flag, but it is set by the cache itself, and
2499    // consequently we have to rely on the cacheResponding flag)
2500    if (pkt->cacheResponding()) {
2501        // do not change the current retry state
2502        bool M5_VAR_USED bypass_success = cache->recvTimingReq(pkt);
2503        assert(bypass_success);
2504        return true;
2505    } else if (blocked || mustSendRetry) {
2506        // either already committed to send a retry, or blocked
2507        success = false;
2508    } else {
2509        // pass it on to the cache, and let the cache decide if we
2510        // have to retry or not
2511        success = cache->recvTimingReq(pkt);
2512    }
2513
2514    // remember if we have to retry
2515    mustSendRetry = !success;
2516    return success;
2517}
2518
2519Tick
2520Cache::CpuSidePort::recvAtomic(PacketPtr pkt)
2521{
2522    return cache->recvAtomic(pkt);
2523}
2524
2525void
2526Cache::CpuSidePort::recvFunctional(PacketPtr pkt)
2527{
2528    // functional request
2529    cache->functionalAccess(pkt, true);
2530}
2531
2532Cache::
2533CpuSidePort::CpuSidePort(const std::string &_name, Cache *_cache,
2534                         const std::string &_label)
2535    : BaseCache::CacheSlavePort(_name, _cache, _label), cache(_cache)
2536{
2537}
2538
2539Cache*
2540CacheParams::create()
2541{
2542    assert(tags);
2543
2544    return new Cache(this);
2545}
2546///////////////
2547//
2548// MemSidePort
2549//
2550///////////////
2551
2552bool
2553Cache::MemSidePort::recvTimingResp(PacketPtr pkt)
2554{
2555    cache->recvTimingResp(pkt);
2556    return true;
2557}
2558
2559// Express snooping requests to memside port
2560void
2561Cache::MemSidePort::recvTimingSnoopReq(PacketPtr pkt)
2562{
2563    // handle snooping requests
2564    cache->recvTimingSnoopReq(pkt);
2565}
2566
2567Tick
2568Cache::MemSidePort::recvAtomicSnoop(PacketPtr pkt)
2569{
2570    return cache->recvAtomicSnoop(pkt);
2571}
2572
2573void
2574Cache::MemSidePort::recvFunctionalSnoop(PacketPtr pkt)
2575{
2576    // functional snoop (note that in contrast to atomic we don't have
2577    // a specific functionalSnoop method, as they have the same
2578    // behaviour regardless)
2579    cache->functionalAccess(pkt, false);
2580}
2581
2582void
2583Cache::CacheReqPacketQueue::sendDeferredPacket()
2584{
2585    // sanity check
2586    assert(!waitingOnRetry);
2587
2588    // there should never be any deferred request packets in the
2589    // queue, instead we resly on the cache to provide the packets
2590    // from the MSHR queue or write queue
2591    assert(deferredPacketReadyTime() == MaxTick);
2592
2593    // check for request packets (requests & writebacks)
2594    PacketPtr pkt = cache.getTimingPacket();
2595    if (pkt == NULL) {
2596        // can happen if e.g. we attempt a writeback and fail, but
2597        // before the retry, the writeback is eliminated because
2598        // we snoop another cache's ReadEx.
2599    } else {
2600        MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
2601        // in most cases getTimingPacket allocates a new packet, and
2602        // we must delete it unless it is successfully sent
2603        bool delete_pkt = !mshr->isForwardNoResponse();
2604
2605        // let our snoop responses go first if there are responses to
2606        // the same addresses we are about to writeback, note that
2607        // this creates a dependency between requests and snoop
2608        // responses, but that should not be a problem since there is
2609        // a chain already and the key is that the snoop responses can
2610        // sink unconditionally
2611        if (snoopRespQueue.hasAddr(pkt->getAddr())) {
2612            DPRINTF(CachePort, "Waiting for snoop response to be sent\n");
2613            Tick when = snoopRespQueue.deferredPacketReadyTime();
2614            schedSendEvent(when);
2615
2616            if (delete_pkt)
2617                delete pkt;
2618
2619            return;
2620        }
2621
2622
2623        waitingOnRetry = !masterPort.sendTimingReq(pkt);
2624
2625        if (waitingOnRetry) {
2626            DPRINTF(CachePort, "now waiting on a retry\n");
2627            if (delete_pkt) {
2628                // we are awaiting a retry, but we
2629                // delete the packet and will be creating a new packet
2630                // when we get the opportunity
2631                delete pkt;
2632            }
2633            // note that we have now masked any requestBus and
2634            // schedSendEvent (we will wait for a retry before
2635            // doing anything), and this is so even if we do not
2636            // care about this packet and might override it before
2637            // it gets retried
2638        } else {
2639            // As part of the call to sendTimingReq the packet is
2640            // forwarded to all neighbouring caches (and any caches
2641            // above them) as a snoop. Thus at this point we know if
2642            // any of the neighbouring caches are responding, and if
2643            // so, we know it is dirty, and we can determine if it is
2644            // being passed as Modified, making our MSHR the ordering
2645            // point
2646            bool pending_modified_resp = !pkt->hasSharers() &&
2647                pkt->cacheResponding();
2648
2649            cache.markInService(mshr, pending_modified_resp);
2650        }
2651    }
2652
2653    // if we succeeded and are not waiting for a retry, schedule the
2654    // next send considering when the next MSHR is ready, note that
2655    // snoop responses have their own packet queue and thus schedule
2656    // their own events
2657    if (!waitingOnRetry) {
2658        schedSendEvent(cache.nextMSHRReadyTime());
2659    }
2660}
2661
2662Cache::
2663MemSidePort::MemSidePort(const std::string &_name, Cache *_cache,
2664                         const std::string &_label)
2665    : BaseCache::CacheMasterPort(_name, _cache, _reqQueue, _snoopRespQueue),
2666      _reqQueue(*_cache, *this, _snoopRespQueue, _label),
2667      _snoopRespQueue(*_cache, *this, _label), cache(_cache)
2668{
2669}
2670