Browse Source

[sim] hacked in a dcache simulator

cs250
Andrew Waterman 15 years ago
parent
commit
46f2fb1d9e
  1. 91
      riscv/icsim.cc
  2. 34
      riscv/icsim.h
  3. 34
      riscv/mmu.h
  4. 34
      riscv/processor.cc
  5. 7
      riscv/processor.h
  6. 24
      riscv/riscv-isa-run.cc
  7. 4
      riscv/sim.cc
  8. 2
      riscv/sim.h

91
riscv/icsim.cc

@ -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;
}

34
riscv/icsim.h

@ -2,29 +2,51 @@
#define _RISCV_ICSIM_H
#include <cstring>
#include <string>
#include <stdint.h>
class lfsr_t
{
public:
lfsr_t() : reg(1) {}
lfsr_t(const lfsr_t& lfsr) : reg(lfsr.reg) {}
uint32_t next() { return reg = (reg>>1)^(-(reg&1) & 0xd0000001); }
private:
uint32_t reg;
};
class icsim_t
{
public:
icsim_t(size_t sets, size_t ways, size_t linesz);
icsim_t(size_t sets, size_t ways, size_t linesz, const char* name);
icsim_t(const icsim_t& rhs);
~icsim_t();
void tick(uint64_t pc, int insnlen);
void tick(uint64_t pc, int insnlen, bool store);
void print_stats();
private:
lfsr_t lfsr;
size_t sets;
size_t ways;
size_t linesz;
size_t idx_shift;
size_t idx_mask;
uint64_t accesses;
uint64_t misses;
uint64_t bytes_fetched;
uint64_t* tags;
uint64_t read_accesses;
uint64_t read_misses;
uint64_t bytes_read;
uint64_t write_accesses;
uint64_t write_misses;
uint64_t bytes_written;
uint64_t writebacks;
std::string name;
static const uint64_t VALID = 1ULL << 63;
static const uint64_t DIRTY = 1ULL << 62;
};
#endif

34
riscv/mmu.h

@ -1,22 +1,42 @@
#include "decode.h"
#include "trap.h"
#include "icsim.h"
class processor_t;
class mmu_t
{
public:
mmu_t(char* _mem, size_t _memsz) : mem(_mem), memsz(_memsz), badvaddr(0) {}
mmu_t(char* _mem, size_t _memsz)
: mem(_mem), memsz(_memsz), badvaddr(0),
icsim(NULL), dcsim(NULL), itlbsim(NULL), dtlbsim(NULL)
{
}
void set_icsim(icsim_t* _icsim) { icsim = _icsim; }
void set_dcsim(icsim_t* _dcsim) { dcsim = _dcsim; }
void set_itlbsim(icsim_t* _itlbsim) { itlbsim = _itlbsim; }
void set_dtlbsim(icsim_t* _dtlbsim) { dtlbsim = _dtlbsim; }
#ifdef RISCV_ENABLE_ICSIM
# define dcsim_tick(dcsim, dtlbsim, addr, size, st) \
do { if(dcsim) (dcsim)->tick(addr, size, st); \
if(dtlbsim) (dtlbsim)->tick(addr, sizeof(reg_t), false); } while(0)
#else
# define dcsim_tick(dcsim, addr, size)
#endif
#define load_func(type) \
type##_t load_##type(reg_t addr) { \
check_align_and_bounds(addr, sizeof(type##_t), false, false); \
dcsim_tick(dcsim, dtlbsim, addr, sizeof(type##_t), false); \
return *(type##_t*)(mem+addr); \
}
#define store_func(type) \
void store_##type(reg_t addr, type##_t val) { \
check_align_and_bounds(addr, sizeof(type##_t), true, false); \
dcsim_tick(dcsim, dtlbsim, addr, sizeof(type##_t), true); \
*(type##_t*)(mem+addr) = val; \
}
@ -30,6 +50,13 @@ public:
insn_t insn;
insn.bits = lo | ((uint32_t)hi << 16);
#ifdef RISCV_ENABLE_ICSIM
if(icsim)
icsim->tick(addr, insn_length(insn), false);
if(itlbsim)
itlbsim->tick(addr, sizeof(reg_t), false);
#endif
return insn;
#else
check_align_and_bounds(addr, 4, false, true);
@ -59,6 +86,11 @@ private:
size_t memsz;
reg_t badvaddr;
icsim_t* icsim;
icsim_t* dcsim;
icsim_t* itlbsim;
icsim_t* dtlbsim;
void check_align(reg_t addr, int size, bool store, bool fetch)
{
if(addr & (size-1))

34
riscv/processor.cc

@ -53,14 +53,32 @@ processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz)
static_assert(sizeof(uint128_t) == 16 && sizeof(int128_t) == 16);
icsim = NULL;
dcsim = NULL;
itlbsim = NULL;
dtlbsim = NULL;
}
processor_t::~processor_t()
{
if(icsim)
icsim->print_stats();
delete icsim;
if(itlbsim)
itlbsim->print_stats();
delete itlbsim;
if(dcsim)
dcsim->print_stats();
delete dcsim;
if(dtlbsim)
dtlbsim->print_stats();
delete dtlbsim;
}
void processor_t::init(uint32_t _id)
void processor_t::init(uint32_t _id, icsim_t* default_icache,
icsim_t* default_dcache)
{
id = _id;
@ -74,7 +92,16 @@ void processor_t::init(uint32_t _id)
}
#ifdef RISCV_ENABLE_ICSIM
icsim = new icsim_t(1024, 1, 32);
icsim = new icsim_t(*default_icache);
mmu.set_icsim(icsim);
itlbsim = new icsim_t(1, 8, 4096, "ITLB");
mmu.set_itlbsim(itlbsim);
#endif
#ifdef RISCV_ENABLE_ICSIM
dcsim = new icsim_t(*default_dcache);
mmu.set_dcsim(dcsim);
dtlbsim = new icsim_t(1, 8, 4096, "DTLB");
mmu.set_dtlbsim(dtlbsim);
#endif
}
@ -134,9 +161,6 @@ void processor_t::step(size_t n, bool noisy)
take_trap(trap_interrupt,noisy);
insn_t insn = mmu.load_insn(pc, sr & SR_EC);
#ifdef RISCV_ENABLE_ICSIM
icsim->tick(pc, insn_length(insn));
#endif
reg_t npc = pc + insn_length(insn);

7
riscv/processor.h

@ -16,7 +16,7 @@ class processor_t
public:
processor_t(sim_t* _sim, char* _mem, size_t _memsz);
~processor_t();
void init(uint32_t _id);
void init(uint32_t _id, icsim_t* defualt_icache, icsim_t* default_dcache);
void step(size_t n, bool noisy);
private:
@ -73,8 +73,11 @@ private:
int nfpr_use;
processor_t* uts[MAX_UTS];
// icache sim
// cache sim
icsim_t* icsim;
icsim_t* dcsim;
icsim_t* itlbsim;
icsim_t* dtlbsim;
friend class sim_t;
};

24
riscv/riscv-isa-run.cc

@ -9,8 +9,9 @@ int main(int argc, char** argv)
bool debug = false;
int nprocs = 1;
int fromhost_fd = -1, tohost_fd = -1;
size_t icsim_sets = 1024, icsim_linesz = 32, icsim_ways = 1;
for(int c; (c = getopt(argc,argv,"dpf:t:")) != -1; )
for(int c; (c = getopt(argc,argv,"dp:f:t:i:")) != -1; )
{
switch(c)
{
@ -26,15 +27,32 @@ int main(int argc, char** argv)
case 't':
tohost_fd = atoi(optarg);
break;
case 'i':
switch(optarg[0])
{
case 's':
icsim_sets = atoi(optarg+1);
break;
case 'l':
icsim_linesz = atoi(optarg+1);
break;
case 'a':
icsim_ways = atoi(optarg+1);
break;
}
break;
}
}
demand(fcntl(fromhost_fd,F_GETFD) >= 0, "fromhost file not open");
demand(fcntl(tohost_fd,F_GETFD) >= 0, "tohost file not open");
appserver_link_t applink(tohost_fd,fromhost_fd);
icsim_t icache(icsim_sets, icsim_ways, icsim_linesz, "I$");
icsim_t dcache(512, 2, 32, "D$");
appserver_link_t applink(tohost_fd, fromhost_fd);
sim_t s(nprocs,MEMSIZE,&applink);
sim_t s(nprocs, MEMSIZE, &applink, &icache, &dcache);
try
{
s.run(debug);

4
riscv/sim.cc

@ -6,7 +6,7 @@
#include <iostream>
#include <climits>
sim_t::sim_t(int _nprocs, size_t _memsz, appserver_link_t* _applink)
sim_t::sim_t(int _nprocs, size_t _memsz, appserver_link_t* _applink, icsim_t* default_icache, icsim_t* default_dcache)
: applink(_applink),
memsz(_memsz),
mem((char*)mmap64(NULL, memsz, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0)),
@ -15,7 +15,7 @@ sim_t::sim_t(int _nprocs, size_t _memsz, appserver_link_t* _applink)
demand(mem != MAP_FAILED, "couldn't allocate target machine's memory");
for(int i = 0; i < (int)procs.size(); i++)
procs[i].init(i);
procs[i].init(i, default_icache, default_dcache);
applink->init(this);
}

2
riscv/sim.h

@ -12,7 +12,7 @@ class appserver_link_t;
class sim_t
{
public:
sim_t(int _nprocs, size_t _memsz, appserver_link_t* _applink);
sim_t(int _nprocs, size_t _memsz, appserver_link_t* _applink, icsim_t* _default_icache, icsim_t* default_dcache);
~sim_t();
void run(bool debug);

Loading…
Cancel
Save