cache_impl.hh

来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· HH 代码 · 共 1,090 行 · 第 1/3 页

HH
1,090
字号
/* * Copyright (c) 2002, 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 * Cache definitions. */#include <assert.h>#include <math.h>#include <cassert>#include <iostream>#include <sstream>#include <string>#include "sim/host.hh"#include "base/misc.hh"#include "cpu/smt.hh"#include "mem/cache/cache.hh"#include "mem/cache/cache_blk.hh"#include "mem/cache/miss/mshr.hh"#include "mem/cache/prefetch/prefetcher.hh"#include "mem/bus/bus.hh"#include "mem/bus/slave_interface.hh"#include "mem/memory_interface.hh"#include "mem/bus/master_interface.hh"#include "mem/mem_debug.hh"#include "sim/sim_events.hh" // for SimExitEventusing namespace std;template<class TagStore, class Buffering, class Coherence>Cache<TagStore,Buffering,Coherence>::Cache(const std::string &_name, HierParams *hier_params,       Cache<TagStore,Buffering,Coherence>::Params &params)    : BaseCache(_name, hier_params, params.baseParams),      prefetchAccess(params.prefetchAccess),       tags(params.tags), missQueue(params.missQueue),      coherence(params.coherence), prefetcher(params.prefetcher),      doCopy(params.doCopy), blockOnCopy(params.blockOnCopy){    if (params.in == NULL) {	topLevelCache = true;    }    tags->setCache(this, params.out->width, params.out->clockRate);    tags->setPrefetcher(prefetcher);    missQueue->setCache(this);    missQueue->setPrefetcher(prefetcher);    coherence->setCache(this);    prefetcher->setCache(this);    prefetcher->setTags(tags);    prefetcher->setBuffer(missQueue);    invalidateReq = new MemReq;    invalidateReq->cmd = Invalidate;}template<class TagStore, class Buffering, class Coherence>voidCache<TagStore,Buffering,Coherence>::regStats(){    BaseCache::regStats();    tags->regStats(name());    missQueue->regStats(name());    coherence->regStats(name());    prefetcher->regStats(name());}template<class TagStore, class Buffering, class Coherence>MemAccessResultCache<TagStore,Buffering,Coherence>::access(MemReqPtr &req){    MemDebug::cacheAccess(req);    BlkType *blk = NULL;    MemReqList writebacks;    int size = blkSize;    int lat = hitLatency;    if (req->cmd == Copy) {	startCopy(req);	/**	 * @todo What return value makes sense on a copy.	 */	return MA_CACHE_MISS;    }    if (prefetchAccess) {	//We are determining prefetches on access stream, call prefetcher	prefetcher->handleMiss(req, curTick);    }    if (!req->isUncacheable()) {	if (req->cmd.isInvalidate() && !req->cmd.isRead()	    && !req->cmd.isWrite()) {	    //Upgrade or Invalidate	    //Look into what happens if two slave caches on bus	    DPRINTF(Cache, "%s %d %x ? blk_addr: %x\n", req->cmd.toString(),		    req->asid, req->paddr & (((ULL(1))<<48)-1),		    req->paddr & ~((Addr)blkSize - 1));	    //@todo Should this return latency have the hit latency in it?//	    respond(req,curTick+lat);	    req->flags |= SATISFIED;	    return MA_HIT;	}	blk = tags->handleAccess(req, lat, writebacks);    } else {	size = req->size;    }    // If this is a block size write/hint (WH64) allocate the block here    // if the coherence protocol allows it.    /** @todo make the fast write alloc (wh64) work with coherence. */    /** @todo Do we want to do fast writes for writebacks as well? */    if (!blk && req->size >= blkSize && coherence->allowFastWrites() && 	(req->cmd == Write || req->cmd == WriteInvalidate) ) {	// not outstanding misses, can do this	MSHR* outstanding_miss = missQueue->findMSHR(req->paddr, req->asid);	if (req->cmd ==WriteInvalidate || !outstanding_miss) {	    if (outstanding_miss) {		warn("WriteInv doing a fastallocate" 		     "with an outstanding miss to the same address\n");	    }	    blk = tags->handleFill(NULL, req, BlkValid | BlkWritable,				   writebacks);	    ++fastWrites;	}    }        while (!writebacks.empty()) {	missQueue->doWriteback(writebacks.front());	writebacks.pop_front();    }    DPRINTF(Cache, "%s %d %x %s blk_addr: %x pc %x\n", req->cmd.toString(),	    req->asid, req->paddr & (((ULL(1))<<48)-1), (blk) ? "hit" : "miss",	    req->paddr & ~((Addr)blkSize - 1), req->pc);    if (blk) {	// Hit	hits[req->cmd.toIndex()][req->thread_num]++;	// clear dirty bit if write through	if (!req->cmd.isNoResponse())	    respond(req, curTick+lat);	return MA_HIT;    }    // Miss    if (!req->isUncacheable()) {	misses[req->cmd.toIndex()][req->thread_num]++;	/** @todo Move miss count code into BaseCache */	if (missCount) {	    --missCount;	    if (missCount == 0)		new SimExitEvent("A cache reached the maximum miss count");	}    }    missQueue->handleMiss(req, size, curTick + hitLatency);    return MA_CACHE_MISS;}template<class TagStore, class Buffering, class Coherence>MemReqPtrCache<TagStore,Buffering,Coherence>::getMemReq(){    MemReqPtr req = missQueue->getMemReq();    if (req) {	if (!req->isUncacheable()) {	    if (req->cmd == Hard_Prefetch) misses[Hard_Prefetch][req->thread_num]++;	    BlkType *blk = tags->findBlock(req);	    MemCmd cmd = coherence->getBusCmd(req->cmd,	    				      (blk)? blk->status : 0);	    missQueue->setBusCmd(req, cmd);	}     }    assert(!doMasterRequest() || missQueue->havePending());    assert(!req || req->time <= curTick);    return req;}template<class TagStore, class Buffering, class Coherence>voidCache<TagStore,Buffering,Coherence>::sendResult(MemReqPtr &req, bool success){    if (success) {	missQueue->markInService(req);	  //Temp Hack for UPGRADES	  if (req->cmd == Upgrade) {	      handleResponse(req);	  }    } else if (req && !req->isUncacheable()) {	missQueue->restoreOrigCmd(req);    }}template<class TagStore, class Buffering, class Coherence>voidCache<TagStore,Buffering,Coherence>::handleResponse(MemReqPtr &req){    MemReqPtr copy_request;    BlkType *blk = NULL;    if (req->mshr) {	MemDebug::cacheResponse(req);	DPRINTF(Cache, "Handling reponse to %x, blk addr: %x\n",req->paddr,		req->paddr & (((ULL(1))<<48)-1));		if (req->isCacheFill() && !req->isNoAllocate()) {	    blk = tags->findBlock(req);	    CacheBlk::State old_state = (blk) ? blk->status : 0;	    MemReqList writebacks;	    blk = tags->handleFill(blk, req->mshr, 				   coherence->getNewState(req,old_state),				   writebacks);	    while (!writebacks.empty()) {		if (writebacks.front()->cmd == Copy) {		    copy_request = writebacks.front();		} else {		    missQueue->doWriteback(writebacks.front());		}		writebacks.pop_front();	    }	}	if (copy_request) {	    // The mshr is handled in handleCopy	    handleCopy(copy_request, req->paddr, blk, req->mshr);	} else {	    missQueue->handleResponse(req, curTick + hitLatency);	}    }}template<class TagStore, class Buffering, class Coherence>voidCache<TagStore,Buffering,Coherence>::pseudoFill(Addr addr, int asid){    // Need to temporarily move this blk into MSHRs    MSHR *mshr = missQueue->allocateTargetList(addr, asid);    int lat;    MemReqList dummy;    // Read the data into the mshr    BlkType *blk = tags->handleAccess(mshr->req, lat, dummy, false);    assert(dummy.empty());    assert(mshr->req->isSatisfied());    // can overload order since it isn't used on non pending blocks    mshr->order = blk->status;    // temporarily remove the block from the cache.    tags->invalidateBlk(addr, asid);}template<class TagStore, class Buffering, class Coherence>voidCache<TagStore,Buffering,Coherence>::pseudoFill(MSHR *mshr){    // Need to temporarily move this blk into MSHRs    assert(mshr->req->cmd == Read);    int lat;    MemReqList dummy;    // Read the data into the mshr    BlkType *blk = tags->handleAccess(mshr->req, lat, dummy, false);    assert(dummy.empty());    assert(mshr->req->isSatisfied());    // can overload order since it isn't used on non pending blocks    mshr->order = blk->status;    // temporarily remove the block from the cache.    tags->invalidateBlk(mshr->req->paddr, mshr->req->asid);}template<class TagStore, class Buffering, class Coherence>voidCache<TagStore,Buffering,Coherence>::startCopy(MemReqPtr &req){    MemDebug::cacheStartCopy(req);    bool delayed = false;    Addr source = req->paddr;    // Fake wh64 for additional copies    Addr dest = req->dest & ~(blkSize - 1);    int asid = req->asid;    cacheCopies++;        bool source_unaligned = source & (blkSize - 1);    bool dest_unaligned = dest & (blkSize - 1);    // Block addresses for unaligned accesses.    Addr source1 = source &  ~(Addr)(blkSize - 1);    Addr source2 = source1 + blkSize;    Addr dest1 = dest & ~(Addr)(blkSize - 1);    Addr dest2 = dest1 + blkSize;    MSHR *source1_mshr = missQueue->findMSHR(source1, asid);    MSHR *source2_mshr = missQueue->findMSHR(source2, asid);    MSHR *dest1_mshr = missQueue->findMSHR(dest1, asid);    MSHR *dest2_mshr = missQueue->findMSHR(dest2, asid);    if (source1_mshr) {	req->flags |= COPY_SOURCE1;	missQueue->addTarget(source1_mshr, req);    }    if (source2_mshr && source_unaligned) {	req->flags |= COPY_SOURCE2;	missQueue->addTarget(source2_mshr, req);    }    if (dest1_mshr) {	req->flags |= COPY_DEST1;	missQueue->addTarget(dest1_mshr, req);    }    if (dest2_mshr && dest_unaligned) {	req->flags |= COPY_DEST2;	missQueue->addTarget(dest2_mshr, req);    }    BlkType *source1_blk = tags->findBlock(source1, asid);    BlkType *source2_blk = tags->findBlock(source2, asid);    BlkType *dest1_blk = tags->findBlock(dest1, asid);    BlkType *dest2_blk = tags->findBlock(dest2, asid);    if (!doCopy) {	// Writeback sources if dirty.	if (source1_blk && source1_blk->isModified()) {	    MemReqPtr writeback = tags->writebackBlk(source1_blk);	    missQueue->doWriteback(writeback);	}	if (source_unaligned && source2_blk && source2_blk->isModified()) {	    MemReqPtr writeback = tags->writebackBlk(source2_blk);	    missQueue->doWriteback(writeback);	}		if (dest_unaligned) {	    // Need to writeback dirty destinations	    if (dest1_blk && dest1_blk->isModified()) {		MemReqPtr writeback = tags->writebackBlk(dest1_blk);		missQueue->doWriteback(writeback);	    }	    if (dest2_blk && dest2_blk->isModified()) {		MemReqPtr writeback = tags->writebackBlk(dest2_blk);		missQueue->doWriteback(writeback);

⌨️ 快捷键说明

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