base_prefetcher.cc

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

CC
256
字号
/* * Copyright (c) 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 * Hardware Prefetcher Definition. */#include "base/trace.hh"#include "cpu/exec_context.hh"#include "mem/cache/base_cache.hh"#include "mem/cache/miss/miss_queue.hh"#include "mem/cache/prefetch/base_prefetcher.hh"#include "mem/cache/tags/cache_tags.hh"#include "cpu/exec_context.hh"#include <list>BasePrefetcher::BasePrefetcher(int size, bool pageStop, bool serialSquash,			       bool cacheCheckPush, bool onlyData)    :size(size), pageStop(pageStop), serialSquash(serialSquash),     cacheCheckPush(cacheCheckPush), only_data(onlyData){}void BasePrefetcher::setCache(BaseCache *_cache){    cache = _cache;    blkSize = cache->getBlockSize();}void BasePrefetcher::regStats(const std::string &name){    pfIdentified	.name(name + ".prefetcher.num_hwpf_identified")	.desc("number of hwpf identified")	;    pfMSHRHit	.name(name + ".prefetcher.num_hwpf_already_in_mshr")	.desc("number of hwpf that were already in mshr")	;        pfCacheHit	.name(name + ".prefetcher.num_hwpf_already_in_cache")	.desc("number of hwpf that were already in the cache")	;        pfBufferHit	.name(name + ".prefetcher.num_hwpf_already_in_prefetcher")	.desc("number of hwpf that were already in the prefetch queue")	;    pfRemovedFull	.name(name + ".prefetcher.num_hwpf_evicted")	.desc("number of hwpf removed due to no buffer left")	;        pfRemovedMSHR	.name(name + ".prefetcher.num_hwpf_removed_MSHR_hit")	.desc("number of hwpf removed because MSHR allocated")	;    pfIssued	.name(name + ".prefetcher.num_hwpf_issued")	.desc("number of hwpf issued")	;        pfSpanPage	.name(name + ".prefetcher.num_hwpf_span_page")	.desc("number of hwpf spanning a virtual page")	;    pfSquashed	.name(name + ".prefetcher.num_hwpf_squashed_from_miss")	.desc("number of hwpf that got squashed due to a miss aborting calculation time")	;}MemReqPtr BasePrefetcher::getMemReq(){    DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name());    if (pf.empty()) {	DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name());	return NULL;    }    MemReqPtr req;    bool keepTrying = false;    do {	req = *pf.begin();	pf.pop_front();	if (!cacheCheckPush) {	    keepTrying = inCache(req);	}	if (pf.empty()) {	    cache->clearMasterRequest(Request_PF);	    if (keepTrying) return NULL; //None left, all were in cache 	}    } while (keepTrying);    pfIssued++;    return req;}voidBasePrefetcher::handleMiss(MemReqPtr &req, Tick time){    if (!req->isUncacheable() && !(req->isInstRead() && only_data))    {	//Calculate the blk address	Addr blkAddr = req->paddr & ~(Addr)(blkSize-1);	//Check if miss is in pfq, if so remove it	std::list<MemReqPtr>::iterator iter = inPrefetch(blkAddr);	if (iter != pf.end()) {	    DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name());	    pfRemovedMSHR++;	    pf.erase(iter);	    if (pf.empty()) 		cache->clearMasterRequest(Request_PF);	}		//Remove anything in queue with delay older than time	//since everything is inserted in time order, start from end 	//and work until pf.empty() or time is earlier	//This is done to emulate Aborting the previous work on a new miss	//Needed for serial calculators like GHB	if (serialSquash) {	    iter = pf.end();	    iter--;	    while (!pf.empty() && ((*iter)->time >= time)) {		pfSquashed++;		pf.pop_back();		iter--;	    } 	    if (pf.empty())		cache->clearMasterRequest(Request_PF);	}		std::list<Addr> addresses;	std::list<Tick> delays;	calculatePrefetch(req, addresses, delays);		std::list<Addr>::iterator addr = addresses.begin();	std::list<Tick>::iterator delay = delays.begin();	while (addr != addresses.end())	{	    DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name());	    //temp calc this here...	    pfIdentified++;	    //create a prefetch memreq	    MemReqPtr prefetch;	    prefetch = new MemReq();	    prefetch->paddr = (*addr);	    prefetch->size = blkSize;	    prefetch->cmd = Hard_Prefetch;	    prefetch->xc = req->xc;	    prefetch->data = new uint8_t[blkSize];	    prefetch->asid = req->asid;	    prefetch->thread_num = req->thread_num;	    prefetch->time = time + (*delay); //@todo ADD LATENCY HERE	    //... initialize	    	    //Check if it is already in the cache 	    if (cacheCheckPush) {		if (inCache(prefetch)) {		    addr++;		    delay++;		    continue;		}	    }	    //Check if it is already in the miss_queue	    if (inMissQueue(prefetch->paddr, prefetch->asid)) {		addr++;		delay++;		continue;	    }	    //Check if it is already in the pf buffer	    if (inPrefetch(prefetch->paddr) != pf.end()) {		pfBufferHit++;		addr++;		delay++;		continue;	    }	    	    //We just remove the head if we are full	    if (pf.size() == size)	    {		DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name());		pfRemovedFull++;		pf.pop_front();	    }	    	    pf.push_back(prefetch);	    prefetch->flags |= CACHE_LINE_FILL;	    	    //Make sure to request the bus, with proper delay	    cache->setMasterRequest(Request_PF, prefetch->time);	    //Increment through the list	    addr++;	    delay++;	}    }}std::list<MemReqPtr>::iteratorBasePrefetcher::inPrefetch(Addr address){    //Guaranteed to only be one match, we always check before inserting    std::list<MemReqPtr>::iterator iter;    for (iter=pf.begin(); iter != pf.end(); iter++) {	if (((*iter)->paddr & ~(Addr)(blkSize-1)) == address) {	    return iter;	}    }    return pf.end();}

⌨️ 快捷键说明

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