noncoherent_cache.cc revision 13859
110037SARM gem5 Developers/*
210037SARM gem5 Developers * Copyright (c) 2010-2018 ARM Limited
310666SAli.Saidi@ARM.com * All rights reserved.
410037SARM gem5 Developers *
510037SARM gem5 Developers * The license below extends only to copyright in the software and shall
610037SARM gem5 Developers * not be construed as granting a license to any other intellectual
710037SARM gem5 Developers * property including but not limited to intellectual property relating
810037SARM gem5 Developers * to a hardware implementation of the functionality of the software
910037SARM gem5 Developers * licensed hereunder.  You may use the software subject to the license
1010037SARM gem5 Developers * terms below provided that you ensure that this notice is replicated
1110037SARM gem5 Developers * unmodified and in its entirety in all distributions of the software,
1210037SARM gem5 Developers * modified or unmodified, in source code or in binary form.
1310037SARM gem5 Developers *
1410037SARM gem5 Developers * Copyright (c) 2002-2005 The Regents of The University of Michigan
1510037SARM gem5 Developers * Copyright (c) 2010,2015 Advanced Micro Devices, Inc.
1610037SARM gem5 Developers * All rights reserved.
1710037SARM gem5 Developers *
1810037SARM gem5 Developers * Redistribution and use in source and binary forms, with or without
1910037SARM gem5 Developers * modification, are permitted provided that the following conditions are
2010037SARM gem5 Developers * met: redistributions of source code must retain the above copyright
2110037SARM gem5 Developers * notice, this list of conditions and the following disclaimer;
2210037SARM gem5 Developers * redistributions in binary form must reproduce the above copyright
2310037SARM gem5 Developers * notice, this list of conditions and the following disclaimer in the
2410037SARM gem5 Developers * documentation and/or other materials provided with the distribution;
2510037SARM gem5 Developers * neither the name of the copyright holders nor the names of its
2610037SARM gem5 Developers * contributors may be used to endorse or promote products derived from
2710037SARM gem5 Developers * this software without specific prior written permission.
2810037SARM gem5 Developers *
2910037SARM gem5 Developers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3010037SARM gem5 Developers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3110037SARM gem5 Developers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3210037SARM gem5 Developers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3310037SARM gem5 Developers * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3410037SARM gem5 Developers * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3510037SARM gem5 Developers * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3610037SARM gem5 Developers * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3710037SARM gem5 Developers * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3810037SARM gem5 Developers * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3910037SARM gem5 Developers * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4010037SARM gem5 Developers *
4110037SARM gem5 Developers * Authors: Erik Hallnor
4210037SARM gem5 Developers *          Dave Greene
4310037SARM gem5 Developers *          Nathan Binkert
4410474Sandreas.hansson@arm.com *          Steve Reinhardt
4510037SARM gem5 Developers *          Ron Dreslinski
4610037SARM gem5 Developers *          Andreas Sandberg
4710037SARM gem5 Developers *          Nikos Nikoleris
4810037SARM gem5 Developers */
4910037SARM gem5 Developers
5012234Sgabeblack@google.com/**
5110037SARM gem5 Developers * @file
5210037SARM gem5 Developers * Cache definitions.
5310037SARM gem5 Developers */
5410037SARM gem5 Developers
5510037SARM gem5 Developers#include "mem/cache/noncoherent_cache.hh"
5610037SARM gem5 Developers
5710037SARM gem5 Developers#include <cassert>
5810037SARM gem5 Developers
5910037SARM gem5 Developers#include "base/logging.hh"
6010037SARM gem5 Developers#include "base/trace.hh"
6110037SARM gem5 Developers#include "base/types.hh"
6210037SARM gem5 Developers#include "debug/Cache.hh"
6310037SARM gem5 Developers#include "mem/cache/cache_blk.hh"
6410037SARM gem5 Developers#include "mem/cache/mshr.hh"
6510037SARM gem5 Developers#include "params/NoncoherentCache.hh"
6610037SARM gem5 Developers
6710037SARM gem5 DevelopersNoncoherentCache::NoncoherentCache(const NoncoherentCacheParams *p)
6810037SARM gem5 Developers    : BaseCache(p, p->system->cacheLineSize())
6910037SARM gem5 Developers{
7010037SARM gem5 Developers}
7110037SARM gem5 Developers
7210037SARM gem5 Developersvoid
7310037SARM gem5 DevelopersNoncoherentCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool, bool)
7412234Sgabeblack@google.com{
7510037SARM gem5 Developers    // As this a non-coherent cache located below the point of
7610037SARM gem5 Developers    // coherency, we do not expect requests that are typically used to
7710037SARM gem5 Developers    // keep caches coherent (e.g., InvalidateReq or UpdateReq).
7810037SARM gem5 Developers    assert(pkt->isRead() || pkt->isWrite());
7910037SARM gem5 Developers    BaseCache::satisfyRequest(pkt, blk);
8010037SARM gem5 Developers}
8110037SARM gem5 Developers
8210037SARM gem5 Developersbool
8310037SARM gem5 DevelopersNoncoherentCache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat,
8410037SARM gem5 Developers                         PacketList &writebacks)
8510037SARM gem5 Developers{
8610037SARM gem5 Developers    bool success = BaseCache::access(pkt, blk, lat, writebacks);
8710037SARM gem5 Developers
8810037SARM gem5 Developers    if (pkt->isWriteback() || pkt->cmd == MemCmd::WriteClean) {
8910037SARM gem5 Developers        assert(blk && blk->isValid());
9010037SARM gem5 Developers        // Writeback and WriteClean can allocate and fill even if the
9110037SARM gem5 Developers        // referenced block was not present or it was invalid. If that
9210037SARM gem5 Developers        // is the case, make sure that the new block is marked as
9310037SARM gem5 Developers        // writable
9410037SARM gem5 Developers        blk->status |= BlkWritable;
9510037SARM gem5 Developers    }
9610037SARM gem5 Developers
9710037SARM gem5 Developers    return success;
9810037SARM gem5 Developers}
9910037SARM gem5 Developers
10010037SARM gem5 Developersvoid
10110037SARM gem5 DevelopersNoncoherentCache::doWritebacks(PacketList& writebacks, Tick forward_time)
10212234Sgabeblack@google.com{
10310037SARM gem5 Developers    while (!writebacks.empty()) {
10410037SARM gem5 Developers        PacketPtr wb_pkt = writebacks.front();
10510037SARM gem5 Developers        allocateWriteBuffer(wb_pkt, forward_time);
10610037SARM gem5 Developers        writebacks.pop_front();
10710037SARM gem5 Developers    }
10810037SARM gem5 Developers}
10910037SARM gem5 Developers
11010037SARM gem5 Developersvoid
11110037SARM gem5 DevelopersNoncoherentCache::doWritebacksAtomic(PacketList& writebacks)
11210037SARM gem5 Developers{
11310037SARM gem5 Developers    while (!writebacks.empty()) {
11410037SARM gem5 Developers        PacketPtr wb_pkt = writebacks.front();
11510037SARM gem5 Developers        memSidePort.sendAtomic(wb_pkt);
11610037SARM gem5 Developers        writebacks.pop_front();
11710037SARM gem5 Developers        delete wb_pkt;
11810037SARM gem5 Developers    }
11910037SARM gem5 Developers}
12010037SARM gem5 Developers
12110037SARM gem5 Developersvoid
12210037SARM gem5 DevelopersNoncoherentCache::handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk,
12310037SARM gem5 Developers                                      Tick forward_time, Tick request_time)
12410037SARM gem5 Developers{
12510037SARM gem5 Developers    // miss
12612234Sgabeblack@google.com    Addr blk_addr = pkt->getBlockAddr(blkSize);
12710037SARM gem5 Developers    MSHR *mshr = mshrQueue.findMatch(blk_addr, pkt->isSecure(), false);
12810037SARM gem5 Developers
12910037SARM gem5 Developers    // We can always write to a non coherent cache if the block is
13010037SARM gem5 Developers    // present and therefore if we have reached this point then the
13110037SARM gem5 Developers    // block should not be in the cache.
13210037SARM gem5 Developers    assert(mshr || !blk || !blk->isValid());
13310037SARM gem5 Developers
13410037SARM gem5 Developers    BaseCache::handleTimingReqMiss(pkt, mshr, blk, forward_time, request_time);
13510037SARM gem5 Developers}
13610037SARM gem5 Developers
13710037SARM gem5 Developersvoid
13810037SARM gem5 DevelopersNoncoherentCache::recvTimingReq(PacketPtr pkt)
13910037SARM gem5 Developers{
14010037SARM gem5 Developers    panic_if(pkt->cacheResponding(), "Should not see packets where cache "
14110037SARM gem5 Developers             "is responding");
14210037SARM gem5 Developers
14310037SARM gem5 Developers    panic_if(!(pkt->isRead() || pkt->isWrite()),
14410037SARM gem5 Developers             "Should only see read and writes at non-coherent cache\n");
14510037SARM gem5 Developers
14610037SARM gem5 Developers    BaseCache::recvTimingReq(pkt);
14710037SARM gem5 Developers}
14810037SARM gem5 Developers
14910037SARM gem5 DevelopersPacketPtr
15010037SARM gem5 DevelopersNoncoherentCache::createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk,
15110037SARM gem5 Developers                                   bool needs_writable,
15210037SARM gem5 Developers                                   bool is_whole_line_write) const
15310037SARM gem5 Developers{
15410037SARM gem5 Developers    // We also fill for writebacks from the coherent caches above us,
15510037SARM gem5 Developers    // and they do not need responses
15610037SARM gem5 Developers    assert(cpu_pkt->needsResponse());
15710037SARM gem5 Developers
15810037SARM gem5 Developers    // A miss can happen only due to missing block
15912234Sgabeblack@google.com    assert(!blk || !blk->isValid());
16010037SARM gem5 Developers
16110037SARM gem5 Developers    PacketPtr pkt = new Packet(cpu_pkt->req, MemCmd::ReadReq, blkSize);
16210037SARM gem5 Developers
16310037SARM gem5 Developers    // the packet should be block aligned
16410037SARM gem5 Developers    assert(pkt->getAddr() == pkt->getBlockAddr(blkSize));
16510037SARM gem5 Developers
16610037SARM gem5 Developers    pkt->allocate();
16710037SARM gem5 Developers    DPRINTF(Cache, "%s created %s from %s\n", __func__, pkt->print(),
16810037SARM gem5 Developers            cpu_pkt->print());
16910037SARM gem5 Developers    return pkt;
17010037SARM gem5 Developers}
17110037SARM gem5 Developers
17210037SARM gem5 Developers
17310037SARM gem5 DevelopersCycles
17410037SARM gem5 DevelopersNoncoherentCache::handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk,
17510037SARM gem5 Developers                                      PacketList &writebacks)
17610037SARM gem5 Developers{
17710037SARM gem5 Developers    PacketPtr bus_pkt = createMissPacket(pkt, blk, true,
17810037SARM gem5 Developers                                         pkt->isWholeLineWrite(blkSize));
17910037SARM gem5 Developers    DPRINTF(Cache, "Sending an atomic %s\n", bus_pkt->print());
18010037SARM gem5 Developers
18110037SARM gem5 Developers    Cycles latency = ticksToCycles(memSidePort.sendAtomic(bus_pkt));
18210037SARM gem5 Developers
18312234Sgabeblack@google.com    assert(bus_pkt->isResponse());
18410037SARM gem5 Developers    // At the moment the only supported downstream requests we issue
18510037SARM gem5 Developers    // are ReadReq and therefore here we should only see the
18610037SARM gem5 Developers    // corresponding responses
18710037SARM gem5 Developers    assert(bus_pkt->isRead());
18810037SARM gem5 Developers    assert(pkt->cmd != MemCmd::UpgradeResp);
18910037SARM gem5 Developers    assert(!bus_pkt->isInvalidate());
19010037SARM gem5 Developers    assert(!bus_pkt->hasSharers());
19110037SARM gem5 Developers
19210037SARM gem5 Developers    // We are now dealing with the response handling
19310037SARM gem5 Developers    DPRINTF(Cache, "Receive response: %s\n", bus_pkt->print());
19411303Ssteve.reinhardt@amd.com
19510037SARM gem5 Developers    if (!bus_pkt->isError()) {
19610037SARM gem5 Developers        // Any reponse that does not have an error should be filling,
19710037SARM gem5 Developers        // afterall it is a read response
19810037SARM gem5 Developers        DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n",
19910037SARM gem5 Developers                bus_pkt->getAddr());
20010037SARM gem5 Developers        blk = handleFill(bus_pkt, blk, writebacks, allocOnFill(bus_pkt->cmd));
20110037SARM gem5 Developers        assert(blk);
20212234Sgabeblack@google.com    }
20310037SARM gem5 Developers    satisfyRequest(pkt, blk);
20410037SARM gem5 Developers
20510037SARM gem5 Developers    maintainClusivity(true, blk);
20610037SARM gem5 Developers
20710037SARM gem5 Developers    // Use the separate bus_pkt to generate response to pkt and
20810037SARM gem5 Developers    // then delete it.
20910037SARM gem5 Developers    if (!pkt->isWriteback() && pkt->cmd != MemCmd::WriteClean) {
21010037SARM gem5 Developers        assert(pkt->needsResponse());
21110037SARM gem5 Developers        pkt->makeAtomicResponse();
21210037SARM gem5 Developers        if (bus_pkt->isError()) {
21310037SARM gem5 Developers            pkt->copyError(bus_pkt);
21410037SARM gem5 Developers        }
21510037SARM gem5 Developers    }
21610037SARM gem5 Developers
21710037SARM gem5 Developers    delete bus_pkt;
21810037SARM gem5 Developers
21910037SARM gem5 Developers    return latency;
22010037SARM gem5 Developers}
22110037SARM gem5 Developers
22210037SARM gem5 DevelopersTick
22310037SARM gem5 DevelopersNoncoherentCache::recvAtomic(PacketPtr pkt)
22410037SARM gem5 Developers{
22510037SARM gem5 Developers    panic_if(pkt->cacheResponding(), "Should not see packets where cache "
22612234Sgabeblack@google.com             "is responding");
22710037SARM gem5 Developers
22810037SARM gem5 Developers    panic_if(!(pkt->isRead() || pkt->isWrite()),
22910037SARM gem5 Developers             "Should only see read and writes at non-coherent cache\n");
23010037SARM gem5 Developers
23110037SARM gem5 Developers    return BaseCache::recvAtomic(pkt);
23210037SARM gem5 Developers}
23310037SARM gem5 Developers
23412234Sgabeblack@google.com
23510037SARM gem5 Developersvoid
23610037SARM gem5 DevelopersNoncoherentCache::functionalAccess(PacketPtr pkt, bool from_cpu_side)
23710037SARM gem5 Developers{
23810037SARM gem5 Developers    panic_if(!from_cpu_side, "Non-coherent cache received functional snoop"
23910037SARM gem5 Developers             " request\n");
24010037SARM gem5 Developers
24110037SARM gem5 Developers    BaseCache::functionalAccess(pkt, from_cpu_side);
24210037SARM gem5 Developers}
24310037SARM gem5 Developers
24410037SARM gem5 Developersvoid
24510037SARM gem5 DevelopersNoncoherentCache::serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt,
24610037SARM gem5 Developers                                     CacheBlk *blk)
24710037SARM gem5 Developers{
24810037SARM gem5 Developers    // First offset for critical word first calculations
24910037SARM gem5 Developers    const int initial_offset = mshr->getTarget()->pkt->getOffset(blkSize);
25010037SARM gem5 Developers
25110037SARM gem5 Developers    MSHR::TargetList targets = mshr->extractServiceableTargets(pkt);
25210037SARM gem5 Developers    for (auto &target: targets) {
25310037SARM gem5 Developers        Packet *tgt_pkt = target.pkt;
25410037SARM gem5 Developers
25510037SARM gem5 Developers        switch (target.source) {
25610037SARM gem5 Developers          case MSHR::Target::FromCPU:
25710037SARM gem5 Developers            // handle deferred requests comming from a cache or core
25810037SARM gem5 Developers            // above
25910037SARM gem5 Developers
26010037SARM gem5 Developers            Tick completion_time;
26112236Sgabeblack@google.com            // Here we charge on completion_time the delay of the xbar if the
26212236Sgabeblack@google.com            // packet comes from it, charged on headerDelay.
26312236Sgabeblack@google.com            completion_time = pkt->headerDelay;
26410037SARM gem5 Developers
26510037SARM gem5 Developers            satisfyRequest(tgt_pkt, blk);
26610037SARM gem5 Developers
26710037SARM gem5 Developers            // How many bytes past the first request is this one
26810037SARM gem5 Developers            int transfer_offset;
26910037SARM gem5 Developers            transfer_offset = tgt_pkt->getOffset(blkSize) - initial_offset;
27010037SARM gem5 Developers            if (transfer_offset < 0) {
27110037SARM gem5 Developers                transfer_offset += blkSize;
27210037SARM gem5 Developers            }
27310037SARM gem5 Developers            // If not critical word (offset) return payloadDelay.
27410037SARM gem5 Developers            // responseLatency is the latency of the return path
27510037SARM gem5 Developers            // from lower level caches/memory to an upper level cache or
27610037SARM gem5 Developers            // the core.
27710037SARM gem5 Developers            completion_time += clockEdge(responseLatency) +
27810037SARM gem5 Developers                (transfer_offset ? pkt->payloadDelay : 0);
27910037SARM gem5 Developers
28010037SARM gem5 Developers            assert(tgt_pkt->req->masterId() < system->maxMasters());
28110037SARM gem5 Developers            missLatency[tgt_pkt->cmdToIndex()][tgt_pkt->req->masterId()] +=
28210037SARM gem5 Developers                completion_time - target.recvTime;
28312234Sgabeblack@google.com
28410037SARM gem5 Developers            tgt_pkt->makeTimingResponse();
28510037SARM gem5 Developers            if (pkt->isError())
28610037SARM gem5 Developers                tgt_pkt->copyError(pkt);
28710037SARM gem5 Developers
28810037SARM gem5 Developers            // Reset the bus additional time as it is now accounted for
28910037SARM gem5 Developers            tgt_pkt->headerDelay = tgt_pkt->payloadDelay = 0;
29010037SARM gem5 Developers            cpuSidePort.schedTimingResp(tgt_pkt, completion_time);
29110037SARM gem5 Developers            break;
29210037SARM gem5 Developers
29310037SARM gem5 Developers          case MSHR::Target::FromPrefetcher:
29410037SARM gem5 Developers            // handle deferred requests comming from a prefetcher
29510037SARM gem5 Developers            // attached to this cache
29610037SARM gem5 Developers            assert(tgt_pkt->cmd == MemCmd::HardPFReq);
29710037SARM gem5 Developers
29810037SARM gem5 Developers            if (blk)
29910037SARM gem5 Developers                blk->status |= BlkHWPrefetched;
30010037SARM gem5 Developers
30110037SARM gem5 Developers            // We have filled the block and the prefetcher does not
30210037SARM gem5 Developers            // require responses.
30310037SARM gem5 Developers            delete tgt_pkt;
30410037SARM gem5 Developers            break;
30510037SARM gem5 Developers
30610037SARM gem5 Developers          default:
30710037SARM gem5 Developers            // we should never see FromSnoop Targets as this is a
30810037SARM gem5 Developers            // non-coherent cache
30910037SARM gem5 Developers            panic("Illegal target->source enum %d\n", target.source);
31010037SARM gem5 Developers        }
31112234Sgabeblack@google.com    }
31210037SARM gem5 Developers
31310037SARM gem5 Developers    // Reponses are filling and bring in writable blocks, therefore
31410037SARM gem5 Developers    // there should be no deferred targets and all the non-deferred
31510037SARM gem5 Developers    // targets are now serviced.
31610037SARM gem5 Developers    assert(mshr->getNumTargets() == 0);
31710037SARM gem5 Developers}
31810037SARM gem5 Developers
31910037SARM gem5 Developersvoid
32010037SARM gem5 DevelopersNoncoherentCache::recvTimingResp(PacketPtr pkt)
32110037SARM gem5 Developers{
32210037SARM gem5 Developers    assert(pkt->isResponse());
32310037SARM gem5 Developers    // At the moment the only supported downstream requests we issue
32410037SARM gem5 Developers    // are ReadReq and therefore here we should only see the
32510037SARM gem5 Developers    // corresponding responses
32610037SARM gem5 Developers    assert(pkt->isRead());
32710037SARM gem5 Developers    assert(pkt->cmd != MemCmd::UpgradeResp);
32810037SARM gem5 Developers    assert(!pkt->isInvalidate());
32910037SARM gem5 Developers    // This cache is non-coherent and any memories below are
33010037SARM gem5 Developers    // non-coherent too (non-coherent caches or the main memory),
33110037SARM gem5 Developers    // therefore the fetched block can be marked as writable.
33210037SARM gem5 Developers    assert(!pkt->hasSharers());
33310037SARM gem5 Developers
33410037SARM gem5 Developers    BaseCache::recvTimingResp(pkt);
33510037SARM gem5 Developers}
33610037SARM gem5 Developers
33710037SARM gem5 DevelopersPacketPtr
33810037SARM gem5 DevelopersNoncoherentCache::evictBlock(CacheBlk *blk)
33910037SARM gem5 Developers{
34010037SARM gem5 Developers    // A dirty block is always written back.
34110037SARM gem5 Developers
34210037SARM gem5 Developers    // A clean block can we written back, if we turned on writebacks
34312236Sgabeblack@google.com    // for clean blocks. This could be useful if there is a cache
34412236Sgabeblack@google.com    // below and we want to make sure the block is cached but if the
34512236Sgabeblack@google.com    // memory below is the main memory WritebackCleans are
34610037SARM gem5 Developers    // unnecessary.
34710037SARM gem5 Developers
34810037SARM gem5 Developers    // If we clean writebacks are not enabled, we do not take any
34910037SARM gem5 Developers    // further action for evictions of clean blocks (i.e., CleanEvicts
35010037SARM gem5 Developers    // are unnecessary).
35110037SARM gem5 Developers    PacketPtr pkt = (blk->isDirty() || writebackClean) ?
35210037SARM gem5 Developers        writebackBlk(blk) : nullptr;
35310037SARM gem5 Developers
35410037SARM gem5 Developers    invalidateBlock(blk);
35510037SARM gem5 Developers
35610037SARM gem5 Developers    return pkt;
35710037SARM gem5 Developers}
35810037SARM gem5 Developers
35910037SARM gem5 DevelopersNoncoherentCache*
36010037SARM gem5 DevelopersNoncoherentCacheParams::create()
36110037SARM gem5 Developers{
36210037SARM gem5 Developers    assert(tags);
36310037SARM gem5 Developers    assert(replacement_policy);
36410037SARM gem5 Developers
36512236Sgabeblack@google.com    return new NoncoherentCache(this);
36612236Sgabeblack@google.com}
36712236Sgabeblack@google.com