aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine/cache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qtmips_machine/cache.cpp')
-rw-r--r--qtmips_machine/cache.cpp72
1 files changed, 56 insertions, 16 deletions
diff --git a/qtmips_machine/cache.cpp b/qtmips_machine/cache.cpp
index f32e0e5..c1e4e7b 100644
--- a/qtmips_machine/cache.cpp
+++ b/qtmips_machine/cache.cpp
@@ -48,6 +48,8 @@ Cache::Cache(MemoryAccess *m, const MachineConfigCache *cc, unsigned memory_acc
hit_write = 0;
miss_read = 0;
miss_write = 0;
+ mem_reads = 0;
+ mem_writes = 0;
dt = nullptr;
replc.lfu = nullptr;
replc.lru = nullptr;
@@ -128,20 +130,27 @@ bool Cache::wword(std::uint32_t address, std::uint32_t value) {
if (!cnf.enabled() ||
(address >= uncached_start && address <= uncached_last)) {
+ mem_writes++;
+ emit memory_writes_update(mem_writes);
return mem->write_word(address, value);
}
std::uint32_t data;
changed = access(address, &data, true, value);
- if (cnf.write_policy() == MachineConfigCache::WP_TROUGH)
+ if (cnf.write_policy() != MachineConfigCache::WP_BACK) {
+ mem_writes++;
+ emit memory_writes_update(mem_writes);
return mem->write_word(address, value);
+ }
return changed;
}
std::uint32_t Cache::rword(std::uint32_t address, bool debug_access) const {
if (!cnf.enabled() ||
(address >= uncached_start && address <= uncached_last)) {
+ mem_reads++;
+ emit memory_reads_update(mem_reads);
return mem->read_word(address, debug_access);
}
@@ -177,20 +186,32 @@ unsigned Cache::miss() const {
return miss_read + miss_write;
}
+unsigned Cache::memory_reads() const {
+ return mem_reads;
+}
+
+unsigned Cache::memory_writes() const {
+ return mem_writes;
+}
+
unsigned Cache::stalled_cycles() const {
return miss_read * (access_pen_r - 1) + miss_write * (access_pen_w - 1);
}
double Cache::speed_improvement() const {
+ unsigned lookup_time;
unsigned comp = hit_read + hit_write + miss_read + miss_write;
if (comp == 0)
return 100.0;
+ lookup_time = hit_read + miss_read;
+ if (cnf.write_policy() == MachineConfigCache::WP_BACK)
+ lookup_time += hit_write + miss_write;
return (double)((miss_read + hit_read) * access_pen_r + (miss_write + hit_write) * access_pen_w) \
- / (double)(hit_write + hit_read + miss_read * access_pen_r + miss_write * access_pen_w) \
+ / (double)(lookup_time + mem_reads * access_pen_r + mem_writes * access_pen_w) \
* 100;
}
-double Cache::usage_efficiency() const {
+double Cache::hit_rate() const {
unsigned comp = hit_read + hit_write + miss_read + miss_write;
if (comp == 0)
return 0.0;
@@ -198,26 +219,31 @@ double Cache::usage_efficiency() const {
}
void Cache::reset() {
- if (!cnf.enabled())
- return;
-
- // Set all cells to ne invalid
- for (unsigned as = 0; as < cnf.associativity(); as++)
- for (unsigned st = 0; st < cnf.sets(); st++)
- dt[as][st].valid = false;
+ // Set all cells to invalid
+ if (cnf.enabled()) {
+ for (unsigned as = 0; as < cnf.associativity(); as++)
+ for (unsigned st = 0; st < cnf.sets(); st++)
+ dt[as][st].valid = false;
+ }
// Note: we don't have to zero replacement policy data as those are zeroed when first used on invalid cell
// Zero hit and miss rate
hit_read = 0;
hit_write = 0;
miss_read = 0;
miss_write = 0;
+ mem_reads = 0;
+ mem_writes = 0;
// Trigger signals
emit hit_update(hit());
emit miss_update(miss());
+ emit memory_reads_update(memory_reads());
+ emit memory_writes_update(memory_writes());
update_statistics();
- for (unsigned as = 0; as < cnf.associativity(); as++)
- for (unsigned st = 0; st < cnf.sets(); st++)
- emit cache_update(as, st, false, false, 0, 0);
+ if (cnf.enabled()) {
+ for (unsigned as = 0; as < cnf.associativity(); as++)
+ for (unsigned st = 0; st < cnf.sets(); st++)
+ emit cache_update(as, st, false, false, 0, 0);
+ }
}
const MachineConfigCache &Cache::config() const {
@@ -262,6 +288,12 @@ bool Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std::
indx++;
// Need to find new block
if (indx >= cnf.associativity()) {
+ // if write through we do not need to alloecate cache line does not allocate
+ if (write && cnf.write_policy() == MachineConfigCache::WP_TROUGH_NOALLOC) {
+ miss_write++;
+ emit miss_update(miss());
+ return false;
+ }
// We have to kick something
switch (cnf.replacement_policy()) {
case MachineConfigCache::RP_RAND:
@@ -319,6 +351,8 @@ bool Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std::
cd.data[i] = mem->read_word(base_address(tag, row) + (4*i));
change_counter++;
}
+ mem_reads += cnf.blocks();
+ emit memory_reads_update(mem_reads);
}
// Update replcement data
@@ -338,7 +372,10 @@ bool Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std::
break;
}
case MachineConfigCache::RP_LFU:
- replc.lfu[row][indx]++;
+ if (cd.valid)
+ replc.lfu[row][indx]++;
+ else
+ replc.lfu[row][indx] = 0;
break;
default:
break;
@@ -362,9 +399,12 @@ bool Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std::
void Cache::kick(unsigned associat_indx, unsigned row) const {
struct cache_data &cd = dt[associat_indx][row];
- if (cd.dirty && cnf.write_policy() == MachineConfigCache::WP_BACK)
+ if (cd.dirty && cnf.write_policy() == MachineConfigCache::WP_BACK) {
for (unsigned i = 0; i < cnf.blocks(); i++)
mem->write_word(base_address(cd.tag, row) + (4*i), cd.data[i]);
+ mem_writes += cnf.blocks();
+ emit memory_writes_update(mem_writes);
+ }
cd.valid = false;
cd.dirty = false;
@@ -396,5 +436,5 @@ std::uint32_t Cache::base_address(std::uint32_t tag, unsigned row) const {
}
void Cache::update_statistics() const {
- emit statistics_update(stalled_cycles(), speed_improvement(), usage_efficiency());
+ emit statistics_update(stalled_cycles(), speed_improvement(), hit_rate());
}