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 + -
显示快捷键?