/*
+ * Copyright (c) 2013,2016 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) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Definitions a fully associative LRU tagstore.
*/
-#include <sstream>
+#include "mem/cache/tags/fa_lru.hh"
-#include <assert.h>
+#include <cassert>
+#include <sstream>
-#include "mem/cache/tags/fa_lru.hh"
#include "base/intmath.hh"
+#include "base/logging.hh"
using namespace std;
-FALRU::FALRU(int _blkSize, int _size, int hit_latency)
- : blkSize(_blkSize), size(_size),
- numBlks(size/blkSize), hitLatency(hit_latency)
+FALRU::FALRU(const Params *p)
+ : BaseTags(p), cacheBoundaries(nullptr)
{
if (!isPowerOf2(blkSize))
fatal("cache block size (in bytes) `%d' must be a power of two",
blkSize);
- if (!(hitLatency > 0))
- fatal("Access latency in cycles must be at least one cycle");
if (!isPowerOf2(size))
fatal("Cache Size must be power of 2 for now");
numCaches = floorLog2(size) - 17;
if (numCaches >0){
cacheBoundaries = new FALRUBlk *[numCaches];
- cacheMask = (1 << numCaches) - 1;
+ cacheMask = (ULL(1) << numCaches) - 1;
} else {
cacheMask = 0;
}
- warmedUp = false;
warmupBound = size/blkSize;
+ numBlocks = size/blkSize;
- blks = new FALRUBlk[numBlks];
+ blks = new FALRUBlk[numBlocks];
head = &(blks[0]);
- tail = &(blks[numBlks-1]);
+ tail = &(blks[numBlocks-1]);
- head->prev = NULL;
+ head->prev = nullptr;
head->next = &(blks[1]);
head->inCache = cacheMask;
- tail->prev = &(blks[numBlks-2]);
- tail->next = NULL;
+ tail->prev = &(blks[numBlocks-2]);
+ tail->next = nullptr;
tail->inCache = 0;
- int index = (1 << 17) / blkSize;
- int j = 0;
+ unsigned index = (1 << 17) / blkSize;
+ unsigned j = 0;
int flags = cacheMask;
- for (int i = 1; i < numBlks-1; i++) {
+ for (unsigned i = 1; i < numBlocks - 1; i++) {
blks[i].inCache = flags;
if (i == index - 1){
cacheBoundaries[j] = &(blks[i]);
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 == numBlks);
+ assert(index == numBlocks);
//assert(check());
}
+FALRU::~FALRU()
+{
+ if (numCaches)
+ delete[] cacheBoundaries;
+
+ delete[] blks;
+}
+
void
-FALRU::regStats(const string &name)
+FALRU::regStats()
{
using namespace Stats;
- BaseTags::regStats(name);
+ BaseTags::regStats();
hits
.init(numCaches+1)
- .name(name + ".falru_hits")
+ .name(name() + ".falru_hits")
.desc("The number of hits in each cache size.")
;
misses
.init(numCaches+1)
- .name(name + ".falru_misses")
+ .name(name() + ".falru_misses")
.desc("The number of misses in each cache size.")
;
accesses
- .name(name + ".falru_accesses")
+ .name(name() + ".falru_accesses")
.desc("The number of accesses to the FA LRU cache.")
;
- for (int i = 0; i < numCaches+1; ++i) {
+ for (unsigned i = 0; i <= numCaches; ++i) {
stringstream size_str;
if (i < 3){
size_str << (1<<(i+7)) <<"K";
if (iter != tagHash.end()) {
return (*iter).second;
}
- return NULL;
+ return nullptr;
}
-bool
-FALRU::probe(int asid, Addr addr) const
+void
+FALRU::invalidate(CacheBlk *blk)
{
- Addr blkAddr = blkAlign(addr);
- FALRUBlk* blk = hashLookup(blkAddr);
- return blk && blk->tag == blkAddr && blk->isValid();
+ assert(blk);
+ tagsInUse--;
}
-void
-FALRU::invalidateBlk(int asid, Addr addr)
+CacheBlk*
+FALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat)
{
- Addr blkAddr = blkAlign(addr);
- FALRUBlk* blk = (*tagHash.find(blkAddr)).second;
- if (blk) {
- assert(blk->tag == blkAddr);
- blk->status = 0;
- blk->isTouched = false;
- tagsInUse--;
- }
+ return accessBlock(addr, is_secure, lat, 0);
}
-FALRUBlk*
-FALRU::findBlock(Addr addr, int asid, int &lat, int *inCache)
+CacheBlk*
+FALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat, int *inCache)
{
accesses++;
int tmp_in_cache = 0;
FALRUBlk* blk = hashLookup(blkAddr);
if (blk && blk->isValid()) {
+ // If a cache hit
+ lat = accessLatency;
+ // Check if the block to be accessed is available. If not,
+ // apply the accessLatency on top of block->whenReady.
+ if (blk->whenReady > curTick() &&
+ cache->ticksToCycles(blk->whenReady - curTick()) >
+ accessLatency) {
+ lat = cache->ticksToCycles(blk->whenReady - curTick()) +
+ accessLatency;
+ }
assert(blk->tag == blkAddr);
tmp_in_cache = blk->inCache;
- for (int i = 0; i < numCaches; i++) {
+ for (unsigned i = 0; i < numCaches; i++) {
if (1<<i & blk->inCache) {
hits[i]++;
} else {
moveToHead(blk);
}
} else {
- blk = NULL;
- for (int i = 0; i < numCaches+1; ++i) {
+ // If a cache miss
+ lat = lookupLatency;
+ blk = nullptr;
+ for (unsigned i = 0; i <= numCaches; ++i) {
misses[i]++;
}
}
*inCache = tmp_in_cache;
}
- lat = hitLatency;
//assert(check());
return blk;
}
-FALRUBlk*
-FALRU::findBlock(Packet * &pkt, int &lat, int *inCache)
-{
- Addr addr = pkt->paddr;
- accesses++;
- int tmp_in_cache = 0;
+CacheBlk*
+FALRU::findBlock(Addr addr, bool is_secure) const
+{
Addr blkAddr = blkAlign(addr);
FALRUBlk* blk = hashLookup(blkAddr);
if (blk && blk->isValid()) {
assert(blk->tag == blkAddr);
- tmp_in_cache = blk->inCache;
- for (int i = 0; i < numCaches; i++) {
- if (1<<i & blk->inCache) {
- hits[i]++;
- } else {
- misses[i]++;
- }
- }
- hits[numCaches]++;
- if (blk != head){
- moveToHead(blk);
- }
} else {
- blk = NULL;
- for (int i = 0; i < numCaches+1; ++i) {
- misses[i]++;
- }
+ blk = nullptr;
}
- if (inCache) {
- *inCache = tmp_in_cache;
- }
-
- lat = hitLatency;
- //assert(check());
return blk;
}
-FALRUBlk*
-FALRU::findBlock(Addr addr, int asid) const
+CacheBlk*
+FALRU::findBlockBySetAndWay(int set, int way) const
{
- Addr blkAddr = blkAlign(addr);
- FALRUBlk* blk = hashLookup(blkAddr);
-
- if (blk && blk->isValid()) {
- assert(blk->tag == blkAddr);
- } else {
- blk = NULL;
- }
- return blk;
+ assert(set == 0);
+ return &blks[way];
}
-FALRUBlk*
-FALRU::findReplacement(Packet * &pkt, PacketList* &writebacks,
- BlkList &compress_blocks)
+CacheBlk*
+FALRU::findVictim(Addr addr)
{
FALRUBlk * blk = tail;
assert(blk->inCache == 0);
moveToHead(blk);
tagHash.erase(blk->tag);
- tagHash[blkAlign(pkt->paddr)] = blk;
+ tagHash[blkAlign(addr)] = blk;
if (blk->isValid()) {
- int thread_num = (blk->xc) ? blk->xc->getThreadNum() : 0;
- replacements[thread_num]++;
+ replacements[0]++;
} else {
tagsInUse++;
blk->isTouched = true;
if (!warmedUp && tagsInUse.value() >= warmupBound) {
warmedUp = true;
- warmupCycle = curTick;
+ warmupCycle = curTick();
}
}
//assert(check());
return blk;
}
+void
+FALRU::insertBlock(PacketPtr pkt, CacheBlk *blk)
+{
+}
+
void
FALRU::moveToHead(FALRUBlk *blk)
{
int updateMask = blk->inCache ^ cacheMask;
- for (int i = 0; i < numCaches; i++){
+ for (unsigned i = 0; i < numCaches; i++){
if ((1<<i) & updateMask) {
cacheBoundaries[i]->inCache &= ~(1<<i);
cacheBoundaries[i] = cacheBoundaries[i]->prev;
blk->inCache = cacheMask;
if (blk != head) {
if (blk == tail){
- assert(blk->next == NULL);
+ assert(blk->next == nullptr);
tail = blk->prev;
- tail->next = NULL;
+ tail->next = nullptr;
} else {
blk->prev->next = blk->next;
blk->next->prev = blk->prev;
}
blk->next = head;
- blk->prev = NULL;
+ blk->prev = nullptr;
head->prev = blk;
head = blk;
}
FALRU::check()
{
FALRUBlk* blk = head;
- int size = 0;
+ int tot_size = 0;
int boundary = 1<<17;
int j = 0;
int flags = cacheMask;
while (blk) {
- size += blkSize;
+ tot_size += blkSize;
if (blk->inCache != flags) {
return false;
}
- if (size == boundary && blk != tail) {
+ if (tot_size == boundary && blk != tail) {
if (cacheBoundaries[j] != blk) {
return false;
}
}
return true;
}
+
+FALRU *
+FALRUParams::create()
+{
+ return new FALRU(this);
+}
+