summaryrefslogtreecommitdiff
path: root/src/mem/cache/tags/split.cc
diff options
context:
space:
mode:
authorRon Dreslinski <rdreslin@umich.edu>2006-06-28 11:02:14 -0400
committerRon Dreslinski <rdreslin@umich.edu>2006-06-28 11:02:14 -0400
commited8564a6b9f0702a40995d95cc4da54de3d35462 (patch)
tree156901f9e5a2e92ddfa44eea664103de5d210aa7 /src/mem/cache/tags/split.cc
parentecab4b426c949dad797df0bde1c0c120b4b5fb00 (diff)
downloadgem5-ed8564a6b9f0702a40995d95cc4da54de3d35462.tar.xz
Was having difficulty with merging the cache, reverted to an early version and will add back in the patches to make it work soon.
src/mem/cache/prefetch/tagged_prefetcher_impl.hh: Trying to merge src/mem/cache/base_cache.cc: src/mem/cache/base_cache.hh: src/mem/cache/cache.cc: src/mem/cache/cache.hh: src/mem/cache/cache_blk.hh: src/mem/cache/cache_builder.cc: src/mem/cache/cache_impl.hh: src/mem/cache/coherence/coherence_protocol.cc: src/mem/cache/coherence/coherence_protocol.hh: src/mem/cache/coherence/simple_coherence.hh: src/mem/cache/coherence/uni_coherence.cc: src/mem/cache/coherence/uni_coherence.hh: src/mem/cache/miss/blocking_buffer.cc: src/mem/cache/miss/blocking_buffer.hh: src/mem/cache/miss/miss_queue.cc: src/mem/cache/miss/miss_queue.hh: src/mem/cache/miss/mshr.cc: src/mem/cache/miss/mshr.hh: src/mem/cache/miss/mshr_queue.cc: src/mem/cache/miss/mshr_queue.hh: src/mem/cache/prefetch/base_prefetcher.cc: src/mem/cache/prefetch/base_prefetcher.hh: src/mem/cache/prefetch/ghb_prefetcher.cc: src/mem/cache/prefetch/ghb_prefetcher.hh: src/mem/cache/prefetch/stride_prefetcher.cc: src/mem/cache/prefetch/stride_prefetcher.hh: src/mem/cache/prefetch/tagged_prefetcher.hh: src/mem/cache/tags/base_tags.cc: src/mem/cache/tags/base_tags.hh: src/mem/cache/tags/fa_lru.cc: src/mem/cache/tags/fa_lru.hh: src/mem/cache/tags/iic.cc: src/mem/cache/tags/iic.hh: src/mem/cache/tags/lru.cc: src/mem/cache/tags/lru.hh: src/mem/cache/tags/repl/gen.cc: src/mem/cache/tags/repl/gen.hh: src/mem/cache/tags/repl/repl.cc: src/mem/cache/tags/repl/repl.hh: src/mem/cache/tags/split.cc: src/mem/cache/tags/split.hh: src/mem/cache/tags/split_blk.hh: src/mem/cache/tags/split_lifo.cc: src/mem/cache/tags/split_lifo.hh: src/mem/cache/tags/split_lru.cc: src/mem/cache/tags/split_lru.hh: Pulling an early version of the cache into the tree due to merging issues. Will apply patches and push. --HG-- extra : convert_revision : 3276e5fb9a6272681a1690babf2b586dd0e1f380
Diffstat (limited to 'src/mem/cache/tags/split.cc')
-rw-r--r--src/mem/cache/tags/split.cc478
1 files changed, 478 insertions, 0 deletions
diff --git a/src/mem/cache/tags/split.cc b/src/mem/cache/tags/split.cc
new file mode 100644
index 000000000..9d9036abb
--- /dev/null
+++ b/src/mem/cache/tags/split.cc
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Lisa 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_cache.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 structure
+Split::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;
+}
+
+void
+Split::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.
+bool
+Split::probe(int asid, Addr addr) const
+{
+ bool success = lru->probe(asid, addr);
+ if (!success) {
+ if (lifo && lifo_net)
+ success = lifo_net->probe(asid, addr);
+ else if (lru_net)
+ success = lru_net->probe(asid, addr);
+ }
+
+ return success;
+}
+
+SplitBlk*
+Split::findBlock(Packet * &pkt, int &lat)
+{
+
+ Addr aligned = blkAlign(pkt->paddr);
+
+ if (memHash.count(aligned)) {
+ memHash[aligned]++;
+ } else if (pkt->nic_pkt) {
+ memHash[aligned] = 1;
+ }
+
+ SplitBlk *blk = lru->findBlock(pkt->paddr, pkt->req->asid, lat);
+ if (blk) {
+ if (pkt->nic_pkt) {
+ NR_CP_hits++;
+ } else {
+ CR_CP_hits++;
+ }
+ } else {
+ if (lifo && lifo_net) {
+ blk = lifo_net->findBlock(pkt->paddr, pkt->req->asid, lat);
+
+ } else if (lru_net) {
+ blk = lru_net->findBlock(pkt->paddr, pkt->req->asid, lat);
+ }
+ if (blk) {
+ if (pkt->nic_pkt) {
+ NR_NP_hits++;
+ } else {
+ CR_NP_hits++;
+ }
+ }
+ }
+
+ if (blk) {
+ Tick latency = curTick - blk->ts;
+ if (blk->isNIC) {
+ if (!blk->isUsed && !pkt->nic_pkt) {
+ useByCPUCycleDist.sample(latency);
+ nicUseByCPUCycleTotal += latency;
+ nicBlksUsedByCPU++;
+ }
+ }
+ blk->isUsed = true;
+
+ if (pkt->nic_pkt) {
+ DPRINTF(Split, "found block in partition %d\n", blk->part);
+ }
+ }
+ return blk;
+}
+
+SplitBlk*
+Split::findBlock(Addr addr, int asid, int &lat)
+{
+ SplitBlk *blk = lru->findBlock(addr, asid, lat);
+ if (!blk) {
+ if (lifo && lifo_net) {
+ blk = lifo_net->findBlock(addr, asid, lat);
+ } else if (lru_net) {
+ blk = lru_net->findBlock(addr, asid, lat);
+ }
+ }
+
+ return blk;
+}
+
+SplitBlk*
+Split::findBlock(Addr addr, int asid) const
+{
+ SplitBlk *blk = lru->findBlock(addr, asid);
+ if (!blk) {
+ if (lifo && lifo_net) {
+ blk = lifo_net->findBlock(addr, asid);
+ } else if (lru_net) {
+ blk = lru_net->findBlock(addr, asid);
+ }
+ }
+
+ return blk;
+}
+
+SplitBlk*
+Split::findReplacement(Packet * &pkt, PacketList* &writebacks,
+ BlkList &compress_blocks)
+{
+ SplitBlk *blk;
+
+ if (pkt->nic_pkt) {
+ DPRINTF(Split, "finding a replacement for nic_req\n");
+ nic_repl++;
+ if (lifo && lifo_net)
+ blk = lifo_net->findReplacement(pkt, writebacks,
+ compress_blocks);
+ else if (lru_net)
+ blk = lru_net->findReplacement(pkt, writebacks,
+ compress_blocks);
+ // in this case, this is an LRU only cache, it's non partitioned
+ else
+ blk = lru->findReplacement(pkt, writebacks, compress_blocks);
+ } else {
+ DPRINTF(Split, "finding replacement for cpu_req\n");
+ blk = lru->findReplacement(pkt, writebacks,
+ compress_blocks);
+ 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;
+
+ return blk;
+}
+
+void
+Split::invalidateBlk(int asid, Addr addr)
+{
+ SplitBlk *blk = lru->findBlock(addr, asid);
+ if (!blk) {
+ if (lifo && lifo_net)
+ blk = lifo_net->findBlock(addr, asid);
+ else if (lru_net)
+ blk = lru_net->findBlock(addr, asid);
+
+ if (!blk)
+ return;
+ }
+
+ blk->status = 0;
+ blk->isTouched = false;
+ tagsInUse--;
+}
+
+void
+Split::doCopy(Addr source, Addr dest, int asid, PacketList* &writebacks)
+{
+ if (lru->probe(asid, source))
+ lru->doCopy(source, dest, asid, writebacks);
+ else {
+ if (lifo && lifo_net)
+ lifo_net->doCopy(source, dest, asid, writebacks);
+ else if (lru_net)
+ lru_net->doCopy(source, dest, asid, writebacks);
+ }
+}
+
+void
+Split::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);
+ }
+}
+
+Addr
+Split::regenerateBlkAddr(Addr tag, int set) const
+{
+ if (lifo_net)
+ return lifo_net->regenerateBlkAddr(tag, set);
+ else
+ return lru->regenerateBlkAddr(tag, set);
+}
+
+Addr
+Split::extractTag(Addr addr, SplitBlk *blk) const
+{
+ 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);
+}
+