base.hh revision 3126
12SN/A/*
21762SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Erik Hallnor
292665Ssaidi@eecs.umich.edu */
302SN/A
312SN/A/**
321717SN/A * @file
331717SN/A * Declares a basic cache interface BaseCache.
342SN/A */
352SN/A
362SN/A#ifndef __BASE_CACHE_HH__
374182Sgblack@eecs.umich.edu#define __BASE_CACHE_HH__
38707SN/A
391858SN/A#include <vector>
4056SN/A#include <string>
414776Sgblack@eecs.umich.edu#include <list>
422856Srdreslin@umich.edu#include <inttypes.h>
432SN/A
443520Sgblack@eecs.umich.edu#include "base/misc.hh"
453520Sgblack@eecs.umich.edu#include "base/statistics.hh"
463520Sgblack@eecs.umich.edu#include "base/trace.hh"
473520Sgblack@eecs.umich.edu#include "mem/mem_object.hh"
482190SN/A#include "mem/packet.hh"
492315SN/A#include "mem/port.hh"
502680Sktlim@umich.edu#include "mem/request.hh"
512SN/A#include "sim/eventq.hh"
522856Srdreslin@umich.edu
532SN/A/**
544182Sgblack@eecs.umich.edu * Reasons for Caches to be Blocked.
554182Sgblack@eecs.umich.edu */
564182Sgblack@eecs.umich.eduenum BlockedCause{
574182Sgblack@eecs.umich.edu    Blocked_NoMSHRs,
584182Sgblack@eecs.umich.edu    Blocked_NoTargets,
592356SN/A    Blocked_NoWBBuffers,
602356SN/A    Blocked_Coherence,
612356SN/A    Blocked_Copy,
622356SN/A    NUM_BLOCKED_CAUSES
632356SN/A};
642356SN/A
652356SN/A/**
662356SN/A * Reasons for cache to request a bus.
673126Sktlim@umich.edu */
682356SN/Aenum RequestCause{
692356SN/A    Request_MSHR,
702356SN/A    Request_WB,
712356SN/A    Request_Coherence,
722356SN/A    Request_PF
732356SN/A};
742856Srdreslin@umich.edu
752SN/A/**
761634SN/A * A basic cache interface. Implements some common functions for speed.
771634SN/A */
781695SN/Aclass BaseCache : public MemObject
793814Ssaidi@eecs.umich.edu{
803814Ssaidi@eecs.umich.edu    class CachePort : public Port
811634SN/A    {
821634SN/A      public:
832359SN/A        BaseCache *cache;
841695SN/A
855100Ssaidi@eecs.umich.edu        CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide);
861695SN/A
875099Ssaidi@eecs.umich.edu      protected:
883814Ssaidi@eecs.umich.edu        virtual bool recvTiming(Packet *pkt);
893814Ssaidi@eecs.umich.edu
901634SN/A        virtual Tick recvAtomic(Packet *pkt);
913495Sktlim@umich.edu
923495Sktlim@umich.edu        virtual void recvFunctional(Packet *pkt);
933495Sktlim@umich.edu
943495Sktlim@umich.edu        virtual void recvStatusChange(Status status);
953495Sktlim@umich.edu
963495Sktlim@umich.edu        virtual void getDeviceAddressRanges(AddrRangeList &resp,
973495Sktlim@umich.edu                                            AddrRangeList &snoop);
983495Sktlim@umich.edu
993495Sktlim@umich.edu        virtual int deviceBlockSize();
1003495Sktlim@umich.edu
1013495Sktlim@umich.edu        virtual void recvRetry();
1023495Sktlim@umich.edu
1033495Sktlim@umich.edu      public:
1043495Sktlim@umich.edu        void setBlocked();
1051858SN/A
1062SN/A        void clearBlocked();
1073520Sgblack@eecs.umich.edu
1083520Sgblack@eecs.umich.edu        bool blocked;
1093520Sgblack@eecs.umich.edu
1102SN/A        bool mustSendRetry;
1112SN/A
1122SN/A        bool isCpuSide;
1132SN/A    };
1142SN/A
1154103Ssaidi@eecs.umich.edu    struct CacheEvent : public Event
1162SN/A    {
1173521Sgblack@eecs.umich.edu        CachePort *cachePort;
1183521Sgblack@eecs.umich.edu        Packet *pkt;
1191917SN/A
1201917SN/A        CacheEvent(CachePort *_cachePort);
1211917SN/A        CacheEvent(CachePort *_cachePort, Packet *_pkt);
1221917SN/A        void process();
1231917SN/A        const char *description();
1241917SN/A    };
1251917SN/A
1261917SN/A  protected:
1271917SN/A    CachePort *cpuSidePort;
1281917SN/A    CachePort *memSidePort;
1291917SN/A
1301917SN/A  public:
1312SN/A    virtual Port *getPort(const std::string &if_name, int idx = -1);
1322SN/A
1332SN/A  private:
1342680Sktlim@umich.edu    //To be defined in cache_impl.hh not in base class
1354182Sgblack@eecs.umich.edu    virtual bool doTimingAccess(Packet *pkt, CachePort *cachePort, bool isCpuSide)
1362SN/A    {
1374776Sgblack@eecs.umich.edu        fatal("No implementation");
1384776Sgblack@eecs.umich.edu    }
1392SN/A
140393SN/A    virtual Tick doAtomicAccess(Packet *pkt, bool isCpuSide)
1414776Sgblack@eecs.umich.edu    {
1424776Sgblack@eecs.umich.edu        fatal("No implementation");
1434776Sgblack@eecs.umich.edu    }
144393SN/A
145393SN/A    virtual void doFunctionalAccess(Packet *pkt, bool isCpuSide)
146393SN/A    {
147393SN/A        fatal("No implementation");
148393SN/A    }
149393SN/A
150393SN/A    void recvStatusChange(Port::Status status, bool isCpuSide)
151393SN/A    {
152393SN/A        if (status == Port::RangeChange)
153393SN/A        {
154393SN/A            if (!isCpuSide)
155393SN/A            {
156393SN/A                cpuSidePort->sendStatusChange(Port::RangeChange);
1572SN/A            }
1584000Ssaidi@eecs.umich.edu            else
1594000Ssaidi@eecs.umich.edu            {
1604000Ssaidi@eecs.umich.edu                memSidePort->sendStatusChange(Port::RangeChange);
1614000Ssaidi@eecs.umich.edu            }
1624000Ssaidi@eecs.umich.edu        }
1634000Ssaidi@eecs.umich.edu    }
1642SN/A
1651400SN/A    virtual Packet *getPacket()
1661400SN/A    {
1671400SN/A        fatal("No implementation");
1681400SN/A    }
1691400SN/A
1701400SN/A    virtual Packet *getCoherencePacket()
1711400SN/A    {
1721400SN/A        fatal("No implementation");
1731400SN/A    }
1741695SN/A
1751400SN/A    virtual void sendResult(Packet* &pkt, bool success)
1761400SN/A    {
1772378SN/A
1783170Sstever@eecs.umich.edu        fatal("No implementation");
1794776Sgblack@eecs.umich.edu    }
1804776Sgblack@eecs.umich.edu
1813661Srdreslin@umich.edu    /**
1821858SN/A     * Bit vector of the blocking reasons for the access path.
1831917SN/A     * @sa #BlockedCause
1843617Sbinkertn@umich.edu     */
1853617Sbinkertn@umich.edu    uint8_t blocked;
1863617Sbinkertn@umich.edu
1873617Sbinkertn@umich.edu    /**
1881400SN/A     * Bit vector for the blocking reasons for the snoop path.
1892356SN/A     * @sa #BlockedCause
1902315SN/A     */
1911917SN/A    uint8_t blockedSnoop;
1925222Sksewell@umich.edu
1935222Sksewell@umich.edu    /**
1945222Sksewell@umich.edu     * Bit vector for the outstanding requests for the master interface.
1955222Sksewell@umich.edu     */
1965222Sksewell@umich.edu    uint8_t masterRequests;
1975222Sksewell@umich.edu
1985222Sksewell@umich.edu    /**
1995222Sksewell@umich.edu     * Bit vector for the outstanding requests for the slave interface.
2005222Sksewell@umich.edu     */
2015222Sksewell@umich.edu    uint8_t slaveRequests;
2025222Sksewell@umich.edu
2035222Sksewell@umich.edu  protected:
2045222Sksewell@umich.edu
2055222Sksewell@umich.edu    /** True if this cache is connected to the CPU. */
2065222Sksewell@umich.edu    bool topLevelCache;
2075222Sksewell@umich.edu
2085222Sksewell@umich.edu    /** Stores time the cache blocked for statistics. */
2095222Sksewell@umich.edu    Tick blockedCycle;
2105222Sksewell@umich.edu
2115222Sksewell@umich.edu    /** Block size of this cache */
2125222Sksewell@umich.edu    const int blkSize;
2135222Sksewell@umich.edu
2145222Sksewell@umich.edu    /** The number of misses to trigger an exit event. */
2155222Sksewell@umich.edu    Counter missCount;
2165222Sksewell@umich.edu
2175222Sksewell@umich.edu  public:
2185222Sksewell@umich.edu    // Statistics
2195222Sksewell@umich.edu    /**
2205222Sksewell@umich.edu     * @addtogroup CacheStatistics
2215222Sksewell@umich.edu     * @{
2225222Sksewell@umich.edu     */
2235222Sksewell@umich.edu
2245222Sksewell@umich.edu    /** Number of hits per thread for each type of command. @sa Packet::Command */
2255222Sksewell@umich.edu    Stats::Vector<> hits[NUM_MEM_CMDS];
2265222Sksewell@umich.edu    /** Number of hits for demand accesses. */
2275222Sksewell@umich.edu    Stats::Formula demandHits;
2285222Sksewell@umich.edu    /** Number of hit for all accesses. */
2295222Sksewell@umich.edu    Stats::Formula overallHits;
2305222Sksewell@umich.edu
2315222Sksewell@umich.edu    /** Number of misses per thread for each type of command. @sa Packet::Command */
2325222Sksewell@umich.edu    Stats::Vector<> misses[NUM_MEM_CMDS];
2335222Sksewell@umich.edu    /** Number of misses for demand accesses. */
2345222Sksewell@umich.edu    Stats::Formula demandMisses;
2355222Sksewell@umich.edu    /** Number of misses for all accesses. */
2365222Sksewell@umich.edu    Stats::Formula overallMisses;
2375222Sksewell@umich.edu
2385222Sksewell@umich.edu    /**
2395222Sksewell@umich.edu     * Total number of cycles per thread/command spent waiting for a miss.
2405222Sksewell@umich.edu     * Used to calculate the average miss latency.
2415222Sksewell@umich.edu     */
2425222Sksewell@umich.edu    Stats::Vector<> missLatency[NUM_MEM_CMDS];
2435222Sksewell@umich.edu    /** Total number of cycles spent waiting for demand misses. */
2445222Sksewell@umich.edu    Stats::Formula demandMissLatency;
2455222Sksewell@umich.edu    /** Total number of cycles spent waiting for all misses. */
2465222Sksewell@umich.edu    Stats::Formula overallMissLatency;
2475222Sksewell@umich.edu
2485222Sksewell@umich.edu    /** The number of accesses per command and thread. */
2495222Sksewell@umich.edu    Stats::Formula accesses[NUM_MEM_CMDS];
2505222Sksewell@umich.edu    /** The number of demand accesses. */
2515222Sksewell@umich.edu    Stats::Formula demandAccesses;
2525222Sksewell@umich.edu    /** The number of overall accesses. */
2535222Sksewell@umich.edu    Stats::Formula overallAccesses;
2545222Sksewell@umich.edu
2555222Sksewell@umich.edu    /** The miss rate per command and thread. */
2565222Sksewell@umich.edu    Stats::Formula missRate[NUM_MEM_CMDS];
2575222Sksewell@umich.edu    /** The miss rate of all demand accesses. */
2585222Sksewell@umich.edu    Stats::Formula demandMissRate;
2595222Sksewell@umich.edu    /** The miss rate for all accesses. */
2605222Sksewell@umich.edu    Stats::Formula overallMissRate;
2615222Sksewell@umich.edu
2625222Sksewell@umich.edu    /** The average miss latency per command and thread. */
2631917SN/A    Stats::Formula avgMissLatency[NUM_MEM_CMDS];
2641400SN/A    /** The average miss latency for demand misses. */
2652SN/A    Stats::Formula demandAvgMissLatency;
2661400SN/A    /** The average miss latency for all misses. */
2672SN/A    Stats::Formula overallAvgMissLatency;
2681400SN/A
2691191SN/A    /** The total number of cycles blocked for each blocked cause. */
2702SN/A    Stats::Vector<> blocked_cycles;
2711129SN/A    /** The number of times this cache blocked for each blocked cause. */
2721917SN/A    Stats::Vector<> blocked_causes;
2732SN/A
2742SN/A    /** The average number of cycles blocked for each blocked cause. */
2752103SN/A    Stats::Formula avg_blocked;
2762103SN/A
2772680Sktlim@umich.edu    /** The number of fast writes (WH64) performed. */
278180SN/A    Stats::Scalar<> fastWrites;
2791492SN/A
2801492SN/A    /** The number of cache copies performed. */
2812798Sktlim@umich.edu    Stats::Scalar<> cacheCopies;
282180SN/A
283180SN/A    /**
284180SN/A     * @}
2854192Sktlim@umich.edu     */
286180SN/A
287124SN/A    /**
288124SN/A     * Register stats for this object.
289124SN/A     */
290124SN/A    virtual void regStats();
2912SN/A
2922SN/A  public:
293124SN/A
294124SN/A    class Params
295124SN/A    {
296124SN/A      public:
297124SN/A        /** List of address ranges of this cache. */
298503SN/A        std::vector<Range<Addr> > addrRange;
2992SN/A        /** The hit latency for this cache. */
300124SN/A        int hitLatency;
301124SN/A        /** The block size of this cache. */
302124SN/A        int blkSize;
303124SN/A        /**
304124SN/A         * The maximum number of misses this cache should handle before
305124SN/A         * ending the simulation.
306124SN/A         */
3072SN/A        Counter maxMisses;
308921SN/A
3093661Srdreslin@umich.edu        /**
3103661Srdreslin@umich.edu         * Construct an instance of this parameter class.
3112378SN/A         */
312921SN/A        Params(std::vector<Range<Addr> > addr_range,
313921SN/A               int hit_latency, int _blkSize, Counter max_misses)
314921SN/A            : addrRange(addr_range), hitLatency(hit_latency), blkSize(_blkSize),
315921SN/A              maxMisses(max_misses)
316921SN/A        {
317921SN/A        }
318921SN/A    };
319921SN/A
320921SN/A    /**
321921SN/A     * Create and initialize a basic cache object.
322921SN/A     * @param name The name of this cache.
323921SN/A     * @param hier_params Pointer to the HierParams object for this hierarchy
324921SN/A     * of this cache.
3252SN/A     * @param params The parameter object for this BaseCache.
3262SN/A     */
327124SN/A    BaseCache(const std::string &name, Params &params)
328124SN/A        : MemObject(name), blocked(0), blockedSnoop(0), masterRequests(0),
329124SN/A          slaveRequests(0), topLevelCache(false),  blkSize(params.blkSize),
330124SN/A          missCount(params.maxMisses)
3312SN/A    {
3322SN/A        //Start ports at null if more than one is created we should panic
333707SN/A        cpuSidePort = NULL;
334707SN/A        memSidePort = NULL;
3351191SN/A    }
3361191SN/A
3371191SN/A    virtual void init();
3381191SN/A
3391191SN/A    /**
3401191SN/A     * Query block size of a cache.
3411191SN/A     * @return  The block size
3421191SN/A     */
3431191SN/A    int getBlockSize() const
3441191SN/A    {
3451191SN/A        return blkSize;
3461191SN/A    }
3471191SN/A
3481191SN/A    /**
3491191SN/A     * Returns true if this cache is connect to the CPU.
3501191SN/A     * @return True if this is a L1 cache.
3511191SN/A     */
3522SN/A    bool isTopLevel()
3532SN/A    {
3542SN/A        return topLevelCache;
3552SN/A    }
3562SN/A
357707SN/A    /**
358707SN/A     * Returns true if the cache is blocked for accesses.
359707SN/A     */
360707SN/A    bool isBlocked()
361707SN/A    {
362707SN/A        return blocked != 0;
363707SN/A    }
364707SN/A
365707SN/A    /**
366707SN/A     * Returns true if the cache is blocked for snoops.
367707SN/A     */
368707SN/A    bool isBlockedForSnoop()
369707SN/A    {
370729SN/A        return blockedSnoop != 0;
3712SN/A    }
3722SN/A
3731717SN/A    /**
374     * Marks the access path of the cache as blocked for the given cause. This
375     * also sets the blocked flag in the slave interface.
376     * @param cause The reason for the cache blocking.
377     */
378    void setBlocked(BlockedCause cause)
379    {
380        uint8_t flag = 1 << cause;
381        if (blocked == 0) {
382            blocked_causes[cause]++;
383            blockedCycle = curTick;
384        }
385        blocked |= flag;
386        DPRINTF(Cache,"Blocking for cause %s\n", cause);
387        cpuSidePort->setBlocked();
388    }
389
390    /**
391     * Marks the snoop path of the cache as blocked for the given cause. This
392     * also sets the blocked flag in the master interface.
393     * @param cause The reason to block the snoop path.
394     */
395    void setBlockedForSnoop(BlockedCause cause)
396    {
397        uint8_t flag = 1 << cause;
398        blockedSnoop |= flag;
399        memSidePort->setBlocked();
400    }
401
402    /**
403     * Marks the cache as unblocked for the given cause. This also clears the
404     * blocked flags in the appropriate interfaces.
405     * @param cause The newly unblocked cause.
406     * @warning Calling this function can cause a blocked request on the bus to
407     * access the cache. The cache must be in a state to handle that request.
408     */
409    void clearBlocked(BlockedCause cause)
410    {
411        uint8_t flag = 1 << cause;
412        DPRINTF(Cache,"Unblocking for cause %s, causes left=%i\n",
413                cause, blocked);
414        if (blocked & flag)
415        {
416            blocked &= ~flag;
417            if (!isBlocked()) {
418                blocked_cycles[cause] += curTick - blockedCycle;
419                DPRINTF(Cache,"Unblocking from all causes\n");
420                cpuSidePort->clearBlocked();
421            }
422        }
423        if (blockedSnoop & flag)
424        {
425            blockedSnoop &= ~flag;
426            if (!isBlockedForSnoop()) {
427                memSidePort->clearBlocked();
428            }
429        }
430    }
431
432    /**
433     * True if the master bus should be requested.
434     * @return True if there are outstanding requests for the master bus.
435     */
436    bool doMasterRequest()
437    {
438        return masterRequests != 0;
439    }
440
441    /**
442     * Request the master bus for the given cause and time.
443     * @param cause The reason for the request.
444     * @param time The time to make the request.
445     */
446    void setMasterRequest(RequestCause cause, Tick time)
447    {
448        if (!doMasterRequest())
449        {
450            BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(memSidePort);
451            reqCpu->schedule(time);
452        }
453        uint8_t flag = 1<<cause;
454        masterRequests |= flag;
455    }
456
457    /**
458     * Clear the master bus request for the given cause.
459     * @param cause The request reason to clear.
460     */
461    void clearMasterRequest(RequestCause cause)
462    {
463        uint8_t flag = 1<<cause;
464        masterRequests &= ~flag;
465    }
466
467    /**
468     * Return true if the slave bus should be requested.
469     * @return True if there are outstanding requests for the slave bus.
470     */
471    bool doSlaveRequest()
472    {
473        return slaveRequests != 0;
474    }
475
476    /**
477     * Request the slave bus for the given reason and time.
478     * @param cause The reason for the request.
479     * @param time The time to make the request.
480     */
481    void setSlaveRequest(RequestCause cause, Tick time)
482    {
483        uint8_t flag = 1<<cause;
484        slaveRequests |= flag;
485        assert("Implement\n" && 0);
486//	si->pktuest(time);
487    }
488
489    /**
490     * Clear the slave bus request for the given reason.
491     * @param cause The request reason to clear.
492     */
493    void clearSlaveRequest(RequestCause cause)
494    {
495        uint8_t flag = 1<<cause;
496        slaveRequests &= ~flag;
497    }
498
499    /**
500     * Send a response to the slave interface.
501     * @param pkt The request being responded to.
502     * @param time The time the response is ready.
503     */
504    void respond(Packet *pkt, Tick time)
505    {
506        pkt->makeTimingResponse();
507        pkt->result = Packet::Success;
508        CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
509        reqCpu->schedule(time);
510    }
511
512    /**
513     * Send a reponse to the slave interface and calculate miss latency.
514     * @param pkt The request to respond to.
515     * @param time The time the response is ready.
516     */
517    void respondToMiss(Packet *pkt, Tick time)
518    {
519        if (!pkt->req->isUncacheable()) {
520            missLatency[pkt->cmdToIndex()][pkt->req->getThreadNum()] += time - pkt->time;
521        }
522        pkt->makeTimingResponse();
523        pkt->result = Packet::Success;
524        CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
525        reqCpu->schedule(time);
526    }
527
528    /**
529     * Suppliess the data if cache to cache transfers are enabled.
530     * @param pkt The bus transaction to fulfill.
531     */
532    void respondToSnoop(Packet *pkt)
533    {
534        assert("Implement\n" && 0);
535//	mi->respond(pkt,curTick + hitLatency);
536    }
537
538    /**
539     * Notification from master interface that a address range changed. Nothing
540     * to do for a cache.
541     */
542    void rangeChange() {}
543
544    void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop, bool isCpuSide)
545    {
546        if (isCpuSide)
547        {
548            AddrRangeList dummy;
549            memSidePort->getPeerAddressRanges(resp, dummy);
550        }
551        else
552        {
553            //This is where snoops get updated
554            return;
555        }
556    }
557};
558
559#endif //__BASE_CACHE_HH__
560