iic.cc

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

CC
872
字号
/* * 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 * Definitions of the Indirect Index Cache tagstore. */#include <algorithm>#include <string>#include <vector>#include <sstream>#include <math.h>#include "mem/cache/base_cache.hh"#include "mem/cache/tags/iic.hh"#include "base/intmath.hh"#include "sim/root.hh" // for curTick#include "base/trace.hh" // for DPRINTFusing namespace std;/** Track the number of accesses to each cache set. */#define PROFILE_IIC 1IIC::IIC(IIC::Params &params) :    hashSets(params.numSets), blkSize(params.blkSize), assoc(params.assoc),     hitLatency(params.hitLatency), subSize(params.subblockSize),     numSub(blkSize/subSize),    trivialSize((FloorLog2(params.size/subSize)*numSub)/8),     tagShift(FloorLog2(blkSize)), blkMask(blkSize - 1),    subShift(FloorLog2(subSize)), subMask(numSub - 1),    hashDelay(params.hashDelay),    numBlocks(params.size/subSize),     numTags(hashSets * assoc + params.size/blkSize -1),     numSecondary(params.size/blkSize),    tagNull(numTags),    primaryBound(hashSets * assoc){    int i;    // Check parameters    if (blkSize < 4 || ((blkSize & (blkSize - 1)) != 0)) {	fatal("Block size must be at least 4 and a power of 2");    }    if (hashSets <= 0 || ((hashSets & (hashSets - 1)) != 0)) {	fatal("# of hashsets must be non-zero and a power of 2");    }    if (assoc <= 0) {	fatal("associativity must be greater than zero");    }    if (hitLatency <= 0) {	fatal("access latency must be greater than zero");    }    if (numSub*subSize != blkSize) {	fatal("blocksize must be evenly divisible by subblock size");    }    // debug stuff     freeSecond = numSecondary;    warmedUp = false;    warmupBound = params.size/blkSize;      // Replacement Policy Initialization    repl = params.rp;    repl->setIIC(this);    //last_miss_time = 0        // allocate data reference counters    dataReferenceCount = new int[numBlocks];    memset(dataReferenceCount, 0, numBlocks*sizeof(int));    // Allocate storage for both internal data and block fast access data.    // We allocate it as one large chunk to reduce overhead and to make     // deletion easier.    int data_index = 0;    dataStore = new uint8_t[(numBlocks + numTags) * blkSize];    dataBlks = new uint8_t*[numBlocks];    for (i = 0; i < numBlocks; ++i) {	dataBlks[i] = &dataStore[data_index];	freeDataBlock(i);	data_index += subSize;    }    assert(data_index == numBlocks * subSize);    // allocate and init tag store    tagStore = new IICTag[numTags];        int blkIndex = 0;    // allocate and init sets    sets = new IICSet[hashSets];    for (i = 0; i < hashSets; ++i) {	sets[i].assoc = assoc;	sets[i].tags = new IICTag*[assoc];	sets[i].chain_ptr = tagNull;		for (int j = 0; j < assoc; ++j) {	    IICTag *tag = &tagStore[blkIndex++];	    tag->chain_ptr = tagNull;	    tag->data_ptr.resize(numSub);	    tag->size = blkSize;	    tag->trivialData = new uint8_t[trivialSize];	    tag->numData = 0;	    sets[i].tags[j] = tag;	    tag->set = i;	    tag->data = &dataStore[data_index];	    data_index += blkSize;	}    }        assert(blkIndex == primaryBound);        for (i = primaryBound; i < tagNull; i++) {	tagStore[i].chain_ptr = i+1;	//setup data ptrs to subblocks	tagStore[i].data_ptr.resize(numSub);	tagStore[i].size = blkSize;	tagStore[i].trivialData = new uint8_t[trivialSize];	tagStore[i].numData = 0;	tagStore[i].set = 0;	tagStore[i].data = &dataStore[data_index];	data_index += blkSize;    }    freelist = primaryBound;}IIC::~IIC(){    delete [] dataReferenceCount;    delete [] dataStore;    delete [] tagStore;    delete [] sets;}/* register cache stats */voidIIC::regStats(const string &name){    using namespace Stats;    BaseTags::regStats(name);    hitHashDepth.init(0, 20, 1);    missHashDepth.init(0, 20, 1);    setAccess.init(0, hashSets, 1);    /** IIC Statistics */    hitHashDepth	.name(name + ".hit_hash_depth_dist")	.desc("Dist. of Hash lookup depths")	.flags(pdf)	;    missHashDepth	.name(name + ".miss_hash_depth_dist")	.desc("Dist. of Hash lookup depths")	.flags(pdf)	;    repl->regStats(name);    if (PROFILE_IIC)	setAccess	    .name(name + ".set_access_dist")	    .desc("Dist. of Accesses across sets")	    .flags(pdf)	    ;    missDepthTotal	.name(name + ".miss_depth_total")	.desc("Total of miss depths")	;    hashMiss	.name(name + ".hash_miss")	.desc("Total of misses in hash table")	;    hitDepthTotal	.name(name + ".hit_depth_total")	.desc("Total of hit depths")	;    hashHit	.name(name + ".hash_hit")	.desc("Total of hites in hash table")	;}// probe cache for presence of given block.boolIIC::probe(int asid, Addr addr) const{    return (findBlock(addr,asid) != NULL);}IICTag*IIC::findBlock(Addr addr, int asid, int &lat){    Addr tag = extractTag(addr);    unsigned set = hash(addr);    int set_lat;    unsigned long chain_ptr;    if (PROFILE_IIC)	setAccess.sample(set);    IICTag *tag_ptr = sets[set].findTag(asid, tag, chain_ptr);    set_lat = 1;    if (tag_ptr == NULL && chain_ptr != tagNull) {	int secondary_depth;	tag_ptr = secondaryChain(asid, tag, chain_ptr, &secondary_depth);	set_lat += secondary_depth;	// set depth for statistics fix this later!!! egh	sets[set].depth = set_lat;	if (tag_ptr != NULL) {	    /* need to move tag into primary table */	    // need to preserve chain: fix this egh	    sets[set].tags[assoc-1]->chain_ptr = tag_ptr->chain_ptr;	    tagSwap(tag_ptr - tagStore, sets[set].tags[assoc-1] - tagStore);	    tag_ptr = sets[set].findTag(asid, tag, chain_ptr);	    assert(tag_ptr!=NULL);	}    }    set_lat = set_lat * hashDelay + hitLatency;    if (tag_ptr != NULL) {	// IIC replacement: if this is not the first element of	//   list, reorder	sets[set].moveToHead(tag_ptr);	    	hitHashDepth.sample(sets[set].depth);	hashHit++;	hitDepthTotal += sets[set].depth;	tag_ptr->status |= BlkReferenced;	lat = set_lat;	if (tag_ptr->whenReady > curTick && tag_ptr->whenReady - curTick > set_lat) {	    lat = tag_ptr->whenReady - curTick;	}	tag_ptr->refCount += 1;    }    else {	// fall through: cache block not found, not a hit...	missHashDepth.sample(sets[set].depth);	hashMiss++;	missDepthTotal += sets[set].depth;	lat = set_lat;    }    return tag_ptr;}IICTag*IIC::findBlock(MemReqPtr &req, int &lat){    Addr addr = req->paddr;    int asid = req->asid;    Addr tag = extractTag(addr);    unsigned set = hash(addr);    int set_lat;    unsigned long chain_ptr;    if (PROFILE_IIC)	setAccess.sample(set);    IICTag *tag_ptr = sets[set].findTag(asid, tag, chain_ptr);    set_lat = 1;    if (tag_ptr == NULL && chain_ptr != tagNull) {	int secondary_depth;	tag_ptr = secondaryChain(asid, tag, chain_ptr, &secondary_depth);	set_lat += secondary_depth;	// set depth for statistics fix this later!!! egh	sets[set].depth = set_lat;	if (tag_ptr != NULL) {	    /* need to move tag into primary table */	    // need to preserve chain: fix this egh	    sets[set].tags[assoc-1]->chain_ptr = tag_ptr->chain_ptr;	    tagSwap(tag_ptr - tagStore, sets[set].tags[assoc-1] - tagStore);	    tag_ptr = sets[set].findTag(asid, tag, chain_ptr);	    assert(tag_ptr!=NULL);	}    }    set_lat = set_lat * hashDelay + hitLatency;    if (tag_ptr != NULL) {	// IIC replacement: if this is not the first element of	//   list, reorder	sets[set].moveToHead(tag_ptr);	    	hitHashDepth.sample(sets[set].depth);	hashHit++;	hitDepthTotal += sets[set].depth;	tag_ptr->status |= BlkReferenced;	lat = set_lat;	if (tag_ptr->whenReady > curTick && tag_ptr->whenReady - curTick > set_lat) {	    lat = tag_ptr->whenReady - curTick;	}	tag_ptr->refCount += 1;    }    else {	// fall through: cache block not found, not a hit...	missHashDepth.sample(sets[set].depth);	hashMiss++;	missDepthTotal += sets[set].depth;	lat = set_lat;    }    return tag_ptr;}IICTag*IIC::findBlock(Addr addr, int asid) const{    Addr tag = extractTag(addr);    unsigned set = hash(addr);    unsigned long chain_ptr;    IICTag *tag_ptr = sets[set].findTag(asid, tag, chain_ptr);    if (tag_ptr == NULL && chain_ptr != tagNull) {	int secondary_depth;	tag_ptr = secondaryChain(asid, tag, chain_ptr, &secondary_depth);    }    return tag_ptr;}IICTag*IIC::findReplacement(MemReqPtr &req, MemReqList &writebacks,		     BlkList &compress_blocks){    DPRINTF(IIC, "Finding Replacement for %x\n", req->paddr);    unsigned set = hash(req->paddr);    IICTag *tag_ptr;    unsigned long *tmp_data = new unsigned long[numSub];    // Get a enough subblocks for a full cache line    for (int i = 0; i < numSub; ++i){	tmp_data[i] = getFreeDataBlock(writebacks);	assert(dataReferenceCount[tmp_data[i]]==0);    }    tag_ptr = getFreeTag(set, writebacks);    tag_ptr->set = set;    for (int i=0; i< numSub; ++i) {	tag_ptr->data_ptr[i] = tmp_data[i];	dataReferenceCount[tag_ptr->data_ptr[i]]++;    }    tag_ptr->numData = numSub;    assert(tag_ptr - tagStore < primaryBound); // make sure it is in primary    tag_ptr->chain_ptr = tagNull;    sets[set].moveToHead(tag_ptr);    delete [] tmp_data;    list<unsigned long> tag_indexes;    repl->doAdvance(tag_indexes);    while (!tag_indexes.empty()) {	if (!tagStore[tag_indexes.front()].isCompressed()) {	    compress_blocks.push_back(&tagStore[tag_indexes.front()]);	}	tag_indexes.pop_front();    }    tag_ptr->re = (void*)repl->add(tag_ptr-tagStore);    return tag_ptr;}voidIIC::freeReplacementBlock(MemReqList & writebacks){    IICTag *tag_ptr;    unsigned long data_ptr;    /* consult replacement policy */    tag_ptr = &tagStore[repl->getRepl()];    assert(tag_ptr->isValid());    DPRINTF(Cache, "Replacing %x in IIC: %s\n",	    regenerateBlkAddr(tag_ptr->tag,0),	    tag_ptr->isModified() ? "writeback" : "clean");    /* write back replaced block data */    if (tag_ptr && (tag_ptr->isValid())) {	int thread_num = (tag_ptr->xc) ? tag_ptr->xc->thread_num : 0;	replacements[thread_num]++;	totalRefs += tag_ptr->refCount;	++sampledRefs;	tag_ptr->refCount = 0;	if (tag_ptr->isModified()) {	    MemReqPtr writeback = 		buildWritebackReq(regenerateBlkAddr(tag_ptr->tag, 0), 				  tag_ptr->asid, tag_ptr->xc, blkSize,				  (cache->doData())?tag_ptr->data:0, 				  tag_ptr->size);	    writebacks.push_back(writeback);	}

⌨️ 快捷键说明

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