iic.cc

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 707 行 · 第 1/2 页

CC
707
字号
    assert(tag_ptr->isValid());    DPRINTF(Cache, "Replacing %x in IIC: %s\n",            regenerateBlkAddr(tag_ptr->tag,0),            tag_ptr->isDirty() ? "writeback" : "clean");    /* write back replaced block data */    if (tag_ptr && (tag_ptr->isValid())) {        replacements[0]++;        totalRefs += tag_ptr->refCount;        ++sampledRefs;        tag_ptr->refCount = 0;        if (tag_ptr->isDirty()) {/*	    PacketPtr writeback =                buildWritebackReq(regenerateBlkAddr(tag_ptr->tag, 0),                                  tag_ptr->req->asid, tag_ptr->xc, blkSize,                                  tag_ptr->data,                                  tag_ptr->size);*/            Request *writebackReq = new Request(regenerateBlkAddr(tag_ptr->tag, 0),                                           blkSize, 0);            PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback,                                             -1);            writeback->allocate();            memcpy(writeback->getPtr<uint8_t>(), tag_ptr->data, blkSize);            writebacks.push_back(writeback);        }    }    // 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(PacketList & 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, PacketList & 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((double)hashSets)/::log((double)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(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].isValid())) {            *_depth = depth;            return &tagStore[chain_ptr];        }        depth++;        chain_ptr = tagStore[chain_ptr].chain_ptr;    }    *_depth = depth;    return NULL;}voidIIC::invalidateBlk(IIC::BlkType *tag_ptr){    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(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,               PacketList & writebacks){    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            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);    }}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 + -
显示快捷键?