split.cc

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

CC
421
字号
/* * Copyright (c) 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * 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. * * Authors: Lisa R. Hsu *//** * @file * Definitions of split cache tag store. */#include <string>#include <iostream>#include <fstream>#include "base/cprintf.hh"#include "base/intmath.hh"#include "base/output.hh"#include "base/trace.hh"#include "mem/cache/base.hh"#include "mem/cache/tags/split.hh"#include "mem/cache/tags/split_lifo.hh"#include "mem/cache/tags/split_lru.hh"using namespace std;using namespace TheISA;// create and initialize a partitioned cache structureSplit::Split(int _numSets, int _blkSize, int total_ways, int LRU1_assoc,             bool _lifo, bool _two_queue, int _hit_latency) :    numSets(_numSets), blkSize(_blkSize), lifo(_lifo), hitLatency(_hit_latency){    DPRINTF(Split, "new split cache!!\n");    DPRINTF(Split, "lru has %d numSets, %d blkSize, %d assoc, and %d hit_latency\n",            numSets, blkSize, LRU1_assoc, hitLatency);    lru = new SplitLRU(_numSets, _blkSize, LRU1_assoc, _hit_latency, 1);    if (total_ways - LRU1_assoc == 0) {        lifo_net = NULL;        lru_net = NULL;    } else {        if (lifo) {            DPRINTF(Split, "Other partition is a LIFO with size %d in bytes. it gets %d ways\n",                    (total_ways - LRU1_assoc)*_numSets*_blkSize, (total_ways - LRU1_assoc));            lifo_net = new SplitLIFO(_blkSize, (total_ways - LRU1_assoc)*_numSets*_blkSize,                                     (total_ways - LRU1_assoc), _hit_latency, _two_queue, 2);            lru_net = NULL;        }        else {            DPRINTF(Split, "other LRU gets %d ways\n", total_ways - LRU1_assoc);            lru_net = new SplitLRU(_numSets, _blkSize, total_ways - LRU1_assoc, _hit_latency, 2);            lifo_net = NULL;        }    }    blkMask = blkSize - 1;    if (!isPowerOf2(total_ways))        warn("total cache ways/columns %d should be power of 2",             total_ways);    warmedUp = false;    /** @todo Make warmup percentage a parameter. */    warmupBound = numSets * total_ways;}Split::~Split(){    delete lru;    if (lifo)        delete lifo_net;    else        delete lru_net;}voidSplit::regStats(const string &name){    using namespace Stats;    BaseTags::regStats(name);    usedEvictDist.init(0,3000,40);    unusedEvictDist.init(0,3000,40);    useByCPUCycleDist.init(0,35,1);    nic_repl        .name(name + ".nic_repl")        .desc("number of replacements in the nic partition")        .precision(0)        ;    cpu_repl        .name(name + ".cpu_repl")        .desc("number of replacements in the cpu partition")        .precision(0)        ;    lru->regStats(name + ".lru");    if (lifo && lifo_net) {        lifo_net->regStats(name + ".lifo_net");    } else if (lru_net) {        lru_net->regStats(name + ".lru_net");    }    nicUsedWhenEvicted        .name(name + ".nicUsedWhenEvicted")        .desc("number of NIC blks that were used before evicted")        ;    nicUsedTotLatency        .name(name + ".nicUsedTotLatency")        .desc("total cycles before eviction of used NIC blks")        ;    nicUsedTotEvicted        .name(name + ".nicUsedTotEvicted")        .desc("total number of used NIC blks evicted")        ;    nicUsedAvgLatency        .name(name + ".nicUsedAvgLatency")        .desc("avg number of cycles a used NIC blk is in cache")        .precision(0)        ;    nicUsedAvgLatency = nicUsedTotLatency / nicUsedTotEvicted;    usedEvictDist        .name(name + ".usedEvictDist")        .desc("distribution of used NIC blk eviction times")        .flags(pdf | cdf)        ;    nicUnusedWhenEvicted        .name(name + ".nicUnusedWhenEvicted")        .desc("number of NIC blks that were unused when evicted")        ;    nicUnusedTotLatency        .name(name + ".nicUnusedTotLatency")        .desc("total cycles before eviction of unused NIC blks")        ;    nicUnusedTotEvicted        .name(name + ".nicUnusedTotEvicted")        .desc("total number of unused NIC blks evicted")        ;    nicUnusedAvgLatency        .name(name + ".nicUnusedAvgLatency")        .desc("avg number of cycles an unused NIC blk is in cache")        .precision(0)        ;    nicUnusedAvgLatency = nicUnusedTotLatency / nicUnusedTotEvicted;    unusedEvictDist        .name(name + ".unusedEvictDist")        .desc("distribution of unused NIC blk eviction times")        .flags(pdf | cdf)        ;    nicUseByCPUCycleTotal        .name(name + ".nicUseByCPUCycleTotal")        .desc("total latency of NIC blks til usage time")        ;    nicBlksUsedByCPU        .name(name + ".nicBlksUsedByCPU")        .desc("total number of NIC blks used")        ;    nicAvgUsageByCPULatency        .name(name + ".nicAvgUsageByCPULatency")        .desc("average number of cycles before a NIC blk that is used gets used")        .precision(0)        ;    nicAvgUsageByCPULatency = nicUseByCPUCycleTotal / nicBlksUsedByCPU;    useByCPUCycleDist        .name(name + ".useByCPUCycleDist")        .desc("the distribution of cycle time in cache before NIC blk is used")        .flags(pdf | cdf)        ;    cpuUsedBlks        .name(name + ".cpuUsedBlks")        .desc("number of cpu blks that were used before evicted")        ;    cpuUnusedBlks        .name(name + ".cpuUnusedBlks")        .desc("number of cpu blks that were unused before evicted")        ;    nicAvgLatency        .name(name + ".nicAvgLatency")        .desc("avg number of cycles a NIC blk is in cache before evicted")        .precision(0)        ;    nicAvgLatency = (nicUnusedTotLatency + nicUsedTotLatency) /        (nicUnusedTotEvicted + nicUsedTotEvicted);    NR_CP_hits        .name(name + ".NR_CP_hits")        .desc("NIC requests hitting in CPU Partition")        ;    NR_NP_hits        .name(name + ".NR_NP_hits")        .desc("NIC requests hitting in NIC Partition")        ;    CR_CP_hits        .name(name + ".CR_CP_hits")        .desc("CPU requests hitting in CPU partition")        ;    CR_NP_hits        .name(name + ".CR_NP_hits")        .desc("CPU requests hitting in NIC partition")        ;}// probe cache for presence of given block.boolSplit::probe(Addr addr) const{    bool success = lru->probe(addr);    if (!success) {        if (lifo && lifo_net)            success = lifo_net->probe(addr);        else if (lru_net)            success = lru_net->probe(addr);    }    return success;}SplitBlk*Split::findBlock(Addr addr, int &lat){    SplitBlk *blk = lru->findBlock(addr, lat);    if (!blk) {        if (lifo && lifo_net) {            blk = lifo_net->findBlock(addr, lat);        } else if (lru_net) {            blk = lru_net->findBlock(addr, lat);        }    }    return blk;}SplitBlk*Split::findBlock(Addr addr) const{    SplitBlk *blk = lru->findBlock(addr);    if (!blk) {        if (lifo && lifo_net) {            blk = lifo_net->findBlock(addr);        } else if (lru_net) {            blk = lru_net->findBlock(addr);        }    }    return blk;}SplitBlk*Split::findReplacement(Addr addr, PacketList &writebacks){    SplitBlk *blk = NULL;    assert(0);#if 0    if (pkt->nic_pkt()) {        DPRINTF(Split, "finding a replacement for nic_req\n");        nic_repl++;        if (lifo && lifo_net)            blk = lifo_net->findReplacement(addr, writebacks);        else if (lru_net)            blk = lru_net->findReplacement(addr, writebacks);        // in this case, this is an LRU only cache, it's non partitioned        else            blk = lru->findReplacement(addr, writebacks);    } else {        DPRINTF(Split, "finding replacement for cpu_req\n");        blk = lru->findReplacement(addr, writebacks);        cpu_repl++;    }    Tick latency = curTick - blk->ts;    if (blk->isNIC) {        if (blk->isUsed) {            nicUsedWhenEvicted++;            usedEvictDist.sample(latency);            nicUsedTotLatency += latency;            nicUsedTotEvicted++;        } else {            nicUnusedWhenEvicted++;            unusedEvictDist.sample(latency);            nicUnusedTotLatency += latency;            nicUnusedTotEvicted++;        }    } else {        if (blk->isUsed) {            cpuUsedBlks++;        } else {            cpuUnusedBlks++;        }    }    // blk attributes for the new blk coming IN    blk->ts = curTick;    blk->isNIC = (pkt->nic_pkt()) ? true : false;#endif    return blk;}voidSplit::invalidateBlk(Split::BlkType *blk){    if (!blk) {        fatal("FIXME!\n");#if 0        if (lifo && lifo_net)            blk = lifo_net->findBlock(addr);        else if (lru_net)            blk = lru_net->findBlock(addr);#endif        if (!blk)            return;    }    blk->status = 0;    blk->isTouched = false;    tagsInUse--;}voidSplit::cleanupRefs(){    lru->cleanupRefs();    if (lifo && lifo_net)        lifo_net->cleanupRefs();    else if (lru_net)        lru_net->cleanupRefs();    ofstream memPrint(simout.resolve("memory_footprint.txt").c_str(),                      ios::trunc);    // this shouldn't be here but it happens at the end, which is what i want    memIter end = memHash.end();    for (memIter iter = memHash.begin(); iter != end; ++iter) {        ccprintf(memPrint, "%8x\t%d\n", (*iter).first, (*iter).second);    }}AddrSplit::regenerateBlkAddr(Addr tag, int set) const{    if (lifo_net)        return lifo_net->regenerateBlkAddr(tag, set);    else        return lru->regenerateBlkAddr(tag, set);}AddrSplit::extractTag(Addr addr) const{    // need to fix this if we want to use it... old interface of    // passing in blk was too weird    assert(0);    return 0;/*    if (blk->part == 2) {        if (lifo_net)            return lifo_net->extractTag(addr);        else if (lru_net)            return lru_net->extractTag(addr);        else            panic("this shouldn't happen");    } else        return lru->extractTag(addr);*/}

⌨️ 快捷键说明

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