Tick whenReady;
/**
- * The set this block belongs to.
+ * The set and way this block belongs to.
* @todo Move this into subclasses when we fix CacheTags to use them.
*/
- int set;
+ int set, way;
/** whether this block has been touched */
bool isTouched;
CacheBlk()
: task_id(ContextSwitchTaskId::Unknown),
asid(-1), tag(0), data(0) ,size(0), status(0), whenReady(0),
- set(-1), isTouched(false), refCount(0),
+ set(-1), way(-1), isTouched(false), refCount(0),
srcMasterId(Request::invldMasterId),
tickInserted(0)
{}
{
CacheBlk *blk = tags->findVictim(addr);
+ // It is valid to return NULL if there is no victim
+ if (!blk)
+ return nullptr;
+
if (blk->isValid()) {
Addr repl_addr = tags->regenerateBlkAddr(blk->tag, blk->set);
MSHR *repl_mshr = mshrQueue.findMatch(repl_addr, blk->isSecure());
/*
- * Copyright (c) 2012-2013 ARM Limited
+ * Copyright (c) 2012-2014 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
return (addr & (Addr)(blkSize-1));
}
+ /**
+ * Find the cache block given set and way
+ * @param set The set of the block.
+ * @param way The way of the block.
+ * @return The cache block.
+ */
+ virtual CacheBlk *findBlockBySetAndWay(int set, int way) const = 0;
+
+ /**
+ * Limit the allocation for the cache ways.
+ * @param ways The maximum number of ways available for replacement.
+ */
+ virtual void setWayAllocationMax(int ways)
+ {
+ panic("This tag class does not implement way allocation limit!\n");
+ }
+
+ /**
+ * Get the way allocation mask limit.
+ * @return The maximum number of ways available for replacement.
+ */
+ virtual int getWayAllocationMax() const
+ {
+ panic("This tag class does not implement way allocation limit!\n");
+ return -1;
+ }
+
+ virtual unsigned getNumSets() const = 0;
+
+ virtual unsigned getNumWays() const = 0;
+
virtual void invalidate(CacheBlk *blk) = 0;
virtual CacheBlk* accessBlock(Addr addr, bool is_secure, Cycles &lat,
/*
- * Copyright (c) 2012-2013 ARM Limited
+ * Copyright (c) 2012-2014 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
using namespace std;
BaseSetAssoc::BaseSetAssoc(const Params *p)
- :BaseTags(p), assoc(p->assoc),
+ :BaseTags(p), assoc(p->assoc), allocAssoc(p->assoc),
numSets(p->size / (p->block_size * p->assoc)),
sequentialAccess(p->sequential_access)
{
blk->size = blkSize;
sets[i].blks[j]=blk;
blk->set = i;
+ blk->way = j;
}
}
}
return blk;
}
+CacheBlk*
+BaseSetAssoc::findBlockBySetAndWay(int set, int way) const
+{
+ return sets[set].blks[way];
+}
+
void
BaseSetAssoc::clearLocks()
{
/*
- * Copyright (c) 2012-2013 ARM Limited
+ * Copyright (c) 2012-2014 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
protected:
/** The associativity of the cache. */
const unsigned assoc;
+ /** The allocatable associativity of the cache (alloc mask). */
+ unsigned allocAssoc;
/** The number of sets in the cache. */
const unsigned numSets;
/** Whether tags and data are accessed sequentially. */
return blkSize;
}
+ /**
+ * Return the number of sets this cache has
+ * @return The number of sets.
+ */
+ unsigned
+ getNumSets() const
+ {
+ return numSets;
+ }
+
+ /**
+ * Return the number of ways this cache has
+ * @return The number of ways.
+ */
+ unsigned
+ getNumWays() const
+ {
+ return assoc;
+ }
+
+ /**
+ * Find the cache block given set and way
+ * @param set The set of the block.
+ * @param way The way of the block.
+ * @return The cache block.
+ */
+ CacheBlk *findBlockBySetAndWay(int set, int way) const;
+
/**
* Invalidate the given block.
* @param blk The block to invalidate.
// Access all tags in parallel, hence one in each way. The data side
// either accesses all blocks in parallel, or one block sequentially on
// a hit. Sequential access with a miss doesn't access data.
- tagAccesses += assoc;
+ tagAccesses += allocAssoc;
if (sequentialAccess) {
if (blk != NULL) {
dataAccesses += 1;
}
} else {
- dataAccesses += assoc;
+ dataAccesses += allocAssoc;
}
if (blk != NULL) {
int set = extractSet(addr);
// prefer to evict an invalid block
- for (int i = 0; i < assoc; ++i) {
+ for (int i = 0; i < allocAssoc; ++i) {
blk = sets[set].blks[i];
- if (!blk->isValid()) {
+ if (!blk->isValid())
break;
- }
}
return blk;
dataAccesses += 1;
}
+ /**
+ * Limit the allocation for the cache ways.
+ * @param ways The maximum number of ways available for replacement.
+ */
+ virtual void setWayAllocationMax(int ways)
+ {
+ fatal_if(ways < 1, "Allocation limit must be greater than zero");
+ allocAssoc = ways;
+ }
+
+ /**
+ * Get the way allocation mask limit.
+ * @return The maximum number of ways available for replacement.
+ */
+ virtual int getWayAllocationMax() const
+ {
+ return allocAssoc;
+ }
+
/**
* Generate the tag from the given address.
* @param addr The address to get the tag from.
blks[i].prev = &(blks[i-1]);
blks[i].next = &(blks[i+1]);
blks[i].isTouched = false;
+ blks[i].set = 0;
+ blks[i].way = i;
}
assert(j == numCaches);
assert(index == numBlocks);
return blk;
}
+CacheBlk*
+FALRU::findBlockBySetAndWay(int set, int way) const
+{
+ assert(set == 0);
+ return &blks[way];
+}
+
CacheBlk*
FALRU::findVictim(Addr addr)
{
return blkSize;
}
+ /**
+ * Return the number of sets this cache has
+ * @return The number of sets.
+ */
+ unsigned
+ getNumSets() const
+ {
+ return 1;
+ }
+
+ /**
+ * Return the number of ways this cache has
+ * @return The number of ways.
+ */
+ unsigned
+ getNumWays() const
+ {
+ return numBlocks;
+ }
+
+ /**
+ * Find the cache block given set and way
+ * @param set The set of the block.
+ * @param way The way of the block.
+ * @return The cache block.
+ */
+ CacheBlk* findBlockBySetAndWay(int set, int way) const;
+
/**
* Align an address to the block size.
* @param addr the address to align.
{
int set = extractSet(addr);
// grab a replacement candidate
- BlkType *blk = sets[set].blks[assoc - 1];
+ BlkType *blk = NULL;
+ for (int i = assoc - 1; i >= 0; i--) {
+ BlkType *b = sets[set].blks[i];
+ if (b->way < allocAssoc) {
+ blk = b;
+ break;
+ }
+ }
+ assert(!blk || blk->way < allocAssoc);
- if (blk->isValid()) {
+ if (blk && blk->isValid()) {
DPRINTF(CacheRepl, "set %x: selecting blk %x for replacement\n",
set, regenerateBlkAddr(blk->tag, set));
}
RandomRepl::findVictim(Addr addr)
{
CacheBlk *blk = BaseSetAssoc::findVictim(addr);
+ unsigned set = extractSet(addr);
// if all blocks are valid, pick a replacement at random
- if (blk->isValid()) {
+ if (blk && blk->isValid()) {
// find a random index within the bounds of the set
int idx = random_mt.random<int>(0, assoc - 1);
+ blk = sets[set].blks[idx];
+ // Enforce allocation limit
+ while (blk->way >= allocAssoc) {
+ idx = (idx + 1) % assoc;
+ blk = sets[set].blks[idx];
+ }
+
assert(idx < assoc);
assert(idx >= 0);
- blk = sets[extractSet(addr)].blks[idx];
+ assert(blk->way < allocAssoc);
DPRINTF(CacheRepl, "set %x: selecting blk %x for replacement\n",
blk->set, regenerateBlkAddr(blk->tag, blk->set));