aboutsummaryrefslogtreecommitdiff
path: root/riscv/cachesim.cc
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2013-02-13 12:59:53 -0800
committerAndrew Waterman <waterman@cs.berkeley.edu>2013-02-13 12:59:53 -0800
commitb119073ab013f387000435ba5a55a3026fc8a8d9 (patch)
tree8480090f710b511a9765bde8c59773bb3c0e0b9e /riscv/cachesim.cc
parent55cc5d40ec16ea0639046ff1487636ba618d0e09 (diff)
downloadspike-b119073ab013f387000435ba5a55a3026fc8a8d9.zip
spike-b119073ab013f387000435ba5a55a3026fc8a8d9.tar.gz
spike-b119073ab013f387000435ba5a55a3026fc8a8d9.tar.bz2
add I$/D$/L2$ simulators
Diffstat (limited to 'riscv/cachesim.cc')
-rw-r--r--riscv/cachesim.cc129
1 files changed, 129 insertions, 0 deletions
diff --git a/riscv/cachesim.cc b/riscv/cachesim.cc
new file mode 100644
index 0000000..d029c29
--- /dev/null
+++ b/riscv/cachesim.cc
@@ -0,0 +1,129 @@
+#include "cachesim.h"
+#include <cstdlib>
+#include <iostream>
+#include <iomanip>
+
+cache_sim_t::cache_sim_t(size_t _sets, size_t _ways, size_t _linesz, const char* _name)
+ : sets(_sets), ways(_ways), linesz(_linesz), name(_name)
+{
+ init();
+}
+
+static void help()
+{
+ std::cerr << "Cache configurations must be of the form" << std::endl;
+ std::cerr << " sets:ways:blocksize" << std::endl;
+ std::cerr << "where sets, ways, and blocksize are positive integers, with" << std::endl;
+ std::cerr << "sets and blocksize both powers of two and blocksize at least 8." << std::endl;
+ exit(1);
+}
+
+cache_sim_t::cache_sim_t(const char* config, const char* _name)
+ : name(_name)
+{
+ const char* wp = strchr(config, ':');
+ if (!wp++) help();
+ const char* bp = strchr(wp, ':');
+ if (!bp++) help();
+
+ sets = atoi(std::string(config, wp).c_str());
+ ways = atoi(std::string(wp, bp).c_str());
+ linesz = atoi(bp);
+
+ init();
+}
+
+void cache_sim_t::init()
+{
+ if(sets == 0 || (sets & (sets-1)))
+ help();
+ if(linesz < 8 || (linesz & (linesz-1)))
+ help();
+
+ idx_shift = 0;
+ for (size_t x = linesz; x; x >>= 1)
+ idx_shift++;
+
+ tags = new uint64_t[sets*ways]();
+ read_accesses = 0;
+ read_misses = 0;
+ bytes_read = 0;
+ write_accesses = 0;
+ write_misses = 0;
+ bytes_written = 0;
+ writebacks = 0;
+
+ miss_handler = NULL;
+}
+
+cache_sim_t::cache_sim_t(const cache_sim_t& rhs)
+ : sets(rhs.sets), ways(rhs.ways), linesz(rhs.linesz),
+ idx_shift(rhs.idx_shift), name(rhs.name)
+{
+ tags = new uint64_t[sets*ways];
+ memcpy(tags, rhs.tags, sets*ways*sizeof(uint64_t));
+}
+
+cache_sim_t::~cache_sim_t()
+{
+ print_stats();
+ delete [] tags;
+}
+
+void cache_sim_t::print_stats()
+{
+ if(read_accesses + write_accesses == 0)
+ return;
+
+ float mr = 100.0f*(read_misses+write_misses)/(read_accesses+write_accesses);
+
+ std::cout << std::setprecision(3) << std::fixed;
+ std::cout << name << " ";
+ std::cout << "Bytes Read: " << bytes_read << std::endl;
+ std::cout << name << " ";
+ std::cout << "Bytes Written: " << bytes_written << std::endl;
+ std::cout << name << " ";
+ std::cout << "Read Accesses: " << read_accesses << std::endl;
+ std::cout << name << " ";
+ std::cout << "Write Accesses: " << write_accesses << std::endl;
+ std::cout << name << " ";
+ std::cout << "Read Misses: " << read_misses << std::endl;
+ std::cout << name << " ";
+ std::cout << "Write Misses: " << write_misses << std::endl;
+ std::cout << name << " ";
+ std::cout << "Writebacks: " << writebacks << std::endl;
+ std::cout << name << " ";
+ std::cout << "Miss Rate: " << mr << '%' << std::endl;
+}
+
+void cache_sim_t::access(uint64_t addr, size_t bytes, bool store)
+{
+ store ? write_accesses++ : read_accesses++;
+ (store ? bytes_written : bytes_read) += bytes;
+
+ size_t idx = (addr >> idx_shift) & (sets-1);
+ size_t tag = (addr >> idx_shift) | VALID;
+ size_t* set_tags = &tags[idx*ways];
+
+ for(size_t i = 0; i < ways; i++)
+ {
+ if(tag == (set_tags[i] & ~DIRTY)) // hit
+ {
+ if(store)
+ set_tags[i] |= DIRTY;
+ return;
+ }
+ }
+
+ store ? write_misses++ : read_misses++;
+
+ size_t way = lfsr.next() % ways;
+ if((set_tags[way] & (VALID | DIRTY)) == (VALID | DIRTY))
+ {
+ uint64_t dirty_addr = (set_tags[way] & ~(VALID | DIRTY)) << idx_shift;
+ if (miss_handler) miss_handler->access(dirty_addr, linesz, true);
+ writebacks++;
+ }
+ if (miss_handler) miss_handler->access(addr & ~(linesz-1), linesz, false);
+ set_tags[way] = tag | (store ? DIRTY : 0);
+}