base.hh revision 12724
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"
6612724Snikos.nikoleris@arm.com#include "mem/cache/blk.hh"
675338Sstever@gmail.com#include "mem/cache/mshr_queue.hh"
6812724Snikos.nikoleris@arm.com#include "mem/cache/tags/base.hh"
6911375Sandreas.hansson@arm.com#include "mem/cache/write_queue.hh"
7012724Snikos.nikoleris@arm.com#include "mem/cache/write_queue_entry.hh"
712810SN/A#include "mem/mem_object.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"
762811SN/A#include "sim/eventq.hh"
7712724Snikos.nikoleris@arm.com#include "sim/serialize.hh"
784626SN/A#include "sim/sim_exit.hh"
798833Sdam.sunwoo@arm.com#include "sim/system.hh"
802810SN/A
8112724Snikos.nikoleris@arm.comclass BaseMasterPort;
8212724Snikos.nikoleris@arm.comclass BasePrefetcher;
8312724Snikos.nikoleris@arm.comclass BaseSlavePort;
8412724Snikos.nikoleris@arm.comclass MSHR;
8512724Snikos.nikoleris@arm.comclass MasterPort;
8612724Snikos.nikoleris@arm.comclass QueueEntry;
8712724Snikos.nikoleris@arm.comstruct BaseCacheParams;
8812724Snikos.nikoleris@arm.com
892810SN/A/**
902810SN/A * A basic cache interface. Implements some common functions for speed.
912810SN/A */
922810SN/Aclass BaseCache : public MemObject
932810SN/A{
9411375Sandreas.hansson@arm.com  protected:
954628SN/A    /**
964628SN/A     * Indexes to enumerate the MSHR queues.
974628SN/A     */
984628SN/A    enum MSHRQueueIndex {
994628SN/A        MSHRQueue_MSHRs,
1004628SN/A        MSHRQueue_WriteBuffer
1014628SN/A    };
1024628SN/A
1038737Skoansin.tan@gmail.com  public:
1044628SN/A    /**
1054628SN/A     * Reasons for caches to be blocked.
1064628SN/A     */
1074628SN/A    enum BlockedCause {
1084628SN/A        Blocked_NoMSHRs = MSHRQueue_MSHRs,
1094628SN/A        Blocked_NoWBBuffers = MSHRQueue_WriteBuffer,
1104628SN/A        Blocked_NoTargets,
1114628SN/A        NUM_BLOCKED_CAUSES
1124628SN/A    };
1134628SN/A
1148737Skoansin.tan@gmail.com  protected:
1154628SN/A
1168856Sandreas.hansson@arm.com    /**
1178856Sandreas.hansson@arm.com     * A cache master port is used for the memory-side port of the
1188856Sandreas.hansson@arm.com     * cache, and in addition to the basic timing port that only sends
1198856Sandreas.hansson@arm.com     * response packets through a transmit list, it also offers the
1208856Sandreas.hansson@arm.com     * ability to schedule and send request packets (requests &
12110942Sandreas.hansson@arm.com     * writebacks). The send event is scheduled through schedSendEvent,
1228856Sandreas.hansson@arm.com     * and the sendDeferredPacket of the timing port is modified to
1238856Sandreas.hansson@arm.com     * consider both the transmit list and the requests from the MSHR.
1248856Sandreas.hansson@arm.com     */
1258922Swilliam.wang@arm.com    class CacheMasterPort : public QueuedMasterPort
1262810SN/A    {
1278856Sandreas.hansson@arm.com
1282844SN/A      public:
1298856Sandreas.hansson@arm.com
1308856Sandreas.hansson@arm.com        /**
1318856Sandreas.hansson@arm.com         * Schedule a send of a request packet (from the MSHR). Note
13210713Sandreas.hansson@arm.com         * that we could already have a retry outstanding.
1338856Sandreas.hansson@arm.com         */
13410942Sandreas.hansson@arm.com        void schedSendEvent(Tick time)
1358856Sandreas.hansson@arm.com        {
13610942Sandreas.hansson@arm.com            DPRINTF(CachePort, "Scheduling send event at %llu\n", time);
13710713Sandreas.hansson@arm.com            reqQueue.schedSendEvent(time);
1388856Sandreas.hansson@arm.com        }
1398856Sandreas.hansson@arm.com
1403738SN/A      protected:
1414458SN/A
1428856Sandreas.hansson@arm.com        CacheMasterPort(const std::string &_name, BaseCache *_cache,
14310713Sandreas.hansson@arm.com                        ReqPacketQueue &_reqQueue,
14410713Sandreas.hansson@arm.com                        SnoopRespPacketQueue &_snoopRespQueue) :
14510713Sandreas.hansson@arm.com            QueuedMasterPort(_name, _cache, _reqQueue, _snoopRespQueue)
1468914Sandreas.hansson@arm.com        { }
1472810SN/A
1488856Sandreas.hansson@arm.com        /**
1498856Sandreas.hansson@arm.com         * Memory-side port always snoops.
1508856Sandreas.hansson@arm.com         *
1518914Sandreas.hansson@arm.com         * @return always true
1528856Sandreas.hansson@arm.com         */
1538922Swilliam.wang@arm.com        virtual bool isSnooping() const { return true; }
1548856Sandreas.hansson@arm.com    };
1553013SN/A
1568856Sandreas.hansson@arm.com    /**
15712724Snikos.nikoleris@arm.com     * Override the default behaviour of sendDeferredPacket to enable
15812724Snikos.nikoleris@arm.com     * the memory-side cache port to also send requests based on the
15912724Snikos.nikoleris@arm.com     * current MSHR status. This queue has a pointer to our specific
16012724Snikos.nikoleris@arm.com     * cache implementation and is used by the MemSidePort.
16112724Snikos.nikoleris@arm.com     */
16212724Snikos.nikoleris@arm.com    class CacheReqPacketQueue : public ReqPacketQueue
16312724Snikos.nikoleris@arm.com    {
16412724Snikos.nikoleris@arm.com
16512724Snikos.nikoleris@arm.com      protected:
16612724Snikos.nikoleris@arm.com
16712724Snikos.nikoleris@arm.com        BaseCache &cache;
16812724Snikos.nikoleris@arm.com        SnoopRespPacketQueue &snoopRespQueue;
16912724Snikos.nikoleris@arm.com
17012724Snikos.nikoleris@arm.com      public:
17112724Snikos.nikoleris@arm.com
17212724Snikos.nikoleris@arm.com        CacheReqPacketQueue(BaseCache &cache, MasterPort &port,
17312724Snikos.nikoleris@arm.com                            SnoopRespPacketQueue &snoop_resp_queue,
17412724Snikos.nikoleris@arm.com                            const std::string &label) :
17512724Snikos.nikoleris@arm.com            ReqPacketQueue(cache, port, label), cache(cache),
17612724Snikos.nikoleris@arm.com            snoopRespQueue(snoop_resp_queue) { }
17712724Snikos.nikoleris@arm.com
17812724Snikos.nikoleris@arm.com        /**
17912724Snikos.nikoleris@arm.com         * Override the normal sendDeferredPacket and do not only
18012724Snikos.nikoleris@arm.com         * consider the transmit list (used for responses), but also
18112724Snikos.nikoleris@arm.com         * requests.
18212724Snikos.nikoleris@arm.com         */
18312724Snikos.nikoleris@arm.com        virtual void sendDeferredPacket();
18412724Snikos.nikoleris@arm.com
18512724Snikos.nikoleris@arm.com        /**
18612724Snikos.nikoleris@arm.com         * Check if there is a conflicting snoop response about to be
18712724Snikos.nikoleris@arm.com         * send out, and if so simply stall any requests, and schedule
18812724Snikos.nikoleris@arm.com         * a send event at the same time as the next snoop response is
18912724Snikos.nikoleris@arm.com         * being sent out.
19012724Snikos.nikoleris@arm.com         */
19112724Snikos.nikoleris@arm.com        bool checkConflictingSnoop(Addr addr)
19212724Snikos.nikoleris@arm.com        {
19312724Snikos.nikoleris@arm.com            if (snoopRespQueue.hasAddr(addr)) {
19412724Snikos.nikoleris@arm.com                DPRINTF(CachePort, "Waiting for snoop response to be "
19512724Snikos.nikoleris@arm.com                        "sent\n");
19612724Snikos.nikoleris@arm.com                Tick when = snoopRespQueue.deferredPacketReadyTime();
19712724Snikos.nikoleris@arm.com                schedSendEvent(when);
19812724Snikos.nikoleris@arm.com                return true;
19912724Snikos.nikoleris@arm.com            }
20012724Snikos.nikoleris@arm.com            return false;
20112724Snikos.nikoleris@arm.com        }
20212724Snikos.nikoleris@arm.com    };
20312724Snikos.nikoleris@arm.com
20412724Snikos.nikoleris@arm.com
20512724Snikos.nikoleris@arm.com    /**
20612724Snikos.nikoleris@arm.com     * The memory-side port extends the base cache master port with
20712724Snikos.nikoleris@arm.com     * access functions for functional, atomic and timing snoops.
20812724Snikos.nikoleris@arm.com     */
20912724Snikos.nikoleris@arm.com    class MemSidePort : public CacheMasterPort
21012724Snikos.nikoleris@arm.com    {
21112724Snikos.nikoleris@arm.com      private:
21212724Snikos.nikoleris@arm.com
21312724Snikos.nikoleris@arm.com        /** The cache-specific queue. */
21412724Snikos.nikoleris@arm.com        CacheReqPacketQueue _reqQueue;
21512724Snikos.nikoleris@arm.com
21612724Snikos.nikoleris@arm.com        SnoopRespPacketQueue _snoopRespQueue;
21712724Snikos.nikoleris@arm.com
21812724Snikos.nikoleris@arm.com        // a pointer to our specific cache implementation
21912724Snikos.nikoleris@arm.com        BaseCache *cache;
22012724Snikos.nikoleris@arm.com
22112724Snikos.nikoleris@arm.com      protected:
22212724Snikos.nikoleris@arm.com
22312724Snikos.nikoleris@arm.com        virtual void recvTimingSnoopReq(PacketPtr pkt);
22412724Snikos.nikoleris@arm.com
22512724Snikos.nikoleris@arm.com        virtual bool recvTimingResp(PacketPtr pkt);
22612724Snikos.nikoleris@arm.com
22712724Snikos.nikoleris@arm.com        virtual Tick recvAtomicSnoop(PacketPtr pkt);
22812724Snikos.nikoleris@arm.com
22912724Snikos.nikoleris@arm.com        virtual void recvFunctionalSnoop(PacketPtr pkt);
23012724Snikos.nikoleris@arm.com
23112724Snikos.nikoleris@arm.com      public:
23212724Snikos.nikoleris@arm.com
23312724Snikos.nikoleris@arm.com        MemSidePort(const std::string &_name, BaseCache *_cache,
23412724Snikos.nikoleris@arm.com                    const std::string &_label);
23512724Snikos.nikoleris@arm.com    };
23612724Snikos.nikoleris@arm.com
23712724Snikos.nikoleris@arm.com    /**
2388856Sandreas.hansson@arm.com     * A cache slave port is used for the CPU-side port of the cache,
2398856Sandreas.hansson@arm.com     * and it is basically a simple timing port that uses a transmit
2408856Sandreas.hansson@arm.com     * list for responses to the CPU (or connected master). In
2418856Sandreas.hansson@arm.com     * addition, it has the functionality to block the port for
2428856Sandreas.hansson@arm.com     * incoming requests. If blocked, the port will issue a retry once
2438856Sandreas.hansson@arm.com     * unblocked.
2448856Sandreas.hansson@arm.com     */
2458922Swilliam.wang@arm.com    class CacheSlavePort : public QueuedSlavePort
2468856Sandreas.hansson@arm.com    {
2475314SN/A
2482811SN/A      public:
2498856Sandreas.hansson@arm.com
2508856Sandreas.hansson@arm.com        /** Do not accept any new requests. */
2512810SN/A        void setBlocked();
2522810SN/A
2538856Sandreas.hansson@arm.com        /** Return to normal operation and accept new requests. */
2542810SN/A        void clearBlocked();
2552810SN/A
25610345SCurtis.Dunham@arm.com        bool isBlocked() const { return blocked; }
25710345SCurtis.Dunham@arm.com
2588856Sandreas.hansson@arm.com      protected:
2598856Sandreas.hansson@arm.com
2608856Sandreas.hansson@arm.com        CacheSlavePort(const std::string &_name, BaseCache *_cache,
2618856Sandreas.hansson@arm.com                       const std::string &_label);
2623606SN/A
2638914Sandreas.hansson@arm.com        /** A normal packet queue used to store responses. */
26410713Sandreas.hansson@arm.com        RespPacketQueue queue;
2658914Sandreas.hansson@arm.com
2662810SN/A        bool blocked;
2672810SN/A
2682897SN/A        bool mustSendRetry;
2692897SN/A
2708856Sandreas.hansson@arm.com      private:
2714458SN/A
27210344Sandreas.hansson@arm.com        void processSendRetry();
27310344Sandreas.hansson@arm.com
27412084Sspwilson2@wisc.edu        EventFunctionWrapper sendRetryEvent;
2758856Sandreas.hansson@arm.com
2762811SN/A    };
2772810SN/A
27812724Snikos.nikoleris@arm.com    /**
27912724Snikos.nikoleris@arm.com     * The CPU-side port extends the base cache slave port with access
28012724Snikos.nikoleris@arm.com     * functions for functional, atomic and timing requests.
28112724Snikos.nikoleris@arm.com     */
28212724Snikos.nikoleris@arm.com    class CpuSidePort : public CacheSlavePort
28312724Snikos.nikoleris@arm.com    {
28412724Snikos.nikoleris@arm.com      private:
28512724Snikos.nikoleris@arm.com
28612724Snikos.nikoleris@arm.com        // a pointer to our specific cache implementation
28712724Snikos.nikoleris@arm.com        BaseCache *cache;
28812724Snikos.nikoleris@arm.com
28912724Snikos.nikoleris@arm.com      protected:
29012724Snikos.nikoleris@arm.com        virtual bool recvTimingSnoopResp(PacketPtr pkt) override;
29112724Snikos.nikoleris@arm.com
29212724Snikos.nikoleris@arm.com        virtual bool tryTiming(PacketPtr pkt) override;
29312724Snikos.nikoleris@arm.com
29412724Snikos.nikoleris@arm.com        virtual bool recvTimingReq(PacketPtr pkt) override;
29512724Snikos.nikoleris@arm.com
29612724Snikos.nikoleris@arm.com        virtual Tick recvAtomic(PacketPtr pkt) override;
29712724Snikos.nikoleris@arm.com
29812724Snikos.nikoleris@arm.com        virtual void recvFunctional(PacketPtr pkt) override;
29912724Snikos.nikoleris@arm.com
30012724Snikos.nikoleris@arm.com        virtual AddrRangeList getAddrRanges() const override;
30112724Snikos.nikoleris@arm.com
30212724Snikos.nikoleris@arm.com      public:
30312724Snikos.nikoleris@arm.com
30412724Snikos.nikoleris@arm.com        CpuSidePort(const std::string &_name, BaseCache *_cache,
30512724Snikos.nikoleris@arm.com                    const std::string &_label);
30612724Snikos.nikoleris@arm.com
30712724Snikos.nikoleris@arm.com    };
30812724Snikos.nikoleris@arm.com
30912724Snikos.nikoleris@arm.com    CpuSidePort cpuSidePort;
31012724Snikos.nikoleris@arm.com    MemSidePort memSidePort;
3113338SN/A
3124626SN/A  protected:
3134626SN/A
3144626SN/A    /** Miss status registers */
3154626SN/A    MSHRQueue mshrQueue;
3164626SN/A
3174626SN/A    /** Write/writeback buffer */
31811375Sandreas.hansson@arm.com    WriteQueue writeBuffer;
3194626SN/A
32012724Snikos.nikoleris@arm.com    /** Tag and data Storage */
32112724Snikos.nikoleris@arm.com    BaseTags *tags;
32212724Snikos.nikoleris@arm.com
32312724Snikos.nikoleris@arm.com    /** Prefetcher */
32412724Snikos.nikoleris@arm.com    BasePrefetcher *prefetcher;
32512724Snikos.nikoleris@arm.com
32612724Snikos.nikoleris@arm.com    /**
32712724Snikos.nikoleris@arm.com     * Notify the prefetcher on every access, not just misses.
32812724Snikos.nikoleris@arm.com     */
32912724Snikos.nikoleris@arm.com    const bool prefetchOnAccess;
33012724Snikos.nikoleris@arm.com
33112724Snikos.nikoleris@arm.com    /**
33212724Snikos.nikoleris@arm.com     * Temporary cache block for occasional transitory use.  We use
33312724Snikos.nikoleris@arm.com     * the tempBlock to fill when allocation fails (e.g., when there
33412724Snikos.nikoleris@arm.com     * is an outstanding request that accesses the victim block) or
33512724Snikos.nikoleris@arm.com     * when we want to avoid allocation (e.g., exclusive caches)
33612724Snikos.nikoleris@arm.com     */
33712724Snikos.nikoleris@arm.com    CacheBlk *tempBlock;
33812724Snikos.nikoleris@arm.com
33912724Snikos.nikoleris@arm.com    /**
34012724Snikos.nikoleris@arm.com     * Upstream caches need this packet until true is returned, so
34112724Snikos.nikoleris@arm.com     * hold it for deletion until a subsequent call
34212724Snikos.nikoleris@arm.com     */
34312724Snikos.nikoleris@arm.com    std::unique_ptr<Packet> pendingDelete;
34412724Snikos.nikoleris@arm.com
34510693SMarco.Balboni@ARM.com    /**
34611375Sandreas.hansson@arm.com     * Mark a request as in service (sent downstream in the memory
34711375Sandreas.hansson@arm.com     * system), effectively making this MSHR the ordering point.
34810693SMarco.Balboni@ARM.com     */
34911375Sandreas.hansson@arm.com    void markInService(MSHR *mshr, bool pending_modified_resp)
3504628SN/A    {
35111375Sandreas.hansson@arm.com        bool wasFull = mshrQueue.isFull();
35211375Sandreas.hansson@arm.com        mshrQueue.markInService(mshr, pending_modified_resp);
35310764Sandreas.hansson@arm.com
35411375Sandreas.hansson@arm.com        if (wasFull && !mshrQueue.isFull()) {
35511375Sandreas.hansson@arm.com            clearBlocked(Blocked_NoMSHRs);
3564628SN/A        }
3574628SN/A    }
3584628SN/A
35911375Sandreas.hansson@arm.com    void markInService(WriteQueueEntry *entry)
3604628SN/A    {
36111375Sandreas.hansson@arm.com        bool wasFull = writeBuffer.isFull();
36211375Sandreas.hansson@arm.com        writeBuffer.markInService(entry);
36311375Sandreas.hansson@arm.com
36411375Sandreas.hansson@arm.com        if (wasFull && !writeBuffer.isFull()) {
36511375Sandreas.hansson@arm.com            clearBlocked(Blocked_NoWBBuffers);
3664628SN/A        }
3674628SN/A    }
3684628SN/A
3699347SAndreas.Sandberg@arm.com    /**
37012724Snikos.nikoleris@arm.com     * Determine whether we should allocate on a fill or not. If this
37112724Snikos.nikoleris@arm.com     * cache is mostly inclusive with regards to the upstream cache(s)
37212724Snikos.nikoleris@arm.com     * we always allocate (for any non-forwarded and cacheable
37312724Snikos.nikoleris@arm.com     * requests). In the case of a mostly exclusive cache, we allocate
37412724Snikos.nikoleris@arm.com     * on fill if the packet did not come from a cache, thus if we:
37512724Snikos.nikoleris@arm.com     * are dealing with a whole-line write (the latter behaves much
37612724Snikos.nikoleris@arm.com     * like a writeback), the original target packet came from a
37712724Snikos.nikoleris@arm.com     * non-caching source, or if we are performing a prefetch or LLSC.
37811197Sandreas.hansson@arm.com     *
37912724Snikos.nikoleris@arm.com     * @param cmd Command of the incoming requesting packet
38012724Snikos.nikoleris@arm.com     * @return Whether we should allocate on the fill
38112724Snikos.nikoleris@arm.com     */
38212724Snikos.nikoleris@arm.com    inline bool allocOnFill(MemCmd cmd) const
38312724Snikos.nikoleris@arm.com    {
38412724Snikos.nikoleris@arm.com        return clusivity == Enums::mostly_incl ||
38512724Snikos.nikoleris@arm.com            cmd == MemCmd::WriteLineReq ||
38612724Snikos.nikoleris@arm.com            cmd == MemCmd::ReadReq ||
38712724Snikos.nikoleris@arm.com            cmd == MemCmd::WriteReq ||
38812724Snikos.nikoleris@arm.com            cmd.isPrefetch() ||
38912724Snikos.nikoleris@arm.com            cmd.isLLSC();
39012724Snikos.nikoleris@arm.com    }
39112724Snikos.nikoleris@arm.com
39212724Snikos.nikoleris@arm.com    /**
39312724Snikos.nikoleris@arm.com     * Does all the processing necessary to perform the provided request.
39412724Snikos.nikoleris@arm.com     * @param pkt The memory request to perform.
39512724Snikos.nikoleris@arm.com     * @param blk The cache block to be updated.
39612724Snikos.nikoleris@arm.com     * @param lat The latency of the access.
39712724Snikos.nikoleris@arm.com     * @param writebacks List for any writebacks that need to be performed.
39812724Snikos.nikoleris@arm.com     * @return Boolean indicating whether the request was satisfied.
39912724Snikos.nikoleris@arm.com     */
40012724Snikos.nikoleris@arm.com    virtual bool access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat,
40112724Snikos.nikoleris@arm.com                        PacketList &writebacks);
40212724Snikos.nikoleris@arm.com
40312724Snikos.nikoleris@arm.com    /*
40412724Snikos.nikoleris@arm.com     * Handle a timing request that hit in the cache
40511197Sandreas.hansson@arm.com     *
40612724Snikos.nikoleris@arm.com     * @param ptk The request packet
40712724Snikos.nikoleris@arm.com     * @param blk The referenced block
40812724Snikos.nikoleris@arm.com     * @param request_time The tick at which the block lookup is compete
40911197Sandreas.hansson@arm.com     */
41012724Snikos.nikoleris@arm.com    virtual void handleTimingReqHit(PacketPtr pkt, CacheBlk *blk,
41112724Snikos.nikoleris@arm.com                                    Tick request_time);
41212724Snikos.nikoleris@arm.com
41312724Snikos.nikoleris@arm.com    /*
41412724Snikos.nikoleris@arm.com     * Handle a timing request that missed in the cache
41512724Snikos.nikoleris@arm.com     *
41612724Snikos.nikoleris@arm.com     * Implementation specific handling for different cache
41712724Snikos.nikoleris@arm.com     * implementations
41812724Snikos.nikoleris@arm.com     *
41912724Snikos.nikoleris@arm.com     * @param ptk The request packet
42012724Snikos.nikoleris@arm.com     * @param blk The referenced block
42112724Snikos.nikoleris@arm.com     * @param forward_time The tick at which we can process dependent requests
42212724Snikos.nikoleris@arm.com     * @param request_time The tick at which the block lookup is compete
42312724Snikos.nikoleris@arm.com     */
42412724Snikos.nikoleris@arm.com    virtual void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk,
42512724Snikos.nikoleris@arm.com                                     Tick forward_time,
42612724Snikos.nikoleris@arm.com                                     Tick request_time) = 0;
42712724Snikos.nikoleris@arm.com
42812724Snikos.nikoleris@arm.com    /*
42912724Snikos.nikoleris@arm.com     * Handle a timing request that missed in the cache
43012724Snikos.nikoleris@arm.com     *
43112724Snikos.nikoleris@arm.com     * Common functionality across different cache implementations
43212724Snikos.nikoleris@arm.com     *
43312724Snikos.nikoleris@arm.com     * @param ptk The request packet
43412724Snikos.nikoleris@arm.com     * @param blk The referenced block
43512724Snikos.nikoleris@arm.com     * @param mshr Any existing mshr for the referenced cache block
43612724Snikos.nikoleris@arm.com     * @param forward_time The tick at which we can process dependent requests
43712724Snikos.nikoleris@arm.com     * @param request_time The tick at which the block lookup is compete
43812724Snikos.nikoleris@arm.com     */
43912724Snikos.nikoleris@arm.com    void handleTimingReqMiss(PacketPtr pkt, MSHR *mshr, CacheBlk *blk,
44012724Snikos.nikoleris@arm.com                             Tick forward_time, Tick request_time);
44112724Snikos.nikoleris@arm.com
44212724Snikos.nikoleris@arm.com    /**
44312724Snikos.nikoleris@arm.com     * Performs the access specified by the request.
44412724Snikos.nikoleris@arm.com     * @param pkt The request to perform.
44512724Snikos.nikoleris@arm.com     */
44612724Snikos.nikoleris@arm.com    virtual void recvTimingReq(PacketPtr pkt);
44712724Snikos.nikoleris@arm.com
44812724Snikos.nikoleris@arm.com    /**
44912724Snikos.nikoleris@arm.com     * Handling the special case of uncacheable write responses to
45012724Snikos.nikoleris@arm.com     * make recvTimingResp less cluttered.
45112724Snikos.nikoleris@arm.com     */
45212724Snikos.nikoleris@arm.com    void handleUncacheableWriteResp(PacketPtr pkt);
45312724Snikos.nikoleris@arm.com
45412724Snikos.nikoleris@arm.com    /**
45512724Snikos.nikoleris@arm.com     * Service non-deferred MSHR targets using the received response
45612724Snikos.nikoleris@arm.com     *
45712724Snikos.nikoleris@arm.com     * Iterates through the list of targets that can be serviced with
45812724Snikos.nikoleris@arm.com     * the current response. Any writebacks that need to performed
45912724Snikos.nikoleris@arm.com     * must be appended to the writebacks parameter.
46012724Snikos.nikoleris@arm.com     *
46112724Snikos.nikoleris@arm.com     * @param mshr The MSHR that corresponds to the reponse
46212724Snikos.nikoleris@arm.com     * @param pkt The response packet
46312724Snikos.nikoleris@arm.com     * @param blk The reference block
46412724Snikos.nikoleris@arm.com     * @param writebacks List of writebacks that need to be performed
46512724Snikos.nikoleris@arm.com     */
46612724Snikos.nikoleris@arm.com    virtual void serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt,
46712724Snikos.nikoleris@arm.com                                    CacheBlk *blk, PacketList& writebacks) = 0;
46812724Snikos.nikoleris@arm.com
46912724Snikos.nikoleris@arm.com    /**
47012724Snikos.nikoleris@arm.com     * Handles a response (cache line fill/write ack) from the bus.
47112724Snikos.nikoleris@arm.com     * @param pkt The response packet
47212724Snikos.nikoleris@arm.com     */
47312724Snikos.nikoleris@arm.com    virtual void recvTimingResp(PacketPtr pkt);
47412724Snikos.nikoleris@arm.com
47512724Snikos.nikoleris@arm.com    /**
47612724Snikos.nikoleris@arm.com     * Snoops bus transactions to maintain coherence.
47712724Snikos.nikoleris@arm.com     * @param pkt The current bus transaction.
47812724Snikos.nikoleris@arm.com     */
47912724Snikos.nikoleris@arm.com    virtual void recvTimingSnoopReq(PacketPtr pkt) = 0;
48012724Snikos.nikoleris@arm.com
48112724Snikos.nikoleris@arm.com    /**
48212724Snikos.nikoleris@arm.com     * Handle a snoop response.
48312724Snikos.nikoleris@arm.com     * @param pkt Snoop response packet
48412724Snikos.nikoleris@arm.com     */
48512724Snikos.nikoleris@arm.com    virtual void recvTimingSnoopResp(PacketPtr pkt) = 0;
48612724Snikos.nikoleris@arm.com
48712724Snikos.nikoleris@arm.com    /**
48812724Snikos.nikoleris@arm.com     * Handle a request in atomic mode that missed in this cache
48912724Snikos.nikoleris@arm.com     *
49012724Snikos.nikoleris@arm.com     * Creates a downstream request, sends it to the memory below and
49112724Snikos.nikoleris@arm.com     * handles the response. As we are in atomic mode all operations
49212724Snikos.nikoleris@arm.com     * are performed immediately.
49312724Snikos.nikoleris@arm.com     *
49412724Snikos.nikoleris@arm.com     * @param pkt The packet with the requests
49512724Snikos.nikoleris@arm.com     * @param blk The referenced block
49612724Snikos.nikoleris@arm.com     * @param writebacks A list with packets for any performed writebacks
49712724Snikos.nikoleris@arm.com     * @return Cycles for handling the request
49812724Snikos.nikoleris@arm.com     */
49912724Snikos.nikoleris@arm.com    virtual Cycles handleAtomicReqMiss(PacketPtr pkt, CacheBlk *blk,
50012724Snikos.nikoleris@arm.com                                       PacketList &writebacks) = 0;
50112724Snikos.nikoleris@arm.com
50212724Snikos.nikoleris@arm.com    /**
50312724Snikos.nikoleris@arm.com     * Performs the access specified by the request.
50412724Snikos.nikoleris@arm.com     * @param pkt The request to perform.
50512724Snikos.nikoleris@arm.com     * @return The number of ticks required for the access.
50612724Snikos.nikoleris@arm.com     */
50712724Snikos.nikoleris@arm.com    virtual Tick recvAtomic(PacketPtr pkt);
50812724Snikos.nikoleris@arm.com
50912724Snikos.nikoleris@arm.com    /**
51012724Snikos.nikoleris@arm.com     * Snoop for the provided request in the cache and return the estimated
51112724Snikos.nikoleris@arm.com     * time taken.
51212724Snikos.nikoleris@arm.com     * @param pkt The memory request to snoop
51312724Snikos.nikoleris@arm.com     * @return The number of ticks required for the snoop.
51412724Snikos.nikoleris@arm.com     */
51512724Snikos.nikoleris@arm.com    virtual Tick recvAtomicSnoop(PacketPtr pkt) = 0;
51612724Snikos.nikoleris@arm.com
51712724Snikos.nikoleris@arm.com    /**
51812724Snikos.nikoleris@arm.com     * Performs the access specified by the request.
51912724Snikos.nikoleris@arm.com     *
52012724Snikos.nikoleris@arm.com     * @param pkt The request to perform.
52112724Snikos.nikoleris@arm.com     * @param fromCpuSide from the CPU side port or the memory side port
52212724Snikos.nikoleris@arm.com     */
52312724Snikos.nikoleris@arm.com    virtual void functionalAccess(PacketPtr pkt, bool from_cpu_side);
52412724Snikos.nikoleris@arm.com
52512724Snikos.nikoleris@arm.com    /**
52612724Snikos.nikoleris@arm.com     * Handle doing the Compare and Swap function for SPARC.
52712724Snikos.nikoleris@arm.com     */
52812724Snikos.nikoleris@arm.com    void cmpAndSwap(CacheBlk *blk, PacketPtr pkt);
52912724Snikos.nikoleris@arm.com
53012724Snikos.nikoleris@arm.com    /**
53112724Snikos.nikoleris@arm.com     * Return the next queue entry to service, either a pending miss
53212724Snikos.nikoleris@arm.com     * from the MSHR queue, a buffered write from the write buffer, or
53312724Snikos.nikoleris@arm.com     * something from the prefetcher. This function is responsible
53412724Snikos.nikoleris@arm.com     * for prioritizing among those sources on the fly.
53512724Snikos.nikoleris@arm.com     */
53612724Snikos.nikoleris@arm.com    QueueEntry* getNextQueueEntry();
53712724Snikos.nikoleris@arm.com
53812724Snikos.nikoleris@arm.com    /**
53912724Snikos.nikoleris@arm.com     * Insert writebacks into the write buffer
54012724Snikos.nikoleris@arm.com     */
54112724Snikos.nikoleris@arm.com    virtual void doWritebacks(PacketList& writebacks, Tick forward_time) = 0;
54212724Snikos.nikoleris@arm.com
54312724Snikos.nikoleris@arm.com    /**
54412724Snikos.nikoleris@arm.com     * Send writebacks down the memory hierarchy in atomic mode
54512724Snikos.nikoleris@arm.com     */
54612724Snikos.nikoleris@arm.com    virtual void doWritebacksAtomic(PacketList& writebacks) = 0;
54712724Snikos.nikoleris@arm.com
54812724Snikos.nikoleris@arm.com    /**
54912724Snikos.nikoleris@arm.com     * Create an appropriate downstream bus request packet.
55012724Snikos.nikoleris@arm.com     *
55112724Snikos.nikoleris@arm.com     * Creates a new packet with the request to be send to the memory
55212724Snikos.nikoleris@arm.com     * below, or nullptr if the current request in cpu_pkt should just
55312724Snikos.nikoleris@arm.com     * be forwarded on.
55412724Snikos.nikoleris@arm.com     *
55512724Snikos.nikoleris@arm.com     * @param cpu_pkt The miss packet that needs to be satisfied.
55612724Snikos.nikoleris@arm.com     * @param blk The referenced block, can be nullptr.
55712724Snikos.nikoleris@arm.com     * @param needs_writable Indicates that the block must be writable
55812724Snikos.nikoleris@arm.com     * even if the request in cpu_pkt doesn't indicate that.
55912724Snikos.nikoleris@arm.com     * @return A packet send to the memory below
56012724Snikos.nikoleris@arm.com     */
56112724Snikos.nikoleris@arm.com    virtual PacketPtr createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk,
56212724Snikos.nikoleris@arm.com                                       bool needs_writable) const = 0;
56312724Snikos.nikoleris@arm.com
56412724Snikos.nikoleris@arm.com    /**
56512724Snikos.nikoleris@arm.com     * Determine if clean lines should be written back or not. In
56612724Snikos.nikoleris@arm.com     * cases where a downstream cache is mostly inclusive we likely
56712724Snikos.nikoleris@arm.com     * want it to act as a victim cache also for lines that have not
56812724Snikos.nikoleris@arm.com     * been modified. Hence, we cannot simply drop the line (or send a
56912724Snikos.nikoleris@arm.com     * clean evict), but rather need to send the actual data.
57012724Snikos.nikoleris@arm.com     */
57112724Snikos.nikoleris@arm.com    const bool writebackClean;
57212724Snikos.nikoleris@arm.com
57312724Snikos.nikoleris@arm.com    /**
57412724Snikos.nikoleris@arm.com     * Writebacks from the tempBlock, resulting on the response path
57512724Snikos.nikoleris@arm.com     * in atomic mode, must happen after the call to recvAtomic has
57612724Snikos.nikoleris@arm.com     * finished (for the right ordering of the packets). We therefore
57712724Snikos.nikoleris@arm.com     * need to hold on to the packets, and have a method and an event
57812724Snikos.nikoleris@arm.com     * to send them.
57912724Snikos.nikoleris@arm.com     */
58012724Snikos.nikoleris@arm.com    PacketPtr tempBlockWriteback;
58112724Snikos.nikoleris@arm.com
58212724Snikos.nikoleris@arm.com    /**
58312724Snikos.nikoleris@arm.com     * Send the outstanding tempBlock writeback. To be called after
58412724Snikos.nikoleris@arm.com     * recvAtomic finishes in cases where the block we filled is in
58512724Snikos.nikoleris@arm.com     * fact the tempBlock, and now needs to be written back.
58612724Snikos.nikoleris@arm.com     */
58712724Snikos.nikoleris@arm.com    void writebackTempBlockAtomic() {
58812724Snikos.nikoleris@arm.com        assert(tempBlockWriteback != nullptr);
58912724Snikos.nikoleris@arm.com        PacketList writebacks{tempBlockWriteback};
59012724Snikos.nikoleris@arm.com        doWritebacksAtomic(writebacks);
59112724Snikos.nikoleris@arm.com        tempBlockWriteback = nullptr;
59212724Snikos.nikoleris@arm.com    }
59312724Snikos.nikoleris@arm.com
59412724Snikos.nikoleris@arm.com    /**
59512724Snikos.nikoleris@arm.com     * An event to writeback the tempBlock after recvAtomic
59612724Snikos.nikoleris@arm.com     * finishes. To avoid other calls to recvAtomic getting in
59712724Snikos.nikoleris@arm.com     * between, we create this event with a higher priority.
59812724Snikos.nikoleris@arm.com     */
59912724Snikos.nikoleris@arm.com    EventFunctionWrapper writebackTempBlockAtomicEvent;
60012724Snikos.nikoleris@arm.com
60112724Snikos.nikoleris@arm.com    /**
60212724Snikos.nikoleris@arm.com     * Perform any necessary updates to the block and perform any data
60312724Snikos.nikoleris@arm.com     * exchange between the packet and the block. The flags of the
60412724Snikos.nikoleris@arm.com     * packet are also set accordingly.
60512724Snikos.nikoleris@arm.com     *
60612724Snikos.nikoleris@arm.com     * @param pkt Request packet from upstream that hit a block
60712724Snikos.nikoleris@arm.com     * @param blk Cache block that the packet hit
60812724Snikos.nikoleris@arm.com     * @param deferred_response Whether this request originally missed
60912724Snikos.nikoleris@arm.com     * @param pending_downgrade Whether the writable flag is to be removed
61012724Snikos.nikoleris@arm.com     */
61112724Snikos.nikoleris@arm.com    virtual void satisfyRequest(PacketPtr pkt, CacheBlk *blk,
61212724Snikos.nikoleris@arm.com                                bool deferred_response = false,
61312724Snikos.nikoleris@arm.com                                bool pending_downgrade = false);
61412724Snikos.nikoleris@arm.com
61512724Snikos.nikoleris@arm.com    /**
61612724Snikos.nikoleris@arm.com     * Maintain the clusivity of this cache by potentially
61712724Snikos.nikoleris@arm.com     * invalidating a block. This method works in conjunction with
61812724Snikos.nikoleris@arm.com     * satisfyRequest, but is separate to allow us to handle all MSHR
61912724Snikos.nikoleris@arm.com     * targets before potentially dropping a block.
62012724Snikos.nikoleris@arm.com     *
62112724Snikos.nikoleris@arm.com     * @param from_cache Whether we have dealt with a packet from a cache
62212724Snikos.nikoleris@arm.com     * @param blk The block that should potentially be dropped
62312724Snikos.nikoleris@arm.com     */
62412724Snikos.nikoleris@arm.com    void maintainClusivity(bool from_cache, CacheBlk *blk);
62512724Snikos.nikoleris@arm.com
62612724Snikos.nikoleris@arm.com    /**
62712724Snikos.nikoleris@arm.com     * Handle a fill operation caused by a received packet.
62812724Snikos.nikoleris@arm.com     *
62912724Snikos.nikoleris@arm.com     * Populates a cache block and handles all outstanding requests for the
63012724Snikos.nikoleris@arm.com     * satisfied fill request. This version takes two memory requests. One
63112724Snikos.nikoleris@arm.com     * contains the fill data, the other is an optional target to satisfy.
63212724Snikos.nikoleris@arm.com     * Note that the reason we return a list of writebacks rather than
63312724Snikos.nikoleris@arm.com     * inserting them directly in the write buffer is that this function
63412724Snikos.nikoleris@arm.com     * is called by both atomic and timing-mode accesses, and in atomic
63512724Snikos.nikoleris@arm.com     * mode we don't mess with the write buffer (we just perform the
63612724Snikos.nikoleris@arm.com     * writebacks atomically once the original request is complete).
63712724Snikos.nikoleris@arm.com     *
63812724Snikos.nikoleris@arm.com     * @param pkt The memory request with the fill data.
63912724Snikos.nikoleris@arm.com     * @param blk The cache block if it already exists.
64012724Snikos.nikoleris@arm.com     * @param writebacks List for any writebacks that need to be performed.
64112724Snikos.nikoleris@arm.com     * @param allocate Whether to allocate a block or use the temp block
64212724Snikos.nikoleris@arm.com     * @return Pointer to the new cache block.
64312724Snikos.nikoleris@arm.com     */
64412724Snikos.nikoleris@arm.com    CacheBlk *handleFill(PacketPtr pkt, CacheBlk *blk,
64512724Snikos.nikoleris@arm.com                         PacketList &writebacks, bool allocate);
64612724Snikos.nikoleris@arm.com
64712724Snikos.nikoleris@arm.com    /**
64812724Snikos.nikoleris@arm.com     * Allocate a new block and perform any necessary writebacks
64912724Snikos.nikoleris@arm.com     *
65012724Snikos.nikoleris@arm.com     * Find a victim block and if necessary prepare writebacks for any
65112724Snikos.nikoleris@arm.com     * existing data. May return nullptr if there are no replaceable
65212724Snikos.nikoleris@arm.com     * blocks.
65312724Snikos.nikoleris@arm.com     *
65412724Snikos.nikoleris@arm.com     * @param addr Physical address of the new block
65512724Snikos.nikoleris@arm.com     * @param is_secure Set if the block should be secure
65612724Snikos.nikoleris@arm.com     * @param writebacks A list of writeback packets for the evicted blocks
65712724Snikos.nikoleris@arm.com     * @return the allocated block
65812724Snikos.nikoleris@arm.com     */
65912724Snikos.nikoleris@arm.com    CacheBlk *allocateBlock(Addr addr, bool is_secure, PacketList &writebacks);
66012724Snikos.nikoleris@arm.com    /**
66112724Snikos.nikoleris@arm.com     * Evict a cache block.
66212724Snikos.nikoleris@arm.com     *
66312724Snikos.nikoleris@arm.com     * Performs a writeback if necesssary and invalidates the block
66412724Snikos.nikoleris@arm.com     *
66512724Snikos.nikoleris@arm.com     * @param blk Block to invalidate
66612724Snikos.nikoleris@arm.com     * @return A packet with the writeback, can be nullptr
66712724Snikos.nikoleris@arm.com     */
66812724Snikos.nikoleris@arm.com    M5_NODISCARD virtual PacketPtr evictBlock(CacheBlk *blk) = 0;
66912724Snikos.nikoleris@arm.com
67012724Snikos.nikoleris@arm.com    /**
67112724Snikos.nikoleris@arm.com     * Evict a cache block.
67212724Snikos.nikoleris@arm.com     *
67312724Snikos.nikoleris@arm.com     * Performs a writeback if necesssary and invalidates the block
67412724Snikos.nikoleris@arm.com     *
67512724Snikos.nikoleris@arm.com     * @param blk Block to invalidate
67612724Snikos.nikoleris@arm.com     * @param writebacks Return a list of packets with writebacks
67712724Snikos.nikoleris@arm.com     */
67812724Snikos.nikoleris@arm.com    virtual void evictBlock(CacheBlk *blk, PacketList &writebacks) = 0;
67912724Snikos.nikoleris@arm.com
68012724Snikos.nikoleris@arm.com    /**
68112724Snikos.nikoleris@arm.com     * Invalidate a cache block.
68212724Snikos.nikoleris@arm.com     *
68312724Snikos.nikoleris@arm.com     * @param blk Block to invalidate
68412724Snikos.nikoleris@arm.com     */
68512724Snikos.nikoleris@arm.com    void invalidateBlock(CacheBlk *blk);
68612724Snikos.nikoleris@arm.com
68712724Snikos.nikoleris@arm.com    /**
68812724Snikos.nikoleris@arm.com     * Create a writeback request for the given block.
68912724Snikos.nikoleris@arm.com     *
69012724Snikos.nikoleris@arm.com     * @param blk The block to writeback.
69112724Snikos.nikoleris@arm.com     * @return The writeback request for the block.
69212724Snikos.nikoleris@arm.com     */
69312724Snikos.nikoleris@arm.com    PacketPtr writebackBlk(CacheBlk *blk);
69412724Snikos.nikoleris@arm.com
69512724Snikos.nikoleris@arm.com    /**
69612724Snikos.nikoleris@arm.com     * Create a writeclean request for the given block.
69712724Snikos.nikoleris@arm.com     *
69812724Snikos.nikoleris@arm.com     * Creates a request that writes the block to the cache below
69912724Snikos.nikoleris@arm.com     * without evicting the block from the current cache.
70012724Snikos.nikoleris@arm.com     *
70112724Snikos.nikoleris@arm.com     * @param blk The block to write clean.
70212724Snikos.nikoleris@arm.com     * @param dest The destination of the write clean operation.
70312724Snikos.nikoleris@arm.com     * @param id Use the given packet id for the write clean operation.
70412724Snikos.nikoleris@arm.com     * @return The generated write clean packet.
70512724Snikos.nikoleris@arm.com     */
70612724Snikos.nikoleris@arm.com    PacketPtr writecleanBlk(CacheBlk *blk, Request::Flags dest, PacketId id);
70711197Sandreas.hansson@arm.com
70811197Sandreas.hansson@arm.com    /**
7099347SAndreas.Sandberg@arm.com     * Write back dirty blocks in the cache using functional accesses.
7109347SAndreas.Sandberg@arm.com     */
71112724Snikos.nikoleris@arm.com    virtual void memWriteback() override;
71212724Snikos.nikoleris@arm.com
7139347SAndreas.Sandberg@arm.com    /**
7149347SAndreas.Sandberg@arm.com     * Invalidates all blocks in the cache.
7159347SAndreas.Sandberg@arm.com     *
7169347SAndreas.Sandberg@arm.com     * @warn Dirty cache lines will not be written back to
7179347SAndreas.Sandberg@arm.com     * memory. Make sure to call functionalWriteback() first if you
7189347SAndreas.Sandberg@arm.com     * want the to write them to memory.
7199347SAndreas.Sandberg@arm.com     */
72012724Snikos.nikoleris@arm.com    virtual void memInvalidate() override;
72112724Snikos.nikoleris@arm.com
7229347SAndreas.Sandberg@arm.com    /**
7239347SAndreas.Sandberg@arm.com     * Determine if there are any dirty blocks in the cache.
7249347SAndreas.Sandberg@arm.com     *
72512724Snikos.nikoleris@arm.com     * @return true if at least one block is dirty, false otherwise.
7269347SAndreas.Sandberg@arm.com     */
72712724Snikos.nikoleris@arm.com    bool isDirty() const;
7289347SAndreas.Sandberg@arm.com
72910821Sandreas.hansson@arm.com    /**
73010821Sandreas.hansson@arm.com     * Determine if an address is in the ranges covered by this
73110821Sandreas.hansson@arm.com     * cache. This is useful to filter snoops.
73210821Sandreas.hansson@arm.com     *
73310821Sandreas.hansson@arm.com     * @param addr Address to check against
73410821Sandreas.hansson@arm.com     *
73510821Sandreas.hansson@arm.com     * @return If the address in question is in range
73610821Sandreas.hansson@arm.com     */
73710821Sandreas.hansson@arm.com    bool inRange(Addr addr) const;
73810821Sandreas.hansson@arm.com
73912724Snikos.nikoleris@arm.com    /**
74012724Snikos.nikoleris@arm.com     * Find next request ready time from among possible sources.
74112724Snikos.nikoleris@arm.com     */
74212724Snikos.nikoleris@arm.com    Tick nextQueueReadyTime() const;
74312724Snikos.nikoleris@arm.com
7444626SN/A    /** Block size of this cache */
7456227Snate@binkert.org    const unsigned blkSize;
7464626SN/A
7474630SN/A    /**
74810693SMarco.Balboni@ARM.com     * The latency of tag lookup of a cache. It occurs when there is
74910693SMarco.Balboni@ARM.com     * an access to the cache.
7504630SN/A     */
75110693SMarco.Balboni@ARM.com    const Cycles lookupLatency;
7529263Smrinmoy.ghosh@arm.com
7539263Smrinmoy.ghosh@arm.com    /**
75411722Ssophiane.senni@gmail.com     * The latency of data access of a cache. It occurs when there is
75511722Ssophiane.senni@gmail.com     * an access to the cache.
75611722Ssophiane.senni@gmail.com     */
75711722Ssophiane.senni@gmail.com    const Cycles dataLatency;
75811722Ssophiane.senni@gmail.com
75911722Ssophiane.senni@gmail.com    /**
76010693SMarco.Balboni@ARM.com     * This is the forward latency of the cache. It occurs when there
76110693SMarco.Balboni@ARM.com     * is a cache miss and a request is forwarded downstream, in
76210693SMarco.Balboni@ARM.com     * particular an outbound miss.
76310693SMarco.Balboni@ARM.com     */
76410693SMarco.Balboni@ARM.com    const Cycles forwardLatency;
76510693SMarco.Balboni@ARM.com
76610693SMarco.Balboni@ARM.com    /** The latency to fill a cache block */
76710693SMarco.Balboni@ARM.com    const Cycles fillLatency;
76810693SMarco.Balboni@ARM.com
76910693SMarco.Balboni@ARM.com    /**
77010693SMarco.Balboni@ARM.com     * The latency of sending reponse to its upper level cache/core on
77110693SMarco.Balboni@ARM.com     * a linefill. The responseLatency parameter captures this
77210693SMarco.Balboni@ARM.com     * latency.
7739263Smrinmoy.ghosh@arm.com     */
7749288Sandreas.hansson@arm.com    const Cycles responseLatency;
7754630SN/A
7764626SN/A    /** The number of targets for each MSHR. */
7774626SN/A    const int numTarget;
7784626SN/A
7796122SSteve.Reinhardt@amd.com    /** Do we forward snoops from mem side port through to cpu side port? */
78011331Sandreas.hansson@arm.com    bool forwardSnoops;
7814626SN/A
7822810SN/A    /**
78312724Snikos.nikoleris@arm.com     * Clusivity with respect to the upstream cache, determining if we
78412724Snikos.nikoleris@arm.com     * fill into both this cache and the cache above on a miss. Note
78512724Snikos.nikoleris@arm.com     * that we currently do not support strict clusivity policies.
78612724Snikos.nikoleris@arm.com     */
78712724Snikos.nikoleris@arm.com    const Enums::Clusivity clusivity;
78812724Snikos.nikoleris@arm.com
78912724Snikos.nikoleris@arm.com    /**
79010884Sandreas.hansson@arm.com     * Is this cache read only, for example the instruction cache, or
79110884Sandreas.hansson@arm.com     * table-walker cache. A cache that is read only should never see
79210884Sandreas.hansson@arm.com     * any writes, and should never get any dirty data (and hence
79310884Sandreas.hansson@arm.com     * never have to do any writebacks).
79410884Sandreas.hansson@arm.com     */
79510884Sandreas.hansson@arm.com    const bool isReadOnly;
79610884Sandreas.hansson@arm.com
79710884Sandreas.hansson@arm.com    /**
7982810SN/A     * Bit vector of the blocking reasons for the access path.
7992810SN/A     * @sa #BlockedCause
8002810SN/A     */
8012810SN/A    uint8_t blocked;
8022810SN/A
8036122SSteve.Reinhardt@amd.com    /** Increasing order number assigned to each incoming request. */
8046122SSteve.Reinhardt@amd.com    uint64_t order;
8056122SSteve.Reinhardt@amd.com
8062810SN/A    /** Stores time the cache blocked for statistics. */
8079288Sandreas.hansson@arm.com    Cycles blockedCycle;
8082810SN/A
8094626SN/A    /** Pointer to the MSHR that has no targets. */
8104626SN/A    MSHR *noTargetMSHR;
8112810SN/A
8122810SN/A    /** The number of misses to trigger an exit event. */
8132810SN/A    Counter missCount;
8142810SN/A
8156122SSteve.Reinhardt@amd.com    /**
8166122SSteve.Reinhardt@amd.com     * The address range to which the cache responds on the CPU side.
8176122SSteve.Reinhardt@amd.com     * Normally this is all possible memory addresses. */
8189529Sandreas.hansson@arm.com    const AddrRangeList addrRanges;
8196122SSteve.Reinhardt@amd.com
8208833Sdam.sunwoo@arm.com  public:
8218833Sdam.sunwoo@arm.com    /** System we are currently operating in. */
8228833Sdam.sunwoo@arm.com    System *system;
8236978SLisa.Hsu@amd.com
8242810SN/A    // Statistics
8252810SN/A    /**
8262810SN/A     * @addtogroup CacheStatistics
8272810SN/A     * @{
8282810SN/A     */
8292810SN/A
83011483Snikos.nikoleris@arm.com    /** Number of hits per thread for each type of command.
83111483Snikos.nikoleris@arm.com        @sa Packet::Command */
8325999Snate@binkert.org    Stats::Vector hits[MemCmd::NUM_MEM_CMDS];
8332810SN/A    /** Number of hits for demand accesses. */
8342810SN/A    Stats::Formula demandHits;
8352810SN/A    /** Number of hit for all accesses. */
8362810SN/A    Stats::Formula overallHits;
8372810SN/A
83811483Snikos.nikoleris@arm.com    /** Number of misses per thread for each type of command.
83911483Snikos.nikoleris@arm.com        @sa Packet::Command */
8405999Snate@binkert.org    Stats::Vector misses[MemCmd::NUM_MEM_CMDS];
8412810SN/A    /** Number of misses for demand accesses. */
8422810SN/A    Stats::Formula demandMisses;
8432810SN/A    /** Number of misses for all accesses. */
8442810SN/A    Stats::Formula overallMisses;
8452810SN/A
8462810SN/A    /**
8472810SN/A     * Total number of cycles per thread/command spent waiting for a miss.
8482810SN/A     * Used to calculate the average miss latency.
8492810SN/A     */
8505999Snate@binkert.org    Stats::Vector missLatency[MemCmd::NUM_MEM_CMDS];
8512810SN/A    /** Total number of cycles spent waiting for demand misses. */
8522810SN/A    Stats::Formula demandMissLatency;
8532810SN/A    /** Total number of cycles spent waiting for all misses. */
8542810SN/A    Stats::Formula overallMissLatency;
8552810SN/A
8562810SN/A    /** The number of accesses per command and thread. */
8574022SN/A    Stats::Formula accesses[MemCmd::NUM_MEM_CMDS];
8582810SN/A    /** The number of demand accesses. */
8592810SN/A    Stats::Formula demandAccesses;
8602810SN/A    /** The number of overall accesses. */
8612810SN/A    Stats::Formula overallAccesses;
8622810SN/A
8632810SN/A    /** The miss rate per command and thread. */
8644022SN/A    Stats::Formula missRate[MemCmd::NUM_MEM_CMDS];
8652810SN/A    /** The miss rate of all demand accesses. */
8662810SN/A    Stats::Formula demandMissRate;
8672810SN/A    /** The miss rate for all accesses. */
8682810SN/A    Stats::Formula overallMissRate;
8692810SN/A
8702810SN/A    /** The average miss latency per command and thread. */
8714022SN/A    Stats::Formula avgMissLatency[MemCmd::NUM_MEM_CMDS];
8722810SN/A    /** The average miss latency for demand misses. */
8732810SN/A    Stats::Formula demandAvgMissLatency;
8742810SN/A    /** The average miss latency for all misses. */
8752810SN/A    Stats::Formula overallAvgMissLatency;
8762810SN/A
8772810SN/A    /** The total number of cycles blocked for each blocked cause. */
8785999Snate@binkert.org    Stats::Vector blocked_cycles;
8792810SN/A    /** The number of times this cache blocked for each blocked cause. */
8805999Snate@binkert.org    Stats::Vector blocked_causes;
8812810SN/A
8822810SN/A    /** The average number of cycles blocked for each blocked cause. */
8832810SN/A    Stats::Formula avg_blocked;
8842810SN/A
88511436SRekai.GonzalezAlberquilla@arm.com    /** The number of times a HW-prefetched block is evicted w/o reference. */
88611436SRekai.GonzalezAlberquilla@arm.com    Stats::Scalar unusedPrefetches;
88711436SRekai.GonzalezAlberquilla@arm.com
8884626SN/A    /** Number of blocks written back per thread. */
8895999Snate@binkert.org    Stats::Vector writebacks;
8904626SN/A
8914626SN/A    /** Number of misses that hit in the MSHRs per command and thread. */
8925999Snate@binkert.org    Stats::Vector mshr_hits[MemCmd::NUM_MEM_CMDS];
8934626SN/A    /** Demand misses that hit in the MSHRs. */
8944626SN/A    Stats::Formula demandMshrHits;
8954626SN/A    /** Total number of misses that hit in the MSHRs. */
8964626SN/A    Stats::Formula overallMshrHits;
8974626SN/A
8984626SN/A    /** Number of misses that miss in the MSHRs, per command and thread. */
8995999Snate@binkert.org    Stats::Vector mshr_misses[MemCmd::NUM_MEM_CMDS];
9004626SN/A    /** Demand misses that miss in the MSHRs. */
9014626SN/A    Stats::Formula demandMshrMisses;
9024626SN/A    /** Total number of misses that miss in the MSHRs. */
9034626SN/A    Stats::Formula overallMshrMisses;
9044626SN/A
9054626SN/A    /** Number of misses that miss in the MSHRs, per command and thread. */
9065999Snate@binkert.org    Stats::Vector mshr_uncacheable[MemCmd::NUM_MEM_CMDS];
9074626SN/A    /** Total number of misses that miss in the MSHRs. */
9084626SN/A    Stats::Formula overallMshrUncacheable;
9094626SN/A
9104626SN/A    /** Total cycle latency of each MSHR miss, per command and thread. */
9115999Snate@binkert.org    Stats::Vector mshr_miss_latency[MemCmd::NUM_MEM_CMDS];
9124626SN/A    /** Total cycle latency of demand MSHR misses. */
9134626SN/A    Stats::Formula demandMshrMissLatency;
9144626SN/A    /** Total cycle latency of overall MSHR misses. */
9154626SN/A    Stats::Formula overallMshrMissLatency;
9164626SN/A
9174626SN/A    /** Total cycle latency of each MSHR miss, per command and thread. */
9185999Snate@binkert.org    Stats::Vector mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS];
9194626SN/A    /** Total cycle latency of overall MSHR misses. */
9204626SN/A    Stats::Formula overallMshrUncacheableLatency;
9214626SN/A
9227461Snate@binkert.org#if 0
9234626SN/A    /** The total number of MSHR accesses per command and thread. */
9244626SN/A    Stats::Formula mshrAccesses[MemCmd::NUM_MEM_CMDS];
9254626SN/A    /** The total number of demand MSHR accesses. */
9264626SN/A    Stats::Formula demandMshrAccesses;
9274626SN/A    /** The total number of MSHR accesses. */
9284626SN/A    Stats::Formula overallMshrAccesses;
9297461Snate@binkert.org#endif
9304626SN/A
9314626SN/A    /** The miss rate in the MSHRs pre command and thread. */
9324626SN/A    Stats::Formula mshrMissRate[MemCmd::NUM_MEM_CMDS];
9334626SN/A    /** The demand miss rate in the MSHRs. */
9344626SN/A    Stats::Formula demandMshrMissRate;
9354626SN/A    /** The overall miss rate in the MSHRs. */
9364626SN/A    Stats::Formula overallMshrMissRate;
9374626SN/A
9384626SN/A    /** The average latency of an MSHR miss, per command and thread. */
9394626SN/A    Stats::Formula avgMshrMissLatency[MemCmd::NUM_MEM_CMDS];
9404626SN/A    /** The average latency of a demand MSHR miss. */
9414626SN/A    Stats::Formula demandAvgMshrMissLatency;
9424626SN/A    /** The average overall latency of an MSHR miss. */
9434626SN/A    Stats::Formula overallAvgMshrMissLatency;
9444626SN/A
9454626SN/A    /** The average latency of an MSHR miss, per command and thread. */
9464626SN/A    Stats::Formula avgMshrUncacheableLatency[MemCmd::NUM_MEM_CMDS];
9474626SN/A    /** The average overall latency of an MSHR miss. */
9484626SN/A    Stats::Formula overallAvgMshrUncacheableLatency;
9494626SN/A
95012702Snikos.nikoleris@arm.com    /** Number of replacements of valid blocks. */
95112702Snikos.nikoleris@arm.com    Stats::Scalar replacements;
95212702Snikos.nikoleris@arm.com
9532810SN/A    /**
9542810SN/A     * @}
9552810SN/A     */
9562810SN/A
9572810SN/A    /**
9582810SN/A     * Register stats for this object.
9592810SN/A     */
96012724Snikos.nikoleris@arm.com    void regStats() override;
9612810SN/A
9622810SN/A  public:
96311053Sandreas.hansson@arm.com    BaseCache(const BaseCacheParams *p, unsigned blk_size);
96412724Snikos.nikoleris@arm.com    ~BaseCache();
9653606SN/A
96612724Snikos.nikoleris@arm.com    void init() override;
9672858SN/A
96812724Snikos.nikoleris@arm.com    BaseMasterPort &getMasterPort(const std::string &if_name,
96912724Snikos.nikoleris@arm.com                                  PortID idx = InvalidPortID) override;
97012724Snikos.nikoleris@arm.com    BaseSlavePort &getSlavePort(const std::string &if_name,
97112724Snikos.nikoleris@arm.com                                PortID idx = InvalidPortID) override;
9728922Swilliam.wang@arm.com
9732810SN/A    /**
9742810SN/A     * Query block size of a cache.
9752810SN/A     * @return  The block size
9762810SN/A     */
9776227Snate@binkert.org    unsigned
9786227Snate@binkert.org    getBlockSize() const
9792810SN/A    {
9802810SN/A        return blkSize;
9812810SN/A    }
9822810SN/A
9838883SAli.Saidi@ARM.com    const AddrRangeList &getAddrRanges() const { return addrRanges; }
9846122SSteve.Reinhardt@amd.com
98510942Sandreas.hansson@arm.com    MSHR *allocateMissBuffer(PacketPtr pkt, Tick time, bool sched_send = true)
9864628SN/A    {
98711892Snikos.nikoleris@arm.com        MSHR *mshr = mshrQueue.allocate(pkt->getBlockAddr(blkSize), blkSize,
98811375Sandreas.hansson@arm.com                                        pkt, time, order++,
98911375Sandreas.hansson@arm.com                                        allocOnFill(pkt->cmd));
99011375Sandreas.hansson@arm.com
99111375Sandreas.hansson@arm.com        if (mshrQueue.isFull()) {
99211375Sandreas.hansson@arm.com            setBlocked((BlockedCause)MSHRQueue_MSHRs);
99311375Sandreas.hansson@arm.com        }
99411375Sandreas.hansson@arm.com
99511375Sandreas.hansson@arm.com        if (sched_send) {
99611375Sandreas.hansson@arm.com            // schedule the send
99711375Sandreas.hansson@arm.com            schedMemSideSendEvent(time);
99811375Sandreas.hansson@arm.com        }
99911375Sandreas.hansson@arm.com
100011375Sandreas.hansson@arm.com        return mshr;
10014628SN/A    }
10024628SN/A
100311375Sandreas.hansson@arm.com    void allocateWriteBuffer(PacketPtr pkt, Tick time)
10044628SN/A    {
100511191Sandreas.hansson@arm.com        // should only see writes or clean evicts here
100611191Sandreas.hansson@arm.com        assert(pkt->isWrite() || pkt->cmd == MemCmd::CleanEvict);
100711191Sandreas.hansson@arm.com
100811892Snikos.nikoleris@arm.com        Addr blk_addr = pkt->getBlockAddr(blkSize);
100911375Sandreas.hansson@arm.com
101011375Sandreas.hansson@arm.com        WriteQueueEntry *wq_entry =
101111375Sandreas.hansson@arm.com            writeBuffer.findMatch(blk_addr, pkt->isSecure());
101211375Sandreas.hansson@arm.com        if (wq_entry && !wq_entry->inService) {
101311744Snikos.nikoleris@arm.com            DPRINTF(Cache, "Potential to merge writeback %s", pkt->print());
101411375Sandreas.hansson@arm.com        }
101511375Sandreas.hansson@arm.com
101611375Sandreas.hansson@arm.com        writeBuffer.allocate(blk_addr, blkSize, pkt, time, order++);
101711375Sandreas.hansson@arm.com
101811375Sandreas.hansson@arm.com        if (writeBuffer.isFull()) {
101911375Sandreas.hansson@arm.com            setBlocked((BlockedCause)MSHRQueue_WriteBuffer);
102011375Sandreas.hansson@arm.com        }
102111375Sandreas.hansson@arm.com
102211375Sandreas.hansson@arm.com        // schedule the send
102311375Sandreas.hansson@arm.com        schedMemSideSendEvent(time);
10244628SN/A    }
10254628SN/A
10262810SN/A    /**
10272810SN/A     * Returns true if the cache is blocked for accesses.
10282810SN/A     */
10299529Sandreas.hansson@arm.com    bool isBlocked() const
10302810SN/A    {
10312810SN/A        return blocked != 0;
10322810SN/A    }
10332810SN/A
10342810SN/A    /**
10352810SN/A     * Marks the access path of the cache as blocked for the given cause. This
10362810SN/A     * also sets the blocked flag in the slave interface.
10372810SN/A     * @param cause The reason for the cache blocking.
10382810SN/A     */
10392810SN/A    void setBlocked(BlockedCause cause)
10402810SN/A    {
10412810SN/A        uint8_t flag = 1 << cause;
10422810SN/A        if (blocked == 0) {
10432810SN/A            blocked_causes[cause]++;
10449288Sandreas.hansson@arm.com            blockedCycle = curCycle();
104512724Snikos.nikoleris@arm.com            cpuSidePort.setBlocked();
10462810SN/A        }
10474630SN/A        blocked |= flag;
10484630SN/A        DPRINTF(Cache,"Blocking for cause %d, mask=%d\n", cause, blocked);
10492810SN/A    }
10502810SN/A
10512810SN/A    /**
10522810SN/A     * Marks the cache as unblocked for the given cause. This also clears the
10532810SN/A     * blocked flags in the appropriate interfaces.
10542810SN/A     * @param cause The newly unblocked cause.
10552810SN/A     * @warning Calling this function can cause a blocked request on the bus to
10562810SN/A     * access the cache. The cache must be in a state to handle that request.
10572810SN/A     */
10582810SN/A    void clearBlocked(BlockedCause cause)
10592810SN/A    {
10602810SN/A        uint8_t flag = 1 << cause;
10614630SN/A        blocked &= ~flag;
10624630SN/A        DPRINTF(Cache,"Unblocking for cause %d, mask=%d\n", cause, blocked);
10634630SN/A        if (blocked == 0) {
10649288Sandreas.hansson@arm.com            blocked_cycles[cause] += curCycle() - blockedCycle;
106512724Snikos.nikoleris@arm.com            cpuSidePort.clearBlocked();
10662810SN/A        }
10672810SN/A    }
10682810SN/A
10692810SN/A    /**
107010942Sandreas.hansson@arm.com     * Schedule a send event for the memory-side port. If already
107110942Sandreas.hansson@arm.com     * scheduled, this may reschedule the event at an earlier
107210942Sandreas.hansson@arm.com     * time. When the specified time is reached, the port is free to
107310942Sandreas.hansson@arm.com     * send either a response, a request, or a prefetch request.
107410942Sandreas.hansson@arm.com     *
107510942Sandreas.hansson@arm.com     * @param time The time when to attempt sending a packet.
10762810SN/A     */
107710942Sandreas.hansson@arm.com    void schedMemSideSendEvent(Tick time)
10782810SN/A    {
107912724Snikos.nikoleris@arm.com        memSidePort.schedSendEvent(time);
10802811SN/A    }
10813503SN/A
108212724Snikos.nikoleris@arm.com    bool inCache(Addr addr, bool is_secure) const {
108312724Snikos.nikoleris@arm.com        return tags->findBlock(addr, is_secure);
108412724Snikos.nikoleris@arm.com    }
10854626SN/A
108612724Snikos.nikoleris@arm.com    bool inMissQueue(Addr addr, bool is_secure) const {
108712724Snikos.nikoleris@arm.com        return mshrQueue.findMatch(addr, is_secure);
108812724Snikos.nikoleris@arm.com    }
10894626SN/A
10908833Sdam.sunwoo@arm.com    void incMissCount(PacketPtr pkt)
10913503SN/A    {
10928833Sdam.sunwoo@arm.com        assert(pkt->req->masterId() < system->maxMasters());
10938833Sdam.sunwoo@arm.com        misses[pkt->cmdToIndex()][pkt->req->masterId()]++;
109410020Smatt.horsnell@ARM.com        pkt->req->incAccessDepth();
10954626SN/A        if (missCount) {
10964626SN/A            --missCount;
10974626SN/A            if (missCount == 0)
10984626SN/A                exitSimLoop("A cache reached the maximum miss count");
10993503SN/A        }
11003503SN/A    }
11018833Sdam.sunwoo@arm.com    void incHitCount(PacketPtr pkt)
11026978SLisa.Hsu@amd.com    {
11038833Sdam.sunwoo@arm.com        assert(pkt->req->masterId() < system->maxMasters());
11048833Sdam.sunwoo@arm.com        hits[pkt->cmdToIndex()][pkt->req->masterId()]++;
11056978SLisa.Hsu@amd.com
11066978SLisa.Hsu@amd.com    }
11073503SN/A
110812724Snikos.nikoleris@arm.com    /**
110912724Snikos.nikoleris@arm.com     * Cache block visitor that writes back dirty cache blocks using
111012724Snikos.nikoleris@arm.com     * functional writes.
111112724Snikos.nikoleris@arm.com     *
111212724Snikos.nikoleris@arm.com     * @return Always returns true.
111312724Snikos.nikoleris@arm.com     */
111412724Snikos.nikoleris@arm.com    bool writebackVisitor(CacheBlk &blk);
111512724Snikos.nikoleris@arm.com
111612724Snikos.nikoleris@arm.com    /**
111712724Snikos.nikoleris@arm.com     * Cache block visitor that invalidates all blocks in the cache.
111812724Snikos.nikoleris@arm.com     *
111912724Snikos.nikoleris@arm.com     * @warn Dirty cache lines will not be written back to memory.
112012724Snikos.nikoleris@arm.com     *
112112724Snikos.nikoleris@arm.com     * @return Always returns true.
112212724Snikos.nikoleris@arm.com     */
112312724Snikos.nikoleris@arm.com    bool invalidateVisitor(CacheBlk &blk);
112412724Snikos.nikoleris@arm.com
112512724Snikos.nikoleris@arm.com    /**
112612724Snikos.nikoleris@arm.com     * Take an MSHR, turn it into a suitable downstream packet, and
112712724Snikos.nikoleris@arm.com     * send it out. This construct allows a queue entry to choose a suitable
112812724Snikos.nikoleris@arm.com     * approach based on its type.
112912724Snikos.nikoleris@arm.com     *
113012724Snikos.nikoleris@arm.com     * @param mshr The MSHR to turn into a packet and send
113112724Snikos.nikoleris@arm.com     * @return True if the port is waiting for a retry
113212724Snikos.nikoleris@arm.com     */
113312724Snikos.nikoleris@arm.com    virtual bool sendMSHRQueuePacket(MSHR* mshr);
113412724Snikos.nikoleris@arm.com
113512724Snikos.nikoleris@arm.com    /**
113612724Snikos.nikoleris@arm.com     * Similar to sendMSHR, but for a write-queue entry
113712724Snikos.nikoleris@arm.com     * instead. Create the packet, and send it, and if successful also
113812724Snikos.nikoleris@arm.com     * mark the entry in service.
113912724Snikos.nikoleris@arm.com     *
114012724Snikos.nikoleris@arm.com     * @param wq_entry The write-queue entry to turn into a packet and send
114112724Snikos.nikoleris@arm.com     * @return True if the port is waiting for a retry
114212724Snikos.nikoleris@arm.com     */
114312724Snikos.nikoleris@arm.com    bool sendWriteQueuePacket(WriteQueueEntry* wq_entry);
114412724Snikos.nikoleris@arm.com
114512724Snikos.nikoleris@arm.com    /**
114612724Snikos.nikoleris@arm.com     * Serialize the state of the caches
114712724Snikos.nikoleris@arm.com     *
114812724Snikos.nikoleris@arm.com     * We currently don't support checkpointing cache state, so this panics.
114912724Snikos.nikoleris@arm.com     */
115012724Snikos.nikoleris@arm.com    void serialize(CheckpointOut &cp) const override;
115112724Snikos.nikoleris@arm.com    void unserialize(CheckpointIn &cp) override;
115212724Snikos.nikoleris@arm.com
115312724Snikos.nikoleris@arm.com};
115412724Snikos.nikoleris@arm.com
115512724Snikos.nikoleris@arm.com/**
115612724Snikos.nikoleris@arm.com * Wrap a method and present it as a cache block visitor.
115712724Snikos.nikoleris@arm.com *
115812724Snikos.nikoleris@arm.com * For example the forEachBlk method in the tag arrays expects a
115912724Snikos.nikoleris@arm.com * callable object/function as their parameter. This class wraps a
116012724Snikos.nikoleris@arm.com * method in an object and presents  callable object that adheres to
116112724Snikos.nikoleris@arm.com * the cache block visitor protocol.
116212724Snikos.nikoleris@arm.com */
116312724Snikos.nikoleris@arm.comclass CacheBlkVisitorWrapper : public CacheBlkVisitor
116412724Snikos.nikoleris@arm.com{
116512724Snikos.nikoleris@arm.com  public:
116612724Snikos.nikoleris@arm.com    typedef bool (BaseCache::*VisitorPtr)(CacheBlk &blk);
116712724Snikos.nikoleris@arm.com
116812724Snikos.nikoleris@arm.com    CacheBlkVisitorWrapper(BaseCache &_cache, VisitorPtr _visitor)
116912724Snikos.nikoleris@arm.com        : cache(_cache), visitor(_visitor) {}
117012724Snikos.nikoleris@arm.com
117112724Snikos.nikoleris@arm.com    bool operator()(CacheBlk &blk) override {
117212724Snikos.nikoleris@arm.com        return (cache.*visitor)(blk);
117312724Snikos.nikoleris@arm.com    }
117412724Snikos.nikoleris@arm.com
117512724Snikos.nikoleris@arm.com  private:
117612724Snikos.nikoleris@arm.com    BaseCache &cache;
117712724Snikos.nikoleris@arm.com    VisitorPtr visitor;
117812724Snikos.nikoleris@arm.com};
117912724Snikos.nikoleris@arm.com
118012724Snikos.nikoleris@arm.com/**
118112724Snikos.nikoleris@arm.com * Cache block visitor that determines if there are dirty blocks in a
118212724Snikos.nikoleris@arm.com * cache.
118312724Snikos.nikoleris@arm.com *
118412724Snikos.nikoleris@arm.com * Use with the forEachBlk method in the tag array to determine if the
118512724Snikos.nikoleris@arm.com * array contains dirty blocks.
118612724Snikos.nikoleris@arm.com */
118712724Snikos.nikoleris@arm.comclass CacheBlkIsDirtyVisitor : public CacheBlkVisitor
118812724Snikos.nikoleris@arm.com{
118912724Snikos.nikoleris@arm.com  public:
119012724Snikos.nikoleris@arm.com    CacheBlkIsDirtyVisitor()
119112724Snikos.nikoleris@arm.com        : _isDirty(false) {}
119212724Snikos.nikoleris@arm.com
119312724Snikos.nikoleris@arm.com    bool operator()(CacheBlk &blk) override {
119412724Snikos.nikoleris@arm.com        if (blk.isDirty()) {
119512724Snikos.nikoleris@arm.com            _isDirty = true;
119612724Snikos.nikoleris@arm.com            return false;
119712724Snikos.nikoleris@arm.com        } else {
119812724Snikos.nikoleris@arm.com            return true;
119912724Snikos.nikoleris@arm.com        }
120012724Snikos.nikoleris@arm.com    }
120112724Snikos.nikoleris@arm.com
120212724Snikos.nikoleris@arm.com    /**
120312724Snikos.nikoleris@arm.com     * Does the array contain a dirty line?
120412724Snikos.nikoleris@arm.com     *
120512724Snikos.nikoleris@arm.com     * @return true if yes, false otherwise.
120612724Snikos.nikoleris@arm.com     */
120712724Snikos.nikoleris@arm.com    bool isDirty() const { return _isDirty; };
120812724Snikos.nikoleris@arm.com
120912724Snikos.nikoleris@arm.com  private:
121012724Snikos.nikoleris@arm.com    bool _isDirty;
12112810SN/A};
12122810SN/A
121311051Sandreas.hansson@arm.com#endif //__MEM_CACHE_BASE_HH__
1214