12810SN/A/*
212724Snikos.nikoleris@arm.com * Copyright (c) 2012-2013, 2015-2016, 2018 ARM Limited
38856Sandreas.hansson@arm.com * All rights reserved.
48856Sandreas.hansson@arm.com *
58856Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
68856Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
78856Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
88856Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
98856Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
108856Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
118856Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
128856Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
138856Sandreas.hansson@arm.com *
142810SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
152810SN/A * All rights reserved.
162810SN/A *
172810SN/A * Redistribution and use in source and binary forms, with or without
182810SN/A * modification, are permitted provided that the following conditions are
192810SN/A * met: redistributions of source code must retain the above copyright
202810SN/A * notice, this list of conditions and the following disclaimer;
212810SN/A * redistributions in binary form must reproduce the above copyright
222810SN/A * notice, this list of conditions and the following disclaimer in the
232810SN/A * documentation and/or other materials provided with the distribution;
242810SN/A * neither the name of the copyright holders nor the names of its
252810SN/A * contributors may be used to endorse or promote products derived from
262810SN/A * this software without specific prior written permission.
272810SN/A *
282810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392810SN/A *
402810SN/A * Authors: Erik Hallnor
414458SN/A *          Steve Reinhardt
424458SN/A *          Ron Dreslinski
4312724Snikos.nikoleris@arm.com *          Andreas Hansson
4412724Snikos.nikoleris@arm.com *          Nikos Nikoleris
452810SN/A */
462810SN/A
472810SN/A/**
482810SN/A * @file
492810SN/A * Declares a basic cache interface BaseCache.
502810SN/A */
512810SN/A
5211051Sandreas.hansson@arm.com#ifndef __MEM_CACHE_BASE_HH__
5311051Sandreas.hansson@arm.com#define __MEM_CACHE_BASE_HH__
542810SN/A
5512724Snikos.nikoleris@arm.com#include <cassert>
5612724Snikos.nikoleris@arm.com#include <cstdint>
577676Snate@binkert.org#include <string>
582810SN/A
5912724Snikos.nikoleris@arm.com#include "base/addr_range.hh"
602810SN/A#include "base/statistics.hh"
612810SN/A#include "base/trace.hh"
626215Snate@binkert.org#include "base/types.hh"
638232Snate@binkert.org#include "debug/Cache.hh"
648232Snate@binkert.org#include "debug/CachePort.hh"
6512724Snikos.nikoleris@arm.com#include "enums/Clusivity.hh"
6613223Sodanrc@yahoo.com.br#include "mem/cache/cache_blk.hh"
6713945Sodanrc@yahoo.com.br#include "mem/cache/compressors/base.hh"
685338Sstever@gmail.com#include "mem/cache/mshr_queue.hh"
6912724Snikos.nikoleris@arm.com#include "mem/cache/tags/base.hh"
7011375Sandreas.hansson@arm.com#include "mem/cache/write_queue.hh"
7112724Snikos.nikoleris@arm.com#include "mem/cache/write_queue_entry.hh"
722810SN/A#include "mem/packet.hh"
7312724Snikos.nikoleris@arm.com#include "mem/packet_queue.hh"
748914Sandreas.hansson@arm.com#include "mem/qport.hh"
758229Snate@binkert.org#include "mem/request.hh"
7613352Snikos.nikoleris@arm.com#include "params/WriteAllocator.hh"
7713892Sgabeblack@google.com#include "sim/clocked_object.hh"
782811SN/A#include "sim/eventq.hh"
7913416Sjavier.bueno@metempsy.com#include "sim/probe/probe.hh"
8012724Snikos.nikoleris@arm.com#include "sim/serialize.hh"
814626SN/A#include "sim/sim_exit.hh"
828833Sdam.sunwoo@arm.com#include "sim/system.hh"
832810SN/A
8412724Snikos.nikoleris@arm.comclass BasePrefetcher;
8512724Snikos.nikoleris@arm.comclass MSHR;
8612724Snikos.nikoleris@arm.comclass MasterPort;
8712724Snikos.nikoleris@arm.comclass QueueEntry;
8812724Snikos.nikoleris@arm.comstruct BaseCacheParams;
8912724Snikos.nikoleris@arm.com
902810SN/A/**
912810SN/A * A basic cache interface. Implements some common functions for speed.
922810SN/A */
9313892Sgabeblack@google.comclass BaseCache : public ClockedObject
942810SN/A{
9511375Sandreas.hansson@arm.com  protected:
964628SN/A    /**
974628SN/A     * Indexes to enumerate the MSHR queues.
984628SN/A     */
994628SN/A    enum MSHRQueueIndex {
1004628SN/A        MSHRQueue_MSHRs,
1014628SN/A        MSHRQueue_WriteBuffer
1024628SN/A    };
1034628SN/A
1048737Skoansin.tan@gmail.com  public:
1054628SN/A    /**
1064628SN/A     * Reasons for caches to be blocked.
1074628SN/A     */
1084628SN/A    enum BlockedCause {
1094628SN/A        Blocked_NoMSHRs = MSHRQueue_MSHRs,
1104628SN/A        Blocked_NoWBBuffers = MSHRQueue_WriteBuffer,
1114628SN/A        Blocked_NoTargets,
1124628SN/A        NUM_BLOCKED_CAUSES
1134628SN/A    };
1144628SN/A
1158737Skoansin.tan@gmail.com  protected:
1164628SN/A
1178856Sandreas.hansson@arm.com    /**
1188856Sandreas.hansson@arm.com     * A cache master port is used for the memory-side port of the
1198856Sandreas.hansson@arm.com     * cache, and in addition to the basic timing port that only sends
1208856Sandreas.hansson@arm.com     * response packets through a transmit list, it also offers the
1218856Sandreas.hansson@arm.com     * ability to schedule and send request packets (requests &
12210942Sandreas.hansson@arm.com     * writebacks). The send event is scheduled through schedSendEvent,
1238856Sandreas.hansson@arm.com     * and the sendDeferredPacket of the timing port is modified to
1248856Sandreas.hansson@arm.com     * consider both the transmit list and the requests from the MSHR.
1258856Sandreas.hansson@arm.com     */
1268922Swilliam.wang@arm.com    class CacheMasterPort : public QueuedMasterPort
1272810SN/A    {
1288856Sandreas.hansson@arm.com
1292844SN/A      public:
1308856Sandreas.hansson@arm.com
1318856Sandreas.hansson@arm.com        /**
1328856Sandreas.hansson@arm.com         * Schedule a send of a request packet (from the MSHR). Note
13310713Sandreas.hansson@arm.com         * that we could already have a retry outstanding.
1348856Sandreas.hansson@arm.com         */
13510942Sandreas.hansson@arm.com        void schedSendEvent(Tick time)
1368856Sandreas.hansson@arm.com        {
13710942Sandreas.hansson@arm.com            DPRINTF(CachePort, "Scheduling send event at %llu\n", time);
13810713Sandreas.hansson@arm.com            reqQueue.schedSendEvent(time);
1398856Sandreas.hansson@arm.com        }
1408856Sandreas.hansson@arm.com
1413738SN/A      protected:
1424458SN/A
1438856Sandreas.hansson@arm.com        CacheMasterPort(const std::string &_name, BaseCache *_cache,
14410713Sandreas.hansson@arm.com                        ReqPacketQueue &_reqQueue,
14510713Sandreas.hansson@arm.com                        SnoopRespPacketQueue &_snoopRespQueue) :
14610713Sandreas.hansson@arm.com            QueuedMasterPort(_name, _cache, _reqQueue, _snoopRespQueue)
1478914Sandreas.hansson@arm.com        { }
1482810SN/A
1498856Sandreas.hansson@arm.com        /**
1508856Sandreas.hansson@arm.com         * Memory-side port always snoops.
1518856Sandreas.hansson@arm.com         *
1528914Sandreas.hansson@arm.com         * @return always true
1538856Sandreas.hansson@arm.com         */
1548922Swilliam.wang@arm.com        virtual bool isSnooping() const { return true; }
1558856Sandreas.hansson@arm.com    };
1563013SN/A
1578856Sandreas.hansson@arm.com    /**
15812724Snikos.nikoleris@arm.com     * Override the default behaviour of sendDeferredPacket to enable
15912724Snikos.nikoleris@arm.com     * the memory-side cache port to also send requests based on the
16012724Snikos.nikoleris@arm.com     * current MSHR status. This queue has a pointer to our specific
16112724Snikos.nikoleris@arm.com     * cache implementation and is used by the MemSidePort.
16212724Snikos.nikoleris@arm.com     */
16312724Snikos.nikoleris@arm.com    class CacheReqPacketQueue : public ReqPacketQueue
16412724Snikos.nikoleris@arm.com    {
16512724Snikos.nikoleris@arm.com
16612724Snikos.nikoleris@arm.com      protected:
16712724Snikos.nikoleris@arm.com
16812724Snikos.nikoleris@arm.com        BaseCache &cache;
16912724Snikos.nikoleris@arm.com        SnoopRespPacketQueue &snoopRespQueue;
17012724Snikos.nikoleris@arm.com
17112724Snikos.nikoleris@arm.com      public:
17212724Snikos.nikoleris@arm.com
17312724Snikos.nikoleris@arm.com        CacheReqPacketQueue(BaseCache &cache, MasterPort &port,
17412724Snikos.nikoleris@arm.com                            SnoopRespPacketQueue &snoop_resp_queue,
17512724Snikos.nikoleris@arm.com                            const std::string &label) :
17612724Snikos.nikoleris@arm.com            ReqPacketQueue(cache, port, label), cache(cache),
17712724Snikos.nikoleris@arm.com            snoopRespQueue(snoop_resp_queue) { }
17812724Snikos.nikoleris@arm.com
17912724Snikos.nikoleris@arm.com        /**
18012724Snikos.nikoleris@arm.com         * Override the normal sendDeferredPacket and do not only
18112724Snikos.nikoleris@arm.com         * consider the transmit list (used for responses), but also
18212724Snikos.nikoleris@arm.com         * requests.
18312724Snikos.nikoleris@arm.com         */
18412724Snikos.nikoleris@arm.com        virtual void sendDeferredPacket();
18512724Snikos.nikoleris@arm.com
18612724Snikos.nikoleris@arm.com        /**
18712724Snikos.nikoleris@arm.com         * Check if there is a conflicting snoop response about to be
18812724Snikos.nikoleris@arm.com         * send out, and if so simply stall any requests, and schedule
18912724Snikos.nikoleris@arm.com         * a send event at the same time as the next snoop response is
19012724Snikos.nikoleris@arm.com         * being sent out.
19113860Sodanrc@yahoo.com.br         *
19213860Sodanrc@yahoo.com.br         * @param pkt The packet to check for conflicts against.
19312724Snikos.nikoleris@arm.com         */
19413860Sodanrc@yahoo.com.br        bool checkConflictingSnoop(const PacketPtr pkt)
19512724Snikos.nikoleris@arm.com        {
19613860Sodanrc@yahoo.com.br            if (snoopRespQueue.checkConflict(pkt, cache.blkSize)) {
19712724Snikos.nikoleris@arm.com                DPRINTF(CachePort, "Waiting for snoop response to be "
19812724Snikos.nikoleris@arm.com                        "sent\n");
19912724Snikos.nikoleris@arm.com                Tick when = snoopRespQueue.deferredPacketReadyTime();
20012724Snikos.nikoleris@arm.com                schedSendEvent(when);
20112724Snikos.nikoleris@arm.com                return true;
20212724Snikos.nikoleris@arm.com            }
20312724Snikos.nikoleris@arm.com            return false;
20412724Snikos.nikoleris@arm.com        }
20512724Snikos.nikoleris@arm.com    };
20612724Snikos.nikoleris@arm.com
20712724Snikos.nikoleris@arm.com
20812724Snikos.nikoleris@arm.com    /**
20912724Snikos.nikoleris@arm.com     * The memory-side port extends the base cache master port with
21012724Snikos.nikoleris@arm.com     * access functions for functional, atomic and timing snoops.
21112724Snikos.nikoleris@arm.com     */
21212724Snikos.nikoleris@arm.com    class MemSidePort : public CacheMasterPort
21312724Snikos.nikoleris@arm.com    {
21412724Snikos.nikoleris@arm.com      private:
21512724Snikos.nikoleris@arm.com
21612724Snikos.nikoleris@arm.com        /** The cache-specific queue. */
21712724Snikos.nikoleris@arm.com        CacheReqPacketQueue _reqQueue;
21812724Snikos.nikoleris@arm.com
21912724Snikos.nikoleris@arm.com        SnoopRespPacketQueue _snoopRespQueue;
22012724Snikos.nikoleris@arm.com
22112724Snikos.nikoleris@arm.com        // a pointer to our specific cache implementation
22212724Snikos.nikoleris@arm.com        BaseCache *cache;
22312724Snikos.nikoleris@arm.com
22412724Snikos.nikoleris@arm.com      protected:
22512724Snikos.nikoleris@arm.com
22612724Snikos.nikoleris@arm.com        virtual void recvTimingSnoopReq(PacketPtr pkt);
22712724Snikos.nikoleris@arm.com
22812724Snikos.nikoleris@arm.com        virtual bool recvTimingResp(PacketPtr pkt);
22912724Snikos.nikoleris@arm.com
23012724Snikos.nikoleris@arm.com        virtual Tick recvAtomicSnoop(PacketPtr pkt);
23112724Snikos.nikoleris@arm.com
23212724Snikos.nikoleris@arm.com        virtual void recvFunctionalSnoop(PacketPtr pkt);
23312724Snikos.nikoleris@arm.com
23412724Snikos.nikoleris@arm.com      public:
23512724Snikos.nikoleris@arm.com
23612724Snikos.nikoleris@arm.com        MemSidePort(const std::string &_name, BaseCache *_cache,
23712724Snikos.nikoleris@arm.com                    const std::string &_label);
23812724Snikos.nikoleris@arm.com    };
23912724Snikos.nikoleris@arm.com
24012724Snikos.nikoleris@arm.com    /**
2418856Sandreas.hansson@arm.com     * A cache slave port is used for the CPU-side port of the cache,
2428856Sandreas.hansson@arm.com     * and it is basically a simple timing port that uses a transmit
2438856Sandreas.hansson@arm.com     * list for responses to the CPU (or connected master). In
2448856Sandreas.hansson@arm.com     * addition, it has the functionality to block the port for
2458856Sandreas.hansson@arm.com     * incoming requests. If blocked, the port will issue a retry once
2468856Sandreas.hansson@arm.com     * unblocked.
2478856Sandreas.hansson@arm.com     */
2488922Swilliam.wang@arm.com    class CacheSlavePort : public QueuedSlavePort
2498856Sandreas.hansson@arm.com    {
2505314SN/A
2512811SN/A      public:
2528856Sandreas.hansson@arm.com
2538856Sandreas.hansson@arm.com        /** Do not accept any new requests. */
2542810SN/A        void setBlocked();
2552810SN/A
2568856Sandreas.hansson@arm.com        /** Return to normal operation and accept new requests. */
2572810SN/A        void clearBlocked();
2582810SN/A
25910345SCurtis.Dunham@arm.com        bool isBlocked() const { return blocked; }
26010345SCurtis.Dunham@arm.com
2618856Sandreas.hansson@arm.com      protected:
2628856Sandreas.hansson@arm.com
2638856Sandreas.hansson@arm.com        CacheSlavePort(const std::string &_name, BaseCache *_cache,
2648856Sandreas.hansson@arm.com                       const std::string &_label);
2653606SN/A
2668914Sandreas.hansson@arm.com        /** A normal packet queue used to store responses. */
26710713Sandreas.hansson@arm.com        RespPacketQueue queue;
2688914Sandreas.hansson@arm.com
2692810SN/A        bool blocked;
2702810SN/A
2712897SN/A        bool mustSendRetry;
2722897SN/A
2738856Sandreas.hansson@arm.com      private:
2744458SN/A
27510344Sandreas.hansson@arm.com        void processSendRetry();
27610344Sandreas.hansson@arm.com
27712084Sspwilson2@wisc.edu        EventFunctionWrapper sendRetryEvent;
2788856Sandreas.hansson@arm.com
2792811SN/A    };
2802810SN/A
28112724Snikos.nikoleris@arm.com    /**
28212724Snikos.nikoleris@arm.com     * The CPU-side port extends the base cache slave port with access
28312724Snikos.nikoleris@arm.com     * functions for functional, atomic and timing requests.
28412724Snikos.nikoleris@arm.com     */
28512724Snikos.nikoleris@arm.com    class CpuSidePort : public CacheSlavePort
28612724Snikos.nikoleris@arm.com    {
28712724Snikos.nikoleris@arm.com      private:
28812724Snikos.nikoleris@arm.com
28912724Snikos.nikoleris@arm.com        // a pointer to our specific cache implementation
29012724Snikos.nikoleris@arm.com        BaseCache *cache;
29112724Snikos.nikoleris@arm.com
29212724Snikos.nikoleris@arm.com      protected:
29312724Snikos.nikoleris@arm.com        virtual bool recvTimingSnoopResp(PacketPtr pkt) override;
29412724Snikos.nikoleris@arm.com
29512724Snikos.nikoleris@arm.com        virtual bool tryTiming(PacketPtr pkt) override;
29612724Snikos.nikoleris@arm.com
29712724Snikos.nikoleris@arm.com        virtual bool recvTimingReq(PacketPtr pkt) override;
29812724Snikos.nikoleris@arm.com
29912724Snikos.nikoleris@arm.com        virtual Tick recvAtomic(PacketPtr pkt) override;
30012724Snikos.nikoleris@arm.com
30112724Snikos.nikoleris@arm.com        virtual void recvFunctional(PacketPtr pkt) override;
30212724Snikos.nikoleris@arm.com
30312724Snikos.nikoleris@arm.com        virtual AddrRangeList getAddrRanges() const override;
30412724Snikos.nikoleris@arm.com
30512724Snikos.nikoleris@arm.com      public:
30612724Snikos.nikoleris@arm.com
30712724Snikos.nikoleris@arm.com        CpuSidePort(const std::string &_name, BaseCache *_cache,
30812724Snikos.nikoleris@arm.com                    const std::string &_label);
30912724Snikos.nikoleris@arm.com
31012724Snikos.nikoleris@arm.com    };
31112724Snikos.nikoleris@arm.com
31212724Snikos.nikoleris@arm.com    CpuSidePort cpuSidePort;
31312724Snikos.nikoleris@arm.com    MemSidePort memSidePort;
3143338SN/A
3154626SN/A  protected:
3164626SN/A
3174626SN/A    /** Miss status registers */
3184626SN/A    MSHRQueue mshrQueue;
3194626SN/A
3204626SN/A    /** Write/writeback buffer */
32111375Sandreas.hansson@arm.com    WriteQueue writeBuffer;
3224626SN/A
32312724Snikos.nikoleris@arm.com    /** Tag and data Storage */
32412724Snikos.nikoleris@arm.com    BaseTags *tags;
32512724Snikos.nikoleris@arm.com
32613945Sodanrc@yahoo.com.br    /** Compression method being used. */
32713945Sodanrc@yahoo.com.br    BaseCacheCompressor* compressor;
32813945Sodanrc@yahoo.com.br
32912724Snikos.nikoleris@arm.com    /** Prefetcher */
33012724Snikos.nikoleris@arm.com    BasePrefetcher *prefetcher;
33112724Snikos.nikoleris@arm.com
33213416Sjavier.bueno@metempsy.com    /** To probe when a cache hit occurs */
33313416Sjavier.bueno@metempsy.com    ProbePointArg<PacketPtr> *ppHit;
33413416Sjavier.bueno@metempsy.com
33513416Sjavier.bueno@metempsy.com    /** To probe when a cache miss occurs */
33613416Sjavier.bueno@metempsy.com    ProbePointArg<PacketPtr> *ppMiss;
33712724Snikos.nikoleris@arm.com
33813717Sivan.pizarro@metempsy.com    /** To probe when a cache fill occurs */
33913717Sivan.pizarro@metempsy.com    ProbePointArg<PacketPtr> *ppFill;
34013717Sivan.pizarro@metempsy.com
34112724Snikos.nikoleris@arm.com    /**
34213352Snikos.nikoleris@arm.com     * The writeAllocator drive optimizations for streaming writes.
34313352Snikos.nikoleris@arm.com     * It first determines whether a WriteReq MSHR should be delayed,
34413352Snikos.nikoleris@arm.com     * thus ensuring that we wait longer in cases when we are write
34513352Snikos.nikoleris@arm.com     * coalescing and allowing all the bytes of the line to be written
34613352Snikos.nikoleris@arm.com     * before the MSHR packet is sent downstream. This works in unison
34713352Snikos.nikoleris@arm.com     * with the tracking in the MSHR to check if the entire line is
34813352Snikos.nikoleris@arm.com     * written. The write mode also affects the behaviour on filling
34913352Snikos.nikoleris@arm.com     * any whole-line writes. Normally the cache allocates the line
35013352Snikos.nikoleris@arm.com     * when receiving the InvalidateResp, but after seeing enough
35113352Snikos.nikoleris@arm.com     * consecutive lines we switch to using the tempBlock, and thus
35213352Snikos.nikoleris@arm.com     * end up not allocating the line, and instead turning the
35313352Snikos.nikoleris@arm.com     * whole-line write into a writeback straight away.
35413352Snikos.nikoleris@arm.com     */
35513352Snikos.nikoleris@arm.com    WriteAllocator * const writeAllocator;
35613352Snikos.nikoleris@arm.com
35713352Snikos.nikoleris@arm.com    /**
35812724Snikos.nikoleris@arm.com     * Temporary cache block for occasional transitory use.  We use
35912724Snikos.nikoleris@arm.com     * the tempBlock to fill when allocation fails (e.g., when there
36012724Snikos.nikoleris@arm.com     * is an outstanding request that accesses the victim block) or
36112724Snikos.nikoleris@arm.com     * when we want to avoid allocation (e.g., exclusive caches)
36212724Snikos.nikoleris@arm.com     */
36312730Sodanrc@yahoo.com.br    TempCacheBlk *tempBlock;
36412724Snikos.nikoleris@arm.com
36512724Snikos.nikoleris@arm.com    /**
36612724Snikos.nikoleris@arm.com     * Upstream caches need this packet until true is returned, so
36712724Snikos.nikoleris@arm.com     * hold it for deletion until a subsequent call
36812724Snikos.nikoleris@arm.com     */
36912724Snikos.nikoleris@arm.com    std::unique_ptr<Packet> pendingDelete;
37012724Snikos.nikoleris@arm.com
37110693SMarco.Balboni@ARM.com    /**
37211375Sandreas.hansson@arm.com     * Mark a request as in service (sent downstream in the memory
37311375Sandreas.hansson@arm.com     * system), effectively making this MSHR the ordering point.
37410693SMarco.Balboni@ARM.com     */
37511375Sandreas.hansson@arm.com    void markInService(MSHR *mshr, bool pending_modified_resp)
3764628SN/A    {
37711375Sandreas.hansson@arm.com        bool wasFull = mshrQueue.isFull();
37811375Sandreas.hansson@arm.com        mshrQueue.markInService(mshr, pending_modified_resp);
37910764Sandreas.hansson@arm.com
38011375Sandreas.hansson@arm.com        if (wasFull && !mshrQueue.isFull()) {
38111375Sandreas.hansson@arm.com            clearBlocked(Blocked_NoMSHRs);
3824628SN/A        }
3834628SN/A    }
3844628SN/A
38511375Sandreas.hansson@arm.com    void markInService(WriteQueueEntry *entry)
3864628SN/A    {
38711375Sandreas.hansson@arm.com        bool wasFull = writeBuffer.isFull();
38811375Sandreas.hansson@arm.com        writeBuffer.markInService(entry);
38911375Sandreas.hansson@arm.com
39011375Sandreas.hansson@arm.com        if (wasFull && !writeBuffer.isFull()) {
39111375Sandreas.hansson@arm.com            clearBlocked(Blocked_NoWBBuffers);
3924628SN/A        }
3934628SN/A    }
3944628SN/A
3959347SAndreas.Sandberg@arm.com    /**
39612724Snikos.nikoleris@arm.com     * Determine whether we should allocate on a fill or not. If this
39712724Snikos.nikoleris@arm.com     * cache is mostly inclusive with regards to the upstream cache(s)
39812724Snikos.nikoleris@arm.com     * we always allocate (for any non-forwarded and cacheable
39912724Snikos.nikoleris@arm.com     * requests). In the case of a mostly exclusive cache, we allocate
40012724Snikos.nikoleris@arm.com     * on fill if the packet did not come from a cache, thus if we:
40112724Snikos.nikoleris@arm.com     * are dealing with a whole-line write (the latter behaves much
40212724Snikos.nikoleris@arm.com     * like a writeback), the original target packet came from a
40312724Snikos.nikoleris@arm.com     * non-caching source, or if we are performing a prefetch or LLSC.
40411197Sandreas.hansson@arm.com     *
40512724Snikos.nikoleris@arm.com     * @param cmd Command of the incoming requesting packet
40612724Snikos.nikoleris@arm.com     * @return Whether we should allocate on the fill
40712724Snikos.nikoleris@arm.com     */
40812724Snikos.nikoleris@arm.com    inline bool allocOnFill(MemCmd cmd) const
40912724Snikos.nikoleris@arm.com    {
41012724Snikos.nikoleris@arm.com        return clusivity == Enums::mostly_incl ||
41112724Snikos.nikoleris@arm.com            cmd == MemCmd::WriteLineReq ||
41212724Snikos.nikoleris@arm.com            cmd == MemCmd::ReadReq ||
41312724Snikos.nikoleris@arm.com            cmd == MemCmd::WriteReq ||
41412724Snikos.nikoleris@arm.com            cmd.isPrefetch() ||
41512724Snikos.nikoleris@arm.com            cmd.isLLSC();
41612724Snikos.nikoleris@arm.com    }
41712724Snikos.nikoleris@arm.com
41812724Snikos.nikoleris@arm.com    /**
41912730Sodanrc@yahoo.com.br     * Regenerate block address using tags.
42012730Sodanrc@yahoo.com.br     * Block address regeneration depends on whether we're using a temporary
42112730Sodanrc@yahoo.com.br     * block or not.
42212730Sodanrc@yahoo.com.br     *
42312730Sodanrc@yahoo.com.br     * @param blk The block to regenerate address.
42412730Sodanrc@yahoo.com.br     * @return The block's address.
42512730Sodanrc@yahoo.com.br     */
42612730Sodanrc@yahoo.com.br    Addr regenerateBlkAddr(CacheBlk* blk);
42712730Sodanrc@yahoo.com.br
42812730Sodanrc@yahoo.com.br    /**
42913749Sodanrc@yahoo.com.br     * Calculate latency of accesses that only touch the tag array.
43013749Sodanrc@yahoo.com.br     * @sa calculateAccessLatency
43113749Sodanrc@yahoo.com.br     *
43213749Sodanrc@yahoo.com.br     * @param delay The delay until the packet's metadata is present.
43313749Sodanrc@yahoo.com.br     * @param lookup_lat Latency of the respective tag lookup.
43413749Sodanrc@yahoo.com.br     * @return The number of ticks that pass due to a tag-only access.
43513749Sodanrc@yahoo.com.br     */
43613749Sodanrc@yahoo.com.br    Cycles calculateTagOnlyLatency(const uint32_t delay,
43713749Sodanrc@yahoo.com.br                                   const Cycles lookup_lat) const;
43813749Sodanrc@yahoo.com.br    /**
43913418Sodanrc@yahoo.com.br     * Calculate access latency in ticks given a tag lookup latency, and
44013418Sodanrc@yahoo.com.br     * whether access was a hit or miss.
44113418Sodanrc@yahoo.com.br     *
44213418Sodanrc@yahoo.com.br     * @param blk The cache block that was accessed.
44313746Sodanrc@yahoo.com.br     * @param delay The delay until the packet's metadata is present.
44413418Sodanrc@yahoo.com.br     * @param lookup_lat Latency of the respective tag lookup.
44513418Sodanrc@yahoo.com.br     * @return The number of ticks that pass due to a block access.
44613418Sodanrc@yahoo.com.br     */
44713746Sodanrc@yahoo.com.br    Cycles calculateAccessLatency(const CacheBlk* blk, const uint32_t delay,
44813418Sodanrc@yahoo.com.br                                  const Cycles lookup_lat) const;
44913418Sodanrc@yahoo.com.br
45013418Sodanrc@yahoo.com.br    /**
45112724Snikos.nikoleris@arm.com     * Does all the processing necessary to perform the provided request.
45212724Snikos.nikoleris@arm.com     * @param pkt The memory request to perform.
45312724Snikos.nikoleris@arm.com     * @param blk The cache block to be updated.
45412724Snikos.nikoleris@arm.com     * @param lat The latency of the access.
45514035Sodanrc@yahoo.com.br     * @param writebacks List for any writebacks that need to be performed.
45612724Snikos.nikoleris@arm.com     * @return Boolean indicating whether the request was satisfied.
45712724Snikos.nikoleris@arm.com     */
45814035Sodanrc@yahoo.com.br    virtual bool access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat,
45914035Sodanrc@yahoo.com.br                        PacketList &writebacks);
46012724Snikos.nikoleris@arm.com
46112724Snikos.nikoleris@arm.com    /*
46212724Snikos.nikoleris@arm.com     * Handle a timing request that hit in the cache
46311197Sandreas.hansson@arm.com     *
46412724Snikos.nikoleris@arm.com     * @param ptk The request packet
46512724Snikos.nikoleris@arm.com     * @param blk The referenced block
46612724Snikos.nikoleris@arm.com     * @param request_time The tick at which the block lookup is compete
46711197Sandreas.hansson@arm.com     */
46812724Snikos.nikoleris@arm.com    virtual void handleTimingReqHit(PacketPtr pkt, CacheBlk *blk,
46912724Snikos.nikoleris@arm.com                                    Tick request_time);
47012724Snikos.nikoleris@arm.com
47112724Snikos.nikoleris@arm.com    /*
47212724Snikos.nikoleris@arm.com     * Handle a timing request that missed in the cache
47312724Snikos.nikoleris@arm.com     *
47412724Snikos.nikoleris@arm.com     * Implementation specific handling for different cache
47512724Snikos.nikoleris@arm.com     * implementations
47612724Snikos.nikoleris@arm.com     *
47712724Snikos.nikoleris@arm.com     * @param ptk The request packet
47812724Snikos.nikoleris@arm.com     * @param blk The referenced block
47912724Snikos.nikoleris@arm.com     * @param forward_time The tick at which we can process dependent requests
48012724Snikos.nikoleris@arm.com     * @param request_time The tick at which the block lookup is compete
48112724Snikos.nikoleris@arm.com     */
48212724Snikos.nikoleris@arm.com    virtual void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk,
48312724Snikos.nikoleris@arm.com                                     Tick forward_time,
48412724Snikos.nikoleris@arm.com                                     Tick request_time) = 0;
48512724Snikos.nikoleris@arm.com
48612724Snikos.nikoleris@arm.com    /*
48712724Snikos.nikoleris@arm.com     * Handle a timing request that missed in the cache
48812724Snikos.nikoleris@arm.com     *
48912724Snikos.nikoleris@arm.com     * Common functionality across different cache implementations
49012724Snikos.nikoleris@arm.com     *
49112724Snikos.nikoleris@arm.com     * @param ptk The request packet
49212724Snikos.nikoleris@arm.com     * @param blk The referenced block
49312724Snikos.nikoleris@arm.com     * @param mshr Any existing mshr for the referenced cache block
49412724Snikos.nikoleris@arm.com     * @param forward_time The tick at which we can process dependent requests
49512724Snikos.nikoleris@arm.com     * @param request_time The tick at which the block lookup is compete
49612724Snikos.nikoleris@arm.com     */
49712724Snikos.nikoleris@arm.com    void handleTimingReqMiss(PacketPtr pkt, MSHR *mshr, CacheBlk *blk,
49812724Snikos.nikoleris@arm.com                             Tick forward_time, Tick request_time);
49912724Snikos.nikoleris@arm.com
50012724Snikos.nikoleris@arm.com    /**
50112724Snikos.nikoleris@arm.com     * Performs the access specified by the request.
50212724Snikos.nikoleris@arm.com     * @param pkt The request to perform.
50312724Snikos.nikoleris@arm.com     */
50412724Snikos.nikoleris@arm.com    virtual void recvTimingReq(PacketPtr pkt);
50512724Snikos.nikoleris@arm.com
50612724Snikos.nikoleris@arm.com    /**
50712724Snikos.nikoleris@arm.com     * Handling the special case of uncacheable write responses to
50812724Snikos.nikoleris@arm.com     * make recvTimingResp less cluttered.
50912724Snikos.nikoleris@arm.com     */
51012724Snikos.nikoleris@arm.com    void handleUncacheableWriteResp(PacketPtr pkt);
51112724Snikos.nikoleris@arm.com
51212724Snikos.nikoleris@arm.com    /**
51312724Snikos.nikoleris@arm.com     * Service non-deferred MSHR targets using the received response
51412724Snikos.nikoleris@arm.com     *
51512724Snikos.nikoleris@arm.com     * Iterates through the list of targets that can be serviced with
51613478Sodanrc@yahoo.com.br     * the current response.
51712724Snikos.nikoleris@arm.com     *
51812724Snikos.nikoleris@arm.com     * @param mshr The MSHR that corresponds to the reponse
51912724Snikos.nikoleris@arm.com     * @param pkt The response packet
52012724Snikos.nikoleris@arm.com     * @param blk The reference block
52112724Snikos.nikoleris@arm.com     */
52212724Snikos.nikoleris@arm.com    virtual void serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt,
52313478Sodanrc@yahoo.com.br                                    CacheBlk *blk) = 0;
52412724Snikos.nikoleris@arm.com
52512724Snikos.nikoleris@arm.com    /**
52612724Snikos.nikoleris@arm.com     * Handles a response (cache line fill/write ack) from the bus.
52712724Snikos.nikoleris@arm.com     * @param pkt The response packet
52812724Snikos.nikoleris@arm.com     */
52912724Snikos.nikoleris@arm.com    virtual void recvTimingResp(PacketPtr pkt);
53012724Snikos.nikoleris@arm.com
53112724Snikos.nikoleris@arm.com    /**
53212724Snikos.nikoleris@arm.com     * Snoops bus transactions to maintain coherence.
53312724Snikos.nikoleris@arm.com     * @param pkt The current bus transaction.
53412724Snikos.nikoleris@arm.com     */
53512724Snikos.nikoleris@arm.com    virtual void recvTimingSnoopReq(PacketPtr pkt) = 0;
53612724Snikos.nikoleris@arm.com
53712724Snikos.nikoleris@arm.com    /**
53812724Snikos.nikoleris@arm.com     * Handle a snoop response.
53912724Snikos.nikoleris@arm.com     * @param pkt Snoop response packet
54012724Snikos.nikoleris@arm.com     */
54112724Snikos.nikoleris@arm.com    virtual void recvTimingSnoopResp(PacketPtr pkt) = 0;
54212724Snikos.nikoleris@arm.com
54312724Snikos.nikoleris@arm.com    /**
54412724Snikos.nikoleris@arm.com     * Handle a request in atomic mode that missed in this cache
54512724Snikos.nikoleris@arm.com     *
54612724Snikos.nikoleris@arm.com     * Creates a downstream request, sends it to the memory below and
54712724Snikos.nikoleris@arm.com     * handles the response. As we are in atomic mode all operations
54812724Snikos.nikoleris@arm.com     * are performed immediately.
54912724Snikos.nikoleris@arm.com     *
55012724Snikos.nikoleris@arm.com     * @param pkt The packet with the requests
55112724Snikos.nikoleris@arm.com     * @param blk The referenced block
55214035Sodanrc@yahoo.com.br     * @param writebacks A list with packets for any performed writebacks
55312724Snikos.nikoleris@arm.com     * @return Cycles for handling the request
55412724Snikos.nikoleris@arm.com     */
55514035Sodanrc@yahoo.com.br    virtual Cycles handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk,
55614035Sodanrc@yahoo.com.br                                       PacketList &writebacks) = 0;
55712724Snikos.nikoleris@arm.com
55812724Snikos.nikoleris@arm.com    /**
55912724Snikos.nikoleris@arm.com     * Performs the access specified by the request.
56012724Snikos.nikoleris@arm.com     * @param pkt The request to perform.
56112724Snikos.nikoleris@arm.com     * @return The number of ticks required for the access.
56212724Snikos.nikoleris@arm.com     */
56312724Snikos.nikoleris@arm.com    virtual Tick recvAtomic(PacketPtr pkt);
56412724Snikos.nikoleris@arm.com
56512724Snikos.nikoleris@arm.com    /**
56612724Snikos.nikoleris@arm.com     * Snoop for the provided request in the cache and return the estimated
56712724Snikos.nikoleris@arm.com     * time taken.
56812724Snikos.nikoleris@arm.com     * @param pkt The memory request to snoop
56912724Snikos.nikoleris@arm.com     * @return The number of ticks required for the snoop.
57012724Snikos.nikoleris@arm.com     */
57112724Snikos.nikoleris@arm.com    virtual Tick recvAtomicSnoop(PacketPtr pkt) = 0;
57212724Snikos.nikoleris@arm.com
57312724Snikos.nikoleris@arm.com    /**
57412724Snikos.nikoleris@arm.com     * Performs the access specified by the request.
57512724Snikos.nikoleris@arm.com     *
57612724Snikos.nikoleris@arm.com     * @param pkt The request to perform.
57712724Snikos.nikoleris@arm.com     * @param fromCpuSide from the CPU side port or the memory side port
57812724Snikos.nikoleris@arm.com     */
57912724Snikos.nikoleris@arm.com    virtual void functionalAccess(PacketPtr pkt, bool from_cpu_side);
58012724Snikos.nikoleris@arm.com
58112724Snikos.nikoleris@arm.com    /**
58212724Snikos.nikoleris@arm.com     * Handle doing the Compare and Swap function for SPARC.
58312724Snikos.nikoleris@arm.com     */
58412724Snikos.nikoleris@arm.com    void cmpAndSwap(CacheBlk *blk, PacketPtr pkt);
58512724Snikos.nikoleris@arm.com
58612724Snikos.nikoleris@arm.com    /**
58712724Snikos.nikoleris@arm.com     * Return the next queue entry to service, either a pending miss
58812724Snikos.nikoleris@arm.com     * from the MSHR queue, a buffered write from the write buffer, or
58912724Snikos.nikoleris@arm.com     * something from the prefetcher. This function is responsible
59012724Snikos.nikoleris@arm.com     * for prioritizing among those sources on the fly.
59112724Snikos.nikoleris@arm.com     */
59212724Snikos.nikoleris@arm.com    QueueEntry* getNextQueueEntry();
59312724Snikos.nikoleris@arm.com
59412724Snikos.nikoleris@arm.com    /**
59512724Snikos.nikoleris@arm.com     * Insert writebacks into the write buffer
59612724Snikos.nikoleris@arm.com     */
59714035Sodanrc@yahoo.com.br    virtual void doWritebacks(PacketList& writebacks, Tick forward_time) = 0;
59812724Snikos.nikoleris@arm.com
59912724Snikos.nikoleris@arm.com    /**
60014035Sodanrc@yahoo.com.br     * Send writebacks down the memory hierarchy in atomic mode
60112724Snikos.nikoleris@arm.com     */
60214035Sodanrc@yahoo.com.br    virtual void doWritebacksAtomic(PacketList& writebacks) = 0;
60312724Snikos.nikoleris@arm.com
60412724Snikos.nikoleris@arm.com    /**
60512724Snikos.nikoleris@arm.com     * Create an appropriate downstream bus request packet.
60612724Snikos.nikoleris@arm.com     *
60712724Snikos.nikoleris@arm.com     * Creates a new packet with the request to be send to the memory
60812724Snikos.nikoleris@arm.com     * below, or nullptr if the current request in cpu_pkt should just
60912724Snikos.nikoleris@arm.com     * be forwarded on.
61012724Snikos.nikoleris@arm.com     *
61112724Snikos.nikoleris@arm.com     * @param cpu_pkt The miss packet that needs to be satisfied.
61212724Snikos.nikoleris@arm.com     * @param blk The referenced block, can be nullptr.
61312724Snikos.nikoleris@arm.com     * @param needs_writable Indicates that the block must be writable
61412724Snikos.nikoleris@arm.com     * even if the request in cpu_pkt doesn't indicate that.
61513350Snikos.nikoleris@arm.com     * @param is_whole_line_write True if there are writes for the
61613350Snikos.nikoleris@arm.com     * whole line
61712724Snikos.nikoleris@arm.com     * @return A packet send to the memory below
61812724Snikos.nikoleris@arm.com     */
61912724Snikos.nikoleris@arm.com    virtual PacketPtr createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk,
62013350Snikos.nikoleris@arm.com                                       bool needs_writable,
62113350Snikos.nikoleris@arm.com                                       bool is_whole_line_write) const = 0;
62212724Snikos.nikoleris@arm.com
62312724Snikos.nikoleris@arm.com    /**
62412724Snikos.nikoleris@arm.com     * Determine if clean lines should be written back or not. In
62512724Snikos.nikoleris@arm.com     * cases where a downstream cache is mostly inclusive we likely
62612724Snikos.nikoleris@arm.com     * want it to act as a victim cache also for lines that have not
62712724Snikos.nikoleris@arm.com     * been modified. Hence, we cannot simply drop the line (or send a
62812724Snikos.nikoleris@arm.com     * clean evict), but rather need to send the actual data.
62912724Snikos.nikoleris@arm.com     */
63012724Snikos.nikoleris@arm.com    const bool writebackClean;
63112724Snikos.nikoleris@arm.com
63212724Snikos.nikoleris@arm.com    /**
63312724Snikos.nikoleris@arm.com     * Writebacks from the tempBlock, resulting on the response path
63412724Snikos.nikoleris@arm.com     * in atomic mode, must happen after the call to recvAtomic has
63512724Snikos.nikoleris@arm.com     * finished (for the right ordering of the packets). We therefore
63612724Snikos.nikoleris@arm.com     * need to hold on to the packets, and have a method and an event
63712724Snikos.nikoleris@arm.com     * to send them.
63812724Snikos.nikoleris@arm.com     */
63912724Snikos.nikoleris@arm.com    PacketPtr tempBlockWriteback;
64012724Snikos.nikoleris@arm.com
64112724Snikos.nikoleris@arm.com    /**
64212724Snikos.nikoleris@arm.com     * Send the outstanding tempBlock writeback. To be called after
64312724Snikos.nikoleris@arm.com     * recvAtomic finishes in cases where the block we filled is in
64412724Snikos.nikoleris@arm.com     * fact the tempBlock, and now needs to be written back.
64512724Snikos.nikoleris@arm.com     */
64612724Snikos.nikoleris@arm.com    void writebackTempBlockAtomic() {
64712724Snikos.nikoleris@arm.com        assert(tempBlockWriteback != nullptr);
64814035Sodanrc@yahoo.com.br        PacketList writebacks{tempBlockWriteback};
64914035Sodanrc@yahoo.com.br        doWritebacksAtomic(writebacks);
65012724Snikos.nikoleris@arm.com        tempBlockWriteback = nullptr;
65112724Snikos.nikoleris@arm.com    }
65212724Snikos.nikoleris@arm.com
65312724Snikos.nikoleris@arm.com    /**
65412724Snikos.nikoleris@arm.com     * An event to writeback the tempBlock after recvAtomic
65512724Snikos.nikoleris@arm.com     * finishes. To avoid other calls to recvAtomic getting in
65612724Snikos.nikoleris@arm.com     * between, we create this event with a higher priority.
65712724Snikos.nikoleris@arm.com     */
65812724Snikos.nikoleris@arm.com    EventFunctionWrapper writebackTempBlockAtomicEvent;
65912724Snikos.nikoleris@arm.com
66012724Snikos.nikoleris@arm.com    /**
66113947Sodanrc@yahoo.com.br     * When a block is overwriten, its compression information must be updated,
66213947Sodanrc@yahoo.com.br     * and it may need to be recompressed. If the compression size changes, the
66313947Sodanrc@yahoo.com.br     * block may either become smaller, in which case there is no side effect,
66413947Sodanrc@yahoo.com.br     * or bigger (data expansion; fat write), in which case the block might not
66513947Sodanrc@yahoo.com.br     * fit in its current location anymore. If that happens, there are usually
66613947Sodanrc@yahoo.com.br     * two options to be taken:
66713947Sodanrc@yahoo.com.br     *
66813947Sodanrc@yahoo.com.br     * - The co-allocated blocks must be evicted to make room for this block.
66913947Sodanrc@yahoo.com.br     *   Simpler, but ignores replacement data.
67013947Sodanrc@yahoo.com.br     * - The block itself is moved elsewhere (used in policies where the CF
67113947Sodanrc@yahoo.com.br     *   determines the location of the block).
67213947Sodanrc@yahoo.com.br     *
67313947Sodanrc@yahoo.com.br     * This implementation uses the first approach.
67413947Sodanrc@yahoo.com.br     *
67513947Sodanrc@yahoo.com.br     * Notice that this is only called for writebacks, which means that L1
67613947Sodanrc@yahoo.com.br     * caches (which see regular Writes), do not support compression.
67713947Sodanrc@yahoo.com.br     * @sa CompressedTags
67813947Sodanrc@yahoo.com.br     *
67913947Sodanrc@yahoo.com.br     * @param blk The block to be overwriten.
68013947Sodanrc@yahoo.com.br     * @param data A pointer to the data to be compressed (blk's new data).
68114035Sodanrc@yahoo.com.br     * @param writebacks List for any writebacks that need to be performed.
68213947Sodanrc@yahoo.com.br     * @return Whether operation is successful or not.
68313947Sodanrc@yahoo.com.br     */
68413947Sodanrc@yahoo.com.br    bool updateCompressionData(CacheBlk *blk, const uint64_t* data,
68514035Sodanrc@yahoo.com.br                               PacketList &writebacks);
68613947Sodanrc@yahoo.com.br
68713947Sodanrc@yahoo.com.br    /**
68812724Snikos.nikoleris@arm.com     * Perform any necessary updates to the block and perform any data
68912724Snikos.nikoleris@arm.com     * exchange between the packet and the block. The flags of the
69012724Snikos.nikoleris@arm.com     * packet are also set accordingly.
69112724Snikos.nikoleris@arm.com     *
69212724Snikos.nikoleris@arm.com     * @param pkt Request packet from upstream that hit a block
69312724Snikos.nikoleris@arm.com     * @param blk Cache block that the packet hit
69412724Snikos.nikoleris@arm.com     * @param deferred_response Whether this request originally missed
69512724Snikos.nikoleris@arm.com     * @param pending_downgrade Whether the writable flag is to be removed
69612724Snikos.nikoleris@arm.com     */
69712724Snikos.nikoleris@arm.com    virtual void satisfyRequest(PacketPtr pkt, CacheBlk *blk,
69812724Snikos.nikoleris@arm.com                                bool deferred_response = false,
69912724Snikos.nikoleris@arm.com                                bool pending_downgrade = false);
70012724Snikos.nikoleris@arm.com
70112724Snikos.nikoleris@arm.com    /**
70212724Snikos.nikoleris@arm.com     * Maintain the clusivity of this cache by potentially
70312724Snikos.nikoleris@arm.com     * invalidating a block. This method works in conjunction with
70412724Snikos.nikoleris@arm.com     * satisfyRequest, but is separate to allow us to handle all MSHR
70512724Snikos.nikoleris@arm.com     * targets before potentially dropping a block.
70612724Snikos.nikoleris@arm.com     *
70712724Snikos.nikoleris@arm.com     * @param from_cache Whether we have dealt with a packet from a cache
70812724Snikos.nikoleris@arm.com     * @param blk The block that should potentially be dropped
70912724Snikos.nikoleris@arm.com     */
71012724Snikos.nikoleris@arm.com    void maintainClusivity(bool from_cache, CacheBlk *blk);
71112724Snikos.nikoleris@arm.com
71212724Snikos.nikoleris@arm.com    /**
71312724Snikos.nikoleris@arm.com     * Handle a fill operation caused by a received packet.
71412724Snikos.nikoleris@arm.com     *
71512724Snikos.nikoleris@arm.com     * Populates a cache block and handles all outstanding requests for the
71612724Snikos.nikoleris@arm.com     * satisfied fill request. This version takes two memory requests. One
71712724Snikos.nikoleris@arm.com     * contains the fill data, the other is an optional target to satisfy.
71814035Sodanrc@yahoo.com.br     * Note that the reason we return a list of writebacks rather than
71914035Sodanrc@yahoo.com.br     * inserting them directly in the write buffer is that this function
72014035Sodanrc@yahoo.com.br     * is called by both atomic and timing-mode accesses, and in atomic
72114035Sodanrc@yahoo.com.br     * mode we don't mess with the write buffer (we just perform the
72214035Sodanrc@yahoo.com.br     * writebacks atomically once the original request is complete).
72312724Snikos.nikoleris@arm.com     *
72412724Snikos.nikoleris@arm.com     * @param pkt The memory request with the fill data.
72512724Snikos.nikoleris@arm.com     * @param blk The cache block if it already exists.
72614035Sodanrc@yahoo.com.br     * @param writebacks List for any writebacks that need to be performed.
72712724Snikos.nikoleris@arm.com     * @param allocate Whether to allocate a block or use the temp block
72812724Snikos.nikoleris@arm.com     * @return Pointer to the new cache block.
72912724Snikos.nikoleris@arm.com     */
73014035Sodanrc@yahoo.com.br    CacheBlk *handleFill(PacketPtr pkt, CacheBlk *blk,
73114035Sodanrc@yahoo.com.br                         PacketList &writebacks, bool allocate);
73212724Snikos.nikoleris@arm.com
73312724Snikos.nikoleris@arm.com    /**
73414035Sodanrc@yahoo.com.br     * Allocate a new block and perform any necessary writebacks
73514035Sodanrc@yahoo.com.br     *
73614035Sodanrc@yahoo.com.br     * Find a victim block and if necessary prepare writebacks for any
73714035Sodanrc@yahoo.com.br     * existing data. May return nullptr if there are no replaceable
73814035Sodanrc@yahoo.com.br     * blocks. If a replaceable block is found, it inserts the new block in
73914035Sodanrc@yahoo.com.br     * its place. The new block, however, is not set as valid yet.
74012724Snikos.nikoleris@arm.com     *
74112754Sodanrc@yahoo.com.br     * @param pkt Packet holding the address to update
74214035Sodanrc@yahoo.com.br     * @param writebacks A list of writeback packets for the evicted blocks
74312724Snikos.nikoleris@arm.com     * @return the allocated block
74412724Snikos.nikoleris@arm.com     */
74514035Sodanrc@yahoo.com.br    CacheBlk *allocateBlock(const PacketPtr pkt, PacketList &writebacks);
74612724Snikos.nikoleris@arm.com    /**
74712724Snikos.nikoleris@arm.com     * Evict a cache block.
74812724Snikos.nikoleris@arm.com     *
74912724Snikos.nikoleris@arm.com     * Performs a writeback if necesssary and invalidates the block
75012724Snikos.nikoleris@arm.com     *
75112724Snikos.nikoleris@arm.com     * @param blk Block to invalidate
75212724Snikos.nikoleris@arm.com     * @return A packet with the writeback, can be nullptr
75312724Snikos.nikoleris@arm.com     */
75412724Snikos.nikoleris@arm.com    M5_NODISCARD virtual PacketPtr evictBlock(CacheBlk *blk) = 0;
75512724Snikos.nikoleris@arm.com
75612724Snikos.nikoleris@arm.com    /**
75712724Snikos.nikoleris@arm.com     * Evict a cache block.
75812724Snikos.nikoleris@arm.com     *
75912724Snikos.nikoleris@arm.com     * Performs a writeback if necesssary and invalidates the block
76012724Snikos.nikoleris@arm.com     *
76112724Snikos.nikoleris@arm.com     * @param blk Block to invalidate
76214035Sodanrc@yahoo.com.br     * @param writebacks Return a list of packets with writebacks
76312724Snikos.nikoleris@arm.com     */
76414035Sodanrc@yahoo.com.br    void evictBlock(CacheBlk *blk, PacketList &writebacks);
76512724Snikos.nikoleris@arm.com
76612724Snikos.nikoleris@arm.com    /**
76712724Snikos.nikoleris@arm.com     * Invalidate a cache block.
76812724Snikos.nikoleris@arm.com     *
76912724Snikos.nikoleris@arm.com     * @param blk Block to invalidate
77012724Snikos.nikoleris@arm.com     */
77112724Snikos.nikoleris@arm.com    void invalidateBlock(CacheBlk *blk);
77212724Snikos.nikoleris@arm.com
77312724Snikos.nikoleris@arm.com    /**
77412724Snikos.nikoleris@arm.com     * Create a writeback request for the given block.
77512724Snikos.nikoleris@arm.com     *
77612724Snikos.nikoleris@arm.com     * @param blk The block to writeback.
77712724Snikos.nikoleris@arm.com     * @return The writeback request for the block.
77812724Snikos.nikoleris@arm.com     */
77912724Snikos.nikoleris@arm.com    PacketPtr writebackBlk(CacheBlk *blk);
78012724Snikos.nikoleris@arm.com
78112724Snikos.nikoleris@arm.com    /**
78212724Snikos.nikoleris@arm.com     * Create a writeclean request for the given block.
78312724Snikos.nikoleris@arm.com     *
78412724Snikos.nikoleris@arm.com     * Creates a request that writes the block to the cache below
78512724Snikos.nikoleris@arm.com     * without evicting the block from the current cache.
78612724Snikos.nikoleris@arm.com     *
78712724Snikos.nikoleris@arm.com     * @param blk The block to write clean.
78812724Snikos.nikoleris@arm.com     * @param dest The destination of the write clean operation.
78912724Snikos.nikoleris@arm.com     * @param id Use the given packet id for the write clean operation.
79012724Snikos.nikoleris@arm.com     * @return The generated write clean packet.
79112724Snikos.nikoleris@arm.com     */
79212724Snikos.nikoleris@arm.com    PacketPtr writecleanBlk(CacheBlk *blk, Request::Flags dest, PacketId id);
79311197Sandreas.hansson@arm.com
79411197Sandreas.hansson@arm.com    /**
7959347SAndreas.Sandberg@arm.com     * Write back dirty blocks in the cache using functional accesses.
7969347SAndreas.Sandberg@arm.com     */
79712724Snikos.nikoleris@arm.com    virtual void memWriteback() override;
79812724Snikos.nikoleris@arm.com
7999347SAndreas.Sandberg@arm.com    /**
8009347SAndreas.Sandberg@arm.com     * Invalidates all blocks in the cache.
8019347SAndreas.Sandberg@arm.com     *
8029347SAndreas.Sandberg@arm.com     * @warn Dirty cache lines will not be written back to
8039347SAndreas.Sandberg@arm.com     * memory. Make sure to call functionalWriteback() first if you
8049347SAndreas.Sandberg@arm.com     * want the to write them to memory.
8059347SAndreas.Sandberg@arm.com     */
80612724Snikos.nikoleris@arm.com    virtual void memInvalidate() override;
80712724Snikos.nikoleris@arm.com
8089347SAndreas.Sandberg@arm.com    /**
8099347SAndreas.Sandberg@arm.com     * Determine if there are any dirty blocks in the cache.
8109347SAndreas.Sandberg@arm.com     *
81112724Snikos.nikoleris@arm.com     * @return true if at least one block is dirty, false otherwise.
8129347SAndreas.Sandberg@arm.com     */
81312724Snikos.nikoleris@arm.com    bool isDirty() const;
8149347SAndreas.Sandberg@arm.com
81510821Sandreas.hansson@arm.com    /**
81610821Sandreas.hansson@arm.com     * Determine if an address is in the ranges covered by this
81710821Sandreas.hansson@arm.com     * cache. This is useful to filter snoops.
81810821Sandreas.hansson@arm.com     *
81910821Sandreas.hansson@arm.com     * @param addr Address to check against
82010821Sandreas.hansson@arm.com     *
82110821Sandreas.hansson@arm.com     * @return If the address in question is in range
82210821Sandreas.hansson@arm.com     */
82310821Sandreas.hansson@arm.com    bool inRange(Addr addr) const;
82410821Sandreas.hansson@arm.com
82512724Snikos.nikoleris@arm.com    /**
82612724Snikos.nikoleris@arm.com     * Find next request ready time from among possible sources.
82712724Snikos.nikoleris@arm.com     */
82812724Snikos.nikoleris@arm.com    Tick nextQueueReadyTime() const;
82912724Snikos.nikoleris@arm.com
8304626SN/A    /** Block size of this cache */
8316227Snate@binkert.org    const unsigned blkSize;
8324626SN/A
8334630SN/A    /**
83410693SMarco.Balboni@ARM.com     * The latency of tag lookup of a cache. It occurs when there is
83510693SMarco.Balboni@ARM.com     * an access to the cache.
8364630SN/A     */
83710693SMarco.Balboni@ARM.com    const Cycles lookupLatency;
8389263Smrinmoy.ghosh@arm.com
8399263Smrinmoy.ghosh@arm.com    /**
84011722Ssophiane.senni@gmail.com     * The latency of data access of a cache. It occurs when there is
84111722Ssophiane.senni@gmail.com     * an access to the cache.
84211722Ssophiane.senni@gmail.com     */
84311722Ssophiane.senni@gmail.com    const Cycles dataLatency;
84411722Ssophiane.senni@gmail.com
84511722Ssophiane.senni@gmail.com    /**
84610693SMarco.Balboni@ARM.com     * This is the forward latency of the cache. It occurs when there
84710693SMarco.Balboni@ARM.com     * is a cache miss and a request is forwarded downstream, in
84810693SMarco.Balboni@ARM.com     * particular an outbound miss.
84910693SMarco.Balboni@ARM.com     */
85010693SMarco.Balboni@ARM.com    const Cycles forwardLatency;
85110693SMarco.Balboni@ARM.com
85210693SMarco.Balboni@ARM.com    /** The latency to fill a cache block */
85310693SMarco.Balboni@ARM.com    const Cycles fillLatency;
85410693SMarco.Balboni@ARM.com
85510693SMarco.Balboni@ARM.com    /**
85610693SMarco.Balboni@ARM.com     * The latency of sending reponse to its upper level cache/core on
85710693SMarco.Balboni@ARM.com     * a linefill. The responseLatency parameter captures this
85810693SMarco.Balboni@ARM.com     * latency.
8599263Smrinmoy.ghosh@arm.com     */
8609288Sandreas.hansson@arm.com    const Cycles responseLatency;
8614630SN/A
86213418Sodanrc@yahoo.com.br    /**
86313418Sodanrc@yahoo.com.br     * Whether tags and data are accessed sequentially.
86413418Sodanrc@yahoo.com.br     */
86513418Sodanrc@yahoo.com.br    const bool sequentialAccess;
86613418Sodanrc@yahoo.com.br
8674626SN/A    /** The number of targets for each MSHR. */
8684626SN/A    const int numTarget;
8694626SN/A
8706122SSteve.Reinhardt@amd.com    /** Do we forward snoops from mem side port through to cpu side port? */
87111331Sandreas.hansson@arm.com    bool forwardSnoops;
8724626SN/A
8732810SN/A    /**
87412724Snikos.nikoleris@arm.com     * Clusivity with respect to the upstream cache, determining if we
87512724Snikos.nikoleris@arm.com     * fill into both this cache and the cache above on a miss. Note
87612724Snikos.nikoleris@arm.com     * that we currently do not support strict clusivity policies.
87712724Snikos.nikoleris@arm.com     */
87812724Snikos.nikoleris@arm.com    const Enums::Clusivity clusivity;
87912724Snikos.nikoleris@arm.com
88012724Snikos.nikoleris@arm.com    /**
88110884Sandreas.hansson@arm.com     * Is this cache read only, for example the instruction cache, or
88210884Sandreas.hansson@arm.com     * table-walker cache. A cache that is read only should never see
88310884Sandreas.hansson@arm.com     * any writes, and should never get any dirty data (and hence
88410884Sandreas.hansson@arm.com     * never have to do any writebacks).
88510884Sandreas.hansson@arm.com     */
88610884Sandreas.hansson@arm.com    const bool isReadOnly;
88710884Sandreas.hansson@arm.com
88810884Sandreas.hansson@arm.com    /**
8892810SN/A     * Bit vector of the blocking reasons for the access path.
8902810SN/A     * @sa #BlockedCause
8912810SN/A     */
8922810SN/A    uint8_t blocked;
8932810SN/A
8946122SSteve.Reinhardt@amd.com    /** Increasing order number assigned to each incoming request. */
8956122SSteve.Reinhardt@amd.com    uint64_t order;
8966122SSteve.Reinhardt@amd.com
8972810SN/A    /** Stores time the cache blocked for statistics. */
8989288Sandreas.hansson@arm.com    Cycles blockedCycle;
8992810SN/A
9004626SN/A    /** Pointer to the MSHR that has no targets. */
9014626SN/A    MSHR *noTargetMSHR;
9022810SN/A
9032810SN/A    /** The number of misses to trigger an exit event. */
9042810SN/A    Counter missCount;
9052810SN/A
9066122SSteve.Reinhardt@amd.com    /**
9076122SSteve.Reinhardt@amd.com     * The address range to which the cache responds on the CPU side.
9086122SSteve.Reinhardt@amd.com     * Normally this is all possible memory addresses. */
9099529Sandreas.hansson@arm.com    const AddrRangeList addrRanges;
9106122SSteve.Reinhardt@amd.com
9118833Sdam.sunwoo@arm.com  public:
9128833Sdam.sunwoo@arm.com    /** System we are currently operating in. */
9138833Sdam.sunwoo@arm.com    System *system;
9146978SLisa.Hsu@amd.com
9152810SN/A    // Statistics
9162810SN/A    /**
9172810SN/A     * @addtogroup CacheStatistics
9182810SN/A     * @{
9192810SN/A     */
9202810SN/A
92111483Snikos.nikoleris@arm.com    /** Number of hits per thread for each type of command.
92211483Snikos.nikoleris@arm.com        @sa Packet::Command */
9235999Snate@binkert.org    Stats::Vector hits[MemCmd::NUM_MEM_CMDS];
9242810SN/A    /** Number of hits for demand accesses. */
9252810SN/A    Stats::Formula demandHits;
9262810SN/A    /** Number of hit for all accesses. */
9272810SN/A    Stats::Formula overallHits;
9282810SN/A
92911483Snikos.nikoleris@arm.com    /** Number of misses per thread for each type of command.
93011483Snikos.nikoleris@arm.com        @sa Packet::Command */
9315999Snate@binkert.org    Stats::Vector misses[MemCmd::NUM_MEM_CMDS];
9322810SN/A    /** Number of misses for demand accesses. */
9332810SN/A    Stats::Formula demandMisses;
9342810SN/A    /** Number of misses for all accesses. */
9352810SN/A    Stats::Formula overallMisses;
9362810SN/A
9372810SN/A    /**
9382810SN/A     * Total number of cycles per thread/command spent waiting for a miss.
9392810SN/A     * Used to calculate the average miss latency.
9402810SN/A     */
9415999Snate@binkert.org    Stats::Vector missLatency[MemCmd::NUM_MEM_CMDS];
9422810SN/A    /** Total number of cycles spent waiting for demand misses. */
9432810SN/A    Stats::Formula demandMissLatency;
9442810SN/A    /** Total number of cycles spent waiting for all misses. */
9452810SN/A    Stats::Formula overallMissLatency;
9462810SN/A
9472810SN/A    /** The number of accesses per command and thread. */
9484022SN/A    Stats::Formula accesses[MemCmd::NUM_MEM_CMDS];
9492810SN/A    /** The number of demand accesses. */
9502810SN/A    Stats::Formula demandAccesses;
9512810SN/A    /** The number of overall accesses. */
9522810SN/A    Stats::Formula overallAccesses;
9532810SN/A
9542810SN/A    /** The miss rate per command and thread. */
9554022SN/A    Stats::Formula missRate[MemCmd::NUM_MEM_CMDS];
9562810SN/A    /** The miss rate of all demand accesses. */
9572810SN/A    Stats::Formula demandMissRate;
9582810SN/A    /** The miss rate for all accesses. */
9592810SN/A    Stats::Formula overallMissRate;
9602810SN/A
9612810SN/A    /** The average miss latency per command and thread. */
9624022SN/A    Stats::Formula avgMissLatency[MemCmd::NUM_MEM_CMDS];
9632810SN/A    /** The average miss latency for demand misses. */
9642810SN/A    Stats::Formula demandAvgMissLatency;
9652810SN/A    /** The average miss latency for all misses. */
9662810SN/A    Stats::Formula overallAvgMissLatency;
9672810SN/A
9682810SN/A    /** The total number of cycles blocked for each blocked cause. */
9695999Snate@binkert.org    Stats::Vector blocked_cycles;
9702810SN/A    /** The number of times this cache blocked for each blocked cause. */
9715999Snate@binkert.org    Stats::Vector blocked_causes;
9722810SN/A
9732810SN/A    /** The average number of cycles blocked for each blocked cause. */
9742810SN/A    Stats::Formula avg_blocked;
9752810SN/A
97611436SRekai.GonzalezAlberquilla@arm.com    /** The number of times a HW-prefetched block is evicted w/o reference. */
97711436SRekai.GonzalezAlberquilla@arm.com    Stats::Scalar unusedPrefetches;
97811436SRekai.GonzalezAlberquilla@arm.com
9794626SN/A    /** Number of blocks written back per thread. */
9805999Snate@binkert.org    Stats::Vector writebacks;
9814626SN/A
9824626SN/A    /** Number of misses that hit in the MSHRs per command and thread. */
9835999Snate@binkert.org    Stats::Vector mshr_hits[MemCmd::NUM_MEM_CMDS];
9844626SN/A    /** Demand misses that hit in the MSHRs. */
9854626SN/A    Stats::Formula demandMshrHits;
9864626SN/A    /** Total number of misses that hit in the MSHRs. */
9874626SN/A    Stats::Formula overallMshrHits;
9884626SN/A
9894626SN/A    /** Number of misses that miss in the MSHRs, per command and thread. */
9905999Snate@binkert.org    Stats::Vector mshr_misses[MemCmd::NUM_MEM_CMDS];
9914626SN/A    /** Demand misses that miss in the MSHRs. */
9924626SN/A    Stats::Formula demandMshrMisses;
9934626SN/A    /** Total number of misses that miss in the MSHRs. */
9944626SN/A    Stats::Formula overallMshrMisses;
9954626SN/A
9964626SN/A    /** Number of misses that miss in the MSHRs, per command and thread. */
9975999Snate@binkert.org    Stats::Vector mshr_uncacheable[MemCmd::NUM_MEM_CMDS];
9984626SN/A    /** Total number of misses that miss in the MSHRs. */
9994626SN/A    Stats::Formula overallMshrUncacheable;
10004626SN/A
10014626SN/A    /** Total cycle latency of each MSHR miss, per command and thread. */
10025999Snate@binkert.org    Stats::Vector mshr_miss_latency[MemCmd::NUM_MEM_CMDS];
10034626SN/A    /** Total cycle latency of demand MSHR misses. */
10044626SN/A    Stats::Formula demandMshrMissLatency;
10054626SN/A    /** Total cycle latency of overall MSHR misses. */
10064626SN/A    Stats::Formula overallMshrMissLatency;
10074626SN/A
10084626SN/A    /** Total cycle latency of each MSHR miss, per command and thread. */
10095999Snate@binkert.org    Stats::Vector mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS];
10104626SN/A    /** Total cycle latency of overall MSHR misses. */
10114626SN/A    Stats::Formula overallMshrUncacheableLatency;
10124626SN/A
10134626SN/A    /** The miss rate in the MSHRs pre command and thread. */
10144626SN/A    Stats::Formula mshrMissRate[MemCmd::NUM_MEM_CMDS];
10154626SN/A    /** The demand miss rate in the MSHRs. */
10164626SN/A    Stats::Formula demandMshrMissRate;
10174626SN/A    /** The overall miss rate in the MSHRs. */
10184626SN/A    Stats::Formula overallMshrMissRate;
10194626SN/A
10204626SN/A    /** The average latency of an MSHR miss, per command and thread. */
10214626SN/A    Stats::Formula avgMshrMissLatency[MemCmd::NUM_MEM_CMDS];
10224626SN/A    /** The average latency of a demand MSHR miss. */
10234626SN/A    Stats::Formula demandAvgMshrMissLatency;
10244626SN/A    /** The average overall latency of an MSHR miss. */
10254626SN/A    Stats::Formula overallAvgMshrMissLatency;
10264626SN/A
10274626SN/A    /** The average latency of an MSHR miss, per command and thread. */
10284626SN/A    Stats::Formula avgMshrUncacheableLatency[MemCmd::NUM_MEM_CMDS];
10294626SN/A    /** The average overall latency of an MSHR miss. */
10304626SN/A    Stats::Formula overallAvgMshrUncacheableLatency;
10314626SN/A
103212702Snikos.nikoleris@arm.com    /** Number of replacements of valid blocks. */
103312702Snikos.nikoleris@arm.com    Stats::Scalar replacements;
103412702Snikos.nikoleris@arm.com
103513947Sodanrc@yahoo.com.br    /** Number of data expansions. */
103613947Sodanrc@yahoo.com.br    Stats::Scalar dataExpansions;
103713947Sodanrc@yahoo.com.br
10382810SN/A    /**
10392810SN/A     * @}
10402810SN/A     */
10412810SN/A
10422810SN/A    /**
10432810SN/A     * Register stats for this object.
10442810SN/A     */
104512724Snikos.nikoleris@arm.com    void regStats() override;
10462810SN/A
104713416Sjavier.bueno@metempsy.com    /** Registers probes. */
104813416Sjavier.bueno@metempsy.com    void regProbePoints() override;
104913416Sjavier.bueno@metempsy.com
10502810SN/A  public:
105111053Sandreas.hansson@arm.com    BaseCache(const BaseCacheParams *p, unsigned blk_size);
105212724Snikos.nikoleris@arm.com    ~BaseCache();
10533606SN/A
105412724Snikos.nikoleris@arm.com    void init() override;
10552858SN/A
105613784Sgabeblack@google.com    Port &getPort(const std::string &if_name,
105713784Sgabeblack@google.com                  PortID idx=InvalidPortID) override;
10588922Swilliam.wang@arm.com
10592810SN/A    /**
10602810SN/A     * Query block size of a cache.
10612810SN/A     * @return  The block size
10622810SN/A     */
10636227Snate@binkert.org    unsigned
10646227Snate@binkert.org    getBlockSize() const
10652810SN/A    {
10662810SN/A        return blkSize;
10672810SN/A    }
10682810SN/A
10698883SAli.Saidi@ARM.com    const AddrRangeList &getAddrRanges() const { return addrRanges; }
10706122SSteve.Reinhardt@amd.com
107110942Sandreas.hansson@arm.com    MSHR *allocateMissBuffer(PacketPtr pkt, Tick time, bool sched_send = true)
10724628SN/A    {
107311892Snikos.nikoleris@arm.com        MSHR *mshr = mshrQueue.allocate(pkt->getBlockAddr(blkSize), blkSize,
107411375Sandreas.hansson@arm.com                                        pkt, time, order++,
107511375Sandreas.hansson@arm.com                                        allocOnFill(pkt->cmd));
107611375Sandreas.hansson@arm.com
107711375Sandreas.hansson@arm.com        if (mshrQueue.isFull()) {
107811375Sandreas.hansson@arm.com            setBlocked((BlockedCause)MSHRQueue_MSHRs);
107911375Sandreas.hansson@arm.com        }
108011375Sandreas.hansson@arm.com
108111375Sandreas.hansson@arm.com        if (sched_send) {
108211375Sandreas.hansson@arm.com            // schedule the send
108311375Sandreas.hansson@arm.com            schedMemSideSendEvent(time);
108411375Sandreas.hansson@arm.com        }
108511375Sandreas.hansson@arm.com
108611375Sandreas.hansson@arm.com        return mshr;
10874628SN/A    }
10884628SN/A
108911375Sandreas.hansson@arm.com    void allocateWriteBuffer(PacketPtr pkt, Tick time)
10904628SN/A    {
109111191Sandreas.hansson@arm.com        // should only see writes or clean evicts here
109211191Sandreas.hansson@arm.com        assert(pkt->isWrite() || pkt->cmd == MemCmd::CleanEvict);
109311191Sandreas.hansson@arm.com
109411892Snikos.nikoleris@arm.com        Addr blk_addr = pkt->getBlockAddr(blkSize);
109511375Sandreas.hansson@arm.com
109613945Sodanrc@yahoo.com.br        // If using compression, on evictions the block is decompressed and
109713945Sodanrc@yahoo.com.br        // the operation's latency is added to the payload delay. Consume
109813945Sodanrc@yahoo.com.br        // that payload delay here, meaning that the data is always stored
109913945Sodanrc@yahoo.com.br        // uncompressed in the writebuffer
110013945Sodanrc@yahoo.com.br        if (compressor) {
110113945Sodanrc@yahoo.com.br            time += pkt->payloadDelay;
110213945Sodanrc@yahoo.com.br            pkt->payloadDelay = 0;
110313945Sodanrc@yahoo.com.br        }
110413945Sodanrc@yahoo.com.br
110511375Sandreas.hansson@arm.com        WriteQueueEntry *wq_entry =
110611375Sandreas.hansson@arm.com            writeBuffer.findMatch(blk_addr, pkt->isSecure());
110711375Sandreas.hansson@arm.com        if (wq_entry && !wq_entry->inService) {
110811744Snikos.nikoleris@arm.com            DPRINTF(Cache, "Potential to merge writeback %s", pkt->print());
110911375Sandreas.hansson@arm.com        }
111011375Sandreas.hansson@arm.com
111111375Sandreas.hansson@arm.com        writeBuffer.allocate(blk_addr, blkSize, pkt, time, order++);
111211375Sandreas.hansson@arm.com
111311375Sandreas.hansson@arm.com        if (writeBuffer.isFull()) {
111411375Sandreas.hansson@arm.com            setBlocked((BlockedCause)MSHRQueue_WriteBuffer);
111511375Sandreas.hansson@arm.com        }
111611375Sandreas.hansson@arm.com
111711375Sandreas.hansson@arm.com        // schedule the send
111811375Sandreas.hansson@arm.com        schedMemSideSendEvent(time);
11194628SN/A    }
11204628SN/A
11212810SN/A    /**
11222810SN/A     * Returns true if the cache is blocked for accesses.
11232810SN/A     */
11249529Sandreas.hansson@arm.com    bool isBlocked() const
11252810SN/A    {
11262810SN/A        return blocked != 0;
11272810SN/A    }
11282810SN/A
11292810SN/A    /**
11302810SN/A     * Marks the access path of the cache as blocked for the given cause. This
11312810SN/A     * also sets the blocked flag in the slave interface.
11322810SN/A     * @param cause The reason for the cache blocking.
11332810SN/A     */
11342810SN/A    void setBlocked(BlockedCause cause)
11352810SN/A    {
11362810SN/A        uint8_t flag = 1 << cause;
11372810SN/A        if (blocked == 0) {
11382810SN/A            blocked_causes[cause]++;
11399288Sandreas.hansson@arm.com            blockedCycle = curCycle();
114012724Snikos.nikoleris@arm.com            cpuSidePort.setBlocked();
11412810SN/A        }
11424630SN/A        blocked |= flag;
11434630SN/A        DPRINTF(Cache,"Blocking for cause %d, mask=%d\n", cause, blocked);
11442810SN/A    }
11452810SN/A
11462810SN/A    /**
11472810SN/A     * Marks the cache as unblocked for the given cause. This also clears the
11482810SN/A     * blocked flags in the appropriate interfaces.
11492810SN/A     * @param cause The newly unblocked cause.
11502810SN/A     * @warning Calling this function can cause a blocked request on the bus to
11512810SN/A     * access the cache. The cache must be in a state to handle that request.
11522810SN/A     */
11532810SN/A    void clearBlocked(BlockedCause cause)
11542810SN/A    {
11552810SN/A        uint8_t flag = 1 << cause;
11564630SN/A        blocked &= ~flag;
11574630SN/A        DPRINTF(Cache,"Unblocking for cause %d, mask=%d\n", cause, blocked);
11584630SN/A        if (blocked == 0) {
11599288Sandreas.hansson@arm.com            blocked_cycles[cause] += curCycle() - blockedCycle;
116012724Snikos.nikoleris@arm.com            cpuSidePort.clearBlocked();
11612810SN/A        }
11622810SN/A    }
11632810SN/A
11642810SN/A    /**
116510942Sandreas.hansson@arm.com     * Schedule a send event for the memory-side port. If already
116610942Sandreas.hansson@arm.com     * scheduled, this may reschedule the event at an earlier
116710942Sandreas.hansson@arm.com     * time. When the specified time is reached, the port is free to
116810942Sandreas.hansson@arm.com     * send either a response, a request, or a prefetch request.
116910942Sandreas.hansson@arm.com     *
117010942Sandreas.hansson@arm.com     * @param time The time when to attempt sending a packet.
11712810SN/A     */
117210942Sandreas.hansson@arm.com    void schedMemSideSendEvent(Tick time)
11732810SN/A    {
117412724Snikos.nikoleris@arm.com        memSidePort.schedSendEvent(time);
11752811SN/A    }
11763503SN/A
117712724Snikos.nikoleris@arm.com    bool inCache(Addr addr, bool is_secure) const {
117812724Snikos.nikoleris@arm.com        return tags->findBlock(addr, is_secure);
117912724Snikos.nikoleris@arm.com    }
11804626SN/A
118113624Sjavier.bueno@metempsy.com    bool hasBeenPrefetched(Addr addr, bool is_secure) const {
118213624Sjavier.bueno@metempsy.com        CacheBlk *block = tags->findBlock(addr, is_secure);
118313624Sjavier.bueno@metempsy.com        if (block) {
118413624Sjavier.bueno@metempsy.com            return block->wasPrefetched();
118513624Sjavier.bueno@metempsy.com        } else {
118613624Sjavier.bueno@metempsy.com            return false;
118713624Sjavier.bueno@metempsy.com        }
118813624Sjavier.bueno@metempsy.com    }
118913624Sjavier.bueno@metempsy.com
119012724Snikos.nikoleris@arm.com    bool inMissQueue(Addr addr, bool is_secure) const {
119112724Snikos.nikoleris@arm.com        return mshrQueue.findMatch(addr, is_secure);
119212724Snikos.nikoleris@arm.com    }
11934626SN/A
11948833Sdam.sunwoo@arm.com    void incMissCount(PacketPtr pkt)
11953503SN/A    {
11968833Sdam.sunwoo@arm.com        assert(pkt->req->masterId() < system->maxMasters());
11978833Sdam.sunwoo@arm.com        misses[pkt->cmdToIndex()][pkt->req->masterId()]++;
119810020Smatt.horsnell@ARM.com        pkt->req->incAccessDepth();
11994626SN/A        if (missCount) {
12004626SN/A            --missCount;
12014626SN/A            if (missCount == 0)
12024626SN/A                exitSimLoop("A cache reached the maximum miss count");
12033503SN/A        }
12043503SN/A    }
12058833Sdam.sunwoo@arm.com    void incHitCount(PacketPtr pkt)
12066978SLisa.Hsu@amd.com    {
12078833Sdam.sunwoo@arm.com        assert(pkt->req->masterId() < system->maxMasters());
12088833Sdam.sunwoo@arm.com        hits[pkt->cmdToIndex()][pkt->req->masterId()]++;
12096978SLisa.Hsu@amd.com
12106978SLisa.Hsu@amd.com    }
12113503SN/A
121212724Snikos.nikoleris@arm.com    /**
121313416Sjavier.bueno@metempsy.com     * Checks if the cache is coalescing writes
121413416Sjavier.bueno@metempsy.com     *
121513416Sjavier.bueno@metempsy.com     * @return True if the cache is coalescing writes
121613416Sjavier.bueno@metempsy.com     */
121713416Sjavier.bueno@metempsy.com    bool coalesce() const;
121813416Sjavier.bueno@metempsy.com
121913416Sjavier.bueno@metempsy.com
122013416Sjavier.bueno@metempsy.com    /**
122112724Snikos.nikoleris@arm.com     * Cache block visitor that writes back dirty cache blocks using
122212724Snikos.nikoleris@arm.com     * functional writes.
122312724Snikos.nikoleris@arm.com     */
122412728Snikos.nikoleris@arm.com    void writebackVisitor(CacheBlk &blk);
122512724Snikos.nikoleris@arm.com
122612724Snikos.nikoleris@arm.com    /**
122712724Snikos.nikoleris@arm.com     * Cache block visitor that invalidates all blocks in the cache.
122812724Snikos.nikoleris@arm.com     *
122912724Snikos.nikoleris@arm.com     * @warn Dirty cache lines will not be written back to memory.
123012724Snikos.nikoleris@arm.com     */
123112728Snikos.nikoleris@arm.com    void invalidateVisitor(CacheBlk &blk);
123212724Snikos.nikoleris@arm.com
123312724Snikos.nikoleris@arm.com    /**
123412724Snikos.nikoleris@arm.com     * Take an MSHR, turn it into a suitable downstream packet, and
123512724Snikos.nikoleris@arm.com     * send it out. This construct allows a queue entry to choose a suitable
123612724Snikos.nikoleris@arm.com     * approach based on its type.
123712724Snikos.nikoleris@arm.com     *
123812724Snikos.nikoleris@arm.com     * @param mshr The MSHR to turn into a packet and send
123912724Snikos.nikoleris@arm.com     * @return True if the port is waiting for a retry
124012724Snikos.nikoleris@arm.com     */
124112724Snikos.nikoleris@arm.com    virtual bool sendMSHRQueuePacket(MSHR* mshr);
124212724Snikos.nikoleris@arm.com
124312724Snikos.nikoleris@arm.com    /**
124412724Snikos.nikoleris@arm.com     * Similar to sendMSHR, but for a write-queue entry
124512724Snikos.nikoleris@arm.com     * instead. Create the packet, and send it, and if successful also
124612724Snikos.nikoleris@arm.com     * mark the entry in service.
124712724Snikos.nikoleris@arm.com     *
124812724Snikos.nikoleris@arm.com     * @param wq_entry The write-queue entry to turn into a packet and send
124912724Snikos.nikoleris@arm.com     * @return True if the port is waiting for a retry
125012724Snikos.nikoleris@arm.com     */
125112724Snikos.nikoleris@arm.com    bool sendWriteQueuePacket(WriteQueueEntry* wq_entry);
125212724Snikos.nikoleris@arm.com
125312724Snikos.nikoleris@arm.com    /**
125412724Snikos.nikoleris@arm.com     * Serialize the state of the caches
125512724Snikos.nikoleris@arm.com     *
125612724Snikos.nikoleris@arm.com     * We currently don't support checkpointing cache state, so this panics.
125712724Snikos.nikoleris@arm.com     */
125812724Snikos.nikoleris@arm.com    void serialize(CheckpointOut &cp) const override;
125912724Snikos.nikoleris@arm.com    void unserialize(CheckpointIn &cp) override;
126012724Snikos.nikoleris@arm.com};
126112724Snikos.nikoleris@arm.com
126213352Snikos.nikoleris@arm.com/**
126313352Snikos.nikoleris@arm.com * The write allocator inspects write packets and detects streaming
126413352Snikos.nikoleris@arm.com * patterns. The write allocator supports a single stream where writes
126513352Snikos.nikoleris@arm.com * are expected to access consecutive locations and keeps track of
126613352Snikos.nikoleris@arm.com * size of the area covered by the concecutive writes in byteCount.
126713352Snikos.nikoleris@arm.com *
126813352Snikos.nikoleris@arm.com * 1) When byteCount has surpassed the coallesceLimit the mode
126913352Snikos.nikoleris@arm.com * switches from ALLOCATE to COALESCE where writes should be delayed
127013352Snikos.nikoleris@arm.com * until the whole block is written at which point a single packet
127113352Snikos.nikoleris@arm.com * (whole line write) can service them.
127213352Snikos.nikoleris@arm.com *
127313352Snikos.nikoleris@arm.com * 2) When byteCount has also exceeded the noAllocateLimit (whole
127413352Snikos.nikoleris@arm.com * line) we switch to NO_ALLOCATE when writes should not allocate in
127513352Snikos.nikoleris@arm.com * the cache but rather send a whole line write to the memory below.
127613352Snikos.nikoleris@arm.com */
127713352Snikos.nikoleris@arm.comclass WriteAllocator : public SimObject {
127813352Snikos.nikoleris@arm.com  public:
127913352Snikos.nikoleris@arm.com    WriteAllocator(const WriteAllocatorParams *p) :
128013352Snikos.nikoleris@arm.com        SimObject(p),
128113352Snikos.nikoleris@arm.com        coalesceLimit(p->coalesce_limit * p->block_size),
128213352Snikos.nikoleris@arm.com        noAllocateLimit(p->no_allocate_limit * p->block_size),
128313352Snikos.nikoleris@arm.com        delayThreshold(p->delay_threshold)
128413352Snikos.nikoleris@arm.com    {
128513352Snikos.nikoleris@arm.com        reset();
128613352Snikos.nikoleris@arm.com    }
128713352Snikos.nikoleris@arm.com
128813352Snikos.nikoleris@arm.com    /**
128913352Snikos.nikoleris@arm.com     * Should writes be coalesced? This is true if the mode is set to
129013352Snikos.nikoleris@arm.com     * NO_ALLOCATE.
129113352Snikos.nikoleris@arm.com     *
129213352Snikos.nikoleris@arm.com     * @return return true if the cache should coalesce writes.
129313352Snikos.nikoleris@arm.com     */
129413352Snikos.nikoleris@arm.com    bool coalesce() const {
129513352Snikos.nikoleris@arm.com        return mode != WriteMode::ALLOCATE;
129613352Snikos.nikoleris@arm.com    }
129713352Snikos.nikoleris@arm.com
129813352Snikos.nikoleris@arm.com    /**
129913352Snikos.nikoleris@arm.com     * Should writes allocate?
130013352Snikos.nikoleris@arm.com     *
130113352Snikos.nikoleris@arm.com     * @return return true if the cache should not allocate for writes.
130213352Snikos.nikoleris@arm.com     */
130313352Snikos.nikoleris@arm.com    bool allocate() const {
130413352Snikos.nikoleris@arm.com        return mode != WriteMode::NO_ALLOCATE;
130513352Snikos.nikoleris@arm.com    }
130613352Snikos.nikoleris@arm.com
130713352Snikos.nikoleris@arm.com    /**
130813352Snikos.nikoleris@arm.com     * Reset the write allocator state, meaning that it allocates for
130913352Snikos.nikoleris@arm.com     * writes and has not recorded any information about qualifying
131013352Snikos.nikoleris@arm.com     * writes that might trigger a switch to coalescing and later no
131113352Snikos.nikoleris@arm.com     * allocation.
131213352Snikos.nikoleris@arm.com     */
131313352Snikos.nikoleris@arm.com    void reset() {
131413352Snikos.nikoleris@arm.com        mode = WriteMode::ALLOCATE;
131513352Snikos.nikoleris@arm.com        byteCount = 0;
131613352Snikos.nikoleris@arm.com        nextAddr = 0;
131713352Snikos.nikoleris@arm.com    }
131813352Snikos.nikoleris@arm.com
131913352Snikos.nikoleris@arm.com    /**
132013352Snikos.nikoleris@arm.com     * Access whether we need to delay the current write.
132113352Snikos.nikoleris@arm.com     *
132213352Snikos.nikoleris@arm.com     * @param blk_addr The block address the packet writes to
132313352Snikos.nikoleris@arm.com     * @return true if the current packet should be delayed
132413352Snikos.nikoleris@arm.com     */
132513352Snikos.nikoleris@arm.com    bool delay(Addr blk_addr) {
132613352Snikos.nikoleris@arm.com        if (delayCtr[blk_addr] > 0) {
132713352Snikos.nikoleris@arm.com            --delayCtr[blk_addr];
132813352Snikos.nikoleris@arm.com            return true;
132913352Snikos.nikoleris@arm.com        } else {
133013352Snikos.nikoleris@arm.com            return false;
133113352Snikos.nikoleris@arm.com        }
133213352Snikos.nikoleris@arm.com    }
133313352Snikos.nikoleris@arm.com
133413352Snikos.nikoleris@arm.com    /**
133513352Snikos.nikoleris@arm.com     * Clear delay counter for the input block
133613352Snikos.nikoleris@arm.com     *
133713352Snikos.nikoleris@arm.com     * @param blk_addr The accessed cache block
133813352Snikos.nikoleris@arm.com     */
133913352Snikos.nikoleris@arm.com    void resetDelay(Addr blk_addr) {
134013352Snikos.nikoleris@arm.com        delayCtr.erase(blk_addr);
134113352Snikos.nikoleris@arm.com    }
134213352Snikos.nikoleris@arm.com
134313352Snikos.nikoleris@arm.com    /**
134413352Snikos.nikoleris@arm.com     * Update the write mode based on the current write
134513352Snikos.nikoleris@arm.com     * packet. This method compares the packet's address with any
134613352Snikos.nikoleris@arm.com     * current stream, and updates the tracking and the mode
134713352Snikos.nikoleris@arm.com     * accordingly.
134813352Snikos.nikoleris@arm.com     *
134913352Snikos.nikoleris@arm.com     * @param write_addr Start address of the write request
135013352Snikos.nikoleris@arm.com     * @param write_size Size of the write request
135113352Snikos.nikoleris@arm.com     * @param blk_addr The block address that this packet writes to
135213352Snikos.nikoleris@arm.com     */
135313352Snikos.nikoleris@arm.com    void updateMode(Addr write_addr, unsigned write_size, Addr blk_addr);
135413352Snikos.nikoleris@arm.com
135513352Snikos.nikoleris@arm.com  private:
135613352Snikos.nikoleris@arm.com    /**
135713352Snikos.nikoleris@arm.com     * The current mode for write coalescing and allocation, either
135813352Snikos.nikoleris@arm.com     * normal operation (ALLOCATE), write coalescing (COALESCE), or
135913352Snikos.nikoleris@arm.com     * write coalescing without allocation (NO_ALLOCATE).
136013352Snikos.nikoleris@arm.com     */
136113352Snikos.nikoleris@arm.com    enum class WriteMode : char {
136213352Snikos.nikoleris@arm.com        ALLOCATE,
136313352Snikos.nikoleris@arm.com        COALESCE,
136413352Snikos.nikoleris@arm.com        NO_ALLOCATE,
136513352Snikos.nikoleris@arm.com    };
136613352Snikos.nikoleris@arm.com    WriteMode mode;
136713352Snikos.nikoleris@arm.com
136813352Snikos.nikoleris@arm.com    /** Address to match writes against to detect streams. */
136913352Snikos.nikoleris@arm.com    Addr nextAddr;
137013352Snikos.nikoleris@arm.com
137113352Snikos.nikoleris@arm.com    /**
137213352Snikos.nikoleris@arm.com     * Bytes written contiguously. Saturating once we no longer
137313352Snikos.nikoleris@arm.com     * allocate.
137413352Snikos.nikoleris@arm.com     */
137513352Snikos.nikoleris@arm.com    uint32_t byteCount;
137613352Snikos.nikoleris@arm.com
137713352Snikos.nikoleris@arm.com    /**
137813352Snikos.nikoleris@arm.com     * Limits for when to switch between the different write modes.
137913352Snikos.nikoleris@arm.com     */
138013352Snikos.nikoleris@arm.com    const uint32_t coalesceLimit;
138113352Snikos.nikoleris@arm.com    const uint32_t noAllocateLimit;
138213352Snikos.nikoleris@arm.com    /**
138313352Snikos.nikoleris@arm.com     * The number of times the allocator will delay an WriteReq MSHR.
138413352Snikos.nikoleris@arm.com     */
138513352Snikos.nikoleris@arm.com    const uint32_t delayThreshold;
138613352Snikos.nikoleris@arm.com
138713352Snikos.nikoleris@arm.com    /**
138813352Snikos.nikoleris@arm.com     * Keep track of the number of times the allocator has delayed an
138913352Snikos.nikoleris@arm.com     * WriteReq MSHR.
139013352Snikos.nikoleris@arm.com     */
139113352Snikos.nikoleris@arm.com    std::unordered_map<Addr, Counter> delayCtr;
139213352Snikos.nikoleris@arm.com};
139313352Snikos.nikoleris@arm.com
139411051Sandreas.hansson@arm.com#endif //__MEM_CACHE_BASE_HH__
1395