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 ¶ms) : 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 + -
显示快捷键?