Repository navigation
Expand file tree
/
Copy pathcache.cpp
More file actions
113 lines (96 loc) · 3.34 KB
/
Copy pathcache.cpp
File metadata and controls
113 lines (96 loc) · 3.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include "cache.h"
#include <cmath>
#include <iostream>
Cache::Cache(int c_size, int b_size, int assoc, ReplacementPolicy p)
: cache_size(c_size), block_size(b_size), associativity(assoc), policy(p), access_counter(0) {
num_sets = cache_size / (block_size * associativity);
offset_bits = static_cast<int>(std::log2(block_size));
index_bits = static_cast<int>(std::log2(num_sets));
sets.reserve(num_sets);
for (int i = 0; i < num_sets; ++i) {
sets.emplace_back(associativity, (int)(block_size / sizeof(int)));
}
}
int Cache::getIndex(uint32_t address) {
return (address >> offset_bits) & (num_sets - 1);
}
int Cache::getTag(uint32_t address) {
return address >> (offset_bits + index_bits);
}
bool Cache::access(uint32_t address, bool& hit) {
access_counter++;
int index = getIndex(address);
int tag = getTag(address);
CacheSet& set = sets[index];
for (auto& block : set.blocks) {
if (block.valid && block.tag == tag) {
hit = true;
hits++;
block.last_used = access_counter; // Update for LRU
return true;
}
}
hit = false;
misses++;
return false;
}
void Cache::insertBlock(uint32_t address) {
access_counter++;
int index = getIndex(address);
int tag = getTag(address);
CacheSet& set = sets[index];
int victim_idx = 0;
bool found_empty = false;
// 1. Look for an invalid block first
for (int i = 0; i < (int)set.blocks.size(); ++i) {
if (!set.blocks[i].valid) {
victim_idx = i;
found_empty = true;
break;
}
}
// 2. Apply replacement policy if cache set is full
if (!found_empty) {
uint64_t min_timestamp = UINT64_MAX;
for (int i = 0; i < (int)set.blocks.size(); ++i) {
uint64_t current_val = (policy == ReplacementPolicy::LRU)
? set.blocks[i].last_used
: set.blocks[i].insertion_time;
if (current_val < min_timestamp) {
min_timestamp = current_val;
victim_idx = i;
}
}
}
// Replace the victim block
CacheBlock& victim = set.blocks[victim_idx];
victim.valid = true;
victim.tag = tag;
victim.dirty = false;
victim.last_used = access_counter; // Fresh access time
victim.insertion_time = access_counter; // Fresh insertion time
}
void Cache::printActiveState(const std::string& cache_name) {
bool has_active_sets = false;
std::cout << " => [" << cache_name << " State]: ";
for (int i = 0; i < num_sets; ++i) {
bool set_has_data = false;
for (const auto& block : sets[i].blocks) {
if (block.valid) set_has_data = true;
}
if (set_has_data) {
if (!has_active_sets) std::cout << "\n"; // formatting
has_active_sets = true;
std::cout << " Set " << i << ": | ";
for (const auto& block : sets[i].blocks) {
if (block.valid) {
std::cout << "Tag: " << block.tag << " (Age: " << block.last_used << ") | ";
} else {
std::cout << "[ Empty ] | ";
}
}
std::cout << "\n";
}
}
if (!has_active_sets) std::cout << "Cold (Empty)\n";
}