1 // See LICENSE for license details.
9 cache_sim_t::cache_sim_t(size_t _sets
, size_t _ways
, size_t _linesz
, const char* _name
)
10 : sets(_sets
), ways(_ways
), linesz(_linesz
), name(_name
)
17 std::cerr
<< "Cache configurations must be of the form" << std::endl
;
18 std::cerr
<< " sets:ways:blocksize" << std::endl
;
19 std::cerr
<< "where sets, ways, and blocksize are positive integers, with" << std::endl
;
20 std::cerr
<< "sets and blocksize both powers of two and blocksize at least 8." << std::endl
;
24 cache_sim_t
* cache_sim_t::construct(const char* config
, const char* name
)
26 const char* wp
= strchr(config
, ':');
28 const char* bp
= strchr(wp
, ':');
31 size_t sets
= atoi(std::string(config
, wp
).c_str());
32 size_t ways
= atoi(std::string(wp
, bp
).c_str());
33 size_t linesz
= atoi(bp
);
35 if (ways
> 4 /* empirical */ && sets
== 1)
36 return new fa_cache_sim_t(ways
, linesz
, name
);
37 return new cache_sim_t(sets
, ways
, linesz
, name
);
40 void cache_sim_t::init()
42 if(sets
== 0 || (sets
& (sets
-1)))
44 if(linesz
< 8 || (linesz
& (linesz
-1)))
48 for (size_t x
= linesz
; x
>1; x
>>= 1)
51 tags
= new uint64_t[sets
*ways
]();
63 cache_sim_t::cache_sim_t(const cache_sim_t
& rhs
)
64 : sets(rhs
.sets
), ways(rhs
.ways
), linesz(rhs
.linesz
),
65 idx_shift(rhs
.idx_shift
), name(rhs
.name
)
67 tags
= new uint64_t[sets
*ways
];
68 memcpy(tags
, rhs
.tags
, sets
*ways
*sizeof(uint64_t));
71 cache_sim_t::~cache_sim_t()
77 void cache_sim_t::print_stats()
79 if(read_accesses
+ write_accesses
== 0)
82 float mr
= 100.0f
*(read_misses
+write_misses
)/(read_accesses
+write_accesses
);
84 std::cout
<< std::setprecision(3) << std::fixed
;
85 std::cout
<< name
<< " ";
86 std::cout
<< "Bytes Read: " << bytes_read
<< std::endl
;
87 std::cout
<< name
<< " ";
88 std::cout
<< "Bytes Written: " << bytes_written
<< std::endl
;
89 std::cout
<< name
<< " ";
90 std::cout
<< "Read Accesses: " << read_accesses
<< std::endl
;
91 std::cout
<< name
<< " ";
92 std::cout
<< "Write Accesses: " << write_accesses
<< std::endl
;
93 std::cout
<< name
<< " ";
94 std::cout
<< "Read Misses: " << read_misses
<< std::endl
;
95 std::cout
<< name
<< " ";
96 std::cout
<< "Write Misses: " << write_misses
<< std::endl
;
97 std::cout
<< name
<< " ";
98 std::cout
<< "Writebacks: " << writebacks
<< std::endl
;
99 std::cout
<< name
<< " ";
100 std::cout
<< "Miss Rate: " << mr
<< '%' << std::endl
;
103 uint64_t* cache_sim_t::check_tag(uint64_t addr
)
105 size_t idx
= (addr
>> idx_shift
) & (sets
-1);
106 size_t tag
= (addr
>> idx_shift
) | VALID
;
108 for (size_t i
= 0; i
< ways
; i
++)
109 if (tag
== (tags
[idx
*ways
+ i
] & ~DIRTY
))
110 return &tags
[idx
*ways
+ i
];
115 uint64_t cache_sim_t::victimize(uint64_t addr
)
117 size_t idx
= (addr
>> idx_shift
) & (sets
-1);
118 size_t way
= lfsr
.next() % ways
;
119 uint64_t victim
= tags
[idx
*ways
+ way
];
120 tags
[idx
*ways
+ way
] = (addr
>> idx_shift
) | VALID
;
124 void cache_sim_t::access(uint64_t addr
, size_t bytes
, bool store
)
126 store
? write_accesses
++ : read_accesses
++;
127 (store
? bytes_written
: bytes_read
) += bytes
;
129 uint64_t* hit_way
= check_tag(addr
);
130 if (likely(hit_way
!= NULL
))
137 store
? write_misses
++ : read_misses
++;
139 uint64_t victim
= victimize(addr
);
141 if ((victim
& (VALID
| DIRTY
)) == (VALID
| DIRTY
))
143 uint64_t dirty_addr
= (victim
& ~(VALID
| DIRTY
)) << idx_shift
;
145 miss_handler
->access(dirty_addr
, linesz
, true);
150 miss_handler
->access(addr
& ~(linesz
-1), linesz
, false);
153 *check_tag(addr
) |= DIRTY
;
156 fa_cache_sim_t::fa_cache_sim_t(size_t ways
, size_t linesz
, const char* name
)
157 : cache_sim_t(1, ways
, linesz
, name
)
161 uint64_t* fa_cache_sim_t::check_tag(uint64_t addr
)
163 auto it
= tags
.find(addr
>> idx_shift
);
164 return it
== tags
.end() ? NULL
: &it
->second
;
167 uint64_t fa_cache_sim_t::victimize(uint64_t addr
)
169 uint64_t old_tag
= 0;
170 if (tags
.size() == ways
)
172 auto it
= tags
.begin();
173 std::advance(it
, lfsr
.next() % ways
);
174 old_tag
= it
->second
;
177 tags
[addr
>> idx_shift
] = (addr
>> idx_shift
) | VALID
;