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