diff --git a/src/gui/dialogs/new/NewDialogCache.ui b/src/gui/dialogs/new/NewDialogCache.ui
index 52f1586e..fb74b4f0 100644
--- a/src/gui/dialogs/new/NewDialogCache.ui
+++ b/src/gui/dialogs/new/NewDialogCache.ui
@@ -97,6 +97,11 @@
Pseudo Least Recently Used (PLRU)
+ -
+
+ Not Most Recently Used (NMRU)
+
+
-
diff --git a/src/machine/machineconfig.h b/src/machine/machineconfig.h
index f331d1eb..5392d9ef 100644
--- a/src/machine/machineconfig.h
+++ b/src/machine/machineconfig.h
@@ -46,7 +46,8 @@ class CacheConfig {
RP_RAND, // Random
RP_LRU, // Least recently used
RP_LFU, // Least frequently used
- RP_PLRU // Pseudo Least recently used
+ RP_PLRU, // Pseudo Least recently used
+ RP_NMRU // Not most recently used
};
enum WritePolicy {
diff --git a/src/machine/memory/cache/cache.test.cpp b/src/machine/memory/cache/cache.test.cpp
index 889e1b19..9f9ce042 100644
--- a/src/machine/memory/cache/cache.test.cpp
+++ b/src/machine/memory/cache/cache.test.cpp
@@ -34,8 +34,8 @@ constexpr array values { 0x4142434445464748 };
* Cache configuration parameters for testing
* (all combinations are tested)
*/
-constexpr array replacement_policies {
- CacheConfig::RP_RAND, CacheConfig::RP_LFU, CacheConfig::RP_LRU, CacheConfig::RP_PLRU
+constexpr array replacement_policies {
+ CacheConfig::RP_RAND, CacheConfig::RP_LFU, CacheConfig::RP_LRU, CacheConfig::RP_PLRU, CacheConfig::RP_NMRU
};
constexpr array write_policies {
CacheConfig::WP_THROUGH_NOALLOC, // THIS
@@ -242,7 +242,7 @@ void TestCache::cache_correctness() {
// stderr, "{ %d, %d }, ", cache.get_hit_count(),
// cache.get_miss_count());
- if (cache_config.replacement_policy() != CacheConfig::RP_RAND) {
+ if ((cache_config.replacement_policy() != CacheConfig::RP_RAND) && (cache_config.replacement_policy() != CacheConfig::RP_NMRU)) {
// Performance of random policy is implementation dependant and
// meaningless.
QCOMPARE(performance, cache_test_performance_data.at(case_number));
diff --git a/src/machine/memory/cache/cache_policy.cpp b/src/machine/memory/cache/cache_policy.cpp
index 7875828e..15a4e35a 100644
--- a/src/machine/memory/cache/cache_policy.cpp
+++ b/src/machine/memory/cache/cache_policy.cpp
@@ -22,6 +22,8 @@ CachePolicy::get_policy_instance(const CacheConfig *config) {
config->associativity(), config->set_count());
case CacheConfig::RP_PLRU:
return std::make_unique(config->associativity(), config->set_count());
+ case CacheConfig::RP_NMRU:
+ return std::make_unique(config->associativity(), config->set_count());
}
} else {
// Disabled cache will never use it.
@@ -172,4 +174,29 @@ size_t CachePolicyPLRU::select_way_to_evict(size_t row) const {
}
return (idx >= associativity) ? (associativity - 1) : idx;
}
+
+CachePolicyNMRU::CachePolicyNMRU(size_t associativity, size_t set_count)
+ : associativity(associativity) {
+ mru_ptr.resize(set_count);
+ for (auto &row : mru_ptr) {
+ row = 0; // Initially point to block 0
+ }
+ std::srand(1); // NOLINT(cert-msc51-cpp)
+}
+
+void CachePolicyNMRU::update_stats(size_t way, size_t row, bool is_valid) {
+ UNUSED(is_valid)
+ auto &row_ptr = mru_ptr.at(row); // Set currently accessed block to most recently used
+ row_ptr = way;
+}
+
+size_t CachePolicyNMRU::select_way_to_evict(size_t row) const {
+ if(associativity == 1) {
+ return 0;
+ }
+ uint32_t idx = std::rand() % (associativity - 1);
+ auto &row_ptr = mru_ptr.at(row);
+ idx = (idx < row_ptr) ? idx : idx + 1;
+ return idx;
+}
} // namespace machine
diff --git a/src/machine/memory/cache/cache_policy.h b/src/machine/memory/cache/cache_policy.h
index b9bf12d6..708fa928 100644
--- a/src/machine/memory/cache/cache_policy.h
+++ b/src/machine/memory/cache/cache_policy.h
@@ -129,6 +129,32 @@ class CachePolicyPLRU final : public CachePolicy {
const size_t associativityCLog2;
};
+/**
+ * Not Most Recently Used
+ *
+ * Select Randomly from Not Most
+ * Recently Used Blocks
+ */
+class CachePolicyNMRU final : public CachePolicy {
+public:
+ /**
+ * @param associativity degree of assiciaivity
+ * @param set_count number of blocks / rows in a way (or sets in
+ * cache)
+ */
+ CachePolicyNMRU(size_t associativity, size_t set_count);
+
+ [[nodiscard]] size_t select_way_to_evict(size_t row) const final;
+
+ void update_stats(size_t way, size_t row, bool is_valid) final;
+
+private:
+ /**
+ * Pointer to Most Recently Used Block
+ */
+ std::vector mru_ptr;
+ const size_t associativity;
+};
} // namespace machine
#endif // CACHE_POLICY_H