opt_cpu.cc

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

CC
243
字号
/* * Copyright (c) 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 * Definition of a memory trace CPU object for optimal caches. Uses a memory  * trace to access a fully associative cache with optimal replacement. */#include <algorithm> // For heap functions.#include "cpu/trace/opt_cpu.hh"#include "cpu/trace/reader/mem_trace_reader.hh"#include "sim/builder.hh"#include "sim/sim_events.hh"using namespace std;OptCPU::OptCPU(const string &name,	       MemTraceReader *_trace,	       int block_size,	       int cache_size,	       int _assoc)    : SimObject(name), tickEvent(this), trace(_trace),      numBlks(cache_size/block_size), assoc(_assoc), numSets(numBlks/assoc),      setMask(numSets - 1){    int log_block_size = 0;    int tmp_block_size = block_size;    while (tmp_block_size > 1) {	++log_block_size;	tmp_block_size = tmp_block_size >> 1;    }    assert(1<<log_block_size == block_size);    MemReqPtr req;    trace->getNextReq(req);    refInfo.resize(numSets);    while (req) {	RefInfo temp;	temp.addr = req->paddr >> log_block_size;	int set = temp.addr & setMask;	refInfo[set].push_back(temp);	trace->getNextReq(req);    }    // Initialize top level of lookup table.    lookupTable.resize(16);        // Annotate references with next ref time.    for (int k = 0; k < numSets; ++k) {	for (RefIndex i = refInfo[k].size() - 1; i >= 0; --i) {	    Addr addr = refInfo[k][i].addr;	    initTable(addr, InfiniteRef);	    refInfo[k][i].nextRefTime = lookupValue(addr);	    setValue(addr, i);	}    }        // Reset the lookup table    for (int j = 0; j < 16; ++j) {	if (lookupTable[j].size() == (1<<16)) {	    for (int k = 0; k < (1<<16); ++k) {		if (lookupTable[j][k].size() == (1<<16)) {		    for (int l = 0; l < (1<<16); ++l) {			lookupTable[j][k][l] = -1;		    }		}	    }	}    }        tickEvent.schedule(0);    hits = 0;    misses = 0;}voidOptCPU::processSet(int set){    // Initialize cache    int blks_in_cache = 0;    RefIndex i = 0;    cacheHeap.clear();    cacheHeap.resize(assoc);        while (blks_in_cache < assoc) {	RefIndex cache_index = lookupValue(refInfo[set][i].addr);	if (cache_index == -1) {	    // First reference to this block	    misses++;	    cache_index = blks_in_cache++;	    setValue(refInfo[set][i].addr, cache_index);	} else {	    hits++;	}	// update cache heap to most recent reference	cacheHeap[cache_index] = i;	if (++i >= refInfo[set].size()) {	    return;	}    }    for (int start = assoc/2; start >= 0; --start) {	heapify(set,start);    }    //verifyHeap(set,0);        for (; i < refInfo[set].size(); ++i) {	RefIndex cache_index = lookupValue(refInfo[set][i].addr);	if (cache_index == -1) {	    // miss	    misses++;	    // replace from cacheHeap[0]	    // mark replaced block as absent	    setValue(refInfo[set][cacheHeap[0]].addr, -1);	    setValue(refInfo[set][i].addr, 0);	    cacheHeap[0] = i;	    heapify(set, 0);	    // Make sure its in the cache	    assert(lookupValue(refInfo[set][i].addr) != -1);	} else {	    // hit	    hits++;	    assert(refInfo[set][cacheHeap[cache_index]].addr == 		   refInfo[set][i].addr);	    assert(refInfo[set][cacheHeap[cache_index]].nextRefTime == i);	    assert(heapLeft(cache_index) >= assoc);	    	    cacheHeap[cache_index] = i;	    processRankIncrease(set, cache_index);	    assert(lookupValue(refInfo[set][i].addr) != -1);	}    }  }voidOptCPU::tick(){    // Do opt simulation        int references = 0;    for (int set = 0; set < numSets; ++set) {	if (!refInfo[set].empty()) {	    processSet(set);	}	references += refInfo[set].size();    }    // exit;    fprintf(stderr,"sys.cpu.misses %d #opt cache misses\n",misses);    fprintf(stderr,"sys.cpu.hits %d #opt cache hits\n", hits);    fprintf(stderr,"sys.cpu.accesses %d #opt cache acceses\n", references);    new SimExitEvent("Finshed Memory Trace");}voidOptCPU::initTable(Addr addr, RefIndex index){    int l1_index = (addr >> 32) & 0x0f;    int l2_index = (addr >> 16) & 0xffff;    assert(l1_index == addr >> 32);    if (lookupTable[l1_index].size() != (1<<16)) {	lookupTable[l1_index].resize(1<<16);    }    if (lookupTable[l1_index][l2_index].size() != (1<<16)) {	lookupTable[l1_index][l2_index].resize(1<<16, index);    }}OptCPU::TickEvent::TickEvent(OptCPU *c)    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c){}voidOptCPU::TickEvent::process(){    cpu->tick();}const char *OptCPU::TickEvent::description(){    return "OptCPU tick event";}BEGIN_DECLARE_SIM_OBJECT_PARAMS(OptCPU)      SimObjectParam<MemTraceReader *> data_trace;     Param<int> size;    Param<int> block_size;Param<int> assoc;END_DECLARE_SIM_OBJECT_PARAMS(OptCPU)BEGIN_INIT_SIM_OBJECT_PARAMS(OptCPU)    INIT_PARAM_DFLT(data_trace, "memory trace", NULL),    INIT_PARAM(size, "cache size"),    INIT_PARAM(block_size, "block size"),    INIT_PARAM(assoc,"associativity")    END_INIT_SIM_OBJECT_PARAMS(OptCPU)CREATE_SIM_OBJECT(OptCPU){    return new OptCPU(getInstanceName(),		      data_trace,		      block_size,		      size,		      assoc);}REGISTER_SIM_OBJECT("OptCPU", OptCPU)

⌨️ 快捷键说明

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