/* 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
enable_64bit
enable_rvc
enable_vec
+enable_icsim
'
ac_precious_vars='build_alias
host_alias
--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
$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
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");
--- /dev/null
+#include "icsim.h"
+#include <stdexcept>
+#include <iostream>
+#include <iomanip>
+
+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;
+ }
+}
--- /dev/null
+#ifndef _RISCV_ICSIM_H
+#define _RISCV_ICSIM_H
+
+#include <cstring>
+#include <stdint.h>
+
+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
#include "decode.h"
#include "trap.h"
+class processor_t;
+
class mmu_t
{
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);
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)
check_align(addr, size, store, fetch);
check_bounds(addr, size, store, fetch);
}
+
+ friend class processor_t;
};
#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
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; i<MAX_UTS; i++)
{
- uts[i] = new processor_t(sim, _mem, _memsz);
+ uts[i] = new processor_t(sim, mmu.mem, mmu.memsz);
+ uts[i]->id = 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)
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);
#include <cstring>
#include "trap.h"
#include "mmu.h"
+#include "icsim.h"
#define MAX_UTS 32
{
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:
int nfpr_use;
processor_t* uts[MAX_UTS];
+ // icache sim
+ icsim_t* icsim;
+
friend class sim_t;
};
appserver_link_t applink(tohost_fd,fromhost_fd);
sim_t s(nprocs,MEMSIZE,&applink);
- s.run(debug);
+ try
+ {
+ s.run(debug);
+ }
+ catch(quit_sim&)
+ {
+ }
}
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"])
processor.cc \
sim.cc \
trap.cc \
+ icsim.cc \
riscv_test_srcs =
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);
}
void sim_t::interactive_quit(const std::string& cmd, const std::vector<std::string>& args)
{
- exit(0);
+ throw quit_sim();
}
reg_t sim_t::get_pc(const std::vector<std::string>& args)
friend class appserver_link_t;
};
+struct quit_sim {};
+
#endif