iic.cc

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

CC
872
字号
    }    // free the data blocks    for (int i = 0; i < tag_ptr->numData; ++i) {	data_ptr = tag_ptr->data_ptr[i];	assert(dataReferenceCount[data_ptr]>0);	if (--dataReferenceCount[data_ptr] == 0) {	    freeDataBlock(data_ptr);	}    }    freeTag(tag_ptr);}unsigned longIIC::getFreeDataBlock(MemReqList & writebacks){    struct IICTag *tag_ptr;    unsigned long data_ptr;    tag_ptr = NULL;    /* find data block */    while (blkFreelist.empty()) {	freeReplacementBlock(writebacks);    }    data_ptr = blkFreelist.front();    blkFreelist.pop_front();    DPRINTF(IICMore,"Found free data at %d\n",data_ptr);    return data_ptr;}IICTag*IIC::getFreeTag(int set, MemReqList & writebacks){    unsigned long tag_index;    IICTag *tag_ptr;    // Add new tag    tag_ptr = sets[set].findFree();    // if no free in primary, and secondary exists    if (!tag_ptr && numSecondary) {	// need to spill a tag into secondary storage	while (freelist == tagNull) {	    // get replacements until one is in secondary	    freeReplacementBlock(writebacks);	}	tag_index = freelist;	freelist = tagStore[freelist].chain_ptr;	freeSecond--;	assert(tag_index != tagNull);	tagSwap(tag_index, sets[set].tags[assoc-1] - tagStore);	tagStore[tag_index].chain_ptr = sets[set].chain_ptr;	sets[set].chain_ptr = tag_index;	tag_ptr = sets[set].tags[assoc-1];    }    DPRINTF(IICMore,"Found free tag at %d\n",tag_ptr - tagStore);    tagsInUse++;    if (!warmedUp && tagsInUse.value() >= warmupBound) {	warmedUp = true;	warmupCycle = curTick;    }           return tag_ptr;}voidIIC::freeTag(IICTag *tag_ptr){    unsigned long tag_index, tmp_index;    // Fix tag_ptr    if (tag_ptr) {	// we have a tag to clear	DPRINTF(IICMore,"Freeing Tag for %x\n",		regenerateBlkAddr(tag_ptr->tag,0));	tagsInUse--;	tag_ptr->status = 0;	tag_ptr->numData = 0;	tag_ptr->re = NULL;	tag_index = tag_ptr - tagStore;	if (tag_index >= primaryBound) {	    // tag_ptr points to secondary store	    assert(tag_index < tagNull); // remove this?? egh	    if (tag_ptr->chain_ptr == tagNull) {		// need to fix chain list		unsigned tmp_set = hash(tag_ptr->tag << tagShift);		if (sets[tmp_set].chain_ptr == tag_index) {		    sets[tmp_set].chain_ptr = tagNull;		} else {		    tmp_index = sets[tmp_set].chain_ptr;		    while (tmp_index != tagNull			   && tagStore[tmp_index].chain_ptr != tag_index) {			tmp_index = tagStore[tmp_index].chain_ptr;		    }		    assert(tmp_index != tagNull);		    tagStore[tmp_index].chain_ptr = tagNull;		}		tag_ptr->chain_ptr = freelist;		freelist = tag_index;		freeSecond++;	    } else {		// copy next chained entry to this tag location		tmp_index = tag_ptr->chain_ptr;		tagSwap(tmp_index, tag_index);		tagStore[tmp_index].chain_ptr = freelist;		freelist = tmp_index;		freeSecond++;	    }	} else {	    // tag_ptr in primary hash table	    assert(tag_index < primaryBound);	    tag_ptr->status = 0;	    unsigned tmp_set = hash(tag_ptr->tag << tagShift);	    if (sets[tmp_set].chain_ptr != tagNull) { // collapse chain		tmp_index = sets[tmp_set].chain_ptr;		tagSwap(tag_index, tmp_index);		tagStore[tmp_index].chain_ptr = freelist;		freelist = tmp_index;		freeSecond++;		sets[tmp_set].chain_ptr = tag_ptr->chain_ptr;		sets[tmp_set].moveToTail(tag_ptr);	    }	}    }}voidIIC::freeDataBlock(unsigned long data_ptr){    assert(dataReferenceCount[data_ptr] == 0);    DPRINTF(IICMore, "Freeing data at %d\n", data_ptr);    blkFreelist.push_front(data_ptr);}/** Use a simple modulo hash. */#define SIMPLE_HASH 0unsignedIIC::hash(Addr addr) const {#if SIMPLE_HASH    return extractTag(addr) % iic_hash_size;#else    Addr tag, mask, x, y;    tag = extractTag(addr);    mask = hashSets-1; /* assumes iic_hash_size is a power of 2 */    x = tag & mask;    y = (tag >> (int)(::log(hashSets)/::log(2))) & mask;    assert (x < hashSets && y < hashSets);    return x ^ y;#endif}voidIICSet::moveToHead(IICTag *tag){    if (tags[0] == tag)	return;    // write 'next' block into blks[i], moving up from MRU toward LRU    // until we overwrite the block we moved to head.    // start by setting up to write 'blk' into blks[0]    int i = 0;    IICTag *next = tag;    do {	assert(i < assoc);	// swap blks[i] and next	IICTag *tmp = tags[i];	tags[i] = next;	next = tmp;	++i;    } while (next != tag);}voidIICSet::moveToTail(IICTag *tag){    if (tags[assoc-1] == tag)	return;    // write 'next' block into blks[i], moving up from MRU toward LRU    // until we overwrite the block we moved to head.    // start by setting up to write 'blk' into blks[0]    int i = assoc - 1;    IICTag *next = tag;    do {	assert(i >= 0);	// swap blks[i] and next	IICTag *tmp = tags[i];	tags[i] = next;	next = tmp;	--i;    } while (next != tag);}voidIIC::tagSwap(unsigned long index1, unsigned long index2){    DPRINTF(IIC,"Swapping tag[%d]=%x for tag[%d]=%x\n",index1,	    tagStore[index1].tag<<tagShift, index2,	    tagStore[index2].tag<<tagShift);    IICTag tmp_tag;    tmp_tag = tagStore[index1];    tagStore[index1] = tagStore[index2];    tagStore[index2] = tmp_tag;    if (tagStore[index1].isValid())	repl->fixTag(tagStore[index1].re, index2, index1);    if (tagStore[index2].isValid())	repl->fixTag(tagStore[index2].re, index1, index2);}IICTag *IIC::secondaryChain(int asid, Addr tag, unsigned long chain_ptr,		    int *_depth) const{    int depth = 0;    while (chain_ptr != tagNull) {	DPRINTF(IIC,"Searching secondary at %d for %x\n", chain_ptr,		tag<<tagShift);	if (tagStore[chain_ptr].tag == tag &&	    tagStore[chain_ptr].asid == asid &&	    (tagStore[chain_ptr].isValid())) {	    *_depth = depth;	    return &tagStore[chain_ptr];	}	depth++;	chain_ptr = tagStore[chain_ptr].chain_ptr;    }    *_depth = depth;    return NULL;}voidIIC::decompressBlock(unsigned long index){    IICTag *tag_ptr = &tagStore[index];    if (tag_ptr->isCompressed()) {	// decompress the data here.    }}voidIIC::compressBlock(unsigned long index){    IICTag *tag_ptr = &tagStore[index];    if (!tag_ptr->isCompressed()) {	// Compress the data here.    }}voidIIC::invalidateBlk(int asid, Addr addr){    IICTag* tag_ptr = findBlock(addr, asid);    if (tag_ptr) {	for (int i = 0; i < tag_ptr->numData; ++i) {	    dataReferenceCount[tag_ptr->data_ptr[i]]--;	    if (dataReferenceCount[tag_ptr->data_ptr[i]] == 0) {		freeDataBlock(tag_ptr->data_ptr[i]);	    }	}	repl->removeEntry(tag_ptr->re);	freeTag(tag_ptr);    }}voidIIC::readData(IICTag *blk, uint8_t *data){    assert(cache->doData());    assert(blk->size <= trivialSize || blk->numData > 0);    int data_size = blk->size;    if (data_size > trivialSize) {	for (int i = 0; i < blk->numData; ++i){	    memcpy(data+i*subSize,		   &(dataBlks[blk->data_ptr[i]][0]),		   (data_size>subSize)?subSize:data_size);	    data_size -= subSize;	}    } else {	memcpy(data,blk->trivialData,data_size);    }}voidIIC::writeData(IICTag *blk, uint8_t *write_data, int size,	       MemReqList & writebacks){    assert(cache->doData());    assert(size < blkSize || !blk->isCompressed());    DPRINTF(IIC, "Writing %d bytes to %x\n", size,	    blk->tag<<tagShift);    // Find the number of subblocks needed, (round up)    int num_subs = (size + (subSize -1))/subSize;    if (size <= trivialSize) {	num_subs = 0;    }    assert(num_subs <= numSub);    if (num_subs > blk->numData) {	// need to allocate more data blocks	for (int i = blk->numData; i < num_subs; ++i){	    blk->data_ptr[i] = getFreeDataBlock(writebacks);	    dataReferenceCount[blk->data_ptr[i]] += 1;	}    } else if (num_subs < blk->numData){	// can free data blocks	for (int i=num_subs; i < blk->numData; ++i){	    // decrement reference count and compare to zero	    /**	     * @todo	     * Make this work with copying.	     */	    if (--dataReferenceCount[blk->data_ptr[i]] == 0) {		freeDataBlock(blk->data_ptr[i]);	    }	}    }    blk->numData = num_subs;    blk->size = size;    assert(size <= trivialSize || blk->numData > 0);    if (size > trivialSize){	for (int i = 0; i < blk->numData; ++i){	    memcpy(&dataBlks[blk->data_ptr[i]][0], write_data + i*subSize,		   (size>subSize)?subSize:size);	    size -= subSize;	}    } else {	memcpy(blk->trivialData,write_data,size);    }}/** * @todo This code can break if the src is evicted to get a tag for the dest. */void IIC::doCopy(Addr source, Addr dest, int asid, MemReqList &writebacks){    IICTag *dest_tag = findBlock(dest, asid);    if (dest_tag) {	for (int i = 0; i < dest_tag->numData; ++i) {	    if (--dataReferenceCount[dest_tag->data_ptr[i]] == 0) {		freeDataBlock(dest_tag->data_ptr[i]);	    }	}	// Reset replacement entry    } else {	dest_tag = getFreeTag(hash(dest), writebacks);	dest_tag->re = (void*) repl->add(dest_tag - tagStore);	dest_tag->set = hash(dest);	dest_tag->tag = extractTag(dest);	dest_tag->asid = asid;	dest_tag->status = BlkValid | BlkWritable;    }    // Find the source tag here since it might move if we need to find a     // tag for the destination.    IICTag *src_tag = findBlock(source, asid);    assert(src_tag);    assert(!cache->doData() || src_tag->size <= trivialSize 	   || src_tag->numData > 0);    // point dest to source data and inc counter    for (int i = 0; i < src_tag->numData; ++i) {	dest_tag->data_ptr[i] = src_tag->data_ptr[i];	++dataReferenceCount[dest_tag->data_ptr[i]];    }    // Maintain fast access data.    memcpy(dest_tag->data, src_tag->data, blkSize);        dest_tag->xc = src_tag->xc;    dest_tag->size = src_tag->size;    dest_tag->numData = src_tag->numData;    if (src_tag->numData == 0) {	// Data is stored in the trivial data, just copy it.	memcpy(dest_tag->trivialData, src_tag->trivialData, src_tag->size);    }        dest_tag->status |= BlkDirty;    if (dest_tag->size < blkSize) {	dest_tag->status |= BlkCompressed;    } else {	dest_tag->status &= ~BlkCompressed;    }}voidIIC::fixCopy(MemReqPtr &req, MemReqList &writebacks){    // if reference counter is greater than 1, do copy    // else do write    Addr blk_addr = blkAlign(req->paddr);    IICTag* blk = findBlock(blk_addr, req->asid);    if (blk->numData > 0 && dataReferenceCount[blk->data_ptr[0]] != 1) {	// copy the data	// Mark the block as referenced so it doesn't get replaced.	blk->status |= BlkReferenced;	for (int i = 0; i < blk->numData; ++i){	    unsigned long new_data = getFreeDataBlock(writebacks);	    // Need to refresh pointer	    /**	     * @todo Remove this refetch once we change IIC to pointer based	     */	    blk = findBlock(blk_addr, req->asid);	    assert(blk);	    if (cache->doData()) {		memcpy(&(dataBlks[new_data][0]),		       &(dataBlks[blk->data_ptr[i]][0]), 		       subSize);	    }	    dataReferenceCount[blk->data_ptr[i]]--;	    dataReferenceCount[new_data]++;	    blk->data_ptr[i] = new_data;	}    }}voidIIC::cleanupRefs(){    for (int i = 0; i < numTags; ++i) {	if (tagStore[i].isValid()) {	    totalRefs += tagStore[i].refCount;	    ++sampledRefs;	}    }}

⌨️ 快捷键说明

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