base.hh revision 4022
16019Shines@cs.fsu.edu/*
210037SARM gem5 Developers * Copyright (c) 2003-2005 The Regents of The University of Michigan
37414SAli.Saidi@ARM.com * All rights reserved.
47414SAli.Saidi@ARM.com *
57414SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
67414SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
77414SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
87414SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
97414SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
107414SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
117414SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
127414SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
137414SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
146019Shines@cs.fsu.edu * this software without specific prior written permission.
156019Shines@cs.fsu.edu *
166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276019Shines@cs.fsu.edu *
286019Shines@cs.fsu.edu * Authors: Erik Hallnor
296019Shines@cs.fsu.edu */
306019Shines@cs.fsu.edu
316019Shines@cs.fsu.edu/**
326019Shines@cs.fsu.edu * @file
336019Shines@cs.fsu.edu * Declares a basic cache interface BaseCache.
346019Shines@cs.fsu.edu */
356019Shines@cs.fsu.edu
366019Shines@cs.fsu.edu#ifndef __BASE_CACHE_HH__
376019Shines@cs.fsu.edu#define __BASE_CACHE_HH__
386019Shines@cs.fsu.edu
396019Shines@cs.fsu.edu#include <vector>
406019Shines@cs.fsu.edu#include <string>
417414SAli.Saidi@ARM.com#include <list>
426019Shines@cs.fsu.edu#include <inttypes.h>
436019Shines@cs.fsu.edu
4411793Sbrandon.potter@amd.com#include "base/misc.hh"
4511793Sbrandon.potter@amd.com#include "base/statistics.hh"
466019Shines@cs.fsu.edu#include "base/trace.hh"
476019Shines@cs.fsu.edu#include "mem/mem_object.hh"
486019Shines@cs.fsu.edu#include "mem/packet.hh"
496019Shines@cs.fsu.edu#include "mem/port.hh"
5012334Sgabeblack@google.com#include "mem/request.hh"
516019Shines@cs.fsu.edu#include "sim/eventq.hh"
528232Snate@binkert.org
536019Shines@cs.fsu.edu/**
5412431Sgabeblack@google.com * Reasons for Caches to be Blocked.
5511854Sbrandon.potter@amd.com */
567678Sgblack@eecs.umich.eduenum BlockedCause{
576019Shines@cs.fsu.edu    Blocked_NoMSHRs,
5811800Sbrandon.potter@amd.com    Blocked_NoTargets,
596019Shines@cs.fsu.edu    Blocked_NoWBBuffers,
606019Shines@cs.fsu.edu    Blocked_Coherence,
616019Shines@cs.fsu.edu    NUM_BLOCKED_CAUSES
626019Shines@cs.fsu.edu};
636019Shines@cs.fsu.edu
6411851Sbrandon.potter@amd.com/**
6511851Sbrandon.potter@amd.com * Reasons for cache to request a bus.
6612448Sgabeblack@google.com */
6712448Sgabeblack@google.comenum RequestCause{
6812432Sgabeblack@google.com    Request_MSHR,
6912448Sgabeblack@google.com    Request_WB,
706019Shines@cs.fsu.edu    Request_Coherence,
7112441Sgabeblack@google.com    Request_PF
7210037SARM gem5 Developers};
7310037SARM gem5 Developers
7411851Sbrandon.potter@amd.comclass MSHR;
7511851Sbrandon.potter@amd.com/**
7611851Sbrandon.potter@amd.com * A basic cache interface. Implements some common functions for speed.
7710037SARM gem5 Developers */
7811905SBrandon.Potter@amd.comclass BaseCache : public MemObject
7911905SBrandon.Potter@amd.com{
8011905SBrandon.Potter@amd.com    class CachePort : public Port
8111905SBrandon.Potter@amd.com    {
8211905SBrandon.Potter@amd.com      public:
8311905SBrandon.Potter@amd.com        BaseCache *cache;
846019Shines@cs.fsu.edu
8511905SBrandon.Potter@amd.com      protected:
8611905SBrandon.Potter@amd.com        CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide);
876019Shines@cs.fsu.edu        virtual void recvStatusChange(Status status);
886019Shines@cs.fsu.edu
8911851Sbrandon.potter@amd.com        virtual void getDeviceAddressRanges(AddrRangeList &resp,
9011851Sbrandon.potter@amd.com                                            AddrRangeList &snoop);
9111851Sbrandon.potter@amd.com
9210037SARM gem5 Developers        virtual int deviceBlockSize();
9311905SBrandon.Potter@amd.com
9411905SBrandon.Potter@amd.com        virtual void recvRetry();
9511905SBrandon.Potter@amd.com
9611905SBrandon.Potter@amd.com      public:
9711905SBrandon.Potter@amd.com        void setBlocked();
9811905SBrandon.Potter@amd.com
9910037SARM gem5 Developers        void clearBlocked();
10011905SBrandon.Potter@amd.com
10111905SBrandon.Potter@amd.com        bool checkFunctional(PacketPtr pkt);
10210037SARM gem5 Developers
10310037SARM gem5 Developers        void checkAndSendFunctional(PacketPtr pkt);
1046019Shines@cs.fsu.edu
10511851Sbrandon.potter@amd.com        bool canDrain() { return drainList.empty() && transmitList.empty(); }
1066019Shines@cs.fsu.edu
10711851Sbrandon.potter@amd.com        bool blocked;
10810318Sandreas.hansson@arm.com
1097640Sgblack@eecs.umich.edu        bool mustSendRetry;
1107640Sgblack@eecs.umich.edu
1117640Sgblack@eecs.umich.edu        bool isCpuSide;
1127640Sgblack@eecs.umich.edu
1137640Sgblack@eecs.umich.edu        bool waitingOnRetry;
1147640Sgblack@eecs.umich.edu
1157640Sgblack@eecs.umich.edu        std::list<PacketPtr> drainList;
1167640Sgblack@eecs.umich.edu
1177640Sgblack@eecs.umich.edu        std::list<std::pair<Tick,PacketPtr> > transmitList;
1187640Sgblack@eecs.umich.edu    };
1197640Sgblack@eecs.umich.edu
1207640Sgblack@eecs.umich.edu    struct CacheEvent : public Event
1216019Shines@cs.fsu.edu    {
1226019Shines@cs.fsu.edu        CachePort *cachePort;
1236019Shines@cs.fsu.edu        PacketPtr pkt;
12411851Sbrandon.potter@amd.com        bool newResponse;
1256019Shines@cs.fsu.edu
12611851Sbrandon.potter@amd.com        CacheEvent(CachePort *_cachePort, bool response);
12710318Sandreas.hansson@arm.com        void process();
12810037SARM gem5 Developers        const char *description();
12910037SARM gem5 Developers    };
13010037SARM gem5 Developers
13110037SARM gem5 Developers  public: //Made public so coherence can get at it.
13210037SARM gem5 Developers    CachePort *cpuSidePort;
13310037SARM gem5 Developers    CachePort *memSidePort;
13410037SARM gem5 Developers
13510037SARM gem5 Developers    CacheEvent *sendEvent;
13610037SARM gem5 Developers    CacheEvent *memSendEvent;
13710037SARM gem5 Developers
13810037SARM gem5 Developers  private:
13910037SARM gem5 Developers    void recvStatusChange(Port::Status status, bool isCpuSide)
14010037SARM gem5 Developers    {
14110037SARM gem5 Developers        if (status == Port::RangeChange){
14210037SARM gem5 Developers            if (!isCpuSide) {
14310037SARM gem5 Developers                cpuSidePort->sendStatusChange(Port::RangeChange);
14410037SARM gem5 Developers            }
14510037SARM gem5 Developers            else {
14610037SARM gem5 Developers                memSidePort->sendStatusChange(Port::RangeChange);
14711851Sbrandon.potter@amd.com            }
14810037SARM gem5 Developers        }
14910037SARM gem5 Developers    }
15010037SARM gem5 Developers
15110037SARM gem5 Developers    virtual PacketPtr getPacket() = 0;
1526400Sgblack@eecs.umich.edu
1536400Sgblack@eecs.umich.edu    virtual PacketPtr getCoherencePacket() = 0;
1546400Sgblack@eecs.umich.edu
1556400Sgblack@eecs.umich.edu    virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success) = 0;
1566400Sgblack@eecs.umich.edu
1576400Sgblack@eecs.umich.edu    virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* mshr, bool success) = 0;
1586400Sgblack@eecs.umich.edu
1596400Sgblack@eecs.umich.edu    /**
1606400Sgblack@eecs.umich.edu     * Bit vector of the blocking reasons for the access path.
1616400Sgblack@eecs.umich.edu     * @sa #BlockedCause
1626400Sgblack@eecs.umich.edu     */
16311389Sbrandon.potter@amd.com    uint8_t blocked;
16411389Sbrandon.potter@amd.com
16511389Sbrandon.potter@amd.com    /**
1666019Shines@cs.fsu.edu     * Bit vector for the blocking reasons for the snoop path.
1676019Shines@cs.fsu.edu     * @sa #BlockedCause
1686019Shines@cs.fsu.edu     */
1696400Sgblack@eecs.umich.edu    uint8_t blockedSnoop;
1706400Sgblack@eecs.umich.edu
1716400Sgblack@eecs.umich.edu    /**
1726400Sgblack@eecs.umich.edu     * Bit vector for the outstanding requests for the master interface.
1736400Sgblack@eecs.umich.edu     */
1746400Sgblack@eecs.umich.edu    uint8_t masterRequests;
1756400Sgblack@eecs.umich.edu
1766400Sgblack@eecs.umich.edu    /**
1776400Sgblack@eecs.umich.edu     * Bit vector for the outstanding requests for the slave interface.
1786400Sgblack@eecs.umich.edu     */
1796400Sgblack@eecs.umich.edu    uint8_t slaveRequests;
1807414SAli.Saidi@ARM.com
1817414SAli.Saidi@ARM.com  protected:
1827414SAli.Saidi@ARM.com
1837414SAli.Saidi@ARM.com    /** Stores time the cache blocked for statistics. */
1847414SAli.Saidi@ARM.com    Tick blockedCycle;
1856400Sgblack@eecs.umich.edu
1866400Sgblack@eecs.umich.edu    /** Block size of this cache */
1876400Sgblack@eecs.umich.edu    const int blkSize;
1886400Sgblack@eecs.umich.edu
1896400Sgblack@eecs.umich.edu    /** The number of misses to trigger an exit event. */
1906400Sgblack@eecs.umich.edu    Counter missCount;
1916400Sgblack@eecs.umich.edu
19210810Sbr@bsdpad.com    /** The drain event. */
19310810Sbr@bsdpad.com    Event *drainEvent;
19410810Sbr@bsdpad.com
19510810Sbr@bsdpad.com  public:
19610810Sbr@bsdpad.com    // Statistics
19710810Sbr@bsdpad.com    /**
19810810Sbr@bsdpad.com     * @addtogroup CacheStatistics
19910810Sbr@bsdpad.com     * @{
20010810Sbr@bsdpad.com     */
20110810Sbr@bsdpad.com
20210810Sbr@bsdpad.com    /** Number of hits per thread for each type of command. @sa Packet::Command */
20310810Sbr@bsdpad.com    Stats::Vector<> hits[MemCmd::NUM_MEM_CMDS];
20410810Sbr@bsdpad.com    /** Number of hits for demand accesses. */
20510810Sbr@bsdpad.com    Stats::Formula demandHits;
20610810Sbr@bsdpad.com    /** Number of hit for all accesses. */
20710810Sbr@bsdpad.com    Stats::Formula overallHits;
20810810Sbr@bsdpad.com
20910810Sbr@bsdpad.com    /** Number of misses per thread for each type of command. @sa Packet::Command */
21010810Sbr@bsdpad.com    Stats::Vector<> misses[MemCmd::NUM_MEM_CMDS];
21110810Sbr@bsdpad.com    /** Number of misses for demand accesses. */
21210810Sbr@bsdpad.com    Stats::Formula demandMisses;
21310810Sbr@bsdpad.com    /** Number of misses for all accesses. */
21410810Sbr@bsdpad.com    Stats::Formula overallMisses;
21510810Sbr@bsdpad.com
21610810Sbr@bsdpad.com    /**
21710810Sbr@bsdpad.com     * Total number of cycles per thread/command spent waiting for a miss.
21810810Sbr@bsdpad.com     * Used to calculate the average miss latency.
21910810Sbr@bsdpad.com     */
22010810Sbr@bsdpad.com    Stats::Vector<> missLatency[MemCmd::NUM_MEM_CMDS];
22110810Sbr@bsdpad.com    /** Total number of cycles spent waiting for demand misses. */
22210810Sbr@bsdpad.com    Stats::Formula demandMissLatency;
22310810Sbr@bsdpad.com    /** Total number of cycles spent waiting for all misses. */
22410810Sbr@bsdpad.com    Stats::Formula overallMissLatency;
22510810Sbr@bsdpad.com
2266400Sgblack@eecs.umich.edu    /** The number of accesses per command and thread. */
22710318Sandreas.hansson@arm.com    Stats::Formula accesses[MemCmd::NUM_MEM_CMDS];
2286400Sgblack@eecs.umich.edu    /** The number of demand accesses. */
2296400Sgblack@eecs.umich.edu    Stats::Formula demandAccesses;
2306400Sgblack@eecs.umich.edu    /** The number of overall accesses. */
2316400Sgblack@eecs.umich.edu    Stats::Formula overallAccesses;
2326400Sgblack@eecs.umich.edu
2336400Sgblack@eecs.umich.edu    /** The miss rate per command and thread. */
2346400Sgblack@eecs.umich.edu    Stats::Formula missRate[MemCmd::NUM_MEM_CMDS];
23511389Sbrandon.potter@amd.com    /** The miss rate of all demand accesses. */
23611389Sbrandon.potter@amd.com    Stats::Formula demandMissRate;
23711389Sbrandon.potter@amd.com    /** The miss rate for all accesses. */
23811389Sbrandon.potter@amd.com    Stats::Formula overallMissRate;
2396400Sgblack@eecs.umich.edu
2406400Sgblack@eecs.umich.edu    /** The average miss latency per command and thread. */
2416400Sgblack@eecs.umich.edu    Stats::Formula avgMissLatency[MemCmd::NUM_MEM_CMDS];
2426400Sgblack@eecs.umich.edu    /** The average miss latency for demand misses. */
2436400Sgblack@eecs.umich.edu    Stats::Formula demandAvgMissLatency;
2446400Sgblack@eecs.umich.edu    /** The average miss latency for all misses. */
2456400Sgblack@eecs.umich.edu    Stats::Formula overallAvgMissLatency;
2466400Sgblack@eecs.umich.edu
2476400Sgblack@eecs.umich.edu    /** The total number of cycles blocked for each blocked cause. */
2486400Sgblack@eecs.umich.edu    Stats::Vector<> blocked_cycles;
2496400Sgblack@eecs.umich.edu    /** The number of times this cache blocked for each blocked cause. */
2506400Sgblack@eecs.umich.edu    Stats::Vector<> blocked_causes;
2516400Sgblack@eecs.umich.edu
2526400Sgblack@eecs.umich.edu    /** The average number of cycles blocked for each blocked cause. */
2536400Sgblack@eecs.umich.edu    Stats::Formula avg_blocked;
2546400Sgblack@eecs.umich.edu
2557414SAli.Saidi@ARM.com    /** The number of fast writes (WH64) performed. */
2566400Sgblack@eecs.umich.edu    Stats::Scalar<> fastWrites;
2576400Sgblack@eecs.umich.edu
2587414SAli.Saidi@ARM.com    /** The number of cache copies performed. */
2597414SAli.Saidi@ARM.com    Stats::Scalar<> cacheCopies;
2607414SAli.Saidi@ARM.com
2616400Sgblack@eecs.umich.edu    /**
2626400Sgblack@eecs.umich.edu     * @}
2636400Sgblack@eecs.umich.edu     */
2646400Sgblack@eecs.umich.edu
2656400Sgblack@eecs.umich.edu    /**
2666400Sgblack@eecs.umich.edu     * Register stats for this object.
2676400Sgblack@eecs.umich.edu     */
2686400Sgblack@eecs.umich.edu    virtual void regStats();
2696400Sgblack@eecs.umich.edu
2706400Sgblack@eecs.umich.edu  public:
2716019Shines@cs.fsu.edu
2726019Shines@cs.fsu.edu    class Params
2736019Shines@cs.fsu.edu    {
2746019Shines@cs.fsu.edu      public:
2756400Sgblack@eecs.umich.edu        /** List of address ranges of this cache. */
2766400Sgblack@eecs.umich.edu        std::vector<Range<Addr> > addrRange;
2776400Sgblack@eecs.umich.edu        /** The hit latency for this cache. */
2787414SAli.Saidi@ARM.com        int hitLatency;
2796400Sgblack@eecs.umich.edu        /** The block size of this cache. */
2806400Sgblack@eecs.umich.edu        int blkSize;
2816400Sgblack@eecs.umich.edu        /**
2826400Sgblack@eecs.umich.edu         * The maximum number of misses this cache should handle before
2836400Sgblack@eecs.umich.edu         * ending the simulation.
2846400Sgblack@eecs.umich.edu         */
2856400Sgblack@eecs.umich.edu        Counter maxMisses;
2866400Sgblack@eecs.umich.edu
2876400Sgblack@eecs.umich.edu        /**
2886400Sgblack@eecs.umich.edu         * Construct an instance of this parameter class.
2896400Sgblack@eecs.umich.edu         */
2906400Sgblack@eecs.umich.edu        Params(std::vector<Range<Addr> > addr_range,
2916400Sgblack@eecs.umich.edu               int hit_latency, int _blkSize, Counter max_misses)
2926400Sgblack@eecs.umich.edu            : addrRange(addr_range), hitLatency(hit_latency), blkSize(_blkSize),
2936400Sgblack@eecs.umich.edu              maxMisses(max_misses)
2946400Sgblack@eecs.umich.edu        {
2956400Sgblack@eecs.umich.edu        }
2966400Sgblack@eecs.umich.edu    };
2976400Sgblack@eecs.umich.edu
2986400Sgblack@eecs.umich.edu    /**
2996400Sgblack@eecs.umich.edu     * Create and initialize a basic cache object.
3006400Sgblack@eecs.umich.edu     * @param name The name of this cache.
3016400Sgblack@eecs.umich.edu     * @param hier_params Pointer to the HierParams object for this hierarchy
3026400Sgblack@eecs.umich.edu     * of this cache.
3036400Sgblack@eecs.umich.edu     * @param params The parameter object for this BaseCache.
30411905SBrandon.Potter@amd.com     */
30511905SBrandon.Potter@amd.com    BaseCache(const std::string &name, Params &params)
30611905SBrandon.Potter@amd.com        : MemObject(name), blocked(0), blockedSnoop(0), masterRequests(0),
3076400Sgblack@eecs.umich.edu          slaveRequests(0), blkSize(params.blkSize),
3086400Sgblack@eecs.umich.edu          missCount(params.maxMisses), drainEvent(NULL)
30911905SBrandon.Potter@amd.com    {
31011905SBrandon.Potter@amd.com        //Start ports at null if more than one is created we should panic
3116400Sgblack@eecs.umich.edu        cpuSidePort = NULL;
3126400Sgblack@eecs.umich.edu        memSidePort = NULL;
31311905SBrandon.Potter@amd.com    }
31410037SARM gem5 Developers
31510037SARM gem5 Developers    ~BaseCache()
31610037SARM gem5 Developers    {
31710037SARM gem5 Developers        delete sendEvent;
31810037SARM gem5 Developers        delete memSendEvent;
31910037SARM gem5 Developers    }
32010037SARM gem5 Developers
32110037SARM gem5 Developers    virtual void init();
32210037SARM gem5 Developers
3236400Sgblack@eecs.umich.edu    /**
3246400Sgblack@eecs.umich.edu     * Query block size of a cache.
3256400Sgblack@eecs.umich.edu     * @return  The block size
3266400Sgblack@eecs.umich.edu     */
3276400Sgblack@eecs.umich.edu    int getBlockSize() const
3287414SAli.Saidi@ARM.com    {
3296400Sgblack@eecs.umich.edu        return blkSize;
3306400Sgblack@eecs.umich.edu    }
3316400Sgblack@eecs.umich.edu
3326400Sgblack@eecs.umich.edu    /**
3336400Sgblack@eecs.umich.edu     * Returns true if the cache is blocked for accesses.
33411905SBrandon.Potter@amd.com     */
3356400Sgblack@eecs.umich.edu    bool isBlocked()
3366400Sgblack@eecs.umich.edu    {
3376400Sgblack@eecs.umich.edu        return blocked != 0;
3386400Sgblack@eecs.umich.edu    }
33910037SARM gem5 Developers
34010037SARM gem5 Developers    /**
3416400Sgblack@eecs.umich.edu     * Returns true if the cache is blocked for snoops.
3426400Sgblack@eecs.umich.edu     */
34310037SARM gem5 Developers    bool isBlockedForSnoop()
3448852Sandreas.hansson@arm.com    {
3456400Sgblack@eecs.umich.edu        return blockedSnoop != 0;
3466400Sgblack@eecs.umich.edu    }
3476400Sgblack@eecs.umich.edu
3486400Sgblack@eecs.umich.edu    /**
3496400Sgblack@eecs.umich.edu     * Marks the access path of the cache as blocked for the given cause. This
3506400Sgblack@eecs.umich.edu     * also sets the blocked flag in the slave interface.
3518852Sandreas.hansson@arm.com     * @param cause The reason for the cache blocking.
3526400Sgblack@eecs.umich.edu     */
3536400Sgblack@eecs.umich.edu    void setBlocked(BlockedCause cause)
3548852Sandreas.hansson@arm.com    {
3557414SAli.Saidi@ARM.com        uint8_t flag = 1 << cause;
3567414SAli.Saidi@ARM.com        if (blocked == 0) {
3577414SAli.Saidi@ARM.com            blocked_causes[cause]++;
3586400Sgblack@eecs.umich.edu            blockedCycle = curTick;
3596019Shines@cs.fsu.edu        }
3606019Shines@cs.fsu.edu        int old_state = blocked;
3616400Sgblack@eecs.umich.edu        if (!(blocked & flag)) {
36210037SARM gem5 Developers            //Wasn't already blocked for this cause
3638852Sandreas.hansson@arm.com            blocked |= flag;
3646400Sgblack@eecs.umich.edu            DPRINTF(Cache,"Blocking for cause %s\n", cause);
3658852Sandreas.hansson@arm.com            if (!old_state)
3666400Sgblack@eecs.umich.edu                cpuSidePort->setBlocked();
3676400Sgblack@eecs.umich.edu        }
3686400Sgblack@eecs.umich.edu    }
3696400Sgblack@eecs.umich.edu
3708852Sandreas.hansson@arm.com    /**
3716400Sgblack@eecs.umich.edu     * Marks the snoop path of the cache as blocked for the given cause. This
3726019Shines@cs.fsu.edu     * also sets the blocked flag in the master interface.
3736400Sgblack@eecs.umich.edu     * @param cause The reason to block the snoop path.
3746400Sgblack@eecs.umich.edu     */
3756019Shines@cs.fsu.edu    void setBlockedForSnoop(BlockedCause cause)
3768852Sandreas.hansson@arm.com    {
3776019Shines@cs.fsu.edu        uint8_t flag = 1 << cause;
3786020Sgblack@eecs.umich.edu        uint8_t old_state = blockedSnoop;
3796400Sgblack@eecs.umich.edu        if (!(blockedSnoop & flag)) {
38011905SBrandon.Potter@amd.com            //Wasn't already blocked for this cause
3816400Sgblack@eecs.umich.edu            blockedSnoop |= flag;
3826400Sgblack@eecs.umich.edu            if (!old_state)
3836400Sgblack@eecs.umich.edu                memSidePort->setBlocked();
3846400Sgblack@eecs.umich.edu        }
3856400Sgblack@eecs.umich.edu    }
3866400Sgblack@eecs.umich.edu
3876400Sgblack@eecs.umich.edu    /**
3886400Sgblack@eecs.umich.edu     * Marks the cache as unblocked for the given cause. This also clears the
3896400Sgblack@eecs.umich.edu     * blocked flags in the appropriate interfaces.
3906400Sgblack@eecs.umich.edu     * @param cause The newly unblocked cause.
3916400Sgblack@eecs.umich.edu     * @warning Calling this function can cause a blocked request on the bus to
3926400Sgblack@eecs.umich.edu     * access the cache. The cache must be in a state to handle that request.
3936400Sgblack@eecs.umich.edu     */
3946400Sgblack@eecs.umich.edu    void clearBlocked(BlockedCause cause)
3956400Sgblack@eecs.umich.edu    {
3966400Sgblack@eecs.umich.edu        uint8_t flag = 1 << cause;
3976019Shines@cs.fsu.edu        DPRINTF(Cache,"Unblocking for cause %s, causes left=%i\n",
3987720Sgblack@eecs.umich.edu                cause, blocked);
3997720Sgblack@eecs.umich.edu        if (blocked & flag)
4007720Sgblack@eecs.umich.edu        {
40110037SARM gem5 Developers            blocked &= ~flag;
40210037SARM gem5 Developers            if (!isBlocked()) {
40311389Sbrandon.potter@amd.com                blocked_cycles[cause] += curTick - blockedCycle;
4047720Sgblack@eecs.umich.edu                DPRINTF(Cache,"Unblocking from all causes\n");
4056400Sgblack@eecs.umich.edu                cpuSidePort->clearBlocked();
40611886Sbrandon.potter@amd.com            }
40711905SBrandon.Potter@amd.com        }
4086019Shines@cs.fsu.edu        if (blockedSnoop & flag)
4096019Shines@cs.fsu.edu        {
4106020Sgblack@eecs.umich.edu            blockedSnoop &= ~flag;
41111851Sbrandon.potter@amd.com            if (!isBlockedForSnoop()) {
4126020Sgblack@eecs.umich.edu                memSidePort->clearBlocked();
4137441SAli.Saidi@ARM.com            }
4146701Sgblack@eecs.umich.edu        }
4156020Sgblack@eecs.umich.edu    }
4166020Sgblack@eecs.umich.edu
41710037SARM gem5 Developers    /**
41811851Sbrandon.potter@amd.com     * True if the master bus should be requested.
41910037SARM gem5 Developers     * @return True if there are outstanding requests for the master bus.
42010037SARM gem5 Developers     */
42110037SARM gem5 Developers    bool doMasterRequest()
42210037SARM gem5 Developers    {
42310037SARM gem5 Developers        return masterRequests != 0;
42410037SARM gem5 Developers    }
42511851Sbrandon.potter@amd.com
4267441SAli.Saidi@ARM.com    /**
4277441SAli.Saidi@ARM.com     * Request the master bus for the given cause and time.
4287441SAli.Saidi@ARM.com     * @param cause The reason for the request.
4297441SAli.Saidi@ARM.com     * @param time The time to make the request.
4307441SAli.Saidi@ARM.com     */
4317441SAli.Saidi@ARM.com    void setMasterRequest(RequestCause cause, Tick time)
4327441SAli.Saidi@ARM.com    {
4337441SAli.Saidi@ARM.com        if (!doMasterRequest() && !memSidePort->waitingOnRetry)
4347441SAli.Saidi@ARM.com        {
4357441SAli.Saidi@ARM.com            BaseCache::CacheEvent * reqCpu =
4367441SAli.Saidi@ARM.com                new BaseCache::CacheEvent(memSidePort, false);
4377441SAli.Saidi@ARM.com            reqCpu->schedule(time);
4387441SAli.Saidi@ARM.com        }
4397441SAli.Saidi@ARM.com        uint8_t flag = 1<<cause;
4407441SAli.Saidi@ARM.com        masterRequests |= flag;
4417441SAli.Saidi@ARM.com    }
4427441SAli.Saidi@ARM.com
44310037SARM gem5 Developers    /**
44411851Sbrandon.potter@amd.com     * Clear the master bus request for the given cause.
44510037SARM gem5 Developers     * @param cause The request reason to clear.
44610037SARM gem5 Developers     */
44710037SARM gem5 Developers    void clearMasterRequest(RequestCause cause)
44810037SARM gem5 Developers    {
4497441SAli.Saidi@ARM.com        uint8_t flag = 1<<cause;
4506020Sgblack@eecs.umich.edu        masterRequests &= ~flag;
45111851Sbrandon.potter@amd.com        checkDrain();
4526020Sgblack@eecs.umich.edu    }
45310037SARM gem5 Developers
4546020Sgblack@eecs.umich.edu    /**
4556020Sgblack@eecs.umich.edu     * Return true if the slave bus should be requested.
4566020Sgblack@eecs.umich.edu     * @return True if there are outstanding requests for the slave bus.
4576020Sgblack@eecs.umich.edu     */
45811851Sbrandon.potter@amd.com    bool doSlaveRequest()
45910037SARM gem5 Developers    {
46010037SARM gem5 Developers        return slaveRequests != 0;
46110037SARM gem5 Developers    }
46210037SARM gem5 Developers
46310037SARM gem5 Developers    /**
46410037SARM gem5 Developers     * Request the slave bus for the given reason and time.
46511851Sbrandon.potter@amd.com     * @param cause The reason for the request.
4666020Sgblack@eecs.umich.edu     * @param time The time to make the request.
46710810Sbr@bsdpad.com     */
46810810Sbr@bsdpad.com    void setSlaveRequest(RequestCause cause, Tick time)
46910810Sbr@bsdpad.com    {
47010810Sbr@bsdpad.com        if (!doSlaveRequest() && !cpuSidePort->waitingOnRetry)
47110810Sbr@bsdpad.com        {
47210810Sbr@bsdpad.com            BaseCache::CacheEvent * reqCpu =
47310810Sbr@bsdpad.com                new BaseCache::CacheEvent(cpuSidePort, false);
47410810Sbr@bsdpad.com            reqCpu->schedule(time);
47510810Sbr@bsdpad.com        }
47610810Sbr@bsdpad.com        uint8_t flag = 1<<cause;
47710810Sbr@bsdpad.com        slaveRequests |= flag;
47810223Ssteve.reinhardt@amd.com    }
4796020Sgblack@eecs.umich.edu
48010037SARM gem5 Developers    /**
48110037SARM gem5 Developers     * Clear the slave bus request for the given reason.
48211851Sbrandon.potter@amd.com     * @param cause The request reason to clear.
48310037SARM gem5 Developers     */
48410810Sbr@bsdpad.com    void clearSlaveRequest(RequestCause cause)
48510810Sbr@bsdpad.com    {
48610810Sbr@bsdpad.com        uint8_t flag = 1<<cause;
48710810Sbr@bsdpad.com        slaveRequests &= ~flag;
48810810Sbr@bsdpad.com        checkDrain();
48910810Sbr@bsdpad.com    }
49010810Sbr@bsdpad.com
49110810Sbr@bsdpad.com    /**
49210810Sbr@bsdpad.com     * Send a response to the slave interface.
49310810Sbr@bsdpad.com     * @param pkt The request being responded to.
49410810Sbr@bsdpad.com     * @param time The time the response is ready.
49510223Ssteve.reinhardt@amd.com     */
49610037SARM gem5 Developers    void respond(PacketPtr pkt, Tick time)
497    {
498        assert(time >= curTick);
499        if (pkt->needsResponse()) {
500/*            CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
501            reqCpu->schedule(time);
502*/
503            if (cpuSidePort->transmitList.empty()) {
504                assert(!sendEvent->scheduled());
505                sendEvent->schedule(time);
506                cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
507                                                    (time,pkt));
508                return;
509            }
510
511            // something is on the list and this belongs at the end
512            if (time >= cpuSidePort->transmitList.back().first) {
513                cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
514                                                    (time,pkt));
515                return;
516            }
517            // Something is on the list and this belongs somewhere else
518            std::list<std::pair<Tick,PacketPtr> >::iterator i =
519                cpuSidePort->transmitList.begin();
520            std::list<std::pair<Tick,PacketPtr> >::iterator end =
521                cpuSidePort->transmitList.end();
522            bool done = false;
523
524            while (i != end && !done) {
525                if (time < i->first) {
526                    if (i == cpuSidePort->transmitList.begin()) {
527                        //Inserting at begining, reschedule
528                        sendEvent->reschedule(time);
529                    }
530                    cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>
531                                                     (time,pkt));
532                    done = true;
533                }
534                i++;
535            }
536        }
537        else {
538            if (pkt->cmd != MemCmd::UpgradeReq)
539            {
540                delete pkt->req;
541                delete pkt;
542            }
543        }
544    }
545
546    /**
547     * Send a reponse to the slave interface and calculate miss latency.
548     * @param pkt The request to respond to.
549     * @param time The time the response is ready.
550     */
551    void respondToMiss(PacketPtr pkt, Tick time)
552    {
553        assert(time >= curTick);
554        if (!pkt->req->isUncacheable()) {
555            missLatency[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] +=
556                time - pkt->time;
557        }
558        if (pkt->needsResponse()) {
559/*            CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
560            reqCpu->schedule(time);
561*/
562            if (cpuSidePort->transmitList.empty()) {
563                assert(!sendEvent->scheduled());
564                sendEvent->schedule(time);
565                cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
566                                                    (time,pkt));
567                return;
568            }
569
570            // something is on the list and this belongs at the end
571            if (time >= cpuSidePort->transmitList.back().first) {
572                cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
573                                                    (time,pkt));
574                return;
575            }
576            // Something is on the list and this belongs somewhere else
577            std::list<std::pair<Tick,PacketPtr> >::iterator i =
578                cpuSidePort->transmitList.begin();
579            std::list<std::pair<Tick,PacketPtr> >::iterator end =
580                cpuSidePort->transmitList.end();
581            bool done = false;
582
583            while (i != end && !done) {
584                if (time < i->first) {
585                    if (i == cpuSidePort->transmitList.begin()) {
586                        //Inserting at begining, reschedule
587                        sendEvent->reschedule(time);
588                    }
589                    cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>
590                                                     (time,pkt));
591                    done = true;
592                }
593                i++;
594            }
595        }
596        else {
597            if (pkt->cmd != MemCmd::UpgradeReq)
598            {
599                delete pkt->req;
600                delete pkt;
601            }
602        }
603    }
604
605    /**
606     * Suppliess the data if cache to cache transfers are enabled.
607     * @param pkt The bus transaction to fulfill.
608     */
609    void respondToSnoop(PacketPtr pkt, Tick time)
610    {
611        assert(time >= curTick);
612        assert (pkt->needsResponse());
613/*        CacheEvent *reqMem = new CacheEvent(memSidePort, pkt);
614        reqMem->schedule(time);
615*/
616        if (memSidePort->transmitList.empty()) {
617            assert(!memSendEvent->scheduled());
618            memSendEvent->schedule(time);
619            memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
620                                                (time,pkt));
621            return;
622        }
623
624        // something is on the list and this belongs at the end
625        if (time >= memSidePort->transmitList.back().first) {
626            memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
627                                                (time,pkt));
628            return;
629        }
630        // Something is on the list and this belongs somewhere else
631        std::list<std::pair<Tick,PacketPtr> >::iterator i =
632            memSidePort->transmitList.begin();
633        std::list<std::pair<Tick,PacketPtr> >::iterator end =
634            memSidePort->transmitList.end();
635        bool done = false;
636
637        while (i != end && !done) {
638            if (time < i->first) {
639                if (i == memSidePort->transmitList.begin()) {
640                    //Inserting at begining, reschedule
641                    memSendEvent->reschedule(time);
642                }
643                memSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>(time,pkt));
644                done = true;
645            }
646            i++;
647        }
648    }
649
650    /**
651     * Notification from master interface that a address range changed. Nothing
652     * to do for a cache.
653     */
654    void rangeChange() {}
655
656    void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop, bool isCpuSide)
657    {
658        if (isCpuSide)
659        {
660            AddrRangeList dummy;
661            memSidePort->getPeerAddressRanges(resp, dummy);
662        }
663        else
664        {
665            //This is where snoops get updated
666            AddrRangeList dummy;
667            cpuSidePort->getPeerAddressRanges(dummy, snoop);
668            return;
669        }
670    }
671
672    virtual unsigned int drain(Event *de);
673
674    void checkDrain()
675    {
676        if (drainEvent && canDrain()) {
677            drainEvent->process();
678            changeState(SimObject::Drained);
679            // Clear the drain event
680            drainEvent = NULL;
681        }
682    }
683
684    bool canDrain()
685    {
686        if (doMasterRequest() || doSlaveRequest()) {
687            return false;
688        } else if (memSidePort && !memSidePort->canDrain()) {
689            return false;
690        } else if (cpuSidePort && !cpuSidePort->canDrain()) {
691            return false;
692        }
693        return true;
694    }
695
696    virtual bool inCache(Addr addr) = 0;
697
698    virtual bool inMissQueue(Addr addr) = 0;
699};
700
701#endif //__BASE_CACHE_HH__
702