112726Snikos.nikoleris@arm.com/*
212726Snikos.nikoleris@arm.com * Copyright (c) 2010-2018 ARM Limited
312726Snikos.nikoleris@arm.com * All rights reserved.
412726Snikos.nikoleris@arm.com *
512726Snikos.nikoleris@arm.com * The license below extends only to copyright in the software and shall
612726Snikos.nikoleris@arm.com * not be construed as granting a license to any other intellectual
712726Snikos.nikoleris@arm.com * property including but not limited to intellectual property relating
812726Snikos.nikoleris@arm.com * to a hardware implementation of the functionality of the software
912726Snikos.nikoleris@arm.com * licensed hereunder.  You may use the software subject to the license
1012726Snikos.nikoleris@arm.com * terms below provided that you ensure that this notice is replicated
1112726Snikos.nikoleris@arm.com * unmodified and in its entirety in all distributions of the software,
1212726Snikos.nikoleris@arm.com * modified or unmodified, in source code or in binary form.
1312726Snikos.nikoleris@arm.com *
1412726Snikos.nikoleris@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
1512726Snikos.nikoleris@arm.com * Copyright (c) 2010,2015 Advanced Micro Devices, Inc.
1612726Snikos.nikoleris@arm.com * All rights reserved.
1712726Snikos.nikoleris@arm.com *
1812726Snikos.nikoleris@arm.com * Redistribution and use in source and binary forms, with or without
1912726Snikos.nikoleris@arm.com * modification, are permitted provided that the following conditions are
2012726Snikos.nikoleris@arm.com * met: redistributions of source code must retain the above copyright
2112726Snikos.nikoleris@arm.com * notice, this list of conditions and the following disclaimer;
2212726Snikos.nikoleris@arm.com * redistributions in binary form must reproduce the above copyright
2312726Snikos.nikoleris@arm.com * notice, this list of conditions and the following disclaimer in the
2412726Snikos.nikoleris@arm.com * documentation and/or other materials provided with the distribution;
2512726Snikos.nikoleris@arm.com * neither the name of the copyright holders nor the names of its
2612726Snikos.nikoleris@arm.com * contributors may be used to endorse or promote products derived from
2712726Snikos.nikoleris@arm.com * this software without specific prior written permission.
2812726Snikos.nikoleris@arm.com *
2912726Snikos.nikoleris@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3012726Snikos.nikoleris@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3112726Snikos.nikoleris@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3212726Snikos.nikoleris@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3312726Snikos.nikoleris@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3412726Snikos.nikoleris@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3512726Snikos.nikoleris@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3612726Snikos.nikoleris@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3712726Snikos.nikoleris@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3812726Snikos.nikoleris@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3912726Snikos.nikoleris@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4012726Snikos.nikoleris@arm.com *
4112726Snikos.nikoleris@arm.com * Authors: Erik Hallnor
4212726Snikos.nikoleris@arm.com *          Dave Greene
4312726Snikos.nikoleris@arm.com *          Nathan Binkert
4412726Snikos.nikoleris@arm.com *          Steve Reinhardt
4512726Snikos.nikoleris@arm.com *          Ron Dreslinski
4612726Snikos.nikoleris@arm.com *          Andreas Sandberg
4712726Snikos.nikoleris@arm.com *          Nikos Nikoleris
4812726Snikos.nikoleris@arm.com */
4912726Snikos.nikoleris@arm.com
5012726Snikos.nikoleris@arm.com/**
5112726Snikos.nikoleris@arm.com * @file
5212726Snikos.nikoleris@arm.com * Cache definitions.
5312726Snikos.nikoleris@arm.com */
5412726Snikos.nikoleris@arm.com
5512726Snikos.nikoleris@arm.com#include "mem/cache/noncoherent_cache.hh"
5612726Snikos.nikoleris@arm.com
5712726Snikos.nikoleris@arm.com#include <cassert>
5812726Snikos.nikoleris@arm.com
5912726Snikos.nikoleris@arm.com#include "base/logging.hh"
6012726Snikos.nikoleris@arm.com#include "base/trace.hh"
6112726Snikos.nikoleris@arm.com#include "base/types.hh"
6212726Snikos.nikoleris@arm.com#include "debug/Cache.hh"
6313223Sodanrc@yahoo.com.br#include "mem/cache/cache_blk.hh"
6412726Snikos.nikoleris@arm.com#include "mem/cache/mshr.hh"
6512726Snikos.nikoleris@arm.com#include "params/NoncoherentCache.hh"
6612726Snikos.nikoleris@arm.com
6712726Snikos.nikoleris@arm.comNoncoherentCache::NoncoherentCache(const NoncoherentCacheParams *p)
6812726Snikos.nikoleris@arm.com    : BaseCache(p, p->system->cacheLineSize())
6912726Snikos.nikoleris@arm.com{
7012726Snikos.nikoleris@arm.com}
7112726Snikos.nikoleris@arm.com
7212726Snikos.nikoleris@arm.comvoid
7312726Snikos.nikoleris@arm.comNoncoherentCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool, bool)
7412726Snikos.nikoleris@arm.com{
7512726Snikos.nikoleris@arm.com    // As this a non-coherent cache located below the point of
7612726Snikos.nikoleris@arm.com    // coherency, we do not expect requests that are typically used to
7712726Snikos.nikoleris@arm.com    // keep caches coherent (e.g., InvalidateReq or UpdateReq).
7812726Snikos.nikoleris@arm.com    assert(pkt->isRead() || pkt->isWrite());
7912726Snikos.nikoleris@arm.com    BaseCache::satisfyRequest(pkt, blk);
8012726Snikos.nikoleris@arm.com}
8112726Snikos.nikoleris@arm.com
8212726Snikos.nikoleris@arm.combool
8314035Sodanrc@yahoo.com.brNoncoherentCache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat,
8414035Sodanrc@yahoo.com.br                         PacketList &writebacks)
8512726Snikos.nikoleris@arm.com{
8614035Sodanrc@yahoo.com.br    bool success = BaseCache::access(pkt, blk, lat, writebacks);
8712726Snikos.nikoleris@arm.com
8812726Snikos.nikoleris@arm.com    if (pkt->isWriteback() || pkt->cmd == MemCmd::WriteClean) {
8912726Snikos.nikoleris@arm.com        assert(blk && blk->isValid());
9012726Snikos.nikoleris@arm.com        // Writeback and WriteClean can allocate and fill even if the
9112726Snikos.nikoleris@arm.com        // referenced block was not present or it was invalid. If that
9212726Snikos.nikoleris@arm.com        // is the case, make sure that the new block is marked as
9312726Snikos.nikoleris@arm.com        // writable
9412726Snikos.nikoleris@arm.com        blk->status |= BlkWritable;
9512726Snikos.nikoleris@arm.com    }
9612726Snikos.nikoleris@arm.com
9712726Snikos.nikoleris@arm.com    return success;
9812726Snikos.nikoleris@arm.com}
9912726Snikos.nikoleris@arm.com
10012726Snikos.nikoleris@arm.comvoid
10114035Sodanrc@yahoo.com.brNoncoherentCache::doWritebacks(PacketList& writebacks, Tick forward_time)
10212726Snikos.nikoleris@arm.com{
10314035Sodanrc@yahoo.com.br    while (!writebacks.empty()) {
10414035Sodanrc@yahoo.com.br        PacketPtr wb_pkt = writebacks.front();
10514035Sodanrc@yahoo.com.br        allocateWriteBuffer(wb_pkt, forward_time);
10614035Sodanrc@yahoo.com.br        writebacks.pop_front();
10714035Sodanrc@yahoo.com.br    }
10812726Snikos.nikoleris@arm.com}
10912726Snikos.nikoleris@arm.com
11012726Snikos.nikoleris@arm.comvoid
11114035Sodanrc@yahoo.com.brNoncoherentCache::doWritebacksAtomic(PacketList& writebacks)
11212726Snikos.nikoleris@arm.com{
11314035Sodanrc@yahoo.com.br    while (!writebacks.empty()) {
11414035Sodanrc@yahoo.com.br        PacketPtr wb_pkt = writebacks.front();
11514035Sodanrc@yahoo.com.br        memSidePort.sendAtomic(wb_pkt);
11614035Sodanrc@yahoo.com.br        writebacks.pop_front();
11714035Sodanrc@yahoo.com.br        delete wb_pkt;
11814035Sodanrc@yahoo.com.br    }
11912726Snikos.nikoleris@arm.com}
12012726Snikos.nikoleris@arm.com
12112726Snikos.nikoleris@arm.comvoid
12212726Snikos.nikoleris@arm.comNoncoherentCache::handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk,
12312726Snikos.nikoleris@arm.com                                      Tick forward_time, Tick request_time)
12412726Snikos.nikoleris@arm.com{
12512726Snikos.nikoleris@arm.com    // miss
12612726Snikos.nikoleris@arm.com    Addr blk_addr = pkt->getBlockAddr(blkSize);
12712726Snikos.nikoleris@arm.com    MSHR *mshr = mshrQueue.findMatch(blk_addr, pkt->isSecure(), false);
12812726Snikos.nikoleris@arm.com
12912726Snikos.nikoleris@arm.com    // We can always write to a non coherent cache if the block is
13012726Snikos.nikoleris@arm.com    // present and therefore if we have reached this point then the
13112726Snikos.nikoleris@arm.com    // block should not be in the cache.
13212726Snikos.nikoleris@arm.com    assert(mshr || !blk || !blk->isValid());
13312726Snikos.nikoleris@arm.com
13412726Snikos.nikoleris@arm.com    BaseCache::handleTimingReqMiss(pkt, mshr, blk, forward_time, request_time);
13512726Snikos.nikoleris@arm.com}
13612726Snikos.nikoleris@arm.com
13712726Snikos.nikoleris@arm.comvoid
13812726Snikos.nikoleris@arm.comNoncoherentCache::recvTimingReq(PacketPtr pkt)
13912726Snikos.nikoleris@arm.com{
14012726Snikos.nikoleris@arm.com    panic_if(pkt->cacheResponding(), "Should not see packets where cache "
14112726Snikos.nikoleris@arm.com             "is responding");
14212726Snikos.nikoleris@arm.com
14312726Snikos.nikoleris@arm.com    panic_if(!(pkt->isRead() || pkt->isWrite()),
14412726Snikos.nikoleris@arm.com             "Should only see read and writes at non-coherent cache\n");
14512726Snikos.nikoleris@arm.com
14612726Snikos.nikoleris@arm.com    BaseCache::recvTimingReq(pkt);
14712726Snikos.nikoleris@arm.com}
14812726Snikos.nikoleris@arm.com
14912726Snikos.nikoleris@arm.comPacketPtr
15012726Snikos.nikoleris@arm.comNoncoherentCache::createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk,
15113350Snikos.nikoleris@arm.com                                   bool needs_writable,
15213350Snikos.nikoleris@arm.com                                   bool is_whole_line_write) const
15312726Snikos.nikoleris@arm.com{
15412726Snikos.nikoleris@arm.com    // We also fill for writebacks from the coherent caches above us,
15512726Snikos.nikoleris@arm.com    // and they do not need responses
15612726Snikos.nikoleris@arm.com    assert(cpu_pkt->needsResponse());
15712726Snikos.nikoleris@arm.com
15812726Snikos.nikoleris@arm.com    // A miss can happen only due to missing block
15912726Snikos.nikoleris@arm.com    assert(!blk || !blk->isValid());
16012726Snikos.nikoleris@arm.com
16112726Snikos.nikoleris@arm.com    PacketPtr pkt = new Packet(cpu_pkt->req, MemCmd::ReadReq, blkSize);
16212726Snikos.nikoleris@arm.com
16312726Snikos.nikoleris@arm.com    // the packet should be block aligned
16412726Snikos.nikoleris@arm.com    assert(pkt->getAddr() == pkt->getBlockAddr(blkSize));
16512726Snikos.nikoleris@arm.com
16612726Snikos.nikoleris@arm.com    pkt->allocate();
16712726Snikos.nikoleris@arm.com    DPRINTF(Cache, "%s created %s from %s\n", __func__, pkt->print(),
16812726Snikos.nikoleris@arm.com            cpu_pkt->print());
16912726Snikos.nikoleris@arm.com    return pkt;
17012726Snikos.nikoleris@arm.com}
17112726Snikos.nikoleris@arm.com
17212726Snikos.nikoleris@arm.com
17312726Snikos.nikoleris@arm.comCycles
17414035Sodanrc@yahoo.com.brNoncoherentCache::handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk,
17514035Sodanrc@yahoo.com.br                                      PacketList &writebacks)
17612726Snikos.nikoleris@arm.com{
17713350Snikos.nikoleris@arm.com    PacketPtr bus_pkt = createMissPacket(pkt, blk, true,
17813350Snikos.nikoleris@arm.com                                         pkt->isWholeLineWrite(blkSize));
17912726Snikos.nikoleris@arm.com    DPRINTF(Cache, "Sending an atomic %s\n", bus_pkt->print());
18012726Snikos.nikoleris@arm.com
18112726Snikos.nikoleris@arm.com    Cycles latency = ticksToCycles(memSidePort.sendAtomic(bus_pkt));
18212726Snikos.nikoleris@arm.com
18312726Snikos.nikoleris@arm.com    assert(bus_pkt->isResponse());
18412726Snikos.nikoleris@arm.com    // At the moment the only supported downstream requests we issue
18512726Snikos.nikoleris@arm.com    // are ReadReq and therefore here we should only see the
18612726Snikos.nikoleris@arm.com    // corresponding responses
18712726Snikos.nikoleris@arm.com    assert(bus_pkt->isRead());
18812726Snikos.nikoleris@arm.com    assert(pkt->cmd != MemCmd::UpgradeResp);
18912726Snikos.nikoleris@arm.com    assert(!bus_pkt->isInvalidate());
19012726Snikos.nikoleris@arm.com    assert(!bus_pkt->hasSharers());
19112726Snikos.nikoleris@arm.com
19212726Snikos.nikoleris@arm.com    // We are now dealing with the response handling
19312726Snikos.nikoleris@arm.com    DPRINTF(Cache, "Receive response: %s\n", bus_pkt->print());
19412726Snikos.nikoleris@arm.com
19512726Snikos.nikoleris@arm.com    if (!bus_pkt->isError()) {
19612726Snikos.nikoleris@arm.com        // Any reponse that does not have an error should be filling,
19712726Snikos.nikoleris@arm.com        // afterall it is a read response
19812726Snikos.nikoleris@arm.com        DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n",
19912726Snikos.nikoleris@arm.com                bus_pkt->getAddr());
20014035Sodanrc@yahoo.com.br        blk = handleFill(bus_pkt, blk, writebacks, allocOnFill(bus_pkt->cmd));
20112726Snikos.nikoleris@arm.com        assert(blk);
20212726Snikos.nikoleris@arm.com    }
20312726Snikos.nikoleris@arm.com    satisfyRequest(pkt, blk);
20412726Snikos.nikoleris@arm.com
20512726Snikos.nikoleris@arm.com    maintainClusivity(true, blk);
20612726Snikos.nikoleris@arm.com
20712726Snikos.nikoleris@arm.com    // Use the separate bus_pkt to generate response to pkt and
20812726Snikos.nikoleris@arm.com    // then delete it.
20912726Snikos.nikoleris@arm.com    if (!pkt->isWriteback() && pkt->cmd != MemCmd::WriteClean) {
21012726Snikos.nikoleris@arm.com        assert(pkt->needsResponse());
21112726Snikos.nikoleris@arm.com        pkt->makeAtomicResponse();
21212726Snikos.nikoleris@arm.com        if (bus_pkt->isError()) {
21312726Snikos.nikoleris@arm.com            pkt->copyError(bus_pkt);
21412726Snikos.nikoleris@arm.com        }
21512726Snikos.nikoleris@arm.com    }
21612726Snikos.nikoleris@arm.com
21712726Snikos.nikoleris@arm.com    delete bus_pkt;
21812726Snikos.nikoleris@arm.com
21912726Snikos.nikoleris@arm.com    return latency;
22012726Snikos.nikoleris@arm.com}
22112726Snikos.nikoleris@arm.com
22212726Snikos.nikoleris@arm.comTick
22312726Snikos.nikoleris@arm.comNoncoherentCache::recvAtomic(PacketPtr pkt)
22412726Snikos.nikoleris@arm.com{
22512726Snikos.nikoleris@arm.com    panic_if(pkt->cacheResponding(), "Should not see packets where cache "
22612726Snikos.nikoleris@arm.com             "is responding");
22712726Snikos.nikoleris@arm.com
22812726Snikos.nikoleris@arm.com    panic_if(!(pkt->isRead() || pkt->isWrite()),
22912726Snikos.nikoleris@arm.com             "Should only see read and writes at non-coherent cache\n");
23012726Snikos.nikoleris@arm.com
23112726Snikos.nikoleris@arm.com    return BaseCache::recvAtomic(pkt);
23212726Snikos.nikoleris@arm.com}
23312726Snikos.nikoleris@arm.com
23412726Snikos.nikoleris@arm.com
23512726Snikos.nikoleris@arm.comvoid
23612726Snikos.nikoleris@arm.comNoncoherentCache::functionalAccess(PacketPtr pkt, bool from_cpu_side)
23712726Snikos.nikoleris@arm.com{
23812726Snikos.nikoleris@arm.com    panic_if(!from_cpu_side, "Non-coherent cache received functional snoop"
23912726Snikos.nikoleris@arm.com             " request\n");
24012726Snikos.nikoleris@arm.com
24112726Snikos.nikoleris@arm.com    BaseCache::functionalAccess(pkt, from_cpu_side);
24212726Snikos.nikoleris@arm.com}
24312726Snikos.nikoleris@arm.com
24412726Snikos.nikoleris@arm.comvoid
24512726Snikos.nikoleris@arm.comNoncoherentCache::serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt,
24613478Sodanrc@yahoo.com.br                                     CacheBlk *blk)
24712726Snikos.nikoleris@arm.com{
24812726Snikos.nikoleris@arm.com    // First offset for critical word first calculations
24913859Sodanrc@yahoo.com.br    const int initial_offset = mshr->getTarget()->pkt->getOffset(blkSize);
25012726Snikos.nikoleris@arm.com
25112726Snikos.nikoleris@arm.com    MSHR::TargetList targets = mshr->extractServiceableTargets(pkt);
25212726Snikos.nikoleris@arm.com    for (auto &target: targets) {
25312726Snikos.nikoleris@arm.com        Packet *tgt_pkt = target.pkt;
25412726Snikos.nikoleris@arm.com
25512726Snikos.nikoleris@arm.com        switch (target.source) {
25612726Snikos.nikoleris@arm.com          case MSHR::Target::FromCPU:
25712726Snikos.nikoleris@arm.com            // handle deferred requests comming from a cache or core
25812726Snikos.nikoleris@arm.com            // above
25912726Snikos.nikoleris@arm.com
26012726Snikos.nikoleris@arm.com            Tick completion_time;
26112726Snikos.nikoleris@arm.com            // Here we charge on completion_time the delay of the xbar if the
26212726Snikos.nikoleris@arm.com            // packet comes from it, charged on headerDelay.
26312726Snikos.nikoleris@arm.com            completion_time = pkt->headerDelay;
26412726Snikos.nikoleris@arm.com
26512726Snikos.nikoleris@arm.com            satisfyRequest(tgt_pkt, blk);
26612726Snikos.nikoleris@arm.com
26712726Snikos.nikoleris@arm.com            // How many bytes past the first request is this one
26812726Snikos.nikoleris@arm.com            int transfer_offset;
26912726Snikos.nikoleris@arm.com            transfer_offset = tgt_pkt->getOffset(blkSize) - initial_offset;
27012726Snikos.nikoleris@arm.com            if (transfer_offset < 0) {
27112726Snikos.nikoleris@arm.com                transfer_offset += blkSize;
27212726Snikos.nikoleris@arm.com            }
27312726Snikos.nikoleris@arm.com            // If not critical word (offset) return payloadDelay.
27412726Snikos.nikoleris@arm.com            // responseLatency is the latency of the return path
27512726Snikos.nikoleris@arm.com            // from lower level caches/memory to an upper level cache or
27612726Snikos.nikoleris@arm.com            // the core.
27712726Snikos.nikoleris@arm.com            completion_time += clockEdge(responseLatency) +
27812726Snikos.nikoleris@arm.com                (transfer_offset ? pkt->payloadDelay : 0);
27912726Snikos.nikoleris@arm.com
28012726Snikos.nikoleris@arm.com            assert(tgt_pkt->req->masterId() < system->maxMasters());
28112726Snikos.nikoleris@arm.com            missLatency[tgt_pkt->cmdToIndex()][tgt_pkt->req->masterId()] +=
28212726Snikos.nikoleris@arm.com                completion_time - target.recvTime;
28312726Snikos.nikoleris@arm.com
28412726Snikos.nikoleris@arm.com            tgt_pkt->makeTimingResponse();
28512726Snikos.nikoleris@arm.com            if (pkt->isError())
28612726Snikos.nikoleris@arm.com                tgt_pkt->copyError(pkt);
28712726Snikos.nikoleris@arm.com
28812726Snikos.nikoleris@arm.com            // Reset the bus additional time as it is now accounted for
28912726Snikos.nikoleris@arm.com            tgt_pkt->headerDelay = tgt_pkt->payloadDelay = 0;
29013564Snikos.nikoleris@arm.com            cpuSidePort.schedTimingResp(tgt_pkt, completion_time);
29112726Snikos.nikoleris@arm.com            break;
29212726Snikos.nikoleris@arm.com
29312726Snikos.nikoleris@arm.com          case MSHR::Target::FromPrefetcher:
29412726Snikos.nikoleris@arm.com            // handle deferred requests comming from a prefetcher
29512726Snikos.nikoleris@arm.com            // attached to this cache
29612726Snikos.nikoleris@arm.com            assert(tgt_pkt->cmd == MemCmd::HardPFReq);
29712726Snikos.nikoleris@arm.com
29812726Snikos.nikoleris@arm.com            if (blk)
29912726Snikos.nikoleris@arm.com                blk->status |= BlkHWPrefetched;
30012726Snikos.nikoleris@arm.com
30112726Snikos.nikoleris@arm.com            // We have filled the block and the prefetcher does not
30212726Snikos.nikoleris@arm.com            // require responses.
30312726Snikos.nikoleris@arm.com            delete tgt_pkt;
30412726Snikos.nikoleris@arm.com            break;
30512726Snikos.nikoleris@arm.com
30612726Snikos.nikoleris@arm.com          default:
30712726Snikos.nikoleris@arm.com            // we should never see FromSnoop Targets as this is a
30812726Snikos.nikoleris@arm.com            // non-coherent cache
30912726Snikos.nikoleris@arm.com            panic("Illegal target->source enum %d\n", target.source);
31012726Snikos.nikoleris@arm.com        }
31112726Snikos.nikoleris@arm.com    }
31212726Snikos.nikoleris@arm.com
31312726Snikos.nikoleris@arm.com    // Reponses are filling and bring in writable blocks, therefore
31412726Snikos.nikoleris@arm.com    // there should be no deferred targets and all the non-deferred
31512726Snikos.nikoleris@arm.com    // targets are now serviced.
31612726Snikos.nikoleris@arm.com    assert(mshr->getNumTargets() == 0);
31712726Snikos.nikoleris@arm.com}
31812726Snikos.nikoleris@arm.com
31912726Snikos.nikoleris@arm.comvoid
32012726Snikos.nikoleris@arm.comNoncoherentCache::recvTimingResp(PacketPtr pkt)
32112726Snikos.nikoleris@arm.com{
32212726Snikos.nikoleris@arm.com    assert(pkt->isResponse());
32312726Snikos.nikoleris@arm.com    // At the moment the only supported downstream requests we issue
32412726Snikos.nikoleris@arm.com    // are ReadReq and therefore here we should only see the
32512726Snikos.nikoleris@arm.com    // corresponding responses
32612726Snikos.nikoleris@arm.com    assert(pkt->isRead());
32712726Snikos.nikoleris@arm.com    assert(pkt->cmd != MemCmd::UpgradeResp);
32812726Snikos.nikoleris@arm.com    assert(!pkt->isInvalidate());
32912726Snikos.nikoleris@arm.com    // This cache is non-coherent and any memories below are
33012726Snikos.nikoleris@arm.com    // non-coherent too (non-coherent caches or the main memory),
33112726Snikos.nikoleris@arm.com    // therefore the fetched block can be marked as writable.
33212726Snikos.nikoleris@arm.com    assert(!pkt->hasSharers());
33312726Snikos.nikoleris@arm.com
33412726Snikos.nikoleris@arm.com    BaseCache::recvTimingResp(pkt);
33512726Snikos.nikoleris@arm.com}
33612726Snikos.nikoleris@arm.com
33712726Snikos.nikoleris@arm.comPacketPtr
33812726Snikos.nikoleris@arm.comNoncoherentCache::evictBlock(CacheBlk *blk)
33912726Snikos.nikoleris@arm.com{
34012726Snikos.nikoleris@arm.com    // A dirty block is always written back.
34112726Snikos.nikoleris@arm.com
34212726Snikos.nikoleris@arm.com    // A clean block can we written back, if we turned on writebacks
34312726Snikos.nikoleris@arm.com    // for clean blocks. This could be useful if there is a cache
34412726Snikos.nikoleris@arm.com    // below and we want to make sure the block is cached but if the
34512726Snikos.nikoleris@arm.com    // memory below is the main memory WritebackCleans are
34612726Snikos.nikoleris@arm.com    // unnecessary.
34712726Snikos.nikoleris@arm.com
34812726Snikos.nikoleris@arm.com    // If we clean writebacks are not enabled, we do not take any
34912726Snikos.nikoleris@arm.com    // further action for evictions of clean blocks (i.e., CleanEvicts
35012726Snikos.nikoleris@arm.com    // are unnecessary).
35112726Snikos.nikoleris@arm.com    PacketPtr pkt = (blk->isDirty() || writebackClean) ?
35212726Snikos.nikoleris@arm.com        writebackBlk(blk) : nullptr;
35312726Snikos.nikoleris@arm.com
35412726Snikos.nikoleris@arm.com    invalidateBlock(blk);
35512726Snikos.nikoleris@arm.com
35612726Snikos.nikoleris@arm.com    return pkt;
35712726Snikos.nikoleris@arm.com}
35812726Snikos.nikoleris@arm.com
35912726Snikos.nikoleris@arm.comNoncoherentCache*
36012726Snikos.nikoleris@arm.comNoncoherentCacheParams::create()
36112726Snikos.nikoleris@arm.com{
36212726Snikos.nikoleris@arm.com    assert(tags);
36312726Snikos.nikoleris@arm.com    assert(replacement_policy);
36412726Snikos.nikoleris@arm.com
36512726Snikos.nikoleris@arm.com    return new NoncoherentCache(this);
36612726Snikos.nikoleris@arm.com}
367