remove the totally obsolete split cache
This commit is contained in:
parent
9836d81c2b
commit
7a28ab2d18
5
src/mem/cache/BaseCache.py
vendored
5
src/mem/cache/BaseCache.py
vendored
|
@ -38,8 +38,6 @@ class BaseCache(MemObject):
|
|||
block_size = Param.Int("block size in bytes")
|
||||
latency = Param.Latency("Latency")
|
||||
hash_delay = Param.Int(1, "time in cycles of hash access")
|
||||
lifo = Param.Bool(False,
|
||||
"whether this NIC partition should use LIFO repl. policy")
|
||||
max_miss_count = Param.Counter(0,
|
||||
"number of misses to handle before calling exit")
|
||||
mshrs = Param.Int("number of MSHRs (max outstanding requests)")
|
||||
|
@ -47,9 +45,6 @@ class BaseCache(MemObject):
|
|||
"always service demand misses first")
|
||||
repl = Param.Repl(NULL, "replacement policy")
|
||||
size = Param.MemorySize("capacity in bytes")
|
||||
split = Param.Bool(False, "whether or not this cache is split")
|
||||
split_size = Param.Int(0,
|
||||
"How many ways of the cache belong to CPU/LRU partition")
|
||||
subblock_size = Param.Int(0,
|
||||
"Size of subblock in IIC used for compression")
|
||||
tgts_per_mshr = Param.Int("max number of accesses per MSHR")
|
||||
|
|
36
src/mem/cache/builder.cc
vendored
36
src/mem/cache/builder.cc
vendored
|
@ -57,14 +57,6 @@
|
|||
#include "mem/cache/tags/iic.hh"
|
||||
#endif
|
||||
|
||||
#if defined(USE_CACHE_SPLIT)
|
||||
#include "mem/cache/tags/split.hh"
|
||||
#endif
|
||||
|
||||
#if defined(USE_CACHE_SPLIT_LIFO)
|
||||
#include "mem/cache/tags/split_lifo.hh"
|
||||
#endif
|
||||
|
||||
//Prefetcher Headers
|
||||
#if defined(USE_GHB)
|
||||
#include "mem/cache/prefetch/ghb.hh"
|
||||
|
@ -122,26 +114,6 @@ using namespace TheISA;
|
|||
#define BUILD_LRU_CACHE BUILD_CACHE_PANIC("lru cache")
|
||||
#endif
|
||||
|
||||
#if defined(USE_CACHE_SPLIT)
|
||||
#define BUILD_SPLIT_CACHE do { \
|
||||
Split *tags = new Split(numSets, block_size, assoc, split_size, lifo, \
|
||||
two_queue, latency); \
|
||||
BUILD_CACHE(Split, tags); \
|
||||
} while (0)
|
||||
#else
|
||||
#define BUILD_SPLIT_CACHE BUILD_CACHE_PANIC("split cache")
|
||||
#endif
|
||||
|
||||
#if defined(USE_CACHE_SPLIT_LIFO)
|
||||
#define BUILD_SPLIT_LIFO_CACHE do { \
|
||||
SplitLIFO *tags = new SplitLIFO(block_size, size, assoc, \
|
||||
latency, two_queue, -1); \
|
||||
BUILD_CACHE(SplitLIFO, tags); \
|
||||
} while (0)
|
||||
#else
|
||||
#define BUILD_SPLIT_LIFO_CACHE BUILD_CACHE_PANIC("lifo cache")
|
||||
#endif
|
||||
|
||||
#if defined(USE_CACHE_IIC)
|
||||
#define BUILD_IIC_CACHE do { \
|
||||
IIC *tags = new IIC(iic_params); \
|
||||
|
@ -156,13 +128,7 @@ using namespace TheISA;
|
|||
if (numSets == 1) { \
|
||||
BUILD_FALRU_CACHE; \
|
||||
} else { \
|
||||
if (split == true) { \
|
||||
BUILD_SPLIT_CACHE; \
|
||||
} else if (lifo == true) { \
|
||||
BUILD_SPLIT_LIFO_CACHE; \
|
||||
} else { \
|
||||
BUILD_LRU_CACHE; \
|
||||
} \
|
||||
BUILD_LRU_CACHE; \
|
||||
} \
|
||||
} else { \
|
||||
BUILD_IIC_CACHE; \
|
||||
|
|
16
src/mem/cache/cache.cc
vendored
16
src/mem/cache/cache.cc
vendored
|
@ -50,14 +50,6 @@
|
|||
#include "mem/cache/tags/iic.hh"
|
||||
#endif
|
||||
|
||||
#if defined(USE_CACHE_SPLIT)
|
||||
#include "mem/cache/tags/split.hh"
|
||||
#endif
|
||||
|
||||
#if defined(USE_CACHE_SPLIT_LIFO)
|
||||
#include "mem/cache/tags/split_lifo.hh"
|
||||
#endif
|
||||
|
||||
#include "mem/cache/cache_impl.hh"
|
||||
|
||||
// Template Instantiations
|
||||
|
@ -76,12 +68,4 @@ template class Cache<IIC>;
|
|||
template class Cache<LRU>;
|
||||
#endif
|
||||
|
||||
#if defined(USE_CACHE_SPLIT)
|
||||
template class Cache<Split>;
|
||||
#endif
|
||||
|
||||
#if defined(USE_CACHE_SPLIT_LIFO)
|
||||
template class Cache<SplitLIFO>;
|
||||
#endif
|
||||
|
||||
#endif //DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
|
4
src/mem/cache/tags/SConscript
vendored
4
src/mem/cache/tags/SConscript
vendored
|
@ -34,13 +34,9 @@ Source('base.cc')
|
|||
Source('fa_lru.cc')
|
||||
Source('iic.cc')
|
||||
Source('lru.cc')
|
||||
Source('split.cc')
|
||||
Source('split_lifo.cc')
|
||||
Source('split_lru.cc')
|
||||
|
||||
SimObject('iic_repl/Repl.py')
|
||||
Source('iic_repl/gen.cc')
|
||||
|
||||
TraceFlag('IIC')
|
||||
TraceFlag('IICMore')
|
||||
TraceFlag('Split')
|
||||
|
|
419
src/mem/cache/tags/split.cc
vendored
419
src/mem/cache/tags/split.cc
vendored
|
@ -1,419 +0,0 @@
|
|||
/*
|
||||
* 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.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(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;
|
||||
}
|
||||
|
||||
void
|
||||
Split::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--;
|
||||
}
|
||||
|
||||
void
|
||||
Split::cleanupRefs()
|
||||
{
|
||||
lru->cleanupRefs();
|
||||
if (lifo && lifo_net)
|
||||
lifo_net->cleanupRefs();
|
||||
else if (lru_net)
|
||||
lru_net->cleanupRefs();
|
||||
|
||||
ostream *memPrint = simout.create("memory_footprint.txt");
|
||||
|
||||
// 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) 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);
|
||||
*/
|
||||
}
|
||||
|
308
src/mem/cache/tags/split.hh
vendored
308
src/mem/cache/tags/split.hh
vendored
|
@ -1,308 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
* Declaration of a split/partitioned tag store.
|
||||
*/
|
||||
|
||||
#ifndef __SPLIT_HH__
|
||||
#define __SPLIT_HH__
|
||||
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
|
||||
#include "mem/cache/blk.hh" // base class
|
||||
#include "mem/cache/tags/split_blk.hh"
|
||||
#include "mem/packet.hh" // for inlined functions
|
||||
#include <assert.h>
|
||||
#include "mem/cache/tags/base.hh"
|
||||
#include "base/hashmap.hh"
|
||||
|
||||
class BaseCache;
|
||||
class SplitLRU;
|
||||
class SplitLIFO;
|
||||
|
||||
/**
|
||||
* A cache tag store.
|
||||
*/
|
||||
class Split : public BaseTags
|
||||
{
|
||||
public:
|
||||
/** Typedef the block type used in this tag store. */
|
||||
typedef SplitBlk BlkType;
|
||||
/** Typedef for a list of pointers to the local block class. */
|
||||
typedef std::list<SplitBlk*> BlkList;
|
||||
protected:
|
||||
/** The number of sets in the cache. */
|
||||
const int numSets;
|
||||
/** The number of bytes in a block. */
|
||||
const int blkSize;
|
||||
/** Whether the 2nd partition (for the nic) is LIFO or not */
|
||||
const bool lifo;
|
||||
/** The hit latency. */
|
||||
const int hitLatency;
|
||||
|
||||
Addr blkMask;
|
||||
|
||||
/** Number of NIC requests that hit in the NIC partition */
|
||||
Stats::Scalar<> NR_NP_hits;
|
||||
/** Number of NIC requests that hit in the CPU partition */
|
||||
Stats::Scalar<> NR_CP_hits;
|
||||
/** Number of CPU requests that hit in the NIC partition */
|
||||
Stats::Scalar<> CR_NP_hits;
|
||||
/** Number of CPU requests that hit in the CPU partition */
|
||||
Stats::Scalar<> CR_CP_hits;
|
||||
/** The number of nic replacements (i.e. misses) */
|
||||
Stats::Scalar<> nic_repl;
|
||||
/** The number of cpu replacements (i.e. misses) */
|
||||
Stats::Scalar<> cpu_repl;
|
||||
|
||||
//For latency studies
|
||||
/** the number of NIC blks that were used before evicted */
|
||||
Stats::Scalar<> nicUsedWhenEvicted;
|
||||
/** the total latency of used NIC blocks in the cache */
|
||||
Stats::Scalar<> nicUsedTotLatency;
|
||||
/** the total number of used NIC blocks evicted */
|
||||
Stats::Scalar<> nicUsedTotEvicted;
|
||||
/** the average number of cycles a used NIC blk is in the cache */
|
||||
Stats::Formula nicUsedAvgLatency;
|
||||
/** the Distribution of used NIC blk eviction times */
|
||||
Stats::Distribution<> usedEvictDist;
|
||||
|
||||
/** the number of NIC blks that were unused before evicted */
|
||||
Stats::Scalar<> nicUnusedWhenEvicted;
|
||||
/** the total latency of unused NIC blks in the cache */
|
||||
Stats::Scalar<> nicUnusedTotLatency;
|
||||
/** the total number of unused NIC blocks evicted */
|
||||
Stats::Scalar<> nicUnusedTotEvicted;
|
||||
/** the average number of cycles an unused NIC blk is in the cache */
|
||||
Stats::Formula nicUnusedAvgLatency;
|
||||
/** the Distribution of unused NIC blk eviction times */
|
||||
Stats::Distribution<> unusedEvictDist;
|
||||
|
||||
/** The total latency of NIC blocks to 1st usage time by CPU */
|
||||
Stats::Scalar<> nicUseByCPUCycleTotal;
|
||||
/** The total number of NIC blocks used */
|
||||
Stats::Scalar<> nicBlksUsedByCPU;
|
||||
/** the average number of cycles before a NIC blk that is used gets used by CPU */
|
||||
Stats::Formula nicAvgUsageByCPULatency;
|
||||
/** the Distribution of cycles time before a NIC blk is used by CPU*/
|
||||
Stats::Distribution<> useByCPUCycleDist;
|
||||
|
||||
/** the number of CPU blks that were used before evicted */
|
||||
Stats::Scalar<> cpuUsedBlks;
|
||||
/** the number of CPU blks that were unused before evicted */
|
||||
Stats::Scalar<> cpuUnusedBlks;
|
||||
|
||||
/** the avg number of cycles before a NIC blk is evicted */
|
||||
Stats::Formula nicAvgLatency;
|
||||
|
||||
typedef m5::hash_map<Addr, int, m5::hash<Addr> > hash_t;
|
||||
typedef hash_t::const_iterator memIter;
|
||||
hash_t memHash;
|
||||
|
||||
|
||||
private:
|
||||
SplitLRU *lru;
|
||||
SplitLRU *lru_net;
|
||||
SplitLIFO *lifo_net;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct and initialize this tag store.
|
||||
* @param _numSets The number of sets in the cache.
|
||||
* @param _blkSize The number of bytes in a block.
|
||||
* @param _assoc The associativity of the cache.
|
||||
* @param _hit_latency The latency in cycles for a hit.
|
||||
*/
|
||||
Split(int _numSets, int _blkSize, int total_ways, int LRU1_assoc,
|
||||
bool _lifo, bool _two_queue, int _hit_latency);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Split();
|
||||
|
||||
/**
|
||||
* Register the stats for this object
|
||||
* @param name The name to prepend to the stats name.
|
||||
*/
|
||||
void regStats(const std::string &name);
|
||||
|
||||
/**
|
||||
* Return the block size.
|
||||
* @return the block size.
|
||||
*/
|
||||
int getBlockSize()
|
||||
{
|
||||
return blkSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subblock size. In the case of Split it is always the block
|
||||
* size.
|
||||
* @return The block size.
|
||||
*/
|
||||
int getSubBlockSize()
|
||||
{
|
||||
return blkSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the address in the cache.
|
||||
* @param asid The address space ID.
|
||||
* @param addr The address to find.
|
||||
* @return True if the address is in the cache.
|
||||
*/
|
||||
bool probe(Addr addr) const;
|
||||
|
||||
/**
|
||||
* Invalidate the given block.
|
||||
* @param blk The block to invalidate.
|
||||
*/
|
||||
void invalidateBlk(BlkType *blk);
|
||||
|
||||
/**
|
||||
* Finds the given address in the cache and update replacement data.
|
||||
* Returns the access latency as a side effect.
|
||||
* @param addr The address to find.
|
||||
* @param asid The address space ID.
|
||||
* @param lat The access latency.
|
||||
* @return Pointer to the cache block if found.
|
||||
*/
|
||||
SplitBlk* findBlock(Addr addr, int &lat);
|
||||
|
||||
/**
|
||||
* Finds the given address in the cache, do not update replacement data.
|
||||
* @param addr The address to find.
|
||||
* @param asid The address space ID.
|
||||
* @return Pointer to the cache block if found.
|
||||
*/
|
||||
SplitBlk* findBlock(Addr addr) const;
|
||||
|
||||
/**
|
||||
* Find a replacement block for the address provided.
|
||||
* @param pkt The request to a find a replacement candidate for.
|
||||
* @param writebacks List for any writebacks to be performed.
|
||||
* @return The block to place the replacement in.
|
||||
*/
|
||||
SplitBlk* findReplacement(Addr addr, PacketList &writebacks);
|
||||
|
||||
|
||||
/**
|
||||
* Generate the tag from the given address.
|
||||
* @param addr The address to get the tag from.
|
||||
* @return The tag of the address.
|
||||
*/
|
||||
Addr extractTag(Addr addr) const;
|
||||
|
||||
/**
|
||||
* Calculate the set index from the address.
|
||||
* @param addr The address to get the set from.
|
||||
* @return The set index of the address.
|
||||
*/
|
||||
int extractSet(Addr addr) const
|
||||
{
|
||||
panic("should never call this!\n");
|
||||
M5_DUMMY_RETURN
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block offset from an address.
|
||||
* @param addr The address to get the offset of.
|
||||
* @return The block offset.
|
||||
*/
|
||||
int extractBlkOffset(Addr addr) const
|
||||
{
|
||||
return (addr & blkMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Align an address to the block size.
|
||||
* @param addr the address to align.
|
||||
* @return The block address.
|
||||
*/
|
||||
Addr blkAlign(Addr addr) const
|
||||
{
|
||||
return (addr & ~(Addr) (blkMask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Regenerate the block address from the tag.
|
||||
* @param tag The tag of the block.
|
||||
* @param set The set of the block.
|
||||
* @return The block address.
|
||||
*/
|
||||
Addr regenerateBlkAddr(Addr tag, int set) const;
|
||||
|
||||
/**
|
||||
* Return the hit latency.
|
||||
* @return the hit latency.
|
||||
*/
|
||||
int getHitLatency() const
|
||||
{
|
||||
return hitLatency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the data out of the internal storage of the given cache block.
|
||||
* @param blk The cache block to read.
|
||||
* @param data The buffer to read the data into.
|
||||
* @return The cache block's data.
|
||||
*/
|
||||
void readData(SplitBlk *blk, uint8_t *data)
|
||||
{
|
||||
std::memcpy(data, blk->data, blk->size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data into the internal storage of the given cache block. Since in
|
||||
* Split does not store data differently this just needs to update the size.
|
||||
* @param blk The cache block to write.
|
||||
* @param data The data to write.
|
||||
* @param size The number of bytes to write.
|
||||
* @param writebacks A list for any writebacks to be performed. May be
|
||||
* needed when writing to a compressed block.
|
||||
*/
|
||||
void writeData(SplitBlk *blk, uint8_t *data, int size,
|
||||
PacketList & writebacks)
|
||||
{
|
||||
assert(size <= blkSize);
|
||||
blk->size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called at end of simulation to complete average block reference stats.
|
||||
*/
|
||||
virtual void cleanupRefs();
|
||||
};
|
||||
|
||||
#endif
|
68
src/mem/cache/tags/split_blk.hh
vendored
68
src/mem/cache/tags/split_blk.hh
vendored
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
* Declaration of partitioned tag store cache block class.
|
||||
*/
|
||||
|
||||
#ifndef __SPLIT_BLK_HH__
|
||||
#define __SPLIT_BLK_HH__
|
||||
|
||||
#include "mem/cache/blk.hh" // base class
|
||||
|
||||
/**
|
||||
* Split cache block.
|
||||
*/
|
||||
class SplitBlk : public CacheBlk {
|
||||
public:
|
||||
/** Has this block been touched? Used to aid calculation of warmup time. */
|
||||
bool isTouched;
|
||||
/** Has this block been used after being brought in? (for LIFO partition) */
|
||||
bool isUsed;
|
||||
/** is this blk a NIC block? (i.e. requested by the NIC) */
|
||||
bool isNIC;
|
||||
/** timestamp of the arrival of this block into the cache */
|
||||
Tick ts;
|
||||
/** the previous block in the LIFO partition (brought in before than me) */
|
||||
SplitBlk *prev;
|
||||
/** the next block in the LIFO partition (brought in later than me) */
|
||||
SplitBlk *next;
|
||||
/** which partition this block is in */
|
||||
int part;
|
||||
|
||||
SplitBlk()
|
||||
: isTouched(false), isUsed(false), isNIC(false), ts(0), prev(NULL), next(NULL),
|
||||
part(0)
|
||||
{}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
331
src/mem/cache/tags/split_lifo.cc
vendored
331
src/mem/cache/tags/split_lifo.cc
vendored
|
@ -1,331 +0,0 @@
|
|||
/*
|
||||
* 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 LIFO tag store usable in a partitioned cache.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "mem/cache/base.hh"
|
||||
#include "base/intmath.hh"
|
||||
#include "mem/cache/tags/split_lifo.hh"
|
||||
#include "sim/core.hh"
|
||||
#include "base/trace.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
SplitBlk*
|
||||
LIFOSet::findBlk(Addr tag) const
|
||||
{
|
||||
for (SplitBlk *blk = firstIn; blk != NULL; blk = blk->next) {
|
||||
if (blk->tag == tag && blk->isValid()) {
|
||||
return blk;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
LIFOSet::moveToLastIn(SplitBlk *blk)
|
||||
{
|
||||
if (blk == lastIn)
|
||||
return;
|
||||
|
||||
if (blk == firstIn) {
|
||||
blk->next->prev = NULL;
|
||||
} else {
|
||||
blk->prev->next = blk->next;
|
||||
blk->next->prev = blk->prev;
|
||||
}
|
||||
blk->next = NULL;
|
||||
blk->prev = lastIn;
|
||||
lastIn->next = blk;
|
||||
|
||||
lastIn = blk;
|
||||
}
|
||||
|
||||
void
|
||||
LIFOSet::moveToFirstIn(SplitBlk *blk)
|
||||
{
|
||||
if (blk == firstIn)
|
||||
return;
|
||||
|
||||
if (blk == lastIn) {
|
||||
blk->prev->next = NULL;
|
||||
} else {
|
||||
blk->next->prev = blk->prev;
|
||||
blk->prev->next = blk->next;
|
||||
}
|
||||
|
||||
blk->prev = NULL;
|
||||
blk->next = firstIn;
|
||||
firstIn->prev = blk;
|
||||
|
||||
firstIn = blk;
|
||||
}
|
||||
|
||||
// create and initialize a LIFO cache structure
|
||||
SplitLIFO::SplitLIFO(int _blkSize, int _size, int _ways, int _hit_latency, bool two_Queue, int _part) :
|
||||
blkSize(_blkSize), size(_size), numBlks(_size/_blkSize), numSets((_size/_ways)/_blkSize), ways(_ways),
|
||||
hitLatency(_hit_latency), twoQueue(two_Queue), part(_part)
|
||||
{
|
||||
if (!isPowerOf2(blkSize))
|
||||
fatal("cache block size (in bytes) must be a power of 2");
|
||||
if (!(hitLatency > 0))
|
||||
fatal("access latency in cycles must be at least on cycle");
|
||||
if (_ways == 0)
|
||||
fatal("if instantiating a splitLIFO, needs non-zero size!");
|
||||
|
||||
|
||||
SplitBlk *blk;
|
||||
int i, j, blkIndex;
|
||||
|
||||
setShift = floorLog2(blkSize);
|
||||
blkMask = blkSize - 1;
|
||||
setMask = numSets - 1;
|
||||
tagShift = setShift + floorLog2(numSets);
|
||||
|
||||
warmedUp = false;
|
||||
/** @todo Make warmup percentage a parameter. */
|
||||
warmupBound = size/blkSize;
|
||||
|
||||
// allocate data blocks
|
||||
blks = new SplitBlk[numBlks];
|
||||
sets = new LIFOSet[numSets];
|
||||
dataBlks = new uint8_t[size];
|
||||
|
||||
/*
|
||||
// these start off point to same blk
|
||||
top = &(blks[0]);
|
||||
head = top;
|
||||
*/
|
||||
|
||||
blkIndex = 0;
|
||||
for (i=0; i < numSets; ++i) {
|
||||
sets[i].ways = ways;
|
||||
sets[i].lastIn = &blks[blkIndex];
|
||||
sets[i].firstIn = &blks[blkIndex + ways - 1];
|
||||
|
||||
/* 3 cases: if there is 1 way, if there are 2 ways, or if there are 3+.
|
||||
in the case of 1 way, last in and first out point to the same blocks,
|
||||
and the next and prev pointers need to be assigned specially. and so on
|
||||
*/
|
||||
/* deal with the first way */
|
||||
blk = &blks[blkIndex];
|
||||
blk->prev = &blks[blkIndex + 1];
|
||||
blk->next = NULL;
|
||||
blk->data = &dataBlks[blkSize*blkIndex];
|
||||
blk->size = blkSize;
|
||||
blk->part = part;
|
||||
blk->set = i;
|
||||
++blkIndex;
|
||||
|
||||
/* if there are "middle" ways, do them here */
|
||||
if (ways > 2) {
|
||||
for (j=1; j < ways-1; ++j) {
|
||||
blk = &blks[blkIndex];
|
||||
blk->data = &dataBlks[blkSize*blkIndex];
|
||||
blk->prev = &blks[blkIndex+1];
|
||||
blk->next = &blks[blkIndex-1];
|
||||
blk->data = &(dataBlks[blkSize*blkIndex]);
|
||||
blk->size = blkSize;
|
||||
blk->part = part;
|
||||
blk->set = i;
|
||||
++blkIndex;
|
||||
}
|
||||
}
|
||||
|
||||
/* do the final way here, depending on whether the final way is the only
|
||||
way or not
|
||||
*/
|
||||
if (ways > 1) {
|
||||
blk = &blks[blkIndex];
|
||||
blk->prev = NULL;
|
||||
blk->next = &blks[blkIndex - 1];
|
||||
blk->data = &dataBlks[blkSize*blkIndex];
|
||||
blk->size = blkSize;
|
||||
blk->part = part;
|
||||
blk->set = i;
|
||||
++blkIndex;
|
||||
} else {
|
||||
blk->prev = NULL;
|
||||
}
|
||||
}
|
||||
assert(blkIndex == numBlks);
|
||||
}
|
||||
|
||||
SplitLIFO::~SplitLIFO()
|
||||
{
|
||||
delete [] blks;
|
||||
delete [] sets;
|
||||
delete [] dataBlks;
|
||||
}
|
||||
|
||||
void
|
||||
SplitLIFO::regStats(const std::string &name)
|
||||
{
|
||||
BaseTags::regStats(name);
|
||||
|
||||
hits
|
||||
.name(name + ".hits")
|
||||
.desc("number of hits on this partition")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
misses
|
||||
.name(name + ".misses")
|
||||
.desc("number of misses in this partition")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
invalidations
|
||||
.name(name + ".invalidations")
|
||||
.desc("number of invalidations in this partition")
|
||||
.precision(0)
|
||||
;
|
||||
}
|
||||
|
||||
// probe cache for presence of given block.
|
||||
bool
|
||||
SplitLIFO::probe(Addr addr) const
|
||||
{
|
||||
Addr tag = extractTag(addr);
|
||||
unsigned myset = extractSet(addr);
|
||||
|
||||
SplitBlk* blk = sets[myset].findBlk(tag);
|
||||
return (blk != NULL);
|
||||
}
|
||||
|
||||
SplitBlk*
|
||||
SplitLIFO::findBlock(Addr addr, int &lat)
|
||||
{
|
||||
Addr tag = extractTag(addr);
|
||||
unsigned set = extractSet(addr);
|
||||
SplitBlk *blk = sets[set].findBlk(tag);
|
||||
|
||||
lat = hitLatency;
|
||||
|
||||
if (blk) {
|
||||
DPRINTF(Split, "Found LIFO blk %#x in set %d, with tag %#x\n",
|
||||
addr, set, tag);
|
||||
hits++;
|
||||
|
||||
if (blk->whenReady > curTick && blk->whenReady - curTick > hitLatency)
|
||||
lat = blk->whenReady - curTick;
|
||||
blk->refCount +=1;
|
||||
|
||||
if (twoQueue) {
|
||||
blk->isUsed = true;
|
||||
sets[set].moveToFirstIn(blk);
|
||||
} else {
|
||||
sets[set].moveToLastIn(blk);
|
||||
}
|
||||
}
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
|
||||
SplitBlk*
|
||||
SplitLIFO::findBlock(Addr addr) const
|
||||
{
|
||||
Addr tag = extractTag(addr);
|
||||
unsigned set = extractSet(addr);
|
||||
SplitBlk *blk = sets[set].findBlk(tag);
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
SplitBlk*
|
||||
SplitLIFO::findReplacement(Addr addr, PacketList &writebacks)
|
||||
{
|
||||
unsigned set = extractSet(addr);
|
||||
|
||||
SplitBlk *firstIn = sets[set].firstIn;
|
||||
SplitBlk *lastIn = sets[set].lastIn;
|
||||
|
||||
SplitBlk *blk;
|
||||
if (twoQueue && firstIn->isUsed) {
|
||||
blk = firstIn;
|
||||
blk->isUsed = false;
|
||||
sets[set].moveToLastIn(blk);
|
||||
} else {
|
||||
int withValue = sets[set].withValue;
|
||||
if (withValue == ways) {
|
||||
blk = lastIn;
|
||||
} else {
|
||||
blk = &(sets[set].firstIn[ways - ++withValue]);
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(Split, "just assigned %#x addr into LIFO, replacing %#x status %#x\n",
|
||||
addr, regenerateBlkAddr(blk->tag, set), blk->status);
|
||||
if (blk->isValid()) {
|
||||
replacements[0]++;
|
||||
totalRefs += blk->refCount;
|
||||
++sampledRefs;
|
||||
blk->refCount = 0;
|
||||
} else {
|
||||
tagsInUse++;
|
||||
blk->isTouched = true;
|
||||
if (!warmedUp && tagsInUse.value() >= warmupBound) {
|
||||
warmedUp = true;
|
||||
warmupCycle = curTick;
|
||||
}
|
||||
}
|
||||
|
||||
misses++;
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
void
|
||||
SplitLIFO::invalidateBlk(SplitLIFO::BlkType *blk)
|
||||
{
|
||||
if (blk) {
|
||||
blk->status = 0;
|
||||
blk->isTouched = false;
|
||||
tagsInUse--;
|
||||
invalidations++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SplitLIFO::cleanupRefs()
|
||||
{
|
||||
for (int i = 0; i < numBlks; ++i) {
|
||||
if (blks[i].isValid()) {
|
||||
totalRefs += blks[i].refCount;
|
||||
++sampledRefs;
|
||||
}
|
||||
}
|
||||
}
|
312
src/mem/cache/tags/split_lifo.hh
vendored
312
src/mem/cache/tags/split_lifo.hh
vendored
|
@ -1,312 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
* Declaration of a LIFO tag store usable in a partitioned cache.
|
||||
*/
|
||||
|
||||
#ifndef __SPLIT_LIFO_HH__
|
||||
#define __SPLIT_LIFO_HH__
|
||||
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
|
||||
#include "mem/cache/blk.hh" // base class
|
||||
#include "mem/cache/tags/split_blk.hh"
|
||||
#include "mem/packet.hh" // for inlined functions
|
||||
#include "base/hashmap.hh"
|
||||
#include <assert.h>
|
||||
#include "mem/cache/tags/base.hh"
|
||||
|
||||
class BaseCache;
|
||||
|
||||
/**
|
||||
* A LIFO set of cache blks
|
||||
*/
|
||||
class LIFOSet {
|
||||
public:
|
||||
/** the number of blocks in this set */
|
||||
int ways;
|
||||
|
||||
/** Cache blocks in this set, maintained in LIFO order where
|
||||
0 = Last in (head) */
|
||||
SplitBlk *lastIn;
|
||||
SplitBlk *firstIn;
|
||||
|
||||
/** has the initial "filling" of this set finished? i.e., have you had
|
||||
* 'ways' number of compulsory misses in this set yet? if withValue == ways,
|
||||
* then yes. withValue is meant to be the number of blocks in the set that have
|
||||
* gone through their first compulsory miss.
|
||||
*/
|
||||
int withValue;
|
||||
|
||||
/**
|
||||
* Find a block matching the tag in this set.
|
||||
* @param asid The address space ID.
|
||||
* @param tag the Tag you are looking for
|
||||
* @return Pointer to the block, if found, NULL otherwise
|
||||
*/
|
||||
SplitBlk* findBlk(Addr tag) const;
|
||||
|
||||
void moveToLastIn(SplitBlk *blk);
|
||||
void moveToFirstIn(SplitBlk *blk);
|
||||
|
||||
LIFOSet()
|
||||
: ways(-1), lastIn(NULL), firstIn(NULL), withValue(0)
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
* A LIFO cache tag store.
|
||||
*/
|
||||
class SplitLIFO : public BaseTags
|
||||
{
|
||||
public:
|
||||
/** Typedef the block type used in this tag store. */
|
||||
typedef SplitBlk BlkType;
|
||||
/** Typedef for a list of pointers to the local block class. */
|
||||
typedef std::list<SplitBlk*> BlkList;
|
||||
protected:
|
||||
/** The number of bytes in a block. */
|
||||
const int blkSize;
|
||||
/** the size of the cache in bytes */
|
||||
const int size;
|
||||
/** the number of blocks in the cache */
|
||||
const int numBlks;
|
||||
/** the number of sets in the cache */
|
||||
const int numSets;
|
||||
/** the number of ways in the cache */
|
||||
const int ways;
|
||||
/** The hit latency. */
|
||||
const int hitLatency;
|
||||
/** whether this is a "2 queue" replacement @sa moveToLastIn @sa moveToFirstIn */
|
||||
const bool twoQueue;
|
||||
/** indicator for which partition this is */
|
||||
const int part;
|
||||
|
||||
/** The cache blocks. */
|
||||
SplitBlk *blks;
|
||||
/** The Cache sets */
|
||||
LIFOSet *sets;
|
||||
/** The data blocks, 1 per cache block. */
|
||||
uint8_t *dataBlks;
|
||||
|
||||
/** The amount to shift the address to get the set. */
|
||||
int setShift;
|
||||
/** The amount to shift the address to get the tag. */
|
||||
int tagShift;
|
||||
/** Mask out all bits that aren't part of the set index. */
|
||||
unsigned setMask;
|
||||
/** Mask out all bits that aren't part of the block offset. */
|
||||
unsigned blkMask;
|
||||
|
||||
|
||||
/** the number of hit in this partition */
|
||||
Stats::Scalar<> hits;
|
||||
/** the number of blocks brought into this partition (i.e. misses) */
|
||||
Stats::Scalar<> misses;
|
||||
/** the number of invalidations in this partition */
|
||||
Stats::Scalar<> invalidations;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct and initialize this tag store.
|
||||
* @param _numSets The number of sets in the cache.
|
||||
* @param _blkSize The number of bytes in a block.
|
||||
* @param _assoc The associativity of the cache.
|
||||
* @param _hit_latency The latency in cycles for a hit.
|
||||
*/
|
||||
SplitLIFO(int _blkSize, int _size, int _ways, int _hit_latency, bool twoQueue, int _part);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~SplitLIFO();
|
||||
|
||||
/**
|
||||
* Register the statistics for this object
|
||||
* @param name The name to precede the stat
|
||||
*/
|
||||
void regStats(const std::string &name);
|
||||
|
||||
/**
|
||||
* Return the block size.
|
||||
* @return the block size.
|
||||
*/
|
||||
int getBlockSize()
|
||||
{
|
||||
return blkSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subblock size. In the case of LIFO it is always the block
|
||||
* size.
|
||||
* @return The block size.
|
||||
*/
|
||||
int getSubBlockSize()
|
||||
{
|
||||
return blkSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the address in the cache.
|
||||
* @param asid The address space ID.
|
||||
* @param addr The address to find.
|
||||
* @return True if the address is in the cache.
|
||||
*/
|
||||
bool probe( Addr addr) const;
|
||||
|
||||
/**
|
||||
* Invalidate the given block.
|
||||
* @param blk The block to invalidate.
|
||||
*/
|
||||
void invalidateBlk(BlkType *blk);
|
||||
|
||||
/**
|
||||
* Finds the given address in the cache and update replacement data.
|
||||
* Returns the access latency as a side effect.
|
||||
* @param addr The address to find.
|
||||
* @param asid The address space ID.
|
||||
* @param lat The access latency.
|
||||
* @return Pointer to the cache block if found.
|
||||
*/
|
||||
SplitBlk* findBlock(Addr addr, int &lat);
|
||||
|
||||
/**
|
||||
* Finds the given address in the cache, do not update replacement data.
|
||||
* @param addr The address to find.
|
||||
* @param asid The address space ID.
|
||||
* @return Pointer to the cache block if found.
|
||||
*/
|
||||
SplitBlk* findBlock(Addr addr) const;
|
||||
|
||||
/**
|
||||
* Find a replacement block for the address provided.
|
||||
* @param pkt The request to a find a replacement candidate for.
|
||||
* @param writebacks List for any writebacks to be performed.
|
||||
* @return The block to place the replacement in.
|
||||
*/
|
||||
SplitBlk* findReplacement(Addr addr, PacketList &writebacks);
|
||||
|
||||
/**
|
||||
* Generate the tag from the given address.
|
||||
* @param addr The address to get the tag from.
|
||||
* @return The tag of the address.
|
||||
*/
|
||||
Addr extractTag(Addr addr) const
|
||||
{
|
||||
return (addr >> tagShift);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the set index from the address.
|
||||
* @param addr The address to get the set from.
|
||||
* @return The set index of the address.
|
||||
*/
|
||||
int extractSet(Addr addr) const
|
||||
{
|
||||
return ((addr >> setShift) & setMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block offset from an address.
|
||||
* @param addr The address to get the offset of.
|
||||
* @return The block offset.
|
||||
*/
|
||||
int extractBlkOffset(Addr addr) const
|
||||
{
|
||||
return (addr & blkMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Align an address to the block size.
|
||||
* @param addr the address to align.
|
||||
* @return The block address.
|
||||
*/
|
||||
Addr blkAlign(Addr addr) const
|
||||
{
|
||||
return (addr & ~(Addr)blkMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Regenerate the block address from the tag.
|
||||
* @param tag The tag of the block.
|
||||
* @param set The set of the block.
|
||||
* @return The block address.
|
||||
*/
|
||||
Addr regenerateBlkAddr(Addr tag, unsigned set) const
|
||||
{
|
||||
return ((tag << tagShift) | ((Addr)set << setShift));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hit latency.
|
||||
* @return the hit latency.
|
||||
*/
|
||||
int getHitLatency() const
|
||||
{
|
||||
return hitLatency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the data out of the internal storage of the given cache block.
|
||||
* @param blk The cache block to read.
|
||||
* @param data The buffer to read the data into.
|
||||
* @return The cache block's data.
|
||||
*/
|
||||
void readData(SplitBlk *blk, uint8_t *data)
|
||||
{
|
||||
std::memcpy(data, blk->data, blk->size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data into the internal storage of the given cache block. Since in
|
||||
* LIFO does not store data differently this just needs to update the size.
|
||||
* @param blk The cache block to write.
|
||||
* @param data The data to write.
|
||||
* @param size The number of bytes to write.
|
||||
* @param writebacks A list for any writebacks to be performed. May be
|
||||
* needed when writing to a compressed block.
|
||||
*/
|
||||
void writeData(SplitBlk *blk, uint8_t *data, int size,
|
||||
PacketList & writebacks)
|
||||
{
|
||||
assert(size <= blkSize);
|
||||
blk->size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called at end of simulation to complete average block reference stats.
|
||||
*/
|
||||
virtual void cleanupRefs();
|
||||
};
|
||||
|
||||
#endif
|
260
src/mem/cache/tags/split_lru.cc
vendored
260
src/mem/cache/tags/split_lru.cc
vendored
|
@ -1,260 +0,0 @@
|
|||
/*
|
||||
* 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 LRU tag store for a partitioned cache.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "mem/cache/base.hh"
|
||||
#include "base/intmath.hh"
|
||||
#include "mem/cache/tags/split_lru.hh"
|
||||
#include "sim/core.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
SplitBlk*
|
||||
SplitCacheSet::findBlk(Addr tag) const
|
||||
{
|
||||
for (int i = 0; i < assoc; ++i) {
|
||||
if (blks[i]->tag == tag && blks[i]->isValid()) {
|
||||
return blks[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SplitCacheSet::moveToHead(SplitBlk *blk)
|
||||
{
|
||||
// nothing to do if blk is already head
|
||||
if (blks[0] == blk)
|
||||
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;
|
||||
SplitBlk *next = blk;
|
||||
|
||||
do {
|
||||
assert(i < assoc);
|
||||
// swap blks[i] and next
|
||||
SplitBlk *tmp = blks[i];
|
||||
blks[i] = next;
|
||||
next = tmp;
|
||||
++i;
|
||||
} while (next != blk);
|
||||
}
|
||||
|
||||
|
||||
// create and initialize a LRU/MRU cache structure
|
||||
SplitLRU::SplitLRU(int _numSets, int _blkSize, int _assoc, int _hit_latency, int _part) :
|
||||
numSets(_numSets), blkSize(_blkSize), assoc(_assoc), hitLatency(_hit_latency), part(_part)
|
||||
{
|
||||
// Check parameters
|
||||
if (blkSize < 4 || !isPowerOf2(blkSize)) {
|
||||
fatal("Block size must be at least 4 and a power of 2");
|
||||
}
|
||||
if (numSets <= 0 || !isPowerOf2(numSets)) {
|
||||
fatal("# of sets must be non-zero and a power of 2");
|
||||
}
|
||||
if (assoc <= 0) {
|
||||
fatal("associativity must be greater than zero");
|
||||
}
|
||||
if (hitLatency <= 0) {
|
||||
fatal("access latency must be greater than zero");
|
||||
}
|
||||
|
||||
SplitBlk *blk;
|
||||
int i, j, blkIndex;
|
||||
|
||||
blkMask = blkSize - 1;
|
||||
setShift = floorLog2(blkSize);
|
||||
setMask = numSets - 1;
|
||||
tagShift = setShift + floorLog2(numSets);
|
||||
warmedUp = false;
|
||||
/** @todo Make warmup percentage a parameter. */
|
||||
warmupBound = numSets * assoc;
|
||||
|
||||
sets = new SplitCacheSet[numSets];
|
||||
blks = new SplitBlk[numSets * assoc];
|
||||
// allocate data storage in one big chunk
|
||||
dataBlks = new uint8_t[numSets*assoc*blkSize];
|
||||
|
||||
blkIndex = 0; // index into blks array
|
||||
for (i = 0; i < numSets; ++i) {
|
||||
sets[i].assoc = assoc;
|
||||
|
||||
sets[i].blks = new SplitBlk*[assoc];
|
||||
|
||||
// link in the data blocks
|
||||
for (j = 0; j < assoc; ++j) {
|
||||
// locate next cache block
|
||||
blk = &blks[blkIndex];
|
||||
blk->data = &dataBlks[blkSize*blkIndex];
|
||||
++blkIndex;
|
||||
|
||||
// invalidate new cache block
|
||||
blk->status = 0;
|
||||
|
||||
//EGH Fix Me : do we need to initialize blk?
|
||||
|
||||
// Setting the tag to j is just to prevent long chains in the hash
|
||||
// table; won't matter because the block is invalid
|
||||
blk->tag = j;
|
||||
blk->whenReady = 0;
|
||||
blk->isTouched = false;
|
||||
blk->size = blkSize;
|
||||
sets[i].blks[j]=blk;
|
||||
blk->set = i;
|
||||
blk->part = part;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SplitLRU::~SplitLRU()
|
||||
{
|
||||
delete [] dataBlks;
|
||||
delete [] blks;
|
||||
delete [] sets;
|
||||
}
|
||||
|
||||
void
|
||||
SplitLRU::regStats(const std::string &name)
|
||||
{
|
||||
BaseTags::regStats(name);
|
||||
|
||||
hits
|
||||
.name(name + ".hits")
|
||||
.desc("number of hits on this partition")
|
||||
.precision(0)
|
||||
;
|
||||
|
||||
misses
|
||||
.name(name + ".misses")
|
||||
.desc("number of misses in this partition")
|
||||
.precision(0)
|
||||
;
|
||||
}
|
||||
|
||||
// probe cache for presence of given block.
|
||||
bool
|
||||
SplitLRU::probe(Addr addr) const
|
||||
{
|
||||
// return(findBlock(Read, addr, asid) != 0);
|
||||
Addr tag = extractTag(addr);
|
||||
unsigned myset = extractSet(addr);
|
||||
|
||||
SplitBlk *blk = sets[myset].findBlk(tag);
|
||||
|
||||
return (blk != NULL); // true if in cache
|
||||
}
|
||||
|
||||
SplitBlk*
|
||||
SplitLRU::findBlock(Addr addr, int &lat)
|
||||
{
|
||||
Addr tag = extractTag(addr);
|
||||
unsigned set = extractSet(addr);
|
||||
SplitBlk *blk = sets[set].findBlk(tag);
|
||||
lat = hitLatency;
|
||||
if (blk != NULL) {
|
||||
// move this block to head of the MRU list
|
||||
sets[set].moveToHead(blk);
|
||||
if (blk->whenReady > curTick && blk->whenReady - curTick > hitLatency){
|
||||
lat = blk->whenReady - curTick;
|
||||
}
|
||||
blk->refCount += 1;
|
||||
hits++;
|
||||
}
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
|
||||
SplitBlk*
|
||||
SplitLRU::findBlock(Addr addr) const
|
||||
{
|
||||
Addr tag = extractTag(addr);
|
||||
unsigned set = extractSet(addr);
|
||||
SplitBlk *blk = sets[set].findBlk(tag);
|
||||
return blk;
|
||||
}
|
||||
|
||||
SplitBlk*
|
||||
SplitLRU::findReplacement(Addr addr, PacketList &writebacks)
|
||||
{
|
||||
unsigned set = extractSet(addr);
|
||||
// grab a replacement candidate
|
||||
SplitBlk *blk = sets[set].blks[assoc-1];
|
||||
sets[set].moveToHead(blk);
|
||||
if (blk->isValid()) {
|
||||
replacements[0]++;
|
||||
totalRefs += blk->refCount;
|
||||
++sampledRefs;
|
||||
blk->refCount = 0;
|
||||
} else if (!blk->isTouched) {
|
||||
tagsInUse++;
|
||||
blk->isTouched = true;
|
||||
if (!warmedUp && tagsInUse.value() >= warmupBound) {
|
||||
warmedUp = true;
|
||||
warmupCycle = curTick;
|
||||
}
|
||||
}
|
||||
|
||||
misses++;
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
void
|
||||
SplitLRU::invalidateBlk(SplitLRU::BlkType *blk)
|
||||
{
|
||||
if (blk) {
|
||||
blk->status = 0;
|
||||
blk->isTouched = false;
|
||||
tagsInUse--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SplitLRU::cleanupRefs()
|
||||
{
|
||||
for (int i = 0; i < numSets*assoc; ++i) {
|
||||
if (blks[i].isValid()) {
|
||||
totalRefs += blks[i].refCount;
|
||||
++sampledRefs;
|
||||
}
|
||||
}
|
||||
}
|
295
src/mem/cache/tags/split_lru.hh
vendored
295
src/mem/cache/tags/split_lru.hh
vendored
|
@ -1,295 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
* Declaration of a LRU tag store for a partitioned cache.
|
||||
*/
|
||||
|
||||
#ifndef __SPLIT_LRU_HH__
|
||||
#define __SPLIT_LRU_HH__
|
||||
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
|
||||
#include "mem/cache/blk.hh" // base class
|
||||
#include "mem/cache/tags/split_blk.hh"
|
||||
#include "mem/packet.hh" // for inlined functions
|
||||
#include <assert.h>
|
||||
#include "mem/cache/tags/base.hh"
|
||||
|
||||
class BaseCache;
|
||||
|
||||
/**
|
||||
* An associative set of cache blocks.
|
||||
*/
|
||||
|
||||
class SplitCacheSet
|
||||
{
|
||||
public:
|
||||
/** The associativity of this set. */
|
||||
int assoc;
|
||||
|
||||
/** Cache blocks in this set, maintained in LRU order 0 = MRU. */
|
||||
SplitBlk **blks;
|
||||
|
||||
/**
|
||||
* Find a block matching the tag in this set.
|
||||
* @param asid The address space ID.
|
||||
* @param tag The Tag to find.
|
||||
* @return Pointer to the block if found.
|
||||
*/
|
||||
SplitBlk* findBlk(Addr tag) const;
|
||||
|
||||
/**
|
||||
* Move the given block to the head of the list.
|
||||
* @param blk The block to move.
|
||||
*/
|
||||
void moveToHead(SplitBlk *blk);
|
||||
};
|
||||
|
||||
/**
|
||||
* A LRU cache tag store.
|
||||
*/
|
||||
class SplitLRU : public BaseTags
|
||||
{
|
||||
public:
|
||||
/** Typedef the block type used in this tag store. */
|
||||
typedef SplitBlk BlkType;
|
||||
/** Typedef for a list of pointers to the local block class. */
|
||||
typedef std::list<SplitBlk*> BlkList;
|
||||
protected:
|
||||
/** The number of sets in the cache. */
|
||||
const int numSets;
|
||||
/** The number of bytes in a block. */
|
||||
const int blkSize;
|
||||
/** The associativity of the cache. */
|
||||
const int assoc;
|
||||
/** The hit latency. */
|
||||
const int hitLatency;
|
||||
/** indicator for which partition this is */
|
||||
const int part;
|
||||
|
||||
/** The cache sets. */
|
||||
SplitCacheSet *sets;
|
||||
|
||||
/** The cache blocks. */
|
||||
SplitBlk *blks;
|
||||
/** The data blocks, 1 per cache block. */
|
||||
uint8_t *dataBlks;
|
||||
|
||||
/** The amount to shift the address to get the set. */
|
||||
int setShift;
|
||||
/** The amount to shift the address to get the tag. */
|
||||
int tagShift;
|
||||
/** Mask out all bits that aren't part of the set index. */
|
||||
unsigned setMask;
|
||||
/** Mask out all bits that aren't part of the block offset. */
|
||||
unsigned blkMask;
|
||||
|
||||
/** number of hits in this partition */
|
||||
Stats::Scalar<> hits;
|
||||
/** number of blocks brought into this partition (i.e. misses) */
|
||||
Stats::Scalar<> misses;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct and initialize this tag store.
|
||||
* @param _numSets The number of sets in the cache.
|
||||
* @param _blkSize The number of bytes in a block.
|
||||
* @param _assoc The associativity of the cache.
|
||||
* @param _hit_latency The latency in cycles for a hit.
|
||||
*/
|
||||
SplitLRU(int _numSets, int _blkSize, int _assoc, int _hit_latency, int _part);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~SplitLRU();
|
||||
|
||||
/**
|
||||
* Register the statistics for this object
|
||||
* @param name The name to precede the stat
|
||||
*/
|
||||
void regStats(const std::string &name);
|
||||
|
||||
/**
|
||||
* Return the block size.
|
||||
* @return the block size.
|
||||
*/
|
||||
int getBlockSize()
|
||||
{
|
||||
return blkSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subblock size. In the case of LRU it is always the block
|
||||
* size.
|
||||
* @return The block size.
|
||||
*/
|
||||
int getSubBlockSize()
|
||||
{
|
||||
return blkSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the address in the cache.
|
||||
* @param asid The address space ID.
|
||||
* @param addr The address to find.
|
||||
* @return True if the address is in the cache.
|
||||
*/
|
||||
bool probe(Addr addr) const;
|
||||
|
||||
/**
|
||||
* Invalidate the given block.
|
||||
* @param blk The block to invalidate.
|
||||
*/
|
||||
void invalidateBlk(BlkType *blk);
|
||||
|
||||
/**
|
||||
* Finds the given address in the cache and update replacement data.
|
||||
* Returns the access latency as a side effect.
|
||||
* @param addr The address to find.
|
||||
* @param asid The address space ID.
|
||||
* @param lat The access latency.
|
||||
* @return Pointer to the cache block if found.
|
||||
*/
|
||||
SplitBlk* findBlock(Addr addr, int &lat);
|
||||
|
||||
/**
|
||||
* Finds the given address in the cache, do not update replacement data.
|
||||
* @param addr The address to find.
|
||||
* @param asid The address space ID.
|
||||
* @return Pointer to the cache block if found.
|
||||
*/
|
||||
SplitBlk* findBlock(Addr addr) const;
|
||||
|
||||
/**
|
||||
* Find a replacement block for the address provided.
|
||||
* @param pkt The request to a find a replacement candidate for.
|
||||
* @param writebacks List for any writebacks to be performed.
|
||||
* @return The block to place the replacement in.
|
||||
*/
|
||||
SplitBlk* findReplacement(Addr addr, PacketList &writebacks);
|
||||
|
||||
/**
|
||||
* Generate the tag from the given address.
|
||||
* @param addr The address to get the tag from.
|
||||
* @return The tag of the address.
|
||||
*/
|
||||
Addr extractTag(Addr addr) const
|
||||
{
|
||||
return (addr >> tagShift);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the set index from the address.
|
||||
* @param addr The address to get the set from.
|
||||
* @return The set index of the address.
|
||||
*/
|
||||
int extractSet(Addr addr) const
|
||||
{
|
||||
return ((addr >> setShift) & setMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block offset from an address.
|
||||
* @param addr The address to get the offset of.
|
||||
* @return The block offset.
|
||||
*/
|
||||
int extractBlkOffset(Addr addr) const
|
||||
{
|
||||
return (addr & blkMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Align an address to the block size.
|
||||
* @param addr the address to align.
|
||||
* @return The block address.
|
||||
*/
|
||||
Addr blkAlign(Addr addr) const
|
||||
{
|
||||
return (addr & ~(Addr)blkMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Regenerate the block address from the tag.
|
||||
* @param tag The tag of the block.
|
||||
* @param set The set of the block.
|
||||
* @return The block address.
|
||||
*/
|
||||
Addr regenerateBlkAddr(Addr tag, unsigned set) const
|
||||
{
|
||||
return ((tag << tagShift) | ((Addr)set << setShift));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hit latency.
|
||||
* @return the hit latency.
|
||||
*/
|
||||
int getHitLatency() const
|
||||
{
|
||||
return hitLatency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the data out of the internal storage of the given cache block.
|
||||
* @param blk The cache block to read.
|
||||
* @param data The buffer to read the data into.
|
||||
* @return The cache block's data.
|
||||
*/
|
||||
void readData(SplitBlk *blk, uint8_t *data)
|
||||
{
|
||||
std::memcpy(data, blk->data, blk->size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data into the internal storage of the given cache block. Since in
|
||||
* LRU does not store data differently this just needs to update the size.
|
||||
* @param blk The cache block to write.
|
||||
* @param data The data to write.
|
||||
* @param size The number of bytes to write.
|
||||
* @param writebacks A list for any writebacks to be performed. May be
|
||||
* needed when writing to a compressed block.
|
||||
*/
|
||||
void writeData(SplitBlk *blk, uint8_t *data, int size,
|
||||
PacketList & writebacks)
|
||||
{
|
||||
assert(size <= blkSize);
|
||||
blk->size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called at end of simulation to complete average block reference stats.
|
||||
*/
|
||||
virtual void cleanupRefs();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -36,7 +36,4 @@
|
|||
*/
|
||||
#define USE_CACHE_LRU 1
|
||||
#define USE_CACHE_FALRU 1
|
||||
// #define USE_CACHE_SPLIT 1
|
||||
// #define USE_CACHE_SPLIT_LIFO 1
|
||||
#define USE_CACHE_IIC 1
|
||||
|
||||
|
|
Loading…
Reference in a new issue