mem: Remove the IIC replacement policy

The IIC replacement policy seems to be unused and has probably
gathered too much bit rot to be useful. This patch removes the IIC and
its associated cache parameters.
This commit is contained in:
Andreas Sandberg 2013-01-07 13:05:39 -05:00
parent 9364d35b8b
commit d44f2f611f
11 changed files with 6 additions and 1854 deletions

View file

@ -52,21 +52,14 @@ class BaseCache(MemObject):
hit_latency = Param.Cycles("The hit latency for this cache")
response_latency = Param.Cycles(
"Additional cache latency for the return path to core on a miss");
hash_delay = Param.Cycles(1, "time in cycles of hash access")
max_miss_count = Param.Counter(0,
"number of misses to handle before calling exit")
mshrs = Param.Int("number of MSHRs (max outstanding requests)")
prioritizeRequests = Param.Bool(False,
"always service demand misses first")
repl = Param.Repl(NULL, "replacement policy")
size = Param.MemorySize("capacity in bytes")
forward_snoops = Param.Bool(True,
"forward snoops from mem side to cpu side")
is_top_level = Param.Bool(False, "Is this cache at the top level (e.g. L1)")
subblock_size = Param.Int(0,
"Size of subblock in IIC used for compression")
tgts_per_mshr = Param.Int("max number of accesses per MSHR")
trace_addr = Param.Addr(0, "address to trace")
two_queue = Param.Bool(False,
"whether the lifo should have two queue replacement")
write_buffers = Param.Int(8, "number of write buffers")

View file

@ -51,10 +51,6 @@
#include "mem/cache/tags/fa_lru.hh"
#endif
#if defined(USE_CACHE_IIC)
#include "mem/cache/tags/iic.hh"
#endif
using namespace std;
@ -87,50 +83,16 @@ using namespace std;
#define BUILD_LRU_CACHE BUILD_CACHE_PANIC("lru cache")
#endif
#if defined(USE_CACHE_IIC)
#define BUILD_IIC_CACHE do { \
IIC *tags = new IIC(iic_params); \
BUILD_CACHE(IIC, tags); \
} while (0)
#else
#define BUILD_IIC_CACHE BUILD_CACHE_PANIC("iic")
#endif
#define BUILD_CACHES do { \
if (repl == NULL) { \
if (numSets == 1) { \
BUILD_FALRU_CACHE; \
} else { \
BUILD_LRU_CACHE; \
} \
} else { \
BUILD_IIC_CACHE; \
} \
} while (0)
BaseCache *
BaseCacheParams::create()
{
int numSets = size / (assoc * block_size);
if (subblock_size == 0) {
subblock_size = block_size;
if (numSets == 1) {
BUILD_FALRU_CACHE;
} else {
BUILD_LRU_CACHE;
}
#if defined(USE_CACHE_IIC)
// Build IIC params
IIC::Params iic_params;
iic_params.size = size;
iic_params.numSets = numSets;
iic_params.blkSize = block_size;
iic_params.assoc = assoc;
iic_params.hashDelay = hash_delay;
iic_params.hitLatency = hit_latency;
iic_params.rp = repl;
iic_params.subblockSize = subblock_size;
#else
const void *repl = NULL;
#endif
BUILD_CACHES;
return NULL;
}

View file

@ -46,10 +46,6 @@
#include "mem/cache/tags/fa_lru.hh"
#endif
#if defined(USE_CACHE_IIC)
#include "mem/cache/tags/iic.hh"
#endif
#include "mem/cache/cache_impl.hh"
// Template Instantiations
@ -60,10 +56,6 @@
template class Cache<FALRU>;
#endif
#if defined(USE_CACHE_IIC)
template class Cache<IIC>;
#endif
#if defined(USE_CACHE_LRU)
template class Cache<LRU>;
#endif

View file

@ -35,12 +35,5 @@ if env['TARGET_ISA'] == 'no':
Source('base.cc')
Source('fa_lru.cc')
Source('iic.cc')
Source('lru.cc')
Source('cacheset.cc')
SimObject('iic_repl/Repl.py')
Source('iic_repl/gen.cc')
DebugFlag('IIC')
DebugFlag('IICMore')

View file

@ -1,649 +0,0 @@
/*
* Copyright (c) 2002-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: Erik Hallnor
*/
/**
* @file
* Definitions of the Indirect Index Cache tagstore.
*/
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include "base/intmath.hh"
#include "base/trace.hh"
#include "debug/Cache.hh"
#include "debug/IIC.hh"
#include "debug/IICMore.hh"
#include "mem/cache/tags/iic.hh"
#include "mem/cache/base.hh"
#include "sim/core.hh"
using namespace std;
/** Track the number of accesses to each cache set. */
#define PROFILE_IIC 1
IIC::IIC(IIC::Params &params) :
hashSets(params.numSets), blkSize(params.blkSize), assoc(params.assoc),
hitLatency(params.hitLatency), subSize(params.subblockSize),
numSub(blkSize/subSize),
trivialSize((floorLog2(params.size/subSize)*numSub)/8),
tagShift(floorLog2(blkSize)), blkMask(blkSize - 1),
subShift(floorLog2(subSize)), subMask(numSub - 1),
hashDelay(params.hashDelay),
numTags(hashSets * assoc + params.size/blkSize -1),
numSecondary(params.size/blkSize),
tagNull(numTags),
primaryBound(hashSets * assoc)
{
// Check parameters
if (blkSize < 4 || !isPowerOf2(blkSize)) {
fatal("Block size must be at least 4 and a power of 2");
}
if (hashSets <= 0 || !isPowerOf2(hashSets)) {
fatal("# of hashsets 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");
}
if (numSub*subSize != blkSize) {
fatal("blocksize must be evenly divisible by subblock size");
}
// debug stuff
freeSecond = numSecondary;
warmedUp = false;
warmupBound = params.size/blkSize;
numBlocks = params.size/subSize;
// Replacement Policy Initialization
repl = params.rp;
repl->setIIC(this);
//last_miss_time = 0
// allocate data reference counters
dataReferenceCount = new int[numBlocks];
memset(dataReferenceCount, 0, numBlocks*sizeof(int));
// Allocate storage for both internal data and block fast access data.
// We allocate it as one large chunk to reduce overhead and to make
// deletion easier.
unsigned data_index = 0;
dataStore = new uint8_t[(numBlocks + numTags) * blkSize];
dataBlks = new uint8_t*[numBlocks];
for (unsigned i = 0; i < numBlocks; ++i) {
dataBlks[i] = &dataStore[data_index];
freeDataBlock(i);
data_index += subSize;
}
assert(data_index == numBlocks * subSize);
// allocate and init tag store
tagStore = new IICTag[numTags];
unsigned blkIndex = 0;
// allocate and init sets
sets = new IICSet[hashSets];
for (unsigned i = 0; i < hashSets; ++i) {
sets[i].assoc = assoc;
sets[i].tags = new IICTag*[assoc];
sets[i].chain_ptr = tagNull;
for (unsigned j = 0; j < assoc; ++j) {
IICTag *tag = &tagStore[blkIndex++];
tag->chain_ptr = tagNull;
tag->data_ptr.resize(numSub);
tag->size = blkSize;
tag->trivialData = new uint8_t[trivialSize];
tag->numData = 0;
sets[i].tags[j] = tag;
tag->set = i;
tag->data = &dataStore[data_index];
data_index += blkSize;
}
}
assert(blkIndex == primaryBound);
for (unsigned i = primaryBound; i < tagNull; i++) {
tagStore[i].chain_ptr = i+1;
//setup data ptrs to subblocks
tagStore[i].data_ptr.resize(numSub);
tagStore[i].size = blkSize;
tagStore[i].trivialData = new uint8_t[trivialSize];
tagStore[i].numData = 0;
tagStore[i].set = 0;
tagStore[i].data = &dataStore[data_index];
data_index += blkSize;
}
freelist = primaryBound;
}
IIC::~IIC()
{
delete [] dataReferenceCount;
delete [] dataStore;
delete [] tagStore;
delete [] sets;
delete [] dataBlks;
}
/* register cache stats */
void
IIC::regStats(const string &name)
{
using namespace Stats;
BaseTags::regStats(name);
hitHashDepth.init(0, 20, 1);
missHashDepth.init(0, 20, 1);
setAccess.init(0, hashSets, 1);
/** IIC Statistics */
hitHashDepth
.name(name + ".hit_hash_depth_dist")
.desc("Dist. of Hash lookup depths")
.flags(pdf)
;
missHashDepth
.name(name + ".miss_hash_depth_dist")
.desc("Dist. of Hash lookup depths")
.flags(pdf)
;
repl->regStatsWithSuffix(name);
if (PROFILE_IIC)
setAccess
.name(name + ".set_access_dist")
.desc("Dist. of Accesses across sets")
.flags(pdf)
;
missDepthTotal
.name(name + ".miss_depth_total")
.desc("Total of miss depths")
;
hashMiss
.name(name + ".hash_miss")
.desc("Total of misses in hash table")
;
hitDepthTotal
.name(name + ".hit_depth_total")
.desc("Total of hit depths")
;
hashHit
.name(name + ".hash_hit")
.desc("Total of hites in hash table")
;
}
IICTag*
IIC::accessBlock(Addr addr, Cycles &lat, int context_src)
{
Addr tag = extractTag(addr);
unsigned set = hash(addr);
Cycles set_lat;
unsigned long chain_ptr = tagNull;
if (PROFILE_IIC)
setAccess.sample(set);
IICTag *tag_ptr = sets[set].findTag(tag, chain_ptr);
set_lat = Cycles(1);
if (tag_ptr == NULL && chain_ptr != tagNull) {
int secondary_depth;
tag_ptr = secondaryChain(tag, chain_ptr, &secondary_depth);
set_lat += Cycles(secondary_depth);
// set depth for statistics fix this later!!! egh
sets[set].depth = set_lat;
if (tag_ptr != NULL) {
/* need to move tag into primary table */
// need to preserve chain: fix this egh
sets[set].tags[assoc-1]->chain_ptr = tag_ptr->chain_ptr;
tagSwap(tag_ptr - tagStore, sets[set].tags[assoc-1] - tagStore);
tag_ptr = sets[set].findTag(tag, chain_ptr);
assert(tag_ptr!=NULL);
}
}
set_lat = Cycles(set_lat * hashDelay + hitLatency);
if (tag_ptr != NULL) {
// IIC replacement: if this is not the first element of
// list, reorder
sets[set].moveToHead(tag_ptr);
hitHashDepth.sample(sets[set].depth);
hashHit++;
hitDepthTotal += sets[set].depth;
tag_ptr->status |= BlkReferenced;
lat = set_lat;
if (tag_ptr->whenReady > curTick() &&
cache->ticksToCycles(tag_ptr->whenReady - curTick()) > set_lat) {
lat = cache->ticksToCycles(tag_ptr->whenReady - curTick());
}
tag_ptr->refCount += 1;
}
else {
// fall through: cache block not found, not a hit...
missHashDepth.sample(sets[set].depth);
hashMiss++;
missDepthTotal += sets[set].depth;
lat = set_lat;
}
return tag_ptr;
}
IICTag*
IIC::findBlock(Addr addr) const
{
Addr tag = extractTag(addr);
unsigned set = hash(addr);
unsigned long chain_ptr = tagNull;
IICTag *tag_ptr = sets[set].findTag(tag, chain_ptr);
if (tag_ptr == NULL && chain_ptr != tagNull) {
int secondary_depth;
tag_ptr = secondaryChain(tag, chain_ptr, &secondary_depth);
}
return tag_ptr;
}
IICTag*
IIC::findVictim(Addr addr, PacketList &writebacks)
{
DPRINTF(IIC, "Finding Replacement for %x\n", addr);
unsigned set = hash(addr);
IICTag *tag_ptr;
unsigned long *tmp_data = new unsigned long[numSub];
// Get a enough subblocks for a full cache line
for (unsigned i = 0; i < numSub; ++i){
tmp_data[i] = getFreeDataBlock(writebacks);
assert(dataReferenceCount[tmp_data[i]]==0);
}
tag_ptr = getFreeTag(set, writebacks);
tag_ptr->set = set;
for (unsigned i = 0; i < numSub; ++i) {
tag_ptr->data_ptr[i] = tmp_data[i];
dataReferenceCount[tag_ptr->data_ptr[i]]++;
}
tag_ptr->numData = numSub;
assert(tag_ptr - tagStore < primaryBound); // make sure it is in primary
tag_ptr->chain_ptr = tagNull;
sets[set].moveToHead(tag_ptr);
delete [] tmp_data;
list<unsigned long> tag_indexes;
repl->doAdvance(tag_indexes);
/*
while (!tag_indexes.empty()) {
if (!tagStore[tag_indexes.front()].isCompressed()) {
compress_blocks.push_back(&tagStore[tag_indexes.front()]);
}
tag_indexes.pop_front();
}
*/
tag_ptr->re = (void*)repl->add(tag_ptr-tagStore);
return tag_ptr;
}
void
IIC::insertBlock(Addr addr, BlkType* blk, int context_src)
{
}
void
IIC::freeReplacementBlock(PacketList & writebacks)
{
IICTag *tag_ptr;
unsigned long data_ptr;
/* consult replacement policy */
tag_ptr = &tagStore[repl->getRepl()];
assert(tag_ptr != NULL);
assert(tag_ptr->isValid());
DPRINTF(Cache, "Replacing %x in IIC: %s\n",
regenerateBlkAddr(tag_ptr->tag,0),
tag_ptr->isDirty() ? "writeback" : "clean");
/* write back replaced block data */
replacements[0]++;
totalRefs += tag_ptr->refCount;
++sampledRefs;
tag_ptr->refCount = 0;
if (tag_ptr->isDirty()) {
/* PacketPtr writeback =
buildWritebackReq(regenerateBlkAddr(tag_ptr->tag, 0),
tag_ptr->req->asid, tag_ptr->xc, blkSize,
tag_ptr->data,
tag_ptr->size);
*/
Request *writebackReq = new Request(regenerateBlkAddr(tag_ptr->tag, 0),
blkSize, 0, Request::wbMasterId);
PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback);
writeback->allocate();
memcpy(writeback->getPtr<uint8_t>(), tag_ptr->data, blkSize);
writebacks.push_back(writeback);
}
// free the data blocks
for (int i = 0; i < tag_ptr->numData; ++i) {
data_ptr = tag_ptr->data_ptr[i];
assert(dataReferenceCount[data_ptr]>0);
if (--dataReferenceCount[data_ptr] == 0) {
freeDataBlock(data_ptr);
}
}
freeTag(tag_ptr);
}
unsigned long
IIC::getFreeDataBlock(PacketList & writebacks)
{
unsigned long data_ptr;
/* find data block */
while (blkFreelist.empty()) {
freeReplacementBlock(writebacks);
}
data_ptr = blkFreelist.front();
blkFreelist.pop_front();
DPRINTF(IICMore,"Found free data at %d\n",data_ptr);
return data_ptr;
}
IICTag*
IIC::getFreeTag(int set, PacketList & writebacks)
{
unsigned long tag_index;
IICTag *tag_ptr;
// Add new tag
tag_ptr = sets[set].findFree();
// if no free in primary, and secondary exists
if (!tag_ptr && numSecondary) {
// need to spill a tag into secondary storage
while (freelist == tagNull) {
// get replacements until one is in secondary
freeReplacementBlock(writebacks);
}
tag_index = freelist;
freelist = tagStore[freelist].chain_ptr;
freeSecond--;
assert(tag_index != tagNull);
tagSwap(tag_index, sets[set].tags[assoc-1] - tagStore);
tagStore[tag_index].chain_ptr = sets[set].chain_ptr;
sets[set].chain_ptr = tag_index;
tag_ptr = sets[set].tags[assoc-1];
}
DPRINTF(IICMore,"Found free tag at %d\n",tag_ptr - tagStore);
tagsInUse++;
if (!warmedUp && tagsInUse.value() >= warmupBound) {
warmedUp = true;
warmupCycle = curTick();
}
return tag_ptr;
}
void
IIC::freeTag(IICTag *tag_ptr)
{
unsigned long tag_index, tmp_index;
// Fix tag_ptr
if (tag_ptr) {
// we have a tag to clear
DPRINTF(IICMore,"Freeing Tag for %x\n",
regenerateBlkAddr(tag_ptr->tag,0));
tagsInUse--;
tag_ptr->status = 0;
tag_ptr->numData = 0;
tag_ptr->re = NULL;
tag_index = tag_ptr - tagStore;
if (tag_index >= primaryBound) {
// tag_ptr points to secondary store
assert(tag_index < tagNull); // remove this?? egh
if (tag_ptr->chain_ptr == tagNull) {
// need to fix chain list
unsigned tmp_set = hash(tag_ptr->tag << tagShift);
if (sets[tmp_set].chain_ptr == tag_index) {
sets[tmp_set].chain_ptr = tagNull;
} else {
tmp_index = sets[tmp_set].chain_ptr;
while (tmp_index != tagNull
&& tagStore[tmp_index].chain_ptr != tag_index) {
tmp_index = tagStore[tmp_index].chain_ptr;
}
assert(tmp_index != tagNull);
tagStore[tmp_index].chain_ptr = tagNull;
}
tag_ptr->chain_ptr = freelist;
freelist = tag_index;
freeSecond++;
} else {
// copy next chained entry to this tag location
tmp_index = tag_ptr->chain_ptr;
tagSwap(tmp_index, tag_index);
tagStore[tmp_index].chain_ptr = freelist;
freelist = tmp_index;
freeSecond++;
}
} else {
// tag_ptr in primary hash table
assert(tag_index < primaryBound);
tag_ptr->status = 0;
unsigned tmp_set = hash(tag_ptr->tag << tagShift);
if (sets[tmp_set].chain_ptr != tagNull) { // collapse chain
tmp_index = sets[tmp_set].chain_ptr;
tagSwap(tag_index, tmp_index);
tagStore[tmp_index].chain_ptr = freelist;
freelist = tmp_index;
freeSecond++;
sets[tmp_set].chain_ptr = tag_ptr->chain_ptr;
sets[tmp_set].moveToTail(tag_ptr);
}
}
}
}
void
IIC::freeDataBlock(unsigned long data_ptr)
{
assert(dataReferenceCount[data_ptr] == 0);
DPRINTF(IICMore, "Freeing data at %d\n", data_ptr);
blkFreelist.push_front(data_ptr);
}
/** Use a simple modulo hash. */
#define SIMPLE_HASH 0
unsigned
IIC::hash(Addr addr) const {
#if SIMPLE_HASH
return extractTag(addr) % iic_hash_size;
#else
Addr tag, mask, x, y;
tag = extractTag(addr);
mask = hashSets-1; /* assumes iic_hash_size is a power of 2 */
x = tag & mask;
y = (tag >> (int)(::log((double)hashSets)/::log((double)2))) & mask;
assert (x < hashSets && y < hashSets);
return x ^ y;
#endif
}
void
IICSet::moveToHead(IICTag *tag)
{
if (tags[0] == tag)
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;
IICTag *next = tag;
do {
assert(i < assoc);
// swap blks[i] and next
IICTag *tmp = tags[i];
tags[i] = next;
next = tmp;
++i;
} while (next != tag);
}
void
IICSet::moveToTail(IICTag *tag)
{
if (tags[assoc-1] == tag)
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 = assoc - 1;
IICTag *next = tag;
do {
assert(i >= 0);
// swap blks[i] and next
IICTag *tmp = tags[i];
tags[i] = next;
next = tmp;
--i;
} while (next != tag);
}
void
IIC::tagSwap(unsigned long index1, unsigned long index2)
{
DPRINTF(IIC,"Swapping tag[%d]=%x for tag[%d]=%x\n",index1,
tagStore[index1].tag<<tagShift, index2,
tagStore[index2].tag<<tagShift);
IICTag tmp_tag;
tmp_tag = tagStore[index1];
tagStore[index1] = tagStore[index2];
tagStore[index2] = tmp_tag;
if (tagStore[index1].isValid())
repl->fixTag(tagStore[index1].re, index2, index1);
if (tagStore[index2].isValid())
repl->fixTag(tagStore[index2].re, index1, index2);
}
IICTag *
IIC::secondaryChain(Addr tag, unsigned long chain_ptr,
int *_depth) const
{
int depth = 0;
while (chain_ptr != tagNull) {
DPRINTF(IIC,"Searching secondary at %d for %x\n", chain_ptr,
tag<<tagShift);
if (tagStore[chain_ptr].tag == tag &&
(tagStore[chain_ptr].isValid())) {
*_depth = depth;
return &tagStore[chain_ptr];
}
depth++;
chain_ptr = tagStore[chain_ptr].chain_ptr;
}
*_depth = depth;
return NULL;
}
void
IIC::invalidate(IIC::BlkType *tag_ptr)
{
if (tag_ptr) {
for (int i = 0; i < tag_ptr->numData; ++i) {
dataReferenceCount[tag_ptr->data_ptr[i]]--;
if (dataReferenceCount[tag_ptr->data_ptr[i]] == 0) {
freeDataBlock(tag_ptr->data_ptr[i]);
}
}
repl->removeEntry(tag_ptr->re);
freeTag(tag_ptr);
}
}
void
IIC::clearLocks()
{
for (int i = 0; i < numTags; i++){
tagStore[i].clearLoadLocks();
}
}
void
IIC::cleanupRefs()
{
for (unsigned i = 0; i < numTags; ++i) {
if (tagStore[i].isValid()) {
totalRefs += tagStore[i].refCount;
++sampledRefs;
}
}
}

View file

@ -1,540 +0,0 @@
/*
* Copyright (c) 2012 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2002-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: Erik Hallnor
*/
/**
* @file
* Declaration of the Indirect Index Cache (IIC) tags store.
*/
#ifndef __IIC_HH__
#define __IIC_HH__
#include <list>
#include <vector>
#include "base/statistics.hh"
#include "mem/cache/tags/iic_repl/repl.hh"
#include "mem/cache/tags/base.hh"
#include "mem/cache/blk.hh"
#include "mem/packet.hh"
class BaseCache; // Forward declaration
/**
* IIC cache blk.
*/
class IICTag : public CacheBlk
{
public:
/**
* Copy the contents of the given IICTag into this one.
* @param rhs The tag to copy.
* @return const reference to this tag.
*/
const IICTag& operator=(const IICTag& rhs)
{
CacheBlk::operator=(rhs);
chain_ptr = rhs.chain_ptr;
re = rhs.re;
set = rhs.set;
trivialData = rhs.trivialData;
numData = rhs.numData;
data_ptr.clear();
for (int i = 0; i < rhs.numData; ++i) {
data_ptr.push_back(rhs.data_ptr[i]);
}
return *this;
}
/** Hash chain pointer into secondary store. */
unsigned long chain_ptr;
/** Data array pointers for each subblock. */
std::vector<unsigned long> data_ptr;
/** Replacement Entry pointer. */
void *re;
/**
* An array to store small compressed data. Conceputally the same size
* as the unsused data array pointers.
*/
uint8_t *trivialData;
/**
* The number of allocated subblocks.
*/
int numData;
};
/**
* A hash set for the IIC primary lookup table.
*/
class IICSet{
public:
/** The associativity of the primary table. */
int assoc;
/** The number of hash chains followed when finding the last block. */
int depth;
/** The current number of blocks on the chain. */
int size;
/** Tag pointer into the secondary tag storage. */
unsigned long chain_ptr;
/** The LRU list of the primary table. MRU is at 0 index. */
IICTag ** tags;
/**
* Find the addr in this set, return the chain pointer to the secondary if
* it isn't found.
* @param asid The address space ID.
* @param tag The address to find.
* @param chain_ptr The chain pointer to start the search of the secondary
* @return Pointer to the tag, NULL if not found.
*/
IICTag* findTag( Addr tag, unsigned long &chain_ptr)
{
depth = 1;
for (int i = 0; i < assoc; ++i) {
if (tags[i]->tag == tag && tags[i]->isValid()) {
return tags[i];
}
}
chain_ptr = this->chain_ptr;
return 0;
}
/**
* Find an usused tag in this set.
* @return Pointer to the unused tag, NULL if none are free.
*/
IICTag* findFree()
{
for (int i = 0; i < assoc; ++i) {
if (!tags[i]->isValid()) {
return tags[i];
}
}
return 0;
}
/**
* Move a tag to the head of the LRU list
* @param tag The tag to move.
*/
void moveToHead(IICTag *tag);
/**
* Move a tag to the tail (LRU) of the LRU list
* @param tag The tag to move.
*/
void moveToTail(IICTag *tag);
};
/**
* The IIC tag store. This is a hardware-realizable, fully-associative tag
* store that uses software replacement, e.g. Gen.
*/
class IIC : public BaseTags
{
public:
/** Typedef of the block type used in this class. */
typedef IICTag BlkType;
/** Typedef for list of pointers to the local block type. */
typedef std::list<IICTag*> BlkList;
protected:
/** The number of set in the primary table. */
const unsigned hashSets;
/** The block size in bytes. */
const unsigned blkSize;
/** The associativity of the primary table. */
const unsigned assoc;
/** The base hit latency. */
const Cycles hitLatency;
/** The subblock size, used for compression. */
const unsigned subSize;
/** The number of subblocks */
const unsigned numSub;
/** The number of bytes used by data pointers */
const unsigned trivialSize;
/** The amount to shift address to get the tag. */
const unsigned tagShift;
/** The mask to get block offset bits. */
const unsigned blkMask;
/** The amount to shift to get the subblock number. */
const unsigned subShift;
/** The mask to get the correct subblock number. */
const unsigned subMask;
/** The latency of a hash lookup. */
const Cycles hashDelay;
/** The total number of tags in primary and secondary. */
const unsigned numTags;
/** The number of tags in the secondary tag store. */
const unsigned numSecondary;
/** The Null tag pointer. */
const unsigned tagNull;
/** The last tag in the primary table. */
const unsigned primaryBound;
/** All of the tags */
IICTag *tagStore;
/**
* Pointer to the head of the secondary freelist (maintained with chain
* pointers.
*/
unsigned long freelist;
/**
* The data block freelist.
*/
std::list<unsigned long> blkFreelist;
/** The primary table. */
IICSet *sets;
/** The replacement policy. */
Repl *repl;
/** An array of data reference counters. */
int *dataReferenceCount;
/** The data blocks. */
uint8_t *dataStore;
/** Storage for the fast access data of each cache block. */
uint8_t **dataBlks;
/**
* Count of the current number of free secondary tags.
* Used for debugging.
*/
int freeSecond;
// IIC Statistics
/**
* @addtogroup IICStatistics IIC Statistics
* @{
*/
/** Hash hit depth of cache hits. */
Stats::Distribution hitHashDepth;
/** Hash depth for cache misses. */
Stats::Distribution missHashDepth;
/** Count of accesses to each hash set. */
Stats::Distribution setAccess;
/** The total hash depth for every miss. */
Stats::Scalar missDepthTotal;
/** The total hash depth for all hits. */
Stats::Scalar hitDepthTotal;
/** The number of hash misses. */
Stats::Scalar hashMiss;
/** The number of hash hits. */
Stats::Scalar hashHit;
/** @} */
public:
/**
* Collection of parameters for the IIC.
*/
class Params {
public:
/** The size in bytes of the cache. */
unsigned size;
/** The number of sets in the primary table. */
unsigned numSets;
/** The block size in bytes. */
unsigned blkSize;
/** The associativity of the primary table. */
unsigned assoc;
/** The number of cycles for each hash lookup. */
Cycles hashDelay;
/** The number of cycles to read the data. */
Cycles hitLatency;
/** The replacement policy. */
Repl *rp;
/** The subblock size in bytes. */
unsigned subblockSize;
};
/**
* Construct and initialize this tag store.
* @param params The IIC parameters.
* @todo
* Should make a way to have less tags in the primary than blks in the
* cache. Also should be able to specify number of secondary blks.
*/
IIC(Params &params);
/**
* Destructor.
*/
virtual ~IIC();
/**
* Register the statistics.
* @param name The name to prepend to the statistic descriptions.
*/
void regStats(const std::string &name);
/**
* Regenerate the block address from the tag.
* @param tag The tag of the block.
* @param set Not needed for the iic.
* @return The block address.
*/
Addr regenerateBlkAddr(Addr tag, int set) {
return (((Addr)tag << tagShift));
}
/**
* Return the block size.
* @return The block size.
*/
unsigned
getBlockSize() const
{
return blkSize;
}
/**
* Return the subblock size.
* @return The subblock size.
*/
unsigned
getSubBlockSize() const
{
return subSize;
}
/**
* Return the hit latency.
* @return the hit latency.
*/
int getHitLatency() const
{
return hitLatency;
}
/**
* Generate the tag from the address.
* @param addr The address to a get a tag for.
* @return the tag.
*/
Addr extractTag(Addr addr) const
{
return (addr >> tagShift);
}
/**
* Return the set, always 0 for IIC.
* @return 0.
*/
int extractSet(Addr addr) const
{
return 0;
}
/**
* Get the block offset of an address.
* @param addr The address to get the offset of.
* @return the block offset of the address.
*/
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);
}
/**
* Swap the position of two tags.
* @param index1 The first tag location.
* @param index2 The second tag location.
*/
void tagSwap(unsigned long index1, unsigned long index2);
/**
* Clear the reference bit of the tag and return its old value.
* @param index The pointer of the tag to manipulate.
* @return The previous state of the reference bit.
*/
bool clearRef(unsigned long index)
{
bool tmp = tagStore[index].isReferenced();
tagStore[index].status &= ~BlkReferenced;
return tmp;
}
/**
* Invalidate a block.
* @param blk The block to invalidate.
*/
void invalidate(BlkType *blk);
/**
* Access block and update replacement data. May not succeed, in which case
* NULL pointer is returned. This has all the implications of a cache
* access and should only be used as such.
* Returns the access latency and inCache flags as a side effect.
* @param addr The address to find.
* @param asid The address space ID.
* @param lat The access latency.
* @return A pointer to the block found, if any.
*/
IICTag* accessBlock(Addr addr, Cycles &lat, int context_src);
/**
* Find the block, do not update the replacement data.
* @param addr The address to find.
* @param asid The address space ID.
* @return A pointer to the block found, if any.
*/
IICTag* 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.
*/
IICTag* findVictim(Addr addr, PacketList &writebacks);
void insertBlock(Addr addr, BlkType *blk, int context_src);
/**
*iterated through all blocks and clear all locks
*Needed to clear all lock tracking at once
*/
virtual void clearLocks();
/**
* Called at end of simulation to complete average block reference stats.
*/
virtual void cleanupRefs();
/**
* Visit each block in the tag store and apply a visitor to the
* block.
*
* The visitor should be a function (or object that behaves like a
* function) that takes a cache block reference as its parameter
* and returns a bool. A visitor can request the traversal to be
* stopped by returning false, returning true causes it to be
* called for the next block in the tag store.
*
* \param visitor Visitor to call on each block.
*/
template <typename V>
void forEachBlk(V &visitor) {
for (unsigned i = 0; i < numTags; ++i) {
if (!visitor(tagStore[i]))
return;
}
}
private:
/**
* Return the hash of the address.
* @param addr The address to hash.
* @return the hash of the address.
*/
unsigned hash(Addr addr) const;
/**
* Search for a block in the secondary tag store. Returns the number of
* hash lookups as a side effect.
* @param asid The address space ID.
* @param tag The tag to match.
* @param chain_ptr The first entry to search.
* @param depth The number of hash lookups made while searching.
* @return A pointer to the block if found.
*/
IICTag *secondaryChain(Addr tag, unsigned long chain_ptr,
int *depth) const;
/**
* Free the resources associated with the next replacement block.
* @param writebacks A list of any writebacks to perform.
*/
void freeReplacementBlock(PacketList & writebacks);
/**
* Return the pointer to a free data block.
* @param writebacks A list of any writebacks to perform.
* @return A pointer to a free data block.
*/
unsigned long getFreeDataBlock(PacketList & writebacks);
/**
* Get a free tag in the given hash set.
* @param set The hash set to search.
* @param writebacks A list of any writebacks to perform.
* @return a pointer to a free tag.
*/
IICTag* getFreeTag(int set, PacketList & writebacks);
/**
* Free the resources associated with the given tag.
* @param tag_ptr The tag to free.
*/
void freeTag(IICTag *tag_ptr);
/**
* Mark the given data block as being available.
* @param data_ptr The data block to free.
*/
void freeDataBlock(unsigned long data_ptr);
};
#endif // __IIC_HH__

View file

@ -1,41 +0,0 @@
# Copyright (c) 2005-2008 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: Nathan Binkert
from m5.SimObject import SimObject
from m5.params import *
class Repl(SimObject):
type = 'Repl'
abstract = True
cxx_header = "mem/cache/tags/iic_repl/repl.hh"
class GenRepl(Repl):
type = 'GenRepl'
cxx_header = "mem/cache/tags/iic_repl/gen.hh"
fresh_res = Param.Int("Fresh pool residency time")
num_pools = Param.Int("Number of priority pools")
pool_res = Param.Int("Pool residency time")

View file

@ -1,207 +0,0 @@
/*
* Copyright (c) 2002-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: Erik Hallnor
* Steve Reinhardt
*/
/**
* @file
* Definitions of the Generational replacement policy.
*/
#include <string>
#include "base/misc.hh"
#include "base/types.hh"
#include "mem/cache/tags/iic_repl/gen.hh"
#include "mem/cache/tags/iic.hh"
#include "params/GenRepl.hh"
using namespace std;
GenRepl::GenRepl(const Params *p) // fix this, should be set by cache
: Repl(p), num_pools(p->num_pools), fresh_res(p->fresh_res),
pool_res(p->pool_res), num_entries(0), num_pool_entries(0), misses(0),
pools(new GenPool[num_pools+1])
{
}
GenRepl::~GenRepl()
{
delete [] pools;
}
unsigned long
GenRepl::getRepl()
{
unsigned long tmp;
GenReplEntry *re;
int i;
int num_seen = 0;
if (!(num_pool_entries>0)) {
fatal("No blks available to replace");
}
num_entries--;
num_pool_entries--;
for (i = 0; i < num_pools; i++) {
while ((re = pools[i].pop())) {
num_seen++;
// Remove invalidated entries
if (!re->valid) {
delete re;
continue;
}
if (iic->clearRef(re->tag_ptr)) {
pools[(((i+1)== num_pools)? i :i+1)].push(re, misses);
}
else {
tmp = re->tag_ptr;
delete re;
repl_pool.sample(i);
return tmp;
}
}
}
fatal("No replacement found");
return 0xffffffff;
}
void
GenRepl::doAdvance(std::list<unsigned long> &demoted)
{
int i;
int num_seen = 0;
GenReplEntry *re;
misses++;
for (i=0; i<num_pools; i++) {
while (misses-pools[i].oldest > pool_res && (re = pools[i].pop())!=NULL) {
if (iic->clearRef(re->tag_ptr)) {
pools[(((i+1)== num_pools)? i :i+1)].push(re, misses);
/** @todo Not really demoted, but use it for now. */
demoted.push_back(re->tag_ptr);
advance_pool.sample(i);
}
else {
pools[(((i-1)<0)?i:i-1)].push(re, misses);
demoted.push_back(re->tag_ptr);
demote_pool.sample(i);
}
}
num_seen += pools[i].size;
}
while (misses-pools[num_pools].oldest > fresh_res
&& (re = pools[num_pools].pop())!=NULL) {
num_pool_entries++;
if (iic->clearRef(re->tag_ptr)) {
pools[num_pools/2].push(re, misses);
/** @todo Not really demoted, but use it for now. */
demoted.push_back(re->tag_ptr);
advance_pool.sample(num_pools);
}
else {
pools[num_pools/2-1].push(re, misses);
demoted.push_back(re->tag_ptr);
demote_pool.sample(num_pools);
}
}
}
void*
GenRepl::add(unsigned long tag_index)
{
GenReplEntry *re = new GenReplEntry;
re->tag_ptr = tag_index;
re->valid = true;
pools[num_pools].push(re, misses);
num_entries++;
return (void*)re;
}
void
GenRepl::regStatsWithSuffix(const string name)
{
using namespace Stats;
/** GEN statistics */
repl_pool
.init(0, 16, 1)
.name(name + ".repl_pool_dist")
.desc("Dist. of Repl. across pools")
.flags(pdf)
;
advance_pool
.init(0, 16, 1)
.name(name + ".advance_pool_dist")
.desc("Dist. of Repl. across pools")
.flags(pdf)
;
demote_pool
.init(0, 16, 1)
.name(name + ".demote_pool_dist")
.desc("Dist. of Repl. across pools")
.flags(pdf)
;
}
int
GenRepl::fixTag(void* _re, unsigned long old_index, unsigned long new_index)
{
GenReplEntry *re = (GenReplEntry*)_re;
assert(re->valid);
if (re->tag_ptr == old_index) {
re->tag_ptr = new_index;
return 1;
}
fatal("Repl entry: tag ptrs do not match");
return 0;
}
bool
GenRepl::findTagPtr(unsigned long index)
{
for (int i = 0; i < num_pools + 1; ++i) {
list<GenReplEntry*>::const_iterator iter = pools[i].entries.begin();
list<GenReplEntry*>::const_iterator end = pools[i].entries.end();
for (; iter != end; ++iter) {
if ((*iter)->valid && (*iter)->tag_ptr == index) {
return true;
}
}
}
return false;
}
GenRepl *
GenReplParams::create()
{
return new GenRepl(this);
}

View file

@ -1,234 +0,0 @@
/*
* Copyright (c) 2002-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: Erik Hallnor
*/
/**
* @file
* Declarations of generational replacement policy
*/
#ifndef ___GEN_HH__
#define __GEN_HH__
#include <list>
#include "base/statistics.hh"
#include "mem/cache/tags/iic_repl/repl.hh"
#include "params/GenRepl.hh"
/**
* Generational Replacement entry.
*/
class GenReplEntry
{
public:
/** Valid flag, used to quickly invalidate bogus entries. */
bool valid;
/** The difference between this entry and the previous in the pool. */
int delta;
/** Pointer to the corresponding tag in the IIC. */
unsigned long tag_ptr;
};
/**
* Generational replacement pool
*/
class GenPool
{
public:
/** The time the last entry was added. */
Tick newest;
/** The time the oldest entry was added. */
Tick oldest;
/** List of the replacement entries in this pool. */
std::list<GenReplEntry*> entries;
/** The number of entries in this pool. */
int size;
/**
* Simple constructor.
*/
GenPool() {
newest = 0;
oldest = 0;
size = 0;
}
/**
* Add an entry to this pool.
* @param re The entry to add.
* @param now The current time.
*/
void push(GenReplEntry *re, Tick now) {
++size;
if (!entries.empty()) {
re->delta = now - newest;
newest = now;
} else {
re->delta = 0;
newest = oldest = now;
}
entries.push_back(re);
}
/**
* Remove an entry from the pool.
* @return The entry at the front of the list.
*/
GenReplEntry* pop() {
GenReplEntry *tmp = NULL;
if (!entries.empty()) {
--size;
tmp = entries.front();
entries.pop_front();
oldest += tmp->delta;
}
return tmp;
}
/**
* Return the entry at the front of the list.
* @return the entry at the front of the list.
*/
GenReplEntry* top() {
return entries.front();
}
/**
* Destructor.
*/
~GenPool() {
while (!entries.empty()) {
GenReplEntry *tmp = entries.front();
entries.pop_front();
delete tmp;
}
}
};
/**
* Generational replacement policy for use with the IIC.
* @todo update to use STL and for efficiency
*/
class GenRepl : public Repl
{
public:
/** The number of pools. */
int num_pools;
/** The amount of time to stay in the fresh pool. */
int fresh_res;
/** The amount of time to stay in the normal pools. */
int pool_res;
/** The maximum number of entries */
int num_entries;
/** The number of entries currently in the pools. */
int num_pool_entries;
/** The number of misses. Used as the internal time. */
Tick misses;
/** The array of pools. */
GenPool *pools;
// Statistics
/**
* @addtogroup CacheStatistics
* @{
*/
/** The number of replacements from each pool. */
Stats::Distribution repl_pool;
/** The number of advances out of each pool. */
Stats::Distribution advance_pool;
/** The number of demotions from each pool. */
Stats::Distribution demote_pool;
/**
* @}
*/
typedef GenReplParams Params;
GenRepl(const Params *p);
/**
* Destructor.
*/
~GenRepl();
/**
* Returns the tag pointer of the cache block to replace.
* @return The tag to replace.
*/
virtual unsigned long getRepl();
/**
* Update replacement data
*/
virtual void doAdvance(std::list<unsigned long> &demoted);
/**
* Add a tag to the replacement policy and return a pointer to the
* replacement entry.
* @param tag_index The tag to add.
* @return The replacement entry.
*/
virtual void* add(unsigned long tag_index);
/**
* Register statistics.
* @param name The name to prepend to statistic descriptions.
*/
virtual void regStatsWithSuffix(const std::string name);
/**
* Update the tag pointer to when the tag moves.
* @param re The replacement entry of the tag.
* @param old_index The old tag pointer.
* @param new_index The new tag pointer.
* @return 1 if successful, 0 otherwise.
*/
virtual int fixTag(void *re, unsigned long old_index,
unsigned long new_index);
/**
* Remove this entry from the replacement policy.
* @param re The replacement entry to remove
*/
virtual void removeEntry(void *re)
{
((GenReplEntry*)re)->valid = false;
}
protected:
/**
* Debug function to verify that there is only one repl entry per tag.
* @param index The tag index to check.
*/
bool findTagPtr(unsigned long index);
};
#endif /* __GEN_HH__ */

View file

@ -1,117 +0,0 @@
/*
* Copyright (c) 2002-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: Erik Hallnor
* Steve Reinhardt
* Nathan Binkert
*/
/**
* @file
* Declaration of a base replacement policy class.
*/
#ifndef __REPL_HH__
#define __REPL_HH__
#include <list>
#include <string>
#include "base/types.hh"
#include "cpu/smt.hh"
#include "sim/sim_object.hh"
class IIC;
/**
* A pure virtual base class that defines the interface of a replacement
* policy.
*/
class Repl : public SimObject
{
public:
/** Pointer to the IIC using this policy. */
IIC *iic;
Repl (const Params *params)
: SimObject(params)
{
iic = NULL;
}
/**
* Set the back pointer to the IIC.
* @param iic_ptr Pointer to the IIC.
*/
void setIIC(IIC *iic_ptr)
{
iic = iic_ptr;
}
/**
* Returns the tag pointer of the cache block to replace.
* @return The tag to replace.
*/
virtual unsigned long getRepl() = 0;
/**
* Update replacement data
*/
virtual void doAdvance(std::list<unsigned long> &demoted) = 0;
/**
* Add a tag to the replacement policy and return a pointer to the
* replacement entry.
* @param tag_index The tag to add.
* @return The replacement entry.
*/
virtual void* add(unsigned long tag_index) = 0;
/**
* Register statistics.
* @param name The name to prepend to statistic descriptions.
*/
virtual void regStatsWithSuffix(const std::string name) = 0;
/**
* Update the tag pointer to when the tag moves.
* @param re The replacement entry of the tag.
* @param old_index The old tag pointer.
* @param new_index The new tag pointer.
* @return 1 if successful, 0 otherwise.
*/
virtual int fixTag(void *re, unsigned long old_index,
unsigned long new_index) = 0;
/**
* Remove this entry from the replacement policy.
* @param re The replacement entry to remove
*/
virtual void removeEntry(void *re) = 0;
};
#endif /* SMT_REPL_HH */

View file

@ -36,4 +36,4 @@
*/
#define USE_CACHE_LRU 1
#define USE_CACHE_FALRU 1
#define USE_CACHE_IIC 1