base_cache.hh

来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· HH 代码 · 共 438 行

HH
438
字号
/* * Copyright (c) 2003, 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator, developed by Nathan Binkert, * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions * from Ron Dreslinski, Dave Greene, Lisa Hsu, Kevin Lim, Ali Saidi, * and Andrew Schultz. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. *//** * @file * Declares a basic cache interface BaseCache. */#ifndef __BASE_CACHE_HH__#define __BASE_CACHE_HH__#include <vector>#include "base/statistics.hh"#include "base/trace.hh"#include "mem/base_mem.hh"#include "mem/bus/base_interface.hh"#include "mem/mem_cmd.hh"#include "mem/mem_req.hh" // For MemReqPtr// Forward declarationsclass Bus;/** * Reasons for Caches to be Blocked. */enum BlockedCause{    Blocked_NoMSHRs,    Blocked_NoTargets,    Blocked_NoWBBuffers,    Blocked_Coherence,    Blocked_Copy,    NUM_BLOCKED_CAUSES};/** * Reasons for cache to request a bus. */enum RequestCause{    Request_MSHR,    Request_WB,    Request_Coherence,    Request_PF};/** * A basic cache interface. Implements some common functions for speed. */class BaseCache : public BaseMem {  private:    /**     * Bit vector of the blocking reasons for the access path.     * @sa #BlockedCause     */    uint8_t blocked;    /**     * Bit vector for the blocking reasons for the snoop path.     * @sa #BlockedCause     */    uint8_t blockedSnoop;    /**     * Bit vector for the outstanding requests for the master interface.     */    uint8_t masterRequests;    /**     * Bit vector for the outstanding requests for the slave interface.     */    uint8_t slaveRequests;  protected:    /** The master interface, typically nearer to Main Memory */    BaseInterface *mi;    /** True if this cache is connected to the CPU. */    bool topLevelCache;    /** Stores time the cache blocked for statistics. */    Tick blockedCycle;    /** Block size of this cache */    const int blkSize;    /** The number of misses to trigger an exit event. */    Counter missCount;  public:    // Statistics    /**     * @addtogroup CacheStatistics     * @{     */    /** Number of hits per thread for each type of command. @sa MemCmd */    Stats::Vector<> hits[NUM_MEM_CMDS];    /** Number of hits for demand accesses. */    Stats::Formula demandHits;    /** Number of hit for all accesses. */    Stats::Formula overallHits;    /** Number of misses per thread for each type of command. @sa MemCmd */    Stats::Vector<> misses[NUM_MEM_CMDS];    /** Number of misses for demand accesses. */    Stats::Formula demandMisses;    /** Number of misses for all accesses. */    Stats::Formula overallMisses;    /**     * Total number of cycles per thread/command spent waiting for a miss.     * Used to calculate the average miss latency.     */    Stats::Vector<> missLatency[NUM_MEM_CMDS];    /** Total number of cycles spent waiting for demand misses. */    Stats::Formula demandMissLatency;    /** Total number of cycles spent waiting for all misses. */    Stats::Formula overallMissLatency;    /** The number of accesses per command and thread. */    Stats::Formula accesses[NUM_MEM_CMDS];    /** The number of demand accesses. */    Stats::Formula demandAccesses;    /** The number of overall accesses. */    Stats::Formula overallAccesses;    /** The miss rate per command and thread. */    Stats::Formula missRate[NUM_MEM_CMDS];    /** The miss rate of all demand accesses. */    Stats::Formula demandMissRate;    /** The miss rate for all accesses. */    Stats::Formula overallMissRate;    /** The average miss latency per command and thread. */    Stats::Formula avgMissLatency[NUM_MEM_CMDS];    /** The average miss latency for demand misses. */    Stats::Formula demandAvgMissLatency;    /** The average miss latency for all misses. */    Stats::Formula overallAvgMissLatency;    /** The total number of cycles blocked for each blocked cause. */    Stats::Vector<> blocked_cycles;    /** The number of times this cache blocked for each blocked cause. */    Stats::Vector<> blocked_causes;    /** The average number of cycles blocked for each blocked cause. */    Stats::Formula avg_blocked;    /** The number of fast writes (WH64) performed. */    Stats::Scalar<> fastWrites;    /** The number of cache copies performed. */    Stats::Scalar<> cacheCopies;    /**     * @}     */    /**     * Register stats for this object.     */    virtual void regStats();  public:    class Params    {      public:	/** List of address ranges of this cache. */	std::vector<Range<Addr> > addrRange;	/** The hit latency for this cache. */	int hitLatency;	/** The block size of this cache. */	int blkSize;	/** 	 * The maximum number of misses this cache should handle before 	 * ending the simulation.	 */	Counter maxMisses;		/**	 * Construct an instance of this parameter class.	 */	Params(std::vector<Range<Addr> > addr_range,	       int hit_latency, int _blkSize, Counter max_misses)	    : addrRange(addr_range), hitLatency(hit_latency), blkSize(_blkSize),	      maxMisses(max_misses)	{	}    };	    /**     * Create and initialize a basic cache object.     * @param name The name of this cache.     * @param hier_params Pointer to the HierParams object for this hierarchy      * of this cache.     * @param params The parameter object for this BaseCache.     */    BaseCache(const std::string &name, HierParams *hier_params, Params &params)	: BaseMem(name, hier_params, params.hitLatency, params.addrRange), 	  blocked(0), blockedSnoop(0), masterRequests(0), slaveRequests(0),	  topLevelCache(false),  blkSize(params.blkSize), 	  missCount(params.maxMisses)    {    }        /**     * Set the master interface for this cache to the one provided.     * @param i The new master interface.     */    void setMasterInterface(BaseInterface *i)    {	mi = i;	std::list<Range<Addr> > ranges;	si->getRange(ranges);	mi->setAddrRange(ranges);    }    /**     * Query block size of a cache.     * @return  The block size     */    int getBlockSize() const    {	return blkSize;    }    /**     * Returns true if this cache is connect to the CPU.     * @return True if this is a L1 cache.     */    bool isTopLevel()    {	return topLevelCache;    }    /**     * Returns true if the cache is blocked for accesses.     */    bool isBlocked()    {	return blocked != 0;    }    /**     * Returns true if the cache is blocked for snoops.     */    bool isBlockedForSnoop()    {	return blockedSnoop != 0;    }    /**     * Marks the access path of the cache as blocked for the given cause. This     * also sets the blocked flag in the slave interface.     * @param cause The reason for the cache blocking.     */    void setBlocked(BlockedCause cause)    {	uint8_t flag = 1 << cause;	if (blocked == 0) {	    blocked_causes[cause]++;	    blockedCycle = curTick;	}	blocked |= flag;	DPRINTF(Cache,"Blocking for cause %s\n", cause);	si->setBlocked();    }    /**     * Marks the snoop path of the cache as blocked for the given cause. This     * also sets the blocked flag in the master interface.     * @param cause The reason to block the snoop path.     */    void setBlockedForSnoop(BlockedCause cause)    {	uint8_t flag = 1 << cause;	blockedSnoop |= flag;	mi->setBlocked();    }    /**     * Marks the cache as unblocked for the given cause. This also clears the     * blocked flags in the appropriate interfaces.     * @param cause The newly unblocked cause.     * @warning Calling this function can cause a blocked request on the bus to     * access the cache. The cache must be in a state to handle that request.     */    void clearBlocked(BlockedCause cause)    {	uint8_t flag = 1 << cause;	blocked &= ~flag;	blockedSnoop &= ~flag;	DPRINTF(Cache,"Unblocking for cause %s, causes left=%i\n", 		cause, blocked);	if (!isBlocked()) {	    blocked_cycles[cause] += curTick - blockedCycle;	    DPRINTF(Cache,"Unblocking from all causes\n");	    si->clearBlocked();	}	if (!isBlockedForSnoop()) {	    mi->clearBlocked();	}    }    /**     * True if the master bus should be requested.     * @return True if there are outstanding requests for the master bus.     */    bool doMasterRequest()    {	return masterRequests != 0;    }    /**     * Request the master bus for the given cause and time.     * @param cause The reason for the request.     * @param time The time to make the request.     */    void setMasterRequest(RequestCause cause, Tick time)    {	uint8_t flag = 1<<cause;	masterRequests |= flag;	mi->request(time);    }    /**     * Clear the master bus request for the given cause.     * @param cause The request reason to clear.     */    void clearMasterRequest(RequestCause cause)    {	uint8_t flag = 1<<cause;	masterRequests &= ~flag;    }    /**     * Return true if the slave bus should be requested.     * @return True if there are outstanding requests for the slave bus.     */    bool doSlaveRequest()    {	return slaveRequests != 0;    }    /**     * Request the slave bus for the given reason and time.     * @param cause The reason for the request.     * @param time The time to make the request.     */    void setSlaveRequest(RequestCause cause, Tick time)    {	uint8_t flag = 1<<cause;	slaveRequests |= flag;	si->request(time);    }    /**     * Clear the slave bus request for the given reason.     * @param cause The request reason to clear.     */    void clearSlaveRequest(RequestCause cause)    {	uint8_t flag = 1<<cause;	slaveRequests &= ~flag;    }    /**     * Send a response to the slave interface.     * @param req The request being responded to.     * @param time The time the response is ready.     */    void respond(MemReqPtr &req, Tick time)    {	si->respond(req,time);    }    /**     * Send a reponse to the slave interface and calculate miss latency.     * @param req The request to respond to.     * @param time The time the response is ready.     */    void respondToMiss(MemReqPtr &req, Tick time)    {	if (!req->isUncacheable()) {	    missLatency[req->cmd.toIndex()][req->thread_num] += time - req->time;	}	si->respond(req,time);    }    /**     * Suppliess the data if cache to cache transfers are enabled.     * @param req The bus transaction to fulfill.     */    void respondToSnoop(MemReqPtr &req)    {	mi->respond(req,curTick + hitLatency);    }    /**     * Notification from master interface that a address range changed. Nothing     * to do for a cache.     */    void rangeChange() {}};#endif //__BASE_CACHE_HH__

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?