aboutsummaryrefslogtreecommitdiff
path: root/riscv/icsim.cc
blob: 308e7ed537e6cc4b1cba5b14d7e08eb74bd52665 (plain)
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
#include "icsim.h"
#include <stdexcept>
#include <iostream>
#include <iomanip>

icsim_t::icsim_t(size_t _sets, size_t _ways, size_t _linesz, const char* _name)
 : sets(_sets), ways(_ways), linesz(_linesz), idx_mask(_sets-1), name(_name)
{
  if(sets == 0 || (sets & (sets-1)))
    throw std::logic_error("sets not a power of 2");
  if(linesz == 0 || (linesz & (linesz-1)))
    throw std::logic_error("linesz not a power of 2");

  idx_shift = 0;
  while(_linesz >>= 1)
    idx_shift++;

  tags = new uint64_t[sets*ways];
  memset(tags, 0, sets*ways*sizeof(uint64_t));

  read_accesses = 0;
  read_misses = 0;
  bytes_read = 0;
  write_accesses = 0;
  write_misses = 0;
  bytes_written = 0;
  writebacks = 0;
}

icsim_t::icsim_t(const icsim_t& rhs)
 : sets(rhs.sets), ways(rhs.ways), linesz(rhs.linesz),
   idx_shift(rhs.idx_shift), idx_mask(rhs.idx_mask), name(rhs.name)
{
  tags = new uint64_t[sets*ways];
  memcpy(tags, rhs.tags, sets*ways*sizeof(uint64_t));
}

icsim_t::~icsim_t()
{
  delete [] tags;
}

void icsim_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;

  float cr = read_accesses == 0 ? 0.0f : 100.0f*bytes_read/(4*read_accesses);
  if(name == "I$")
  {
    std::cout << name << " ";
    std::cout << "RVC compression ratio: " << cr << '%' << std::endl;
  }
}

void icsim_t::tick(uint64_t pc, int insnlen, bool store)
{
  store ? write_accesses++ : read_accesses++;
  (store ? bytes_written : bytes_read) += insnlen;

  size_t idx = (pc >> idx_shift) & idx_mask;
  size_t tag = (pc >> idx_shift) | VALID;

  for(size_t i = 0; i < ways; i++)
  {
    if(tag == (tags[idx + i*sets] & ~DIRTY)) // hit
    {
      if(store)
        tags[idx + i*sets] |= DIRTY;
      return;
    }
  }

  store ? write_misses++ : read_misses++;

  size_t way = lfsr.next() % ways;
  if((tags[idx + way*sets] & (VALID | DIRTY)) == (VALID | DIRTY))
    writebacks++;
  tags[idx + way*sets] = tag;
}