diff --git a/src/mem/cache/tags/SConscript b/src/mem/cache/tags/SConscript index 1412286a7..d593be86e 100644 --- a/src/mem/cache/tags/SConscript +++ b/src/mem/cache/tags/SConscript @@ -37,3 +37,4 @@ Source('base_set_assoc.cc') Source('lru.cc') Source('random_repl.cc') Source('fa_lru.cc') +Source('nmru.cc') diff --git a/src/mem/cache/tags/Tags.py b/src/mem/cache/tags/Tags.py index 6c0b85044..68e5fe8f0 100644 --- a/src/mem/cache/tags/Tags.py +++ b/src/mem/cache/tags/Tags.py @@ -80,3 +80,8 @@ class FALRU(BaseTags): type = 'FALRU' cxx_class = 'FALRU' cxx_header = "mem/cache/tags/fa_lru.hh" + +class NMRU(BaseSetAssoc): + type = 'NMRU' + cxx_class = 'NMRU' + cxx_header = "mem/cache/tags/nmru.hh" diff --git a/src/mem/cache/tags/nmru.cc b/src/mem/cache/tags/nmru.cc new file mode 100644 index 000000000..bfd129a58 --- /dev/null +++ b/src/mem/cache/tags/nmru.cc @@ -0,0 +1,79 @@ +/** + * @file + * Definitions of a NMRU tag store. + */ + +#include "mem/cache/tags/nmru.hh" + +#include "base/random.hh" +#include "debug/CacheRepl.hh" +#include "mem/cache/base.hh" + +NMRU::NMRU(const Params *p) : BaseSetAssoc(p) +{ + +} + +BaseSetAssoc::BlkType* +NMRU::accessBlock(Addr addr, bool is_secure, Cycles &lat, int master_id) +{ + // Accesses are based on parent class, no need to do anything special + BlkType *blk = BaseSetAssoc::accessBlock(addr, is_secure, lat, master_id); + + if (blk != NULL) { + // move this block to head of the MRU list + sets[blk->set].moveToHead(blk); + DPRINTF(CacheRepl, "set %x: moving blk %x (%s) to MRU\n", + blk->set, regenerateBlkAddr(blk->tag, blk->set), + is_secure ? "s" : "ns"); + } + + return blk; +} + +BaseSetAssoc::BlkType* +NMRU::findVictim(Addr addr) +{ + BlkType *blk = BaseSetAssoc::findVictim(addr); + + // if all blocks are valid, pick a replacement that is not MRU at random + if (blk->isValid()) { + // find a random index within the bounds of the set + int idx = random_mt.random(1, assoc - 1); + assert(idx < assoc); + assert(idx >= 0); + blk = sets[extractSet(addr)].blks[idx]; + + DPRINTF(CacheRepl, + "set %x: selecting blk %x for replacement\n", + blk->set, + regenerateBlkAddr(blk->tag, blk->set)); + } + + return blk; +} + +void +NMRU::insertBlock(PacketPtr pkt, BlkType *blk) +{ + BaseSetAssoc::insertBlock(pkt, blk); + + int set = extractSet(pkt->getAddr()); + sets[set].moveToHead(blk); +} + +void +NMRU::invalidate(BlkType *blk) +{ + BaseSetAssoc::invalidate(blk); + + // should be evicted before valid blocks + int set = blk->set; + sets[set].moveToTail(blk); +} + +NMRU* +NMRUParams::create() +{ + return new NMRU(this); +} diff --git a/src/mem/cache/tags/nmru.hh b/src/mem/cache/tags/nmru.hh new file mode 100644 index 000000000..bc1b35a79 --- /dev/null +++ b/src/mem/cache/tags/nmru.hh @@ -0,0 +1,33 @@ +#ifndef __MEM_CACHE_TAGS_NMRU_HH__ +#define __MEM_CACHE_TAGS_NMRU_HH__ + +#include "mem/cache/tags/base_set_assoc.hh" +#include "params/NMRU.hh" + +class NMRU : public BaseSetAssoc +{ +public: + /** Convenience typedef. */ + typedef NMRUParams Params; + + /** + * Construct and initialize this tag store. + */ + NMRU(const Params *p); + + /** + * Destructor + */ + ~NMRU() {} + + /** + * Required functions for this subclass to implement + */ + BlkType* accessBlock(Addr addr, bool is_secure, Cycles &lat, + int context_src); + BlkType* findVictim(Addr addr); + void insertBlock(PacketPtr pkt, BlkType *blk); + void invalidate(BlkType *blk); +}; + +#endif // __MEM_CACHE_TAGS_NMRU_HH__