base.hh revision 3738
15703SN/A/*
25703SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
35703SN/A * All rights reserved.
48825Snilay@cs.wisc.edu *
57935SN/A * Redistribution and use in source and binary forms, with or without
67935SN/A * modification, are permitted provided that the following conditions are
77935SN/A * met: redistributions of source code must retain the above copyright
85703SN/A * notice, this list of conditions and the following disclaimer;
95703SN/A * redistributions in binary form must reproduce the above copyright
105703SN/A * notice, this list of conditions and the following disclaimer in the
115703SN/A * documentation and/or other materials provided with the distribution;
125703SN/A * neither the name of the copyright holders nor the names of its
135703SN/A * contributors may be used to endorse or promote products derived from
148835SAli.Saidi@ARM.com * this software without specific prior written permission.
155703SN/A *
168835SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177670SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185703SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
198464SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
208721SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
218835SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225703SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235703SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245703SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255703SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265703SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277935SN/A *
287935SN/A * Authors: Erik Hallnor
297935SN/A */
307935SN/A
317935SN/A/**
327935SN/A * @file
337935SN/A * Declares a basic cache interface BaseCache.
348721SN/A */
355703SN/A
365703SN/A#ifndef __BASE_CACHE_HH__
375703SN/A#define __BASE_CACHE_HH__
385703SN/A
395703SN/A#include <vector>
408721SN/A#include <string>
418721SN/A#include <list>
428721SN/A#include <inttypes.h>
435703SN/A
448721SN/A#include "base/misc.hh"
458721SN/A#include "base/statistics.hh"
465703SN/A#include "base/trace.hh"
475703SN/A#include "mem/mem_object.hh"
485703SN/A#include "mem/packet.hh"
495703SN/A#include "mem/port.hh"
505703SN/A#include "mem/request.hh"
515703SN/A#include "sim/eventq.hh"
525703SN/A
535703SN/A/**
548241SN/A * Reasons for Caches to be Blocked.
558241SN/A */
565703SN/Aenum BlockedCause{
575703SN/A    Blocked_NoMSHRs,
585703SN/A    Blocked_NoTargets,
595703SN/A    Blocked_NoWBBuffers,
605703SN/A    Blocked_Coherence,
615703SN/A    NUM_BLOCKED_CAUSES
625876SN/A};
635703SN/A
645703SN/A/**
655703SN/A * Reasons for cache to request a bus.
665703SN/A */
675703SN/Aenum RequestCause{
685703SN/A    Request_MSHR,
695703SN/A    Request_WB,
705703SN/A    Request_Coherence,
715703SN/A    Request_PF
725703SN/A};
735703SN/A
745703SN/Aclass MSHR;
755703SN/A/**
765703SN/A * A basic cache interface. Implements some common functions for speed.
775703SN/A */
785703SN/Aclass BaseCache : public MemObject
795703SN/A{
805703SN/A    class CachePort : public Port
815703SN/A    {
825703SN/A      public:
835703SN/A        BaseCache *cache;
845703SN/A
855703SN/A      protected:
865703SN/A        CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide);
875703SN/A        virtual void recvStatusChange(Status status);
885703SN/A
895703SN/A        virtual void getDeviceAddressRanges(AddrRangeList &resp,
905703SN/A                                            AddrRangeList &snoop);
915703SN/A
925703SN/A        virtual int deviceBlockSize();
935703SN/A
945703SN/A        virtual void recvRetry();
955703SN/A
965703SN/A      public:
975703SN/A        void setBlocked();
985703SN/A
995703SN/A        void clearBlocked();
1005703SN/A
1015703SN/A        bool checkFunctional(PacketPtr pkt);
1025703SN/A
1035703SN/A        void checkAndSendFunctional(PacketPtr pkt);
1045703SN/A
1055703SN/A        bool canDrain() { return drainList.empty() && transmitList.empty(); }
1065703SN/A
1075703SN/A        bool blocked;
1088825Snilay@cs.wisc.edu
1095703SN/A        bool mustSendRetry;
1105703SN/A
1115703SN/A        bool isCpuSide;
1125703SN/A
1135703SN/A        bool waitingOnRetry;
1145703SN/A
1155703SN/A        std::list<PacketPtr> drainList;
1165703SN/A
1175703SN/A        std::list<std::pair<Tick,PacketPtr> > transmitList;
1185703SN/A    };
1195703SN/A
1205703SN/A    struct CacheEvent : public Event
1215703SN/A    {
1225703SN/A        CachePort *cachePort;
1235703SN/A        PacketPtr pkt;
1245703SN/A        bool newResponse;
1255703SN/A
1265703SN/A        CacheEvent(CachePort *_cachePort, bool response);
1275703SN/A        void process();
1285703SN/A        const char *description();
1295703SN/A    };
1305703SN/A
1315703SN/A  public: //Made public so coherence can get at it.
1325703SN/A    CachePort *cpuSidePort;
1335703SN/A    CachePort *memSidePort;
1348521SN/A
1355703SN/A    CacheEvent *sendEvent;
1365703SN/A    CacheEvent *memSendEvent;
1375703SN/A
1385703SN/A  private:
1395703SN/A    void recvStatusChange(Port::Status status, bool isCpuSide)
1408825Snilay@cs.wisc.edu    {
1415703SN/A        if (status == Port::RangeChange){
1425703SN/A            if (!isCpuSide) {
1435703SN/A                cpuSidePort->sendStatusChange(Port::RangeChange);
1445703SN/A            }
1455703SN/A            else {
1465703SN/A                memSidePort->sendStatusChange(Port::RangeChange);
1475703SN/A            }
1485703SN/A        }
1496123SN/A    }
1505703SN/A
1518135SN/A    virtual PacketPtr getPacket() = 0;
1525703SN/A
1535703SN/A    virtual PacketPtr getCoherencePacket() = 0;
1545703SN/A
1555876SN/A    virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success) = 0;
1568835SAli.Saidi@ARM.com
1575703SN/A    virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* mshr, bool success) = 0;
1585703SN/A
1595703SN/A    /**
1605703SN/A     * Bit vector of the blocking reasons for the access path.
1618835SAli.Saidi@ARM.com     * @sa #BlockedCause
1625703SN/A     */
1635703SN/A    uint8_t blocked;
1645703SN/A
1655703SN/A    /**
1665703SN/A     * Bit vector for the blocking reasons for the snoop path.
1675703SN/A     * @sa #BlockedCause
1685703SN/A     */
1695703SN/A    uint8_t blockedSnoop;
1706024SN/A
1715703SN/A    /**
1725703SN/A     * Bit vector for the outstanding requests for the master interface.
1735703SN/A     */
1745703SN/A    uint8_t masterRequests;
1757761SN/A
1767761SN/A    /**
1775703SN/A     * Bit vector for the outstanding requests for the slave interface.
1785703SN/A     */
1795703SN/A    uint8_t slaveRequests;
1805703SN/A
1815703SN/A  protected:
1825703SN/A
1835703SN/A    /** Stores time the cache blocked for statistics. */
1845703SN/A    Tick blockedCycle;
1855703SN/A
1865703SN/A    /** Block size of this cache */
1875703SN/A    const int blkSize;
1885703SN/A
1895703SN/A    /** The number of misses to trigger an exit event. */
1905703SN/A    Counter missCount;
1915703SN/A
1925703SN/A    /** The drain event. */
1935703SN/A    Event *drainEvent;
1945703SN/A
1955703SN/A  public:
1965703SN/A    // Statistics
1975703SN/A    /**
1985703SN/A     * @addtogroup CacheStatistics
1995703SN/A     * @{
2005703SN/A     */
2015703SN/A
2025703SN/A    /** Number of hits per thread for each type of command. @sa Packet::Command */
2035703SN/A    Stats::Vector<> hits[NUM_MEM_CMDS];
2045703SN/A    /** Number of hits for demand accesses. */
2055703SN/A    Stats::Formula demandHits;
2065703SN/A    /** Number of hit for all accesses. */
2075703SN/A    Stats::Formula overallHits;
2085703SN/A
2095703SN/A    /** Number of misses per thread for each type of command. @sa Packet::Command */
2105703SN/A    Stats::Vector<> misses[NUM_MEM_CMDS];
2115703SN/A    /** Number of misses for demand accesses. */
2125703SN/A    Stats::Formula demandMisses;
2135703SN/A    /** Number of misses for all accesses. */
2145703SN/A    Stats::Formula overallMisses;
2155703SN/A
2165703SN/A    /**
2175703SN/A     * Total number of cycles per thread/command spent waiting for a miss.
2185703SN/A     * Used to calculate the average miss latency.
2195703SN/A     */
2205703SN/A    Stats::Vector<> missLatency[NUM_MEM_CMDS];
2215703SN/A    /** Total number of cycles spent waiting for demand misses. */
2225703SN/A    Stats::Formula demandMissLatency;
2235703SN/A    /** Total number of cycles spent waiting for all misses. */
2245703SN/A    Stats::Formula overallMissLatency;
2255703SN/A
2265703SN/A    /** The number of accesses per command and thread. */
2275703SN/A    Stats::Formula accesses[NUM_MEM_CMDS];
2285703SN/A    /** The number of demand accesses. */
2295703SN/A    Stats::Formula demandAccesses;
2305703SN/A    /** The number of overall accesses. */
2315703SN/A    Stats::Formula overallAccesses;
2325703SN/A
2335703SN/A    /** The miss rate per command and thread. */
2345703SN/A    Stats::Formula missRate[NUM_MEM_CMDS];
2355703SN/A    /** The miss rate of all demand accesses. */
2365703SN/A    Stats::Formula demandMissRate;
2375703SN/A    /** The miss rate for all accesses. */
2385703SN/A    Stats::Formula overallMissRate;
2395703SN/A
2405703SN/A    /** The average miss latency per command and thread. */
2415703SN/A    Stats::Formula avgMissLatency[NUM_MEM_CMDS];
2425703SN/A    /** The average miss latency for demand misses. */
2435703SN/A    Stats::Formula demandAvgMissLatency;
2445703SN/A    /** The average miss latency for all misses. */
2455703SN/A    Stats::Formula overallAvgMissLatency;
2465703SN/A
2475703SN/A    /** The total number of cycles blocked for each blocked cause. */
2485703SN/A    Stats::Vector<> blocked_cycles;
2495703SN/A    /** The number of times this cache blocked for each blocked cause. */
2505703SN/A    Stats::Vector<> blocked_causes;
2515703SN/A
2525703SN/A    /** The average number of cycles blocked for each blocked cause. */
2535703SN/A    Stats::Formula avg_blocked;
2545703SN/A
2555703SN/A    /** The number of fast writes (WH64) performed. */
2565703SN/A    Stats::Scalar<> fastWrites;
2575703SN/A
2585703SN/A    /** The number of cache copies performed. */
2595703SN/A    Stats::Scalar<> cacheCopies;
2605703SN/A
2615703SN/A    /**
2625703SN/A     * @}
2635703SN/A     */
2645703SN/A
2655703SN/A    /**
2665703SN/A     * Register stats for this object.
2675703SN/A     */
2685703SN/A    virtual void regStats();
2695703SN/A
2707761SN/A  public:
2717761SN/A
2727761SN/A    class Params
2735703SN/A    {
2747761SN/A      public:
2755703SN/A        /** List of address ranges of this cache. */
2765703SN/A        std::vector<Range<Addr> > addrRange;
2777761SN/A        /** The hit latency for this cache. */
2787761SN/A        int hitLatency;
2797761SN/A        /** The block size of this cache. */
2807761SN/A        int blkSize;
2817761SN/A        /**
2827761SN/A         * The maximum number of misses this cache should handle before
2837761SN/A         * ending the simulation.
2847761SN/A         */
2857761SN/A        Counter maxMisses;
2867761SN/A
2877761SN/A        /**
2887761SN/A         * Construct an instance of this parameter class.
2897761SN/A         */
2907761SN/A        Params(std::vector<Range<Addr> > addr_range,
2917761SN/A               int hit_latency, int _blkSize, Counter max_misses)
2927761SN/A            : addrRange(addr_range), hitLatency(hit_latency), blkSize(_blkSize),
2937761SN/A              maxMisses(max_misses)
2947761SN/A        {
2957761SN/A        }
2967761SN/A    };
2977761SN/A
2987761SN/A    /**
2997761SN/A     * Create and initialize a basic cache object.
3007761SN/A     * @param name The name of this cache.
3017761SN/A     * @param hier_params Pointer to the HierParams object for this hierarchy
3027761SN/A     * of this cache.
3037761SN/A     * @param params The parameter object for this BaseCache.
3047761SN/A     */
3057761SN/A    BaseCache(const std::string &name, Params &params)
3067761SN/A        : MemObject(name), blocked(0), blockedSnoop(0), masterRequests(0),
3077761SN/A          slaveRequests(0), blkSize(params.blkSize),
3087761SN/A          missCount(params.maxMisses), drainEvent(NULL)
3097761SN/A    {
3107761SN/A        //Start ports at null if more than one is created we should panic
3117761SN/A        cpuSidePort = NULL;
3127761SN/A        memSidePort = NULL;
3137761SN/A    }
3147761SN/A
3157761SN/A    ~BaseCache()
3167761SN/A    {
3177761SN/A        delete sendEvent;
3187761SN/A        delete memSendEvent;
3197761SN/A    }
3207761SN/A
3217761SN/A    virtual void init();
3227761SN/A
3237761SN/A    /**
3247761SN/A     * Query block size of a cache.
3257761SN/A     * @return  The block size
3267761SN/A     */
3277761SN/A    int getBlockSize() const
3287761SN/A    {
3297761SN/A        return blkSize;
3307761SN/A    }
3317761SN/A
3327761SN/A    /**
3337761SN/A     * Returns true if the cache is blocked for accesses.
3347761SN/A     */
3357761SN/A    bool isBlocked()
3367761SN/A    {
3377761SN/A        return blocked != 0;
3387761SN/A    }
3397761SN/A
3407761SN/A    /**
3417761SN/A     * Returns true if the cache is blocked for snoops.
3427761SN/A     */
3437761SN/A    bool isBlockedForSnoop()
3447761SN/A    {
3457761SN/A        return blockedSnoop != 0;
3467761SN/A    }
3477761SN/A
3487761SN/A    /**
3497761SN/A     * Marks the access path of the cache as blocked for the given cause. This
3507761SN/A     * also sets the blocked flag in the slave interface.
3517761SN/A     * @param cause The reason for the cache blocking.
3527761SN/A     */
3537761SN/A    void setBlocked(BlockedCause cause)
3547761SN/A    {
3557761SN/A        uint8_t flag = 1 << cause;
3567761SN/A        if (blocked == 0) {
3577761SN/A            blocked_causes[cause]++;
3587761SN/A            blockedCycle = curTick;
3597761SN/A        }
3607761SN/A        int old_state = blocked;
3617761SN/A        if (!(blocked & flag)) {
3627761SN/A            //Wasn't already blocked for this cause
3637761SN/A            blocked |= flag;
3647761SN/A            DPRINTF(Cache,"Blocking for cause %s\n", cause);
3657761SN/A            if (!old_state)
3667761SN/A                cpuSidePort->setBlocked();
3677761SN/A        }
3687761SN/A    }
3697761SN/A
3707761SN/A    /**
3717761SN/A     * Marks the snoop path of the cache as blocked for the given cause. This
3727761SN/A     * also sets the blocked flag in the master interface.
3737761SN/A     * @param cause The reason to block the snoop path.
3747761SN/A     */
3757761SN/A    void setBlockedForSnoop(BlockedCause cause)
3767761SN/A    {
3777761SN/A        uint8_t flag = 1 << cause;
3787761SN/A        uint8_t old_state = blockedSnoop;
3797761SN/A        if (!(blockedSnoop & flag)) {
3807761SN/A            //Wasn't already blocked for this cause
3817761SN/A            blockedSnoop |= flag;
3827761SN/A            if (!old_state)
3837761SN/A                memSidePort->setBlocked();
3847761SN/A        }
3857761SN/A    }
3867761SN/A
3877761SN/A    /**
3887761SN/A     * Marks the cache as unblocked for the given cause. This also clears the
3897761SN/A     * blocked flags in the appropriate interfaces.
3907761SN/A     * @param cause The newly unblocked cause.
3917761SN/A     * @warning Calling this function can cause a blocked request on the bus to
3925703SN/A     * access the cache. The cache must be in a state to handle that request.
3935703SN/A     */
3945703SN/A    void clearBlocked(BlockedCause cause)
3955703SN/A    {
3967761SN/A        uint8_t flag = 1 << cause;
3977761SN/A        DPRINTF(Cache,"Unblocking for cause %s, causes left=%i\n",
3987761SN/A                cause, blocked);
3995703SN/A        if (blocked & flag)
4007761SN/A        {
4015703SN/A            blocked &= ~flag;
4025703SN/A            if (!isBlocked()) {
4035703SN/A                blocked_cycles[cause] += curTick - blockedCycle;
4045703SN/A                DPRINTF(Cache,"Unblocking from all causes\n");
4055703SN/A                cpuSidePort->clearBlocked();
4065703SN/A            }
4075703SN/A        }
4087761SN/A        if (blockedSnoop & flag)
4097761SN/A        {
4107761SN/A            blockedSnoop &= ~flag;
4117761SN/A            if (!isBlockedForSnoop()) {
4127761SN/A                memSidePort->clearBlocked();
4137761SN/A            }
4147761SN/A        }
4157761SN/A    }
4167761SN/A
4177761SN/A    /**
4187761SN/A     * True if the master bus should be requested.
4197761SN/A     * @return True if there are outstanding requests for the master bus.
4207761SN/A     */
4217761SN/A    bool doMasterRequest()
4227761SN/A    {
4237761SN/A        return masterRequests != 0;
4247761SN/A    }
4257761SN/A
4265703SN/A    /**
4275703SN/A     * Request the master bus for the given cause and time.
4287761SN/A     * @param cause The reason for the request.
4295703SN/A     * @param time The time to make the request.
4307761SN/A     */
4315703SN/A    void setMasterRequest(RequestCause cause, Tick time)
4325703SN/A    {
4335703SN/A        if (!doMasterRequest() && !memSidePort->waitingOnRetry)
4345703SN/A        {
4355703SN/A            BaseCache::CacheEvent * reqCpu =
4365703SN/A                new BaseCache::CacheEvent(memSidePort, false);
4375703SN/A            reqCpu->schedule(time);
4385703SN/A        }
4395703SN/A        uint8_t flag = 1<<cause;
4405703SN/A        masterRequests |= flag;
4416123SN/A    }
4425703SN/A
4438135SN/A    /**
4445703SN/A     * Clear the master bus request for the given cause.
4455703SN/A     * @param cause The request reason to clear.
4465703SN/A     */
4475876SN/A    void clearMasterRequest(RequestCause cause)
4488835SAli.Saidi@ARM.com    {
4495703SN/A        uint8_t flag = 1<<cause;
4505703SN/A        masterRequests &= ~flag;
4515703SN/A        checkDrain();
4525703SN/A    }
4538835SAli.Saidi@ARM.com
4545703SN/A    /**
4555703SN/A     * Return true if the slave bus should be requested.
4565703SN/A     * @return True if there are outstanding requests for the slave bus.
4575703SN/A     */
4585703SN/A    bool doSlaveRequest()
4595703SN/A    {
4605703SN/A        return slaveRequests != 0;
4615703SN/A    }
4625703SN/A
4635703SN/A    /**
4645703SN/A     * Request the slave bus for the given reason and time.
4656024SN/A     * @param cause The reason for the request.
4665703SN/A     * @param time The time to make the request.
4675703SN/A     */
4685703SN/A    void setSlaveRequest(RequestCause cause, Tick time)
4695703SN/A    {
4705703SN/A        if (!doSlaveRequest() && !cpuSidePort->waitingOnRetry)
4715703SN/A        {
4725703SN/A            BaseCache::CacheEvent * reqCpu =
4735703SN/A                new BaseCache::CacheEvent(cpuSidePort, false);
4745703SN/A            reqCpu->schedule(time);
4755703SN/A        }
4765703SN/A        uint8_t flag = 1<<cause;
4775703SN/A        slaveRequests |= flag;
4788241SN/A    }
4798241SN/A
4805703SN/A    /**
4815703SN/A     * Clear the slave bus request for the given reason.
4825703SN/A     * @param cause The request reason to clear.
4835703SN/A     */
4845703SN/A    void clearSlaveRequest(RequestCause cause)
4855703SN/A    {
4865876SN/A        uint8_t flag = 1<<cause;
4875703SN/A        slaveRequests &= ~flag;
4885703SN/A        checkDrain();
4895703SN/A    }
4905703SN/A
4915703SN/A    /**
4925703SN/A     * Send a response to the slave interface.
4935703SN/A     * @param pkt The request being responded to.
4945703SN/A     * @param time The time the response is ready.
4955703SN/A     */
4965703SN/A    void respond(PacketPtr pkt, Tick time)
4975703SN/A    {
4985703SN/A        assert(time >= curTick);
4995703SN/A        if (pkt->needsResponse()) {
5005703SN/A/*            CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
5015703SN/A            reqCpu->schedule(time);
5025703SN/A*/
5035703SN/A            if (cpuSidePort->transmitList.empty()) {
5045703SN/A                assert(!sendEvent->scheduled());
5055703SN/A                sendEvent->schedule(time);
5065703SN/A                cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
5075703SN/A                                                    (time,pkt));
5085703SN/A                return;
5095703SN/A            }
5105703SN/A
5115703SN/A            // something is on the list and this belongs at the end
5125703SN/A            if (time >= cpuSidePort->transmitList.back().first) {
5135703SN/A                cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
5145703SN/A                                                    (time,pkt));
5155703SN/A                return;
5165703SN/A            }
5175703SN/A            // Something is on the list and this belongs somewhere else
5185703SN/A            std::list<std::pair<Tick,PacketPtr> >::iterator i =
5195703SN/A                cpuSidePort->transmitList.begin();
5205703SN/A            std::list<std::pair<Tick,PacketPtr> >::iterator end =
5215703SN/A                cpuSidePort->transmitList.end();
5225703SN/A            bool done = false;
5235703SN/A
5245703SN/A            while (i != end && !done) {
5255703SN/A                if (time < i->first) {
5265703SN/A                    if (i == cpuSidePort->transmitList.begin()) {
5275703SN/A                        //Inserting at begining, reschedule
5285703SN/A                        sendEvent->reschedule(time);
5295703SN/A                    }
5305703SN/A                    cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>
5315703SN/A                                                     (time,pkt));
5328825Snilay@cs.wisc.edu                    done = true;
5335703SN/A                }
5345703SN/A                i++;
5355703SN/A            }
5365703SN/A        }
5375703SN/A        else {
5385703SN/A            if (pkt->cmd != Packet::UpgradeReq)
5395703SN/A            {
5405703SN/A                delete pkt->req;
5415703SN/A                delete pkt;
5425703SN/A            }
5435703SN/A        }
5445703SN/A    }
5455703SN/A
5465703SN/A    /**
5475703SN/A     * Send a reponse to the slave interface and calculate miss latency.
5485703SN/A     * @param pkt The request to respond to.
5495703SN/A     * @param time The time the response is ready.
5505703SN/A     */
5515703SN/A    void respondToMiss(PacketPtr pkt, Tick time)
5525703SN/A    {
5535703SN/A        assert(time >= curTick);
5545703SN/A        if (!pkt->req->isUncacheable()) {
5555703SN/A            missLatency[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] +=
5565703SN/A                time - pkt->time;
5575703SN/A        }
5588521SN/A        if (pkt->needsResponse()) {
5595703SN/A/*            CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
5605703SN/A            reqCpu->schedule(time);
5615703SN/A*/
5625703SN/A            if (cpuSidePort->transmitList.empty()) {
5635703SN/A                assert(!sendEvent->scheduled());
5648825Snilay@cs.wisc.edu                sendEvent->schedule(time);
5655703SN/A                cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
5665703SN/A                                                    (time,pkt));
5675703SN/A                return;
5685703SN/A            }
5695703SN/A
5705703SN/A            // something is on the list and this belongs at the end
5715703SN/A            if (time >= cpuSidePort->transmitList.back().first) {
5725703SN/A                cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
5736123SN/A                                                    (time,pkt));
5745703SN/A                return;
5758135SN/A            }
5765703SN/A            // Something is on the list and this belongs somewhere else
5775703SN/A            std::list<std::pair<Tick,PacketPtr> >::iterator i =
5785703SN/A                cpuSidePort->transmitList.begin();
5795876SN/A            std::list<std::pair<Tick,PacketPtr> >::iterator end =
5808835SAli.Saidi@ARM.com                cpuSidePort->transmitList.end();
5815703SN/A            bool done = false;
5825703SN/A
5835703SN/A            while (i != end && !done) {
5845703SN/A                if (time < i->first) {
5858835SAli.Saidi@ARM.com                    if (i == cpuSidePort->transmitList.begin()) {
5865703SN/A                        //Inserting at begining, reschedule
5875703SN/A                        sendEvent->reschedule(time);
5885703SN/A                    }
5895703SN/A                    cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>
5905703SN/A                                                     (time,pkt));
5915703SN/A                    done = true;
5925703SN/A                }
5935703SN/A                i++;
5946024SN/A            }
5955703SN/A        }
5965703SN/A        else {
5975703SN/A            if (pkt->cmd != Packet::UpgradeReq)
5985703SN/A            {
5997761SN/A                delete pkt->req;
6007761SN/A                delete pkt;
6015703SN/A            }
6025703SN/A        }
6035703SN/A    }
6045703SN/A
6055703SN/A    /**
6065703SN/A     * Suppliess the data if cache to cache transfers are enabled.
6075703SN/A     * @param pkt The bus transaction to fulfill.
6085703SN/A     */
6095703SN/A    void respondToSnoop(PacketPtr pkt, Tick time)
6105703SN/A    {
6115703SN/A        assert(time >= curTick);
6125703SN/A        assert (pkt->needsResponse());
6135703SN/A/*        CacheEvent *reqMem = new CacheEvent(memSidePort, pkt);
6145703SN/A        reqMem->schedule(time);
6155703SN/A*/
6165703SN/A        if (memSidePort->transmitList.empty()) {
6175703SN/A            assert(!memSendEvent->scheduled());
6185703SN/A            memSendEvent->schedule(time);
6195703SN/A            memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
6205703SN/A                                                (time,pkt));
6215703SN/A            return;
6225703SN/A        }
6235703SN/A
6245703SN/A        // something is on the list and this belongs at the end
6255703SN/A        if (time >= memSidePort->transmitList.back().first) {
6265703SN/A            memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
6275703SN/A                                                (time,pkt));
6285703SN/A            return;
6295703SN/A        }
6305703SN/A        // Something is on the list and this belongs somewhere else
6315703SN/A        std::list<std::pair<Tick,PacketPtr> >::iterator i =
6325703SN/A            memSidePort->transmitList.begin();
6335703SN/A        std::list<std::pair<Tick,PacketPtr> >::iterator end =
6345703SN/A            memSidePort->transmitList.end();
6355703SN/A        bool done = false;
6365703SN/A
6375703SN/A        while (i != end && !done) {
6385703SN/A            if (time < i->first) {
6395703SN/A                if (i == memSidePort->transmitList.begin()) {
6405703SN/A                    //Inserting at begining, reschedule
6415703SN/A                    memSendEvent->reschedule(time);
6425703SN/A                }
6435703SN/A                memSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>(time,pkt));
6445703SN/A                done = true;
6455703SN/A            }
6465703SN/A            i++;
6475703SN/A        }
6485703SN/A    }
6495703SN/A
6505703SN/A    /**
6515703SN/A     * Notification from master interface that a address range changed. Nothing
6525703SN/A     * to do for a cache.
6535703SN/A     */
6545703SN/A    void rangeChange() {}
6555703SN/A
6565703SN/A    void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop, bool isCpuSide)
6575703SN/A    {
6585703SN/A        if (isCpuSide)
6595703SN/A        {
6605703SN/A            AddrRangeList dummy;
6615703SN/A            memSidePort->getPeerAddressRanges(resp, dummy);
6625703SN/A        }
6635703SN/A        else
6645703SN/A        {
6655703SN/A            //This is where snoops get updated
6665703SN/A            AddrRangeList dummy;
6675703SN/A            cpuSidePort->getPeerAddressRanges(dummy, snoop);
6685703SN/A            return;
6695703SN/A        }
6705703SN/A    }
6715703SN/A
6725703SN/A    virtual unsigned int drain(Event *de);
6735703SN/A
6745703SN/A    void checkDrain()
6755703SN/A    {
6765703SN/A        if (drainEvent && canDrain()) {
6775703SN/A            drainEvent->process();
6785703SN/A            changeState(SimObject::Drained);
6795703SN/A            // Clear the drain event
6805703SN/A            drainEvent = NULL;
6815703SN/A        }
6825703SN/A    }
6835703SN/A
6845703SN/A    bool canDrain()
6855703SN/A    {
6865703SN/A        if (doMasterRequest() || doSlaveRequest()) {
6875703SN/A            return false;
6885703SN/A        } else if (memSidePort && !memSidePort->canDrain()) {
6895703SN/A            return false;
6905703SN/A        } else if (cpuSidePort && !cpuSidePort->canDrain()) {
6915703SN/A            return false;
6925703SN/A        }
6935703SN/A        return true;
6947761SN/A    }
6957761SN/A};
6967761SN/A
6975703SN/A#endif //__BASE_CACHE_HH__
6987761SN/A