mem: Make caches way aware

This patch makes cache sets aware of the way number. This enables
some nice features such as the ablity to restrict way allocation. The
implemented mechanism allows to set a maximum way number to be
allocated 'k' which must fulfill 0 < k <= N (where N is the number of
ways). In the future more sophisticated mechasims can be implemented.
This commit is contained in:
David Guillen-Fandos
2015-07-30 03:41:42 -04:00
parent 5a18e181ff
commit 0c89c15b23
9 changed files with 159 additions and 16 deletions

View File

@@ -107,10 +107,10 @@ class CacheBlk
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;
@@ -168,7 +168,7 @@ class CacheBlk
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)
{}

View File

@@ -1581,6 +1581,10 @@ Cache::allocateBlock(Addr addr, bool is_secure, PacketList &writebacks)
{
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());

View File

@@ -1,5 +1,5 @@
/*
* 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
@@ -196,6 +196,37 @@ class BaseTags : public ClockedObject
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,

View File

@@ -1,5 +1,5 @@
/*
* 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
@@ -54,7 +54,7 @@
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)
{
@@ -108,6 +108,7 @@ BaseSetAssoc::BaseSetAssoc(const Params *p)
blk->size = blkSize;
sets[i].blks[j]=blk;
blk->set = i;
blk->way = j;
}
}
}
@@ -128,6 +129,12 @@ BaseSetAssoc::findBlock(Addr addr, bool is_secure) const
return blk;
}
CacheBlk*
BaseSetAssoc::findBlockBySetAndWay(int set, int way) const
{
return sets[set].blks[way];
}
void
BaseSetAssoc::clearLocks()
{

View File

@@ -1,5 +1,5 @@
/*
* 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
@@ -87,6 +87,8 @@ class BaseSetAssoc : public BaseTags
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. */
@@ -145,6 +147,34 @@ public:
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.
@@ -183,13 +213,13 @@ public:
// 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) {
@@ -227,11 +257,10 @@ public:
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;
@@ -291,6 +320,25 @@ public:
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.

View File

@@ -101,6 +101,8 @@ FALRU::FALRU(const Params *p)
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);
@@ -226,6 +228,13 @@ FALRU::findBlock(Addr addr, bool is_secure) const
return blk;
}
CacheBlk*
FALRU::findBlockBySetAndWay(int set, int way) const
{
assert(set == 0);
return &blks[way];
}
CacheBlk*
FALRU::findVictim(Addr addr)
{

View File

@@ -235,6 +235,34 @@ public:
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.

View File

@@ -75,9 +75,17 @@ LRU::findVictim(Addr addr)
{
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));
}

View File

@@ -54,14 +54,22 @@ CacheBlk*
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));