From 481c9e8fd8a89106f70b73b6bd62e08f5b1e688a Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 15 Apr 2011 14:32:54 -0700 Subject: [sim] added icache simulator (disabled by default) --- config.h.in | 3 +++ configure | 15 ++++++++++++++ riscv/applink.cc | 2 +- riscv/icsim.cc | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ riscv/icsim.h | 30 +++++++++++++++++++++++++++ riscv/mmu.h | 9 +++++++++ riscv/processor.cc | 20 ++++++++++++++++-- riscv/processor.h | 7 ++++++- riscv/riscv-isa-run.cc | 8 +++++++- riscv/riscv.ac | 5 +++++ riscv/riscv.mk.in | 1 + riscv/sim.cc | 4 ++-- riscv/sim.h | 2 ++ 13 files changed, 154 insertions(+), 7 deletions(-) create mode 100644 riscv/icsim.cc create mode 100644 riscv/icsim.h diff --git a/config.h.in b/config.h.in index e592810..cf21aff 100644 --- a/config.h.in +++ b/config.h.in @@ -27,6 +27,9 @@ /* Define if floating-point instructions are supported */ #undef RISCV_ENABLE_FPU +/* Define if instruction cache simulator is enabled */ +#undef RISCV_ENABLE_ICSIM + /* Define if instruction compression is supported */ #undef RISCV_ENABLE_RVC diff --git a/configure b/configure index ad0b907..709daa8 100755 --- a/configure +++ b/configure @@ -639,6 +639,7 @@ enable_fpu enable_64bit enable_rvc enable_vec +enable_icsim ' ac_precious_vars='build_alias host_alias @@ -1275,6 +1276,7 @@ Optional Features: --disable-64bit Disable 64-bit mode --disable-rvc Disable instruction compression --disable-vec Disable vector processor + --disable-icsim Enable instruction cache simulator Some influential environment variables: CC C compiler command @@ -4075,6 +4077,19 @@ $as_echo "#define RISCV_ENABLE_VEC /**/" >>confdefs.h fi +# Check whether --enable-icsim was given. +if test "${enable_icsim+set}" = set; then : + enableval=$enable_icsim; +fi + +if test "x$enable_icsim" = "xyes"; then : + + +$as_echo "#define RISCV_ENABLE_ICSIM /**/" >>confdefs.h + + +fi + libopc=`dirname \`which riscv-gcc\``/../`$ac_config_guess`/riscv/lib/libopcodes.a as_ac_File=`$as_echo "ac_cv_file_$libopc" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $libopc" >&5 diff --git a/riscv/applink.cc b/riscv/applink.cc index 6592438..5ced320 100644 --- a/riscv/applink.cc +++ b/riscv/applink.cc @@ -107,7 +107,7 @@ int appserver_link_t::wait_for_packet() break; case APP_CMD_STOP: send_packet(&ackpacket); - exit(0); + throw quit_sim(); case APP_CMD_READ_MEM: demand(p.addr % APP_DATA_ALIGN == 0, "misaligned address"); demand(p.data_size % APP_DATA_ALIGN == 0, "misaligned data"); diff --git a/riscv/icsim.cc b/riscv/icsim.cc new file mode 100644 index 0000000..73d6e9c --- /dev/null +++ b/riscv/icsim.cc @@ -0,0 +1,55 @@ +#include "icsim.h" +#include +#include +#include + +icsim_t::icsim_t(size_t _sets, size_t _ways, size_t _linesz) +{ + 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)); +} + +icsim_t::~icsim_t() +{ + float mr = 100.0f*misses/accesses; + float cr = 100.0f*bytes_fetched/(4*accesses); + + 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; + + delete [] tags; +} + +void icsim_t::tick(uint64_t pc, int insnlen) +{ + accesses++; + bytes_fetched += insnlen; + + size_t idx = (pc >> idx_shift) & idx_mask; + size_t tag = (pc >> idx_shift) | VALID; + if(tag != tags[idx]) + { + misses++; + tags[idx] = tag; + } +} diff --git a/riscv/icsim.h b/riscv/icsim.h new file mode 100644 index 0000000..122730c --- /dev/null +++ b/riscv/icsim.h @@ -0,0 +1,30 @@ +#ifndef _RISCV_ICSIM_H +#define _RISCV_ICSIM_H + +#include +#include + +class icsim_t +{ +public: + icsim_t(size_t sets, size_t ways, size_t linesz); + ~icsim_t(); + + void tick(uint64_t pc, int insnlen); +private: + 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; + + static const uint64_t VALID = 1ULL << 63; +}; + +#endif diff --git a/riscv/mmu.h b/riscv/mmu.h index f7bd8ce..289c200 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -1,6 +1,8 @@ #include "decode.h" #include "trap.h" +class processor_t; + class mmu_t { public: @@ -20,6 +22,7 @@ public: insn_t load_insn(reg_t addr, bool rvc) { + #ifdef RISCV_ENABLE_RVC check_align_and_bounds(addr, rvc ? 2 : 4, false, true); uint16_t lo = *(uint16_t*)(mem+addr); uint16_t hi = *(uint16_t*)(mem+addr+2); @@ -28,6 +31,10 @@ public: insn.bits = lo | ((uint32_t)hi << 16); return insn; + #else + check_align_and_bounds(addr, 4, false, true); + return *(insn_t*)(mem+addr); + #endif } load_func(uint8) @@ -81,4 +88,6 @@ private: check_align(addr, size, store, fetch); check_bounds(addr, size, store, fetch); } + + friend class processor_t; }; diff --git a/riscv/processor.cc b/riscv/processor.cc index 360b755..471afab 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -7,6 +7,7 @@ #include "common.h" #include "config.h" #include "sim.h" +#include "icsim.h" #include "softfloat.h" #include "platform.h" // softfloat isNaNF32UI, etc. #include "internals.h" // ditto @@ -50,19 +51,31 @@ processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz) static_assert(sizeof(insn_t) == 4); static_assert(sizeof(uint128_t) == 16 && sizeof(int128_t) == 16); + + icsim = NULL; +} + +processor_t::~processor_t() +{ + delete icsim; } -void processor_t::init(uint32_t _id, char* _mem, size_t _memsz) +void processor_t::init(uint32_t _id) { id = _id; for (int i=0; iid = id; uts[i]->set_sr(uts[i]->sr | SR_EF); uts[i]->set_sr(uts[i]->sr | SR_EV); uts[i]->utidx = i; } + + #ifdef RISCV_ENABLE_ICSIM + icsim = new icsim_t(1024, 1, 32); + #endif } void processor_t::set_sr(uint32_t val) @@ -121,6 +134,9 @@ 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); diff --git a/riscv/processor.h b/riscv/processor.h index 34c31ac..5c524c0 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -5,6 +5,7 @@ #include #include "trap.h" #include "mmu.h" +#include "icsim.h" #define MAX_UTS 32 @@ -14,7 +15,8 @@ class processor_t { public: processor_t(sim_t* _sim, char* _mem, size_t _memsz); - void init(uint32_t _id, char* _mem, size_t _memsz); + ~processor_t(); + void init(uint32_t _id); void step(size_t n, bool noisy); private: @@ -71,6 +73,9 @@ private: int nfpr_use; processor_t* uts[MAX_UTS]; + // icache sim + icsim_t* icsim; + friend class sim_t; }; diff --git a/riscv/riscv-isa-run.cc b/riscv/riscv-isa-run.cc index 098e68b..83bb286 100644 --- a/riscv/riscv-isa-run.cc +++ b/riscv/riscv-isa-run.cc @@ -35,5 +35,11 @@ int main(int argc, char** argv) appserver_link_t applink(tohost_fd,fromhost_fd); sim_t s(nprocs,MEMSIZE,&applink); - s.run(debug); + try + { + s.run(debug); + } + catch(quit_sim&) + { + } } diff --git a/riscv/riscv.ac b/riscv/riscv.ac index 36c701a..897b21f 100644 --- a/riscv/riscv.ac +++ b/riscv/riscv.ac @@ -18,6 +18,11 @@ AS_IF([test "x$enable_vec" != "xno"], [ AC_DEFINE([RISCV_ENABLE_VEC],,[Define if vector processor is supported]) ]) +AC_ARG_ENABLE([icsim], AS_HELP_STRING([--disable-icsim], [Enable instruction cache simulator])) +AS_IF([test "x$enable_icsim" = "xyes"], [ + AC_DEFINE([RISCV_ENABLE_ICSIM],,[Define if instruction cache simulator is enabled]) +]) + libopc=`dirname \`which riscv-gcc\``/../`$ac_config_guess`/riscv/lib/libopcodes.a AC_CHECK_FILES([$libopc],[have_libopcodes="yes"],[have_libopcodes="no"]) diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 6d55c80..f53bc13 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -18,6 +18,7 @@ riscv_srcs = \ processor.cc \ sim.cc \ trap.cc \ + icsim.cc \ riscv_test_srcs = diff --git a/riscv/sim.cc b/riscv/sim.cc index fbea374..50264ed 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -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, mem, memsz); + procs[i].init(i); applink->init(this); } @@ -141,7 +141,7 @@ void sim_t::interactive_run_proc(const std::string& cmd, const std::vector& args) { - exit(0); + throw quit_sim(); } reg_t sim_t::get_pc(const std::vector& args) diff --git a/riscv/sim.h b/riscv/sim.h index 4763713..722fe64 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -57,4 +57,6 @@ private: friend class appserver_link_t; }; +struct quit_sim {}; + #endif -- cgit v1.1