|
|
|
@ -3,53 +3,98 @@ |
|
|
|
#include <iostream> |
|
|
|
#include <iomanip> |
|
|
|
|
|
|
|
icsim_t::icsim_t(size_t _sets, size_t _ways, size_t _linesz) |
|
|
|
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) |
|
|
|
{ |
|
|
|
sets = _sets; |
|
|
|
ways = _ways; |
|
|
|
linesz = _linesz; |
|
|
|
|
|
|
|
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"); |
|
|
|
if(ways != 1) |
|
|
|
throw std::logic_error("set associativity currently unsupported"); |
|
|
|
|
|
|
|
idx_mask = sets-1; |
|
|
|
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() |
|
|
|
{ |
|
|
|
float mr = 100.0f*misses/accesses; |
|
|
|
float cr = 100.0f*bytes_fetched/(4*accesses); |
|
|
|
delete [] tags; |
|
|
|
} |
|
|
|
|
|
|
|
std::cout << "Instruction cache statsistics" << std::endl; |
|
|
|
std::cout << "Bytes fetched: " << bytes_fetched << std::endl; |
|
|
|
std::cout << "Hits: " << (accesses-misses) << std::endl; |
|
|
|
std::cout << "Misses: " << misses << std::endl; |
|
|
|
std::cout << "Miss rate: " << std::setprecision(3) << mr << '%' << std::endl; |
|
|
|
std::cout << "RVC compression ratio: " << cr << '%' << std::endl; |
|
|
|
void icsim_t::print_stats() |
|
|
|
{ |
|
|
|
if(read_accesses + write_accesses == 0) |
|
|
|
return; |
|
|
|
|
|
|
|
delete [] tags; |
|
|
|
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) |
|
|
|
void icsim_t::tick(uint64_t pc, int insnlen, bool store) |
|
|
|
{ |
|
|
|
accesses++; |
|
|
|
bytes_fetched += insnlen; |
|
|
|
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; |
|
|
|
if(tag != tags[idx]) |
|
|
|
|
|
|
|
for(size_t i = 0; i < ways; i++) |
|
|
|
{ |
|
|
|
misses++; |
|
|
|
tags[idx] = tag; |
|
|
|
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; |
|
|
|
} |
|
|
|
|