308e7ed537e6cc4b1cba5b14d7e08eb74bd52665
[riscv-isa-sim.git] / riscv / icsim.cc
1 #include "icsim.h"
2 #include <stdexcept>
3 #include <iostream>
4 #include <iomanip>
5
6 icsim_t::icsim_t(size_t _sets, size_t _ways, size_t _linesz, const char* _name)
7 : sets(_sets), ways(_ways), linesz(_linesz), idx_mask(_sets-1), name(_name)
8 {
9 if(sets == 0 || (sets & (sets-1)))
10 throw std::logic_error("sets not a power of 2");
11 if(linesz == 0 || (linesz & (linesz-1)))
12 throw std::logic_error("linesz not a power of 2");
13
14 idx_shift = 0;
15 while(_linesz >>= 1)
16 idx_shift++;
17
18 tags = new uint64_t[sets*ways];
19 memset(tags, 0, sets*ways*sizeof(uint64_t));
20
21 read_accesses = 0;
22 read_misses = 0;
23 bytes_read = 0;
24 write_accesses = 0;
25 write_misses = 0;
26 bytes_written = 0;
27 writebacks = 0;
28 }
29
30 icsim_t::icsim_t(const icsim_t& rhs)
31 : sets(rhs.sets), ways(rhs.ways), linesz(rhs.linesz),
32 idx_shift(rhs.idx_shift), idx_mask(rhs.idx_mask), name(rhs.name)
33 {
34 tags = new uint64_t[sets*ways];
35 memcpy(tags, rhs.tags, sets*ways*sizeof(uint64_t));
36 }
37
38 icsim_t::~icsim_t()
39 {
40 delete [] tags;
41 }
42
43 void icsim_t::print_stats()
44 {
45 if(read_accesses + write_accesses == 0)
46 return;
47
48 float mr = 100.0f*(read_misses+write_misses)/(read_accesses+write_accesses);
49
50 std::cout << std::setprecision(3) << std::fixed;
51 std::cout << name << " ";
52 std::cout << "Bytes Read: " << bytes_read << std::endl;
53 std::cout << name << " ";
54 std::cout << "Bytes Written: " << bytes_written << std::endl;
55 std::cout << name << " ";
56 std::cout << "Read Accesses: " << read_accesses << std::endl;
57 std::cout << name << " ";
58 std::cout << "Write Accesses: " << write_accesses << std::endl;
59 std::cout << name << " ";
60 std::cout << "Read Misses: " << read_misses << std::endl;
61 std::cout << name << " ";
62 std::cout << "Write Misses: " << write_misses << std::endl;
63 std::cout << name << " ";
64 std::cout << "Writebacks: " << writebacks << std::endl;
65 std::cout << name << " ";
66 std::cout << "Miss Rate: " << mr << '%' << std::endl;
67
68 float cr = read_accesses == 0 ? 0.0f : 100.0f*bytes_read/(4*read_accesses);
69 if(name == "I$")
70 {
71 std::cout << name << " ";
72 std::cout << "RVC compression ratio: " << cr << '%' << std::endl;
73 }
74 }
75
76 void icsim_t::tick(uint64_t pc, int insnlen, bool store)
77 {
78 store ? write_accesses++ : read_accesses++;
79 (store ? bytes_written : bytes_read) += insnlen;
80
81 size_t idx = (pc >> idx_shift) & idx_mask;
82 size_t tag = (pc >> idx_shift) | VALID;
83
84 for(size_t i = 0; i < ways; i++)
85 {
86 if(tag == (tags[idx + i*sets] & ~DIRTY)) // hit
87 {
88 if(store)
89 tags[idx + i*sets] |= DIRTY;
90 return;
91 }
92 }
93
94 store ? write_misses++ : read_misses++;
95
96 size_t way = lfsr.next() % ways;
97 if((tags[idx + way*sets] & (VALID | DIRTY)) == (VALID | DIRTY))
98 writebacks++;
99 tags[idx + way*sets] = tag;
100 }