remove the totally obsolete split cache

This commit is contained in:
Lisa Hsu 2008-10-23 16:11:28 -04:00
parent 9836d81c2b
commit 7a28ab2d18
12 changed files with 1 additions and 2056 deletions

View file

@ -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")

View file

@ -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; \

View file

@ -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

View file

@ -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')

View file

@ -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);
*/
}

View file

@ -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

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -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

View file

@ -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