From b119073ab013f387000435ba5a55a3026fc8a8d9 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 13 Feb 2013 12:59:53 -0800 Subject: add I$/D$/L2$ simulators --- riscv/cachesim.cc | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 riscv/cachesim.cc (limited to 'riscv/cachesim.cc') 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 +#include +#include + +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); +} -- cgit v1.1