From: Megan Wachs Date: Mon, 17 Apr 2017 17:59:38 +0000 (-0700) Subject: Merge remote-tracking branch 'origin/priv-1.10' into HEAD X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=84e1ac19ed5a69224aa8c3f920e3840fbc670771;hp=773fab34d46e2ddaf4318b851ab23bd813f168ad;p=riscv-isa-sim.git Merge remote-tracking branch 'origin/priv-1.10' into HEAD --- diff --git a/LICENSE b/LICENSE index 53e0e66..34f576b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ -Copyright (c) 2013, The Regents of the University of California (Regents). -All Rights Reserved. +Copyright (c) 2010-2017, The Regents of the University of California +(Regents). All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md index 901c7f4..a5ed802 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Build Steps We assume that the RISCV environment variable is set to the RISC-V tools install path, and that the riscv-fesvr package is installed there. + $ apt-get install device-tree-compiler $ mkdir build $ cd build $ ../configure --prefix=$RISCV --with-fesvr=$RISCV diff --git a/config.h.in b/config.h.in index a4070ff..137f195 100644 --- a/config.h.in +++ b/config.h.in @@ -6,6 +6,9 @@ /* Default value for --isa switch */ #undef DEFAULT_ISA +/* Path to the device-tree-compiler */ +#undef DTC + /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ #undef DUMMY_ROCC_ENABLED @@ -66,9 +69,15 @@ /* Enable commit log generation */ #undef RISCV_ENABLE_COMMITLOG +/* Enable hardware management of PTE accessed and dirty bits */ +#undef RISCV_ENABLE_DIRTY + /* Enable PC histogram generation */ #undef RISCV_ENABLE_HISTOGRAM +/* Enable hardware support for misaligned loads and stores */ +#undef RISCV_ENABLE_MISALIGNED + /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ #undef SOFTFLOAT_ENABLED diff --git a/configure b/configure index 2c946e7..77bab30 100755 --- a/configure +++ b/configure @@ -636,6 +636,7 @@ enable_stow EGREP GREP CXXCPP +DTC RANLIB AR ac_ct_CXX @@ -675,6 +676,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -703,6 +705,8 @@ with_isa with_fesvr enable_commitlog enable_histogram +enable_dirty +enable_misaligned ' ac_precious_vars='build_alias host_alias @@ -756,6 +760,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1008,6 +1013,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1145,7 +1159,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1298,6 +1312,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1336,6 +1351,10 @@ Optional Features: Enable all optional subprojects --enable-commitlog Enable commit log generation --enable-histogram Enable PC histogram generation + --enable-dirty Enable hardware management of PTE accessed and dirty + bits + --enable-misaligned Enable hardware support for misaligned loads and + stores Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -3363,6 +3382,51 @@ else RANLIB="$ac_cv_prog_RANLIB" fi +# Extract the first word of "dtc", so it can be a program name with args. +set dummy dtc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DTC+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DTC in + [\\/]* | ?:[\\/]*) + ac_cv_path_DTC="$DTC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DTC="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +DTC=$ac_cv_path_DTC +if test -n "$DTC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTC" >&5 +$as_echo "$DTC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +cat >>confdefs.h <<_ACEOF +#define DTC "$DTC" +_ACEOF + ac_ext=cpp @@ -4605,6 +4669,32 @@ if test "x$enable_histogram" = "xyes"; then : $as_echo "#define RISCV_ENABLE_HISTOGRAM /**/" >>confdefs.h +fi + +# Check whether --enable-dirty was given. +if test "${enable_dirty+set}" = set; then : + enableval=$enable_dirty; +fi + +if test "x$enable_dirty" = "xyes"; then : + + +$as_echo "#define RISCV_ENABLE_DIRTY /**/" >>confdefs.h + + +fi + +# Check whether --enable-misaligned was given. +if test "${enable_misaligned+set}" = set; then : + enableval=$enable_misaligned; +fi + +if test "x$enable_misaligned" = "xyes"; then : + + +$as_echo "#define RISCV_ENABLE_MISALIGNED /**/" >>confdefs.h + + fi diff --git a/configure.ac b/configure.ac index dbf50c9..ea64de7 100644 --- a/configure.ac +++ b/configure.ac @@ -51,6 +51,8 @@ AC_PROG_CC AC_PROG_CXX AC_CHECK_TOOL([AR],[ar]) AC_CHECK_TOOL([RANLIB],[ranlib]) +AC_PATH_PROG([DTC],[dtc]) +AC_DEFINE_UNQUOTED(DTC, ["$DTC"], [Path to the device-tree-compiler]) AC_C_BIGENDIAN(AC_MSG_ERROR([Spike requires a little-endian host])) diff --git a/remote_bitbang.cc b/remote_bitbang.cc new file mode 100644 index 0000000..9d0ca90 --- /dev/null +++ b/remote_bitbang.cc @@ -0,0 +1,174 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "remote_bitbang.h" + +#if 1 +# define D(x) x +#else +# define D(x) +#endif + +/////////// remote_bitbang_t + +remote_bitbang_t::remote_bitbang_t(uint16_t port, jtag_dtm_t *tap) : + tap(tap), + socket_fd(0), + client_fd(0), + recv_start(0), + recv_end(0) +{ + socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (socket_fd == -1) { + fprintf(stderr, "remote_bitbang failed to make socket: %s (%d)\n", + strerror(errno), errno); + abort(); + } + + fcntl(socket_fd, F_SETFL, O_NONBLOCK); + int reuseaddr = 1; + if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, + sizeof(int)) == -1) { + fprintf(stderr, "remote_bitbang failed setsockopt: %s (%d)\n", + strerror(errno), errno); + abort(); + } + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(port); + + if (bind(socket_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) { + fprintf(stderr, "remote_bitbang failed to bind socket: %s (%d)\n", + strerror(errno), errno); + abort(); + } + + if (listen(socket_fd, 1) == -1) { + fprintf(stderr, "remote_bitbang failed to listen on socket: %s (%d)\n", + strerror(errno), errno); + abort(); + } + + socklen_t addrlen = sizeof(addr); + if (getsockname(socket_fd, (struct sockaddr *) &addr, &addrlen) == -1) { + fprintf(stderr, "remote_bitbang getsockname failed: %s (%d)\n", + strerror(errno), errno); + abort(); + } + + printf("Listening for remote bitbang connection on port %d.\n", + ntohs(addr.sin_port)); + fflush(stdout); +} + +void remote_bitbang_t::accept() +{ + client_fd = ::accept(socket_fd, NULL, NULL); + if (client_fd == -1) { + if (errno == EAGAIN) { + // No client waiting to connect right now. + } else { + fprintf(stderr, "failed to accept on socket: %s (%d)\n", strerror(errno), + errno); + abort(); + } + } else { + fcntl(client_fd, F_SETFL, O_NONBLOCK); + } +} + +void remote_bitbang_t::tick() +{ + if (client_fd > 0) { + execute_commands(); + } else { + this->accept(); + } +} + +void remote_bitbang_t::execute_commands() +{ + static char send_buf[buf_size]; + unsigned total_processed = 0; + bool quit = false; + bool in_rti = tap->state() == RUN_TEST_IDLE; + bool entered_rti = false; + while (1) { + if (recv_start < recv_end) { + unsigned send_offset = 0; + while (recv_start < recv_end) { + uint8_t command = recv_buf[recv_start]; + + switch (command) { + case 'B': /* fprintf(stderr, "*BLINK*\n"); */ break; + case 'b': /* fprintf(stderr, "_______\n"); */ break; + case 'r': tap->reset(); break; + case '0': tap->set_pins(0, 0, 0); break; + case '1': tap->set_pins(0, 0, 1); break; + case '2': tap->set_pins(0, 1, 0); break; + case '3': tap->set_pins(0, 1, 1); break; + case '4': tap->set_pins(1, 0, 0); break; + case '5': tap->set_pins(1, 0, 1); break; + case '6': tap->set_pins(1, 1, 0); break; + case '7': tap->set_pins(1, 1, 1); break; + case 'R': send_buf[send_offset++] = tap->tdo() ? '1' : '0'; break; + case 'Q': quit = true; break; + default: + fprintf(stderr, "remote_bitbang got unsupported command '%c'\n", + command); + } + recv_start++; + total_processed++; + if (!in_rti && tap->state() == RUN_TEST_IDLE) { + entered_rti = true; + break; + } + in_rti = false; + } + unsigned sent = 0; + while (sent < send_offset) { + ssize_t bytes = write(client_fd, send_buf + sent, send_offset); + if (bytes == -1) { + fprintf(stderr, "failed to write to socket: %s (%d)\n", strerror(errno), errno); + abort(); + } + sent += bytes; + } + } + + if (total_processed > buf_size || quit || entered_rti) { + // Don't go forever, because that could starve the main simulation. + break; + } + + recv_start = 0; + recv_end = read(client_fd, recv_buf, buf_size); + + if (recv_end == -1) { + if (errno == EAGAIN) { + // We'll try again the next call. + } else { + fprintf(stderr, "remote_bitbang failed to read on socket: %s (%d)\n", + strerror(errno), errno); + abort(); + } + } + if (recv_end == 0 || quit) { + // The remote disconnected. + close(client_fd); + client_fd = 0; + break; + } + } +} diff --git a/remote_bitbang.h b/remote_bitbang.h new file mode 100644 index 0000000..1db4d55 --- /dev/null +++ b/remote_bitbang.h @@ -0,0 +1,34 @@ +#ifndef REMOTE_BITBANG_H +#define REMOTE_BITBANG_H + +#include + +#include "jtag_dtm.h" + +class remote_bitbang_t +{ +public: + // Create a new server, listening for connections from localhost on the given + // port. + remote_bitbang_t(uint16_t port, jtag_dtm_t *tap); + + // Do a bit of work. + void tick(); + +private: + jtag_dtm_t *tap; + + int socket_fd; + int client_fd; + + static const ssize_t buf_size = 64 * 1024; + char recv_buf[buf_size]; + ssize_t recv_start, recv_end; + + // Check for a client connecting, and accept if there is one. + void accept(); + // Execute any commands the client has for us. + void execute_commands(); +}; + +#endif diff --git a/riscv/clint.cc b/riscv/clint.cc new file mode 100644 index 0000000..08508b4 --- /dev/null +++ b/riscv/clint.cc @@ -0,0 +1,72 @@ +#include "devices.h" +#include "processor.h" + +clint_t::clint_t(std::vector& procs) + : procs(procs), mtimecmp(procs.size()) +{ +} + +/* 0000 msip hart 0 + * 0004 msip hart 1 + * 4000 mtimecmp hart 0 lo + * 4004 mtimecmp hart 0 hi + * 4008 mtimecmp hart 1 lo + * 400c mtimecmp hart 1 hi + * bff8 mtime lo + * bffc mtime hi + */ + +#define MSIP_BASE 0x0 +#define MTIMECMP_BASE 0x4000 +#define MTIME_BASE 0xbff8 + +bool clint_t::load(reg_t addr, size_t len, uint8_t* bytes) +{ + if (addr >= MSIP_BASE && addr + len <= MSIP_BASE + procs.size()*sizeof(msip_t)) { + std::vector msip(procs.size()); + for (size_t i = 0; i < procs.size(); ++i) + msip[i] = !!(procs[i]->state.mip & MIP_MSIP); + memcpy(bytes, (uint8_t*)&msip[0] + addr - MSIP_BASE, len); + } else if (addr >= MTIMECMP_BASE && addr + len <= MTIMECMP_BASE + procs.size()*sizeof(mtimecmp_t)) { + memcpy(bytes, (uint8_t*)&mtimecmp[0] + addr - MTIMECMP_BASE, len); + } else if (addr >= MTIME_BASE && addr + len <= MTIME_BASE + sizeof(mtime_t)) { + memcpy(bytes, (uint8_t*)&mtime + addr - MTIME_BASE, len); + } else { + return false; + } + return true; +} + +bool clint_t::store(reg_t addr, size_t len, const uint8_t* bytes) +{ + if (addr >= MSIP_BASE && addr + len <= MSIP_BASE + procs.size()*sizeof(msip_t)) { + std::vector msip(procs.size()); + std::vector mask(procs.size(), 0); + memcpy((uint8_t*)&msip[0] + addr - MSIP_BASE, bytes, len); + memset((uint8_t*)&mask[0] + addr - MSIP_BASE, 0xff, len); + for (size_t i = 0; i < procs.size(); ++i) { + if (!(mask[i] & 0xFF)) continue; + procs[i]->state.mip &= ~MIP_MSIP; + if (!!(msip[i] & 1)) + procs[i]->state.mip |= MIP_MSIP; + } + } else if (addr >= MTIMECMP_BASE && addr + len <= MTIMECMP_BASE + procs.size()*sizeof(mtimecmp_t)) { + memcpy((uint8_t*)&mtimecmp[0] + addr - MTIMECMP_BASE, bytes, len); + } else if (addr >= MTIME_BASE && addr + len <= MTIME_BASE + sizeof(mtime_t)) { + memcpy((uint8_t*)&mtime + addr - MTIME_BASE, bytes, len); + } else { + return false; + } + increment(0); + return true; +} + +void clint_t::increment(reg_t inc) +{ + mtime += inc; + for (size_t i = 0; i < procs.size(); i++) { + procs[i]->state.mip &= ~MIP_MTIP; + if (mtime >= mtimecmp[i]) + procs[i]->state.mip |= MIP_MTIP; + } +} diff --git a/riscv/decode.h b/riscv/decode.h index e78a587..7667b27 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -7,17 +7,22 @@ # error spike requires a two''s-complement c++ implementation #endif +#ifdef WORDS_BIGENDIAN +# error spike requires a little-endian host +#endif + #include #include #include #include "encoding.h" #include "config.h" #include "common.h" +#include "softfloat_types.h" +#include "specialize.h" #include typedef int64_t sreg_t; typedef uint64_t reg_t; -typedef uint64_t freg_t; const int NXPR = 32; const int NFPR = 32; @@ -130,7 +135,7 @@ private: #ifndef RISCV_ENABLE_COMMITLOG # define WRITE_REG(reg, value) STATE.XPR.write(reg, value) -# define WRITE_FREG(reg, value) DO_WRITE_FREG(reg, value) +# define WRITE_FREG(reg, value) DO_WRITE_FREG(reg, freg(value)) #else # define WRITE_REG(reg, value) ({ \ reg_t wdata = (value); /* value may have side effects */ \ @@ -138,7 +143,7 @@ private: STATE.XPR.write(reg, wdata); \ }) # define WRITE_FREG(reg, value) ({ \ - freg_t wdata = (value); /* value may have side effects */ \ + freg_t wdata = freg(value); /* value may have side effects */ \ STATE.log_reg_write = (commit_log_reg_t){((reg) << 1) | 1, wdata}; \ DO_WRITE_FREG(reg, wdata); \ }) @@ -170,13 +175,13 @@ private: #define JUMP_TARGET (pc + insn.uj_imm()) #define RM ({ int rm = insn.rm(); \ if(rm == 7) rm = STATE.frm; \ - if(rm > 4) throw trap_illegal_instruction(); \ + if(rm > 4) throw trap_illegal_instruction(0); \ rm; }) #define get_field(reg, mask) (((reg) & (decltype(reg))(mask)) / ((mask) & ~((mask) << 1))) #define set_field(reg, mask, val) (((reg) & ~(decltype(reg))(mask)) | (((decltype(reg))(val) * ((mask) & ~((mask) << 1))) & (decltype(reg))(mask))) -#define require(x) if (unlikely(!(x))) throw trap_illegal_instruction() +#define require(x) if (unlikely(!(x))) throw trap_illegal_instruction(0) #define require_privilege(p) require(STATE.prv >= (p)) #define require_rv64 require(xlen == 64) #define require_rv32 require(xlen == 32) @@ -202,9 +207,10 @@ private: } while(0) #define set_pc_and_serialize(x) \ - do { set_pc(x); /* check alignment */ \ + do { reg_t __npc = (x); \ + set_pc(__npc); /* check alignment */ \ npc = PC_SERIALIZE_AFTER; \ - STATE.pc = (x); \ + STATE.pc = __npc; \ } while(0) /* Sentinel PC values to serialize simulator pipeline */ @@ -213,8 +219,23 @@ private: #define invalid_pc(pc) ((pc) & 1) /* Convenience wrappers to simplify softfloat code sequences */ -#define f32(x) ((float32_t){(uint32_t)x}) -#define f64(x) ((float64_t){(uint64_t)x}) +#define isBoxedF32(r) (((r) & 0xffffffff00000000) == 0xffffffff00000000) +#define unboxF32(r) (isBoxedF32(r) ? (r) : defaultNaNF32UI) +#define unboxF64(r) (r) +struct freg_t { uint64_t v; }; +inline float32_t f32(uint32_t v) { return { v }; } +inline float64_t f64(uint64_t v) { return { v }; } +inline float32_t f32(freg_t r) { return f32(unboxF32(r.v)); } +inline float64_t f64(freg_t r) { return f64(unboxF64(r.v)); } +inline freg_t freg(float32_t f) { return { ((decltype(freg_t::v))-1 << 32) | f.v }; } +inline freg_t freg(float64_t f) { return { f.v }; } +inline freg_t freg(freg_t f) { return f; } +#define F64_SIGN ((decltype(freg_t::v))1 << 63) +#define F32_SIGN ((decltype(freg_t::v))1 << 31) +#define fsgnj32(a, b, n, x) \ + f32((f32(a).v & ~F32_SIGN) | ((((x) ? f32(a).v : (n) ? F32_SIGN : 0) ^ f32(b).v) & F32_SIGN)) +#define fsgnj64(a, b, n, x) \ + f64((f64(a).v & ~F64_SIGN) | ((((x) ? f64(a).v : (n) ? F64_SIGN : 0) ^ f64(b).v) & F64_SIGN)) #define validate_csr(which, write) ({ \ if (!STATE.serialized) return PC_SERIALIZE_BEFORE; \ @@ -222,7 +243,7 @@ private: unsigned csr_priv = get_field((which), 0x300); \ unsigned csr_read_only = get_field((which), 0xC00) == 3; \ if (((write) && csr_read_only) || STATE.prv < csr_priv) \ - throw trap_illegal_instruction(); \ + throw trap_illegal_instruction(0); \ (which); }) #define DEBUG_START 0x20000 diff --git a/riscv/devices.h b/riscv/devices.h index cb3b6d9..f3ecb67 100644 --- a/riscv/devices.h +++ b/riscv/devices.h @@ -34,17 +34,20 @@ class rom_device_t : public abstract_device_t { std::vector data; }; -class rtc_t : public abstract_device_t { +class clint_t : public abstract_device_t { public: - rtc_t(std::vector&); + clint_t(std::vector&); bool load(reg_t addr, size_t len, uint8_t* bytes); bool store(reg_t addr, size_t len, const uint8_t* bytes); - size_t size() { return regs.size() * sizeof(regs[0]); } + size_t size() { return CLINT_SIZE; } void increment(reg_t inc); private: + typedef uint64_t mtime_t; + typedef uint64_t mtimecmp_t; + typedef uint32_t msip_t; std::vector& procs; - std::vector regs; - uint64_t time() { return regs[0]; } + mtime_t mtime; + std::vector mtimecmp; }; #endif diff --git a/riscv/encoding.h b/riscv/encoding.h index 35e0f9f..55f8461 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -17,9 +17,11 @@ #define MSTATUS_FS 0x00006000 #define MSTATUS_XS 0x00018000 #define MSTATUS_MPRV 0x00020000 -#define MSTATUS_PUM 0x00040000 +#define MSTATUS_SUM 0x00040000 #define MSTATUS_MXR 0x00080000 -#define MSTATUS_VM 0x1F000000 +#define MSTATUS_TVM 0x00100000 +#define MSTATUS_TW 0x00200000 +#define MSTATUS_TSR 0x00400000 #define MSTATUS32_SD 0x80000000 #define MSTATUS64_SD 0x8000000000000000 @@ -30,7 +32,8 @@ #define SSTATUS_SPP 0x00000100 #define SSTATUS_FS 0x00006000 #define SSTATUS_XS 0x00018000 -#define SSTATUS_PUM 0x00040000 +#define SSTATUS_SUM 0x00040000 +#define SSTATUS_MXR 0x00080000 #define SSTATUS32_SD 0x80000000 #define SSTATUS64_SD 0x8000000000000000 @@ -107,12 +110,30 @@ #define PRV_H 2 #define PRV_M 3 -#define VM_MBARE 0 -#define VM_MBB 1 -#define VM_MBBID 2 -#define VM_SV32 8 -#define VM_SV39 9 -#define VM_SV48 10 +#define SPTBR32_MODE 0x80000000 +#define SPTBR32_ASID 0x7FC00000 +#define SPTBR32_PPN 0x003FFFFF +#define SPTBR64_MODE 0xF000000000000000 +#define SPTBR64_ASID 0x0FFFF00000000000 +#define SPTBR64_PPN 0x00000FFFFFFFFFFF + +#define SPTBR_MODE_OFF 0 +#define SPTBR_MODE_SV32 1 +#define SPTBR_MODE_SV39 8 +#define SPTBR_MODE_SV48 9 +#define SPTBR_MODE_SV57 10 +#define SPTBR_MODE_SV64 11 + +#define PMP_R 0x01 +#define PMP_W 0x02 +#define PMP_X 0x04 +#define PMP_A 0x18 +#define PMP_L 0x80 +#define PMP_SHIFT 2 + +#define PMP_TOR 0x08 +#define PMP_NA4 0x10 +#define PMP_NAPOT 0x18 #define IRQ_S_SOFT 1 #define IRQ_H_SOFT 2 @@ -127,9 +148,8 @@ #define IRQ_HOST 13 #define DEFAULT_RSTVEC 0x00001000 -#define DEFAULT_NMIVEC 0x00001004 -#define DEFAULT_MTVEC 0x00001010 -#define CONFIG_STRING_ADDR 0x0000100C +#define CLINT_BASE 0x02000000 +#define CLINT_SIZE 0x000c0000 #define EXT_IO_BASE 0x40000000 #define DRAM_BASE 0x80000000 @@ -150,14 +170,16 @@ #ifdef __riscv -#ifdef __riscv64 +#if __riscv_xlen == 64 # define MSTATUS_SD MSTATUS64_SD # define SSTATUS_SD SSTATUS64_SD # define RISCV_PGLEVEL_BITS 9 +# define SPTBR_MODE SPTBR64_MODE #else # define MSTATUS_SD MSTATUS32_SD # define SSTATUS_SD SSTATUS32_SD # define RISCV_PGLEVEL_BITS 10 +# define SPTBR_MODE SPTBR32_MODE #endif #define RISCV_PGSHIFT 12 #define RISCV_PGSIZE (1 << RISCV_PGSHIFT) @@ -171,30 +193,18 @@ __tmp; }) #define write_csr(reg, val) ({ \ - if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ - asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ - else \ - asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) + asm volatile ("csrw " #reg ", %0" :: "rK"(val)); }) #define swap_csr(reg, val) ({ unsigned long __tmp; \ - if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ - asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \ - else \ - asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \ + asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "rK"(val)); \ __tmp; }) #define set_csr(reg, bit) ({ unsigned long __tmp; \ - if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ - asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ - else \ - asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \ __tmp; }) #define clear_csr(reg, bit) ({ unsigned long __tmp; \ - if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ - asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ - else \ - asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \ __tmp; }) #define rdtime() read_csr(time) @@ -208,7 +218,7 @@ #endif #endif -/* Automatically generated by parse-opcodes */ +/* Automatically generated by parse-opcodes. */ #ifndef RISCV_ENCODING_H #define RISCV_ENCODING_H #define MATCH_BEQ 0x63 @@ -397,8 +407,8 @@ #define MASK_MRET 0xffffffff #define MATCH_DRET 0x7b200073 #define MASK_DRET 0xffffffff -#define MATCH_SFENCE_VM 0x10400073 -#define MASK_SFENCE_VM 0xfff07fff +#define MATCH_SFENCE_VMA 0x12000073 +#define MASK_SFENCE_VMA 0xfe007fff #define MATCH_WFI 0x10500073 #define MASK_WFI 0xffffffff #define MATCH_CSRRW 0x1073 @@ -457,6 +467,34 @@ #define MASK_FCVT_D_S 0xfff0007f #define MATCH_FSQRT_D 0x5a000053 #define MASK_FSQRT_D 0xfff0007f +#define MATCH_FADD_Q 0x6000053 +#define MASK_FADD_Q 0xfe00007f +#define MATCH_FSUB_Q 0xe000053 +#define MASK_FSUB_Q 0xfe00007f +#define MATCH_FMUL_Q 0x16000053 +#define MASK_FMUL_Q 0xfe00007f +#define MATCH_FDIV_Q 0x1e000053 +#define MASK_FDIV_Q 0xfe00007f +#define MATCH_FSGNJ_Q 0x26000053 +#define MASK_FSGNJ_Q 0xfe00707f +#define MATCH_FSGNJN_Q 0x26001053 +#define MASK_FSGNJN_Q 0xfe00707f +#define MATCH_FSGNJX_Q 0x26002053 +#define MASK_FSGNJX_Q 0xfe00707f +#define MATCH_FMIN_Q 0x2e000053 +#define MASK_FMIN_Q 0xfe00707f +#define MATCH_FMAX_Q 0x2e001053 +#define MASK_FMAX_Q 0xfe00707f +#define MATCH_FCVT_S_Q 0x40300053 +#define MASK_FCVT_S_Q 0xfff0007f +#define MATCH_FCVT_Q_S 0x46000053 +#define MASK_FCVT_Q_S 0xfff0007f +#define MATCH_FCVT_D_Q 0x42300053 +#define MASK_FCVT_D_Q 0xfff0007f +#define MATCH_FCVT_Q_D 0x46100053 +#define MASK_FCVT_Q_D 0xfff0007f +#define MATCH_FSQRT_Q 0x5e000053 +#define MASK_FSQRT_Q 0xfff0007f #define MATCH_FLE_S 0xa0000053 #define MASK_FLE_S 0xfe00707f #define MATCH_FLT_S 0xa0001053 @@ -469,6 +507,12 @@ #define MASK_FLT_D 0xfe00707f #define MATCH_FEQ_D 0xa2002053 #define MASK_FEQ_D 0xfe00707f +#define MATCH_FLE_Q 0xa6000053 +#define MASK_FLE_Q 0xfe00707f +#define MATCH_FLT_Q 0xa6001053 +#define MASK_FLT_Q 0xfe00707f +#define MATCH_FEQ_Q 0xa6002053 +#define MASK_FEQ_Q 0xfe00707f #define MATCH_FCVT_W_S 0xc0000053 #define MASK_FCVT_W_S 0xfff0007f #define MATCH_FCVT_WU_S 0xc0100053 @@ -493,6 +537,18 @@ #define MASK_FMV_X_D 0xfff0707f #define MATCH_FCLASS_D 0xe2001053 #define MASK_FCLASS_D 0xfff0707f +#define MATCH_FCVT_W_Q 0xc6000053 +#define MASK_FCVT_W_Q 0xfff0007f +#define MATCH_FCVT_WU_Q 0xc6100053 +#define MASK_FCVT_WU_Q 0xfff0007f +#define MATCH_FCVT_L_Q 0xc6200053 +#define MASK_FCVT_L_Q 0xfff0007f +#define MATCH_FCVT_LU_Q 0xc6300053 +#define MASK_FCVT_LU_Q 0xfff0007f +#define MATCH_FMV_X_Q 0xe6000053 +#define MASK_FMV_X_Q 0xfff0707f +#define MATCH_FCLASS_Q 0xe6001053 +#define MASK_FCLASS_Q 0xfff0707f #define MATCH_FCVT_S_W 0xd0000053 #define MASK_FCVT_S_W 0xfff0007f #define MATCH_FCVT_S_WU 0xd0100053 @@ -513,14 +569,28 @@ #define MASK_FCVT_D_LU 0xfff0007f #define MATCH_FMV_D_X 0xf2000053 #define MASK_FMV_D_X 0xfff0707f +#define MATCH_FCVT_Q_W 0xd6000053 +#define MASK_FCVT_Q_W 0xfff0007f +#define MATCH_FCVT_Q_WU 0xd6100053 +#define MASK_FCVT_Q_WU 0xfff0007f +#define MATCH_FCVT_Q_L 0xd6200053 +#define MASK_FCVT_Q_L 0xfff0007f +#define MATCH_FCVT_Q_LU 0xd6300053 +#define MASK_FCVT_Q_LU 0xfff0007f +#define MATCH_FMV_Q_X 0xf6000053 +#define MASK_FMV_Q_X 0xfff0707f #define MATCH_FLW 0x2007 #define MASK_FLW 0x707f #define MATCH_FLD 0x3007 #define MASK_FLD 0x707f +#define MATCH_FLQ 0x4007 +#define MASK_FLQ 0x707f #define MATCH_FSW 0x2027 #define MASK_FSW 0x707f #define MATCH_FSD 0x3027 #define MASK_FSD 0x707f +#define MATCH_FSQ 0x4027 +#define MASK_FSQ 0x707f #define MATCH_FMADD_S 0x43 #define MASK_FMADD_S 0x600007f #define MATCH_FMSUB_S 0x47 @@ -537,6 +607,14 @@ #define MASK_FNMSUB_D 0x600007f #define MATCH_FNMADD_D 0x200004f #define MASK_FNMADD_D 0x600007f +#define MATCH_FMADD_Q 0x6000043 +#define MASK_FMADD_Q 0x600007f +#define MATCH_FMSUB_Q 0x6000047 +#define MASK_FMSUB_Q 0x600007f +#define MATCH_FNMSUB_Q 0x600004b +#define MASK_FNMSUB_Q 0x600007f +#define MATCH_FNMADD_Q 0x600004f +#define MASK_FNMADD_Q 0x600007f #define MATCH_C_NOP 0x1 #define MASK_C_NOP 0xffff #define MATCH_C_ADDI16SP 0x6101 @@ -707,6 +785,7 @@ #define CSR_SSTATUS 0x100 #define CSR_SIE 0x104 #define CSR_STVEC 0x105 +#define CSR_SCOUNTEREN 0x106 #define CSR_SSCRATCH 0x140 #define CSR_SEPC 0x141 #define CSR_SCAUSE 0x142 @@ -719,11 +798,32 @@ #define CSR_MIDELEG 0x303 #define CSR_MIE 0x304 #define CSR_MTVEC 0x305 +#define CSR_MCOUNTEREN 0x306 #define CSR_MSCRATCH 0x340 #define CSR_MEPC 0x341 #define CSR_MCAUSE 0x342 #define CSR_MBADADDR 0x343 #define CSR_MIP 0x344 +#define CSR_PMPCFG0 0x3a0 +#define CSR_PMPCFG1 0x3a1 +#define CSR_PMPCFG2 0x3a2 +#define CSR_PMPCFG3 0x3a3 +#define CSR_PMPADDR0 0x3b0 +#define CSR_PMPADDR1 0x3b1 +#define CSR_PMPADDR2 0x3b2 +#define CSR_PMPADDR3 0x3b3 +#define CSR_PMPADDR4 0x3b4 +#define CSR_PMPADDR5 0x3b5 +#define CSR_PMPADDR6 0x3b6 +#define CSR_PMPADDR7 0x3b7 +#define CSR_PMPADDR8 0x3b8 +#define CSR_PMPADDR9 0x3b9 +#define CSR_PMPADDR10 0x3ba +#define CSR_PMPADDR11 0x3bb +#define CSR_PMPADDR12 0x3bc +#define CSR_PMPADDR13 0x3bd +#define CSR_PMPADDR14 0x3be +#define CSR_PMPADDR15 0x3bf #define CSR_TSELECT 0x7a0 #define CSR_TDATA1 0x7a1 #define CSR_TDATA2 0x7a2 @@ -762,8 +862,6 @@ #define CSR_MHPMCOUNTER29 0xb1d #define CSR_MHPMCOUNTER30 0xb1e #define CSR_MHPMCOUNTER31 0xb1f -#define CSR_MUCOUNTEREN 0x320 -#define CSR_MSCOUNTEREN 0x321 #define CSR_MHPMEVENT3 0x323 #define CSR_MHPMEVENT4 0x324 #define CSR_MHPMEVENT5 0x325 @@ -861,17 +959,20 @@ #define CSR_MHPMCOUNTER30H 0xb9e #define CSR_MHPMCOUNTER31H 0xb9f #define CAUSE_MISALIGNED_FETCH 0x0 -#define CAUSE_FAULT_FETCH 0x1 +#define CAUSE_FETCH_ACCESS 0x1 #define CAUSE_ILLEGAL_INSTRUCTION 0x2 #define CAUSE_BREAKPOINT 0x3 #define CAUSE_MISALIGNED_LOAD 0x4 -#define CAUSE_FAULT_LOAD 0x5 +#define CAUSE_LOAD_ACCESS 0x5 #define CAUSE_MISALIGNED_STORE 0x6 -#define CAUSE_FAULT_STORE 0x7 +#define CAUSE_STORE_ACCESS 0x7 #define CAUSE_USER_ECALL 0x8 #define CAUSE_SUPERVISOR_ECALL 0x9 #define CAUSE_HYPERVISOR_ECALL 0xa #define CAUSE_MACHINE_ECALL 0xb +#define CAUSE_FETCH_PAGE_FAULT 0xc +#define CAUSE_LOAD_PAGE_FAULT 0xd +#define CAUSE_STORE_PAGE_FAULT 0xf #endif #ifdef DECLARE_INSN DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ) @@ -967,7 +1068,7 @@ DECLARE_INSN(sret, MATCH_SRET, MASK_SRET) DECLARE_INSN(hret, MATCH_HRET, MASK_HRET) DECLARE_INSN(mret, MATCH_MRET, MASK_MRET) DECLARE_INSN(dret, MATCH_DRET, MASK_DRET) -DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM) +DECLARE_INSN(sfence_vma, MATCH_SFENCE_VMA, MASK_SFENCE_VMA) DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI) DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW) DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS) @@ -997,12 +1098,29 @@ DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D) DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D) DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S) DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D) +DECLARE_INSN(fadd_q, MATCH_FADD_Q, MASK_FADD_Q) +DECLARE_INSN(fsub_q, MATCH_FSUB_Q, MASK_FSUB_Q) +DECLARE_INSN(fmul_q, MATCH_FMUL_Q, MASK_FMUL_Q) +DECLARE_INSN(fdiv_q, MATCH_FDIV_Q, MASK_FDIV_Q) +DECLARE_INSN(fsgnj_q, MATCH_FSGNJ_Q, MASK_FSGNJ_Q) +DECLARE_INSN(fsgnjn_q, MATCH_FSGNJN_Q, MASK_FSGNJN_Q) +DECLARE_INSN(fsgnjx_q, MATCH_FSGNJX_Q, MASK_FSGNJX_Q) +DECLARE_INSN(fmin_q, MATCH_FMIN_Q, MASK_FMIN_Q) +DECLARE_INSN(fmax_q, MATCH_FMAX_Q, MASK_FMAX_Q) +DECLARE_INSN(fcvt_s_q, MATCH_FCVT_S_Q, MASK_FCVT_S_Q) +DECLARE_INSN(fcvt_q_s, MATCH_FCVT_Q_S, MASK_FCVT_Q_S) +DECLARE_INSN(fcvt_d_q, MATCH_FCVT_D_Q, MASK_FCVT_D_Q) +DECLARE_INSN(fcvt_q_d, MATCH_FCVT_Q_D, MASK_FCVT_Q_D) +DECLARE_INSN(fsqrt_q, MATCH_FSQRT_Q, MASK_FSQRT_Q) DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S) DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S) DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S) DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D) DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D) DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D) +DECLARE_INSN(fle_q, MATCH_FLE_Q, MASK_FLE_Q) +DECLARE_INSN(flt_q, MATCH_FLT_Q, MASK_FLT_Q) +DECLARE_INSN(feq_q, MATCH_FEQ_Q, MASK_FEQ_Q) DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S) DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S) DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S) @@ -1015,6 +1133,12 @@ DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D) DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D) DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D) DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D) +DECLARE_INSN(fcvt_w_q, MATCH_FCVT_W_Q, MASK_FCVT_W_Q) +DECLARE_INSN(fcvt_wu_q, MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q) +DECLARE_INSN(fcvt_l_q, MATCH_FCVT_L_Q, MASK_FCVT_L_Q) +DECLARE_INSN(fcvt_lu_q, MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q) +DECLARE_INSN(fmv_x_q, MATCH_FMV_X_Q, MASK_FMV_X_Q) +DECLARE_INSN(fclass_q, MATCH_FCLASS_Q, MASK_FCLASS_Q) DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W) DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU) DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L) @@ -1025,10 +1149,17 @@ DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU) DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L) DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU) DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X) +DECLARE_INSN(fcvt_q_w, MATCH_FCVT_Q_W, MASK_FCVT_Q_W) +DECLARE_INSN(fcvt_q_wu, MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU) +DECLARE_INSN(fcvt_q_l, MATCH_FCVT_Q_L, MASK_FCVT_Q_L) +DECLARE_INSN(fcvt_q_lu, MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU) +DECLARE_INSN(fmv_q_x, MATCH_FMV_Q_X, MASK_FMV_Q_X) DECLARE_INSN(flw, MATCH_FLW, MASK_FLW) DECLARE_INSN(fld, MATCH_FLD, MASK_FLD) +DECLARE_INSN(flq, MATCH_FLQ, MASK_FLQ) DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW) DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD) +DECLARE_INSN(fsq, MATCH_FSQ, MASK_FSQ) DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S) DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S) DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S) @@ -1037,6 +1168,10 @@ DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D) DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D) DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D) DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D) +DECLARE_INSN(fmadd_q, MATCH_FMADD_Q, MASK_FMADD_Q) +DECLARE_INSN(fmsub_q, MATCH_FMSUB_Q, MASK_FMSUB_Q) +DECLARE_INSN(fnmsub_q, MATCH_FNMSUB_Q, MASK_FNMSUB_Q) +DECLARE_INSN(fnmadd_q, MATCH_FNMADD_Q, MASK_FNMADD_Q) DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP) DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP) DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR) @@ -1143,6 +1278,7 @@ DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31) DECLARE_CSR(sstatus, CSR_SSTATUS) DECLARE_CSR(sie, CSR_SIE) DECLARE_CSR(stvec, CSR_STVEC) +DECLARE_CSR(scounteren, CSR_SCOUNTEREN) DECLARE_CSR(sscratch, CSR_SSCRATCH) DECLARE_CSR(sepc, CSR_SEPC) DECLARE_CSR(scause, CSR_SCAUSE) @@ -1155,11 +1291,32 @@ DECLARE_CSR(medeleg, CSR_MEDELEG) DECLARE_CSR(mideleg, CSR_MIDELEG) DECLARE_CSR(mie, CSR_MIE) DECLARE_CSR(mtvec, CSR_MTVEC) +DECLARE_CSR(mcounteren, CSR_MCOUNTEREN) DECLARE_CSR(mscratch, CSR_MSCRATCH) DECLARE_CSR(mepc, CSR_MEPC) DECLARE_CSR(mcause, CSR_MCAUSE) DECLARE_CSR(mbadaddr, CSR_MBADADDR) DECLARE_CSR(mip, CSR_MIP) +DECLARE_CSR(pmpcfg0, CSR_PMPCFG0) +DECLARE_CSR(pmpcfg1, CSR_PMPCFG1) +DECLARE_CSR(pmpcfg2, CSR_PMPCFG2) +DECLARE_CSR(pmpcfg3, CSR_PMPCFG3) +DECLARE_CSR(pmpaddr0, CSR_PMPADDR0) +DECLARE_CSR(pmpaddr1, CSR_PMPADDR1) +DECLARE_CSR(pmpaddr2, CSR_PMPADDR2) +DECLARE_CSR(pmpaddr3, CSR_PMPADDR3) +DECLARE_CSR(pmpaddr4, CSR_PMPADDR4) +DECLARE_CSR(pmpaddr5, CSR_PMPADDR5) +DECLARE_CSR(pmpaddr6, CSR_PMPADDR6) +DECLARE_CSR(pmpaddr7, CSR_PMPADDR7) +DECLARE_CSR(pmpaddr8, CSR_PMPADDR8) +DECLARE_CSR(pmpaddr9, CSR_PMPADDR9) +DECLARE_CSR(pmpaddr10, CSR_PMPADDR10) +DECLARE_CSR(pmpaddr11, CSR_PMPADDR11) +DECLARE_CSR(pmpaddr12, CSR_PMPADDR12) +DECLARE_CSR(pmpaddr13, CSR_PMPADDR13) +DECLARE_CSR(pmpaddr14, CSR_PMPADDR14) +DECLARE_CSR(pmpaddr15, CSR_PMPADDR15) DECLARE_CSR(tselect, CSR_TSELECT) DECLARE_CSR(tdata1, CSR_TDATA1) DECLARE_CSR(tdata2, CSR_TDATA2) @@ -1198,8 +1355,6 @@ DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28) DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29) DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30) DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31) -DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN) -DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN) DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3) DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4) DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5) @@ -1299,15 +1454,18 @@ DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H) #endif #ifdef DECLARE_CAUSE DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH) -DECLARE_CAUSE("fault fetch", CAUSE_FAULT_FETCH) +DECLARE_CAUSE("fetch access", CAUSE_FETCH_ACCESS) DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION) DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT) DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD) -DECLARE_CAUSE("fault load", CAUSE_FAULT_LOAD) +DECLARE_CAUSE("load access", CAUSE_LOAD_ACCESS) DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE) -DECLARE_CAUSE("fault store", CAUSE_FAULT_STORE) +DECLARE_CAUSE("store access", CAUSE_STORE_ACCESS) DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL) DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL) DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL) DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL) +DECLARE_CAUSE("fetch page fault", CAUSE_FETCH_PAGE_FAULT) +DECLARE_CAUSE("load page fault", CAUSE_LOAD_PAGE_FAULT) +DECLARE_CAUSE("store page fault", CAUSE_STORE_PAGE_FAULT) #endif diff --git a/riscv/execute.cc b/riscv/execute.cc index 0ac0e0a..7734ca2 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -79,7 +79,7 @@ void processor_t::step(size_t n) if (unlikely(invalid_pc(pc))) { \ switch (pc) { \ case PC_SERIALIZE_BEFORE: state.serialized = true; break; \ - case PC_SERIALIZE_AFTER: instret++; break; \ + case PC_SERIALIZE_AFTER: n = ++instret; break; \ default: abort(); \ } \ pc = state.pc; \ @@ -91,7 +91,7 @@ void processor_t::step(size_t n) try { - take_interrupt(); + take_pending_interrupt(); if (unlikely(slow_path())) { diff --git a/riscv/extension.cc b/riscv/extension.cc index 5321c42..520c2ed 100644 --- a/riscv/extension.cc +++ b/riscv/extension.cc @@ -9,17 +9,12 @@ extension_t::~extension_t() void extension_t::illegal_instruction() { - throw trap_illegal_instruction(); + throw trap_illegal_instruction(0); } void extension_t::raise_interrupt() { - reg_t prv = p->get_state()->prv; - reg_t mie = get_field(p->get_state()->mstatus, MSTATUS_MIE); - - if (prv < PRV_M || (prv == PRV_M && mie)) - p->raise_interrupt(IRQ_COP); - + p->take_interrupt((reg_t)1 << IRQ_COP); // must not return throw std::logic_error("a COP exception was posted, but interrupts are disabled!"); } diff --git a/riscv/insn_template.h b/riscv/insn_template.h index 0dd0aa1..07aa16b 100644 --- a/riscv/insn_template.h +++ b/riscv/insn_template.h @@ -4,5 +4,6 @@ #include "mulhi.h" #include "softfloat.h" #include "internals.h" +#include "specialize.h" #include "tracer.h" #include diff --git a/riscv/insns/c_ebreak.h b/riscv/insns/c_ebreak.h index a17200f..128b86b 100644 --- a/riscv/insns/c_ebreak.h +++ b/riscv/insns/c_ebreak.h @@ -1,2 +1,2 @@ require_extension('C'); -throw trap_breakpoint(); +throw trap_breakpoint(pc); diff --git a/riscv/insns/c_fld.h b/riscv/insns/c_fld.h index 10d14f8..319615b 100644 --- a/riscv/insns/c_fld.h +++ b/riscv/insns/c_fld.h @@ -1,4 +1,4 @@ require_extension('C'); require_extension('D'); require_fp; -WRITE_RVC_FRS2S(MMU.load_int64(RVC_RS1S + insn.rvc_ld_imm())); +WRITE_RVC_FRS2S(f64(MMU.load_uint64(RVC_RS1S + insn.rvc_ld_imm()))); diff --git a/riscv/insns/c_fldsp.h b/riscv/insns/c_fldsp.h index 8b1e19f..534eef7 100644 --- a/riscv/insns/c_fldsp.h +++ b/riscv/insns/c_fldsp.h @@ -1,4 +1,4 @@ require_extension('C'); require_extension('D'); require_fp; -WRITE_FRD(MMU.load_int64(RVC_SP + insn.rvc_ldsp_imm())); +WRITE_FRD(f64(MMU.load_uint64(RVC_SP + insn.rvc_ldsp_imm()))); diff --git a/riscv/insns/c_flw.h b/riscv/insns/c_flw.h index 0be27a9..682566c 100644 --- a/riscv/insns/c_flw.h +++ b/riscv/insns/c_flw.h @@ -2,7 +2,7 @@ require_extension('C'); if (xlen == 32) { require_extension('F'); require_fp; - WRITE_RVC_FRS2S(MMU.load_int32(RVC_RS1S + insn.rvc_lw_imm())); + WRITE_RVC_FRS2S(f32(MMU.load_uint32(RVC_RS1S + insn.rvc_lw_imm()))); } else { // c.ld WRITE_RVC_RS2S(MMU.load_int64(RVC_RS1S + insn.rvc_ld_imm())); } diff --git a/riscv/insns/c_flwsp.h b/riscv/insns/c_flwsp.h index 26a4721..79058c4 100644 --- a/riscv/insns/c_flwsp.h +++ b/riscv/insns/c_flwsp.h @@ -2,7 +2,7 @@ require_extension('C'); if (xlen == 32) { require_extension('F'); require_fp; - WRITE_FRD(MMU.load_int32(RVC_SP + insn.rvc_lwsp_imm())); + WRITE_FRD(f32(MMU.load_uint32(RVC_SP + insn.rvc_lwsp_imm()))); } else { // c.ldsp require(insn.rvc_rd() != 0); WRITE_RD(MMU.load_int64(RVC_SP + insn.rvc_ldsp_imm())); diff --git a/riscv/insns/c_fsd.h b/riscv/insns/c_fsd.h index 84f1a7f..8743266 100644 --- a/riscv/insns/c_fsd.h +++ b/riscv/insns/c_fsd.h @@ -1,4 +1,4 @@ require_extension('C'); require_extension('D'); require_fp; -MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_FRS2S); +MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_FRS2S.v); diff --git a/riscv/insns/c_fsdsp.h b/riscv/insns/c_fsdsp.h index 5c5c680..f62f8ff 100644 --- a/riscv/insns/c_fsdsp.h +++ b/riscv/insns/c_fsdsp.h @@ -1,4 +1,4 @@ require_extension('C'); require_extension('D'); require_fp; -MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_FRS2); +MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_FRS2.v); diff --git a/riscv/insns/c_fsw.h b/riscv/insns/c_fsw.h index 8923fef..b924a46 100644 --- a/riscv/insns/c_fsw.h +++ b/riscv/insns/c_fsw.h @@ -2,7 +2,7 @@ require_extension('C'); if (xlen == 32) { require_extension('F'); require_fp; - MMU.store_uint32(RVC_RS1S + insn.rvc_lw_imm(), RVC_FRS2S); + MMU.store_uint32(RVC_RS1S + insn.rvc_lw_imm(), RVC_FRS2S.v); } else { // c.sd MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S); } diff --git a/riscv/insns/c_fswsp.h b/riscv/insns/c_fswsp.h index c13aa12..011de55 100644 --- a/riscv/insns/c_fswsp.h +++ b/riscv/insns/c_fswsp.h @@ -2,7 +2,7 @@ require_extension('C'); if (xlen == 32) { require_extension('F'); require_fp; - MMU.store_uint32(RVC_SP + insn.rvc_swsp_imm(), RVC_FRS2); + MMU.store_uint32(RVC_SP + insn.rvc_swsp_imm(), RVC_FRS2.v); } else { // c.sdsp MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2); } diff --git a/riscv/insns/ebreak.h b/riscv/insns/ebreak.h index c22776c..736cebe 100644 --- a/riscv/insns/ebreak.h +++ b/riscv/insns/ebreak.h @@ -1 +1 @@ -throw trap_breakpoint(); +throw trap_breakpoint(pc); diff --git a/riscv/insns/fadd_d.h b/riscv/insns/fadd_d.h index 9990174..4a436e2 100644 --- a/riscv/insns/fadd_d.h +++ b/riscv/insns/fadd_d.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f64_add(f64(FRS1), f64(FRS2)).v); +WRITE_FRD(f64_add(f64(FRS1), f64(FRS2))); set_fp_exceptions; diff --git a/riscv/insns/fadd_s.h b/riscv/insns/fadd_s.h index cdef36a..cc18d58 100644 --- a/riscv/insns/fadd_s.h +++ b/riscv/insns/fadd_s.h @@ -1,5 +1,5 @@ require_extension('F'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f32_add(f32(FRS1), f32(FRS2)).v); +WRITE_FRD(f32_add(f32(FRS1), f32(FRS2))); set_fp_exceptions; diff --git a/riscv/insns/fcvt_d_l.h b/riscv/insns/fcvt_d_l.h index fece227..08716cf 100644 --- a/riscv/insns/fcvt_d_l.h +++ b/riscv/insns/fcvt_d_l.h @@ -2,5 +2,5 @@ require_extension('D'); require_rv64; require_fp; softfloat_roundingMode = RM; -WRITE_FRD(i64_to_f64(RS1).v); +WRITE_FRD(i64_to_f64(RS1)); set_fp_exceptions; diff --git a/riscv/insns/fcvt_d_lu.h b/riscv/insns/fcvt_d_lu.h index 775c7ae..306d7fe 100644 --- a/riscv/insns/fcvt_d_lu.h +++ b/riscv/insns/fcvt_d_lu.h @@ -2,5 +2,5 @@ require_extension('D'); require_rv64; require_fp; softfloat_roundingMode = RM; -WRITE_FRD(ui64_to_f64(RS1).v); +WRITE_FRD(ui64_to_f64(RS1)); set_fp_exceptions; diff --git a/riscv/insns/fcvt_d_s.h b/riscv/insns/fcvt_d_s.h index ec778cc..5f805b0 100644 --- a/riscv/insns/fcvt_d_s.h +++ b/riscv/insns/fcvt_d_s.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f32_to_f64(f32(FRS1)).v); +WRITE_FRD(f32_to_f64(f32(FRS1))); set_fp_exceptions; diff --git a/riscv/insns/fcvt_d_w.h b/riscv/insns/fcvt_d_w.h index 753250d..4c4861c 100644 --- a/riscv/insns/fcvt_d_w.h +++ b/riscv/insns/fcvt_d_w.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(i32_to_f64((int32_t)RS1).v); +WRITE_FRD(i32_to_f64((int32_t)RS1)); set_fp_exceptions; diff --git a/riscv/insns/fcvt_d_wu.h b/riscv/insns/fcvt_d_wu.h index af893b3..1dbf218 100644 --- a/riscv/insns/fcvt_d_wu.h +++ b/riscv/insns/fcvt_d_wu.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(ui32_to_f64((uint32_t)RS1).v); +WRITE_FRD(ui32_to_f64((uint32_t)RS1)); set_fp_exceptions; diff --git a/riscv/insns/fcvt_s_d.h b/riscv/insns/fcvt_s_d.h index 211bbba..4033335 100644 --- a/riscv/insns/fcvt_s_d.h +++ b/riscv/insns/fcvt_s_d.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f64_to_f32(f64(FRS1)).v); +WRITE_FRD(f64_to_f32(f64(FRS1))); set_fp_exceptions; diff --git a/riscv/insns/fcvt_s_l.h b/riscv/insns/fcvt_s_l.h index 1c0581a..9abcc80 100644 --- a/riscv/insns/fcvt_s_l.h +++ b/riscv/insns/fcvt_s_l.h @@ -2,5 +2,5 @@ require_extension('F'); require_rv64; require_fp; softfloat_roundingMode = RM; -WRITE_FRD(i64_to_f32(RS1).v); +WRITE_FRD(i64_to_f32(RS1)); set_fp_exceptions; diff --git a/riscv/insns/fcvt_s_lu.h b/riscv/insns/fcvt_s_lu.h index e9bf78e..70c676e 100644 --- a/riscv/insns/fcvt_s_lu.h +++ b/riscv/insns/fcvt_s_lu.h @@ -2,5 +2,5 @@ require_extension('F'); require_rv64; require_fp; softfloat_roundingMode = RM; -WRITE_FRD(ui64_to_f32(RS1).v); +WRITE_FRD(ui64_to_f32(RS1)); set_fp_exceptions; diff --git a/riscv/insns/fcvt_s_w.h b/riscv/insns/fcvt_s_w.h index 9411cbd..1ddabd8 100644 --- a/riscv/insns/fcvt_s_w.h +++ b/riscv/insns/fcvt_s_w.h @@ -1,5 +1,5 @@ require_extension('F'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(i32_to_f32((int32_t)RS1).v); +WRITE_FRD(i32_to_f32((int32_t)RS1)); set_fp_exceptions; diff --git a/riscv/insns/fcvt_s_wu.h b/riscv/insns/fcvt_s_wu.h index a6cf836..c1394c3 100644 --- a/riscv/insns/fcvt_s_wu.h +++ b/riscv/insns/fcvt_s_wu.h @@ -1,5 +1,5 @@ require_extension('F'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(ui32_to_f32((uint32_t)RS1).v); +WRITE_FRD(ui32_to_f32((uint32_t)RS1)); set_fp_exceptions; diff --git a/riscv/insns/fdiv_d.h b/riscv/insns/fdiv_d.h index d8943de..ae7911a 100644 --- a/riscv/insns/fdiv_d.h +++ b/riscv/insns/fdiv_d.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f64_div(f64(FRS1), f64(FRS2)).v); +WRITE_FRD(f64_div(f64(FRS1), f64(FRS2))); set_fp_exceptions; diff --git a/riscv/insns/fdiv_s.h b/riscv/insns/fdiv_s.h index 66ac48d..c74ff04 100644 --- a/riscv/insns/fdiv_s.h +++ b/riscv/insns/fdiv_s.h @@ -1,5 +1,5 @@ require_extension('F'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f32_div(f32(FRS1), f32(FRS2)).v); +WRITE_FRD(f32_div(f32(FRS1), f32(FRS2))); set_fp_exceptions; diff --git a/riscv/insns/fld.h b/riscv/insns/fld.h index 0b50b8a..4dea1d4 100644 --- a/riscv/insns/fld.h +++ b/riscv/insns/fld.h @@ -1,3 +1,3 @@ require_extension('D'); require_fp; -WRITE_FRD(MMU.load_int64(RS1 + insn.i_imm())); +WRITE_FRD(f64(MMU.load_uint64(RS1 + insn.i_imm()))); diff --git a/riscv/insns/flw.h b/riscv/insns/flw.h index 489e743..6129754 100644 --- a/riscv/insns/flw.h +++ b/riscv/insns/flw.h @@ -1,3 +1,3 @@ require_extension('F'); require_fp; -WRITE_FRD(MMU.load_uint32(RS1 + insn.i_imm())); +WRITE_FRD(f32(MMU.load_uint32(RS1 + insn.i_imm()))); diff --git a/riscv/insns/fmadd_d.h b/riscv/insns/fmadd_d.h index 98f1cbc..ab22beb 100644 --- a/riscv/insns/fmadd_d.h +++ b/riscv/insns/fmadd_d.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f64_mulAdd(f64(FRS1), f64(FRS2), f64(FRS3)).v); +WRITE_FRD(f64_mulAdd(f64(FRS1), f64(FRS2), f64(FRS3))); set_fp_exceptions; diff --git a/riscv/insns/fmadd_s.h b/riscv/insns/fmadd_s.h index a78ed25..e919190 100644 --- a/riscv/insns/fmadd_s.h +++ b/riscv/insns/fmadd_s.h @@ -1,5 +1,5 @@ require_extension('F'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f32_mulAdd(f32(FRS1), f32(FRS2), f32(FRS3)).v); +WRITE_FRD(f32_mulAdd(f32(FRS1), f32(FRS2), f32(FRS3))); set_fp_exceptions; diff --git a/riscv/insns/fmax_d.h b/riscv/insns/fmax_d.h index f0bea9b..9c8e5b3 100644 --- a/riscv/insns/fmax_d.h +++ b/riscv/insns/fmax_d.h @@ -1,4 +1,6 @@ require_extension('D'); require_fp; -WRITE_FRD(isNaNF64UI(FRS2) || f64_le_quiet(f64(FRS2), f64(FRS1)) ? FRS1 : FRS2); +WRITE_FRD(f64_le_quiet(f64(FRS2), f64(FRS1)) || isNaNF64UI(f64(FRS2).v) ? FRS1 : FRS2); +if ((isNaNF64UI(f64(FRS1).v) && isNaNF64UI(f64(FRS2).v)) || softfloat_exceptionFlags) + WRITE_FRD(f64(defaultNaNF64UI)); set_fp_exceptions; diff --git a/riscv/insns/fmax_s.h b/riscv/insns/fmax_s.h index 33b2bc6..2f570ea 100644 --- a/riscv/insns/fmax_s.h +++ b/riscv/insns/fmax_s.h @@ -1,4 +1,6 @@ require_extension('F'); require_fp; -WRITE_FRD(isNaNF32UI(FRS2) || f32_le_quiet(f32(FRS2), f32(FRS1)) ? FRS1 : FRS2); +WRITE_FRD(f32_le_quiet(f32(FRS2), f32(FRS1)) || isNaNF32UI(f32(FRS2).v) ? FRS1 : FRS2); +if ((isNaNF32UI(f32(FRS1).v) && isNaNF32UI(f32(FRS2).v)) || softfloat_exceptionFlags) + WRITE_FRD(f32(defaultNaNF32UI)); set_fp_exceptions; diff --git a/riscv/insns/fmin_d.h b/riscv/insns/fmin_d.h index e22b6ea..cd40e15 100644 --- a/riscv/insns/fmin_d.h +++ b/riscv/insns/fmin_d.h @@ -1,4 +1,6 @@ require_extension('D'); require_fp; -WRITE_FRD(isNaNF64UI(FRS2) || f64_lt_quiet(f64(FRS1), f64(FRS2)) ? FRS1 : FRS2); +WRITE_FRD(f64_lt_quiet(f64(FRS1), f64(FRS2)) || isNaNF64UI(f64(FRS2).v) ? FRS1 : FRS2); +if ((isNaNF64UI(f64(FRS1).v) && isNaNF64UI(f64(FRS2).v)) || softfloat_exceptionFlags) + WRITE_FRD(f64(defaultNaNF64UI)); set_fp_exceptions; diff --git a/riscv/insns/fmin_s.h b/riscv/insns/fmin_s.h index 0ebb3a8..b813f45 100644 --- a/riscv/insns/fmin_s.h +++ b/riscv/insns/fmin_s.h @@ -1,4 +1,6 @@ require_extension('F'); require_fp; -WRITE_FRD(isNaNF32UI(FRS2) || f32_lt_quiet(f32(FRS1), f32(FRS2)) ? FRS1 : FRS2); +WRITE_FRD(f32_lt_quiet(f32(FRS1), f32(FRS2)) || isNaNF32UI(f32(FRS2).v) ? FRS1 : FRS2); +if ((isNaNF32UI(f32(FRS1).v) && isNaNF32UI(f32(FRS2).v)) || softfloat_exceptionFlags) + WRITE_FRD(f32(defaultNaNF32UI)); set_fp_exceptions; diff --git a/riscv/insns/fmsub_d.h b/riscv/insns/fmsub_d.h index afcea88..5b5bc0f 100644 --- a/riscv/insns/fmsub_d.h +++ b/riscv/insns/fmsub_d.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f64_mulAdd(f64(FRS1), f64(FRS2), f64(FRS3 ^ (uint64_t)INT64_MIN)).v); +WRITE_FRD(f64_mulAdd(f64(FRS1), f64(FRS2), f64(f64(FRS3).v ^ F64_SIGN))); set_fp_exceptions; diff --git a/riscv/insns/fmsub_s.h b/riscv/insns/fmsub_s.h index 45945da..d46c887 100644 --- a/riscv/insns/fmsub_s.h +++ b/riscv/insns/fmsub_s.h @@ -1,5 +1,5 @@ require_extension('F'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f32_mulAdd(f32(FRS1), f32(FRS2), f32(FRS3 ^ (uint32_t)INT32_MIN)).v); +WRITE_FRD(f32_mulAdd(f32(FRS1), f32(FRS2), f32(f32(FRS3).v ^ F32_SIGN))); set_fp_exceptions; diff --git a/riscv/insns/fmul_d.h b/riscv/insns/fmul_d.h index 04e7402..9189d8d 100644 --- a/riscv/insns/fmul_d.h +++ b/riscv/insns/fmul_d.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f64_mul(f64(FRS1), f64(FRS2)).v); +WRITE_FRD(f64_mul(f64(FRS1), f64(FRS2))); set_fp_exceptions; diff --git a/riscv/insns/fmul_s.h b/riscv/insns/fmul_s.h index 9ae7b3c..145d5ce 100644 --- a/riscv/insns/fmul_s.h +++ b/riscv/insns/fmul_s.h @@ -1,5 +1,5 @@ require_extension('F'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f32_mul(f32(FRS1), f32(FRS2)).v); +WRITE_FRD(f32_mul(f32(FRS1), f32(FRS2))); set_fp_exceptions; diff --git a/riscv/insns/fmv_d_x.h b/riscv/insns/fmv_d_x.h index c3f6049..0bff5fb 100644 --- a/riscv/insns/fmv_d_x.h +++ b/riscv/insns/fmv_d_x.h @@ -1,4 +1,4 @@ require_extension('D'); require_rv64; require_fp; -WRITE_FRD(RS1); +WRITE_FRD(f64(RS1)); diff --git a/riscv/insns/fmv_s_x.h b/riscv/insns/fmv_s_x.h index 2daf6da..5f71323 100644 --- a/riscv/insns/fmv_s_x.h +++ b/riscv/insns/fmv_s_x.h @@ -1,3 +1,3 @@ require_extension('F'); require_fp; -WRITE_FRD(zext32(RS1)); +WRITE_FRD(f32(RS1)); diff --git a/riscv/insns/fmv_x_d.h b/riscv/insns/fmv_x_d.h index b97d7f5..da8e72a 100644 --- a/riscv/insns/fmv_x_d.h +++ b/riscv/insns/fmv_x_d.h @@ -1,4 +1,4 @@ require_extension('D'); require_rv64; require_fp; -WRITE_RD(FRS1); +WRITE_RD(FRS1.v); diff --git a/riscv/insns/fmv_x_s.h b/riscv/insns/fmv_x_s.h index 1bee87f..b722479 100644 --- a/riscv/insns/fmv_x_s.h +++ b/riscv/insns/fmv_x_s.h @@ -1,3 +1,3 @@ require_extension('F'); require_fp; -WRITE_RD(sext32(FRS1)); +WRITE_RD(sext32(FRS1.v)); diff --git a/riscv/insns/fnmadd_d.h b/riscv/insns/fnmadd_d.h index d6e1f04..e8dd743 100644 --- a/riscv/insns/fnmadd_d.h +++ b/riscv/insns/fnmadd_d.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f64_mulAdd(f64(FRS1 ^ (uint64_t)INT64_MIN), f64(FRS2), f64(FRS3 ^ (uint64_t)INT64_MIN)).v); +WRITE_FRD(f64_mulAdd(f64(f64(FRS1).v ^ F64_SIGN), f64(FRS2), f64(f64(FRS3).v ^ F64_SIGN))); set_fp_exceptions; diff --git a/riscv/insns/fnmadd_s.h b/riscv/insns/fnmadd_s.h index 0d0b2e9..1c2996e 100644 --- a/riscv/insns/fnmadd_s.h +++ b/riscv/insns/fnmadd_s.h @@ -1,5 +1,5 @@ require_extension('F'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f32_mulAdd(f32(FRS1 ^ (uint32_t)INT32_MIN), f32(FRS2), f32(FRS3 ^ (uint32_t)INT32_MIN)).v); +WRITE_FRD(f32_mulAdd(f32(f32(FRS1).v ^ F32_SIGN), f32(FRS2), f32(f32(FRS3).v ^ F32_SIGN))); set_fp_exceptions; diff --git a/riscv/insns/fnmsub_d.h b/riscv/insns/fnmsub_d.h index ee74cab..c29a0b9 100644 --- a/riscv/insns/fnmsub_d.h +++ b/riscv/insns/fnmsub_d.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f64_mulAdd(f64(FRS1 ^ (uint64_t)INT64_MIN), f64(FRS2), f64(FRS3)).v); +WRITE_FRD(f64_mulAdd(f64(f64(FRS1).v ^ F64_SIGN), f64(FRS2), f64(FRS3))); set_fp_exceptions; diff --git a/riscv/insns/fnmsub_s.h b/riscv/insns/fnmsub_s.h index 3e0b8ea..4c61fc7 100644 --- a/riscv/insns/fnmsub_s.h +++ b/riscv/insns/fnmsub_s.h @@ -1,5 +1,5 @@ require_extension('F'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f32_mulAdd(f32(FRS1 ^ (uint32_t)INT32_MIN), f32(FRS2), f32(FRS3)).v); +WRITE_FRD(f32_mulAdd(f32(f32(FRS1).v ^ F32_SIGN), f32(FRS2), f32(FRS3))); set_fp_exceptions; diff --git a/riscv/insns/fsd.h b/riscv/insns/fsd.h index 63cc8e5..679cc95 100644 --- a/riscv/insns/fsd.h +++ b/riscv/insns/fsd.h @@ -1,3 +1,3 @@ require_extension('D'); require_fp; -MMU.store_uint64(RS1 + insn.s_imm(), FRS2); +MMU.store_uint64(RS1 + insn.s_imm(), FRS2.v); diff --git a/riscv/insns/fsgnj_d.h b/riscv/insns/fsgnj_d.h index 52648a1..78f9ce7 100644 --- a/riscv/insns/fsgnj_d.h +++ b/riscv/insns/fsgnj_d.h @@ -1,3 +1,3 @@ require_extension('D'); require_fp; -WRITE_FRD((FRS1 &~ INT64_MIN) | (FRS2 & INT64_MIN)); +WRITE_FRD(fsgnj64(FRS1, FRS2, false, false)); diff --git a/riscv/insns/fsgnj_s.h b/riscv/insns/fsgnj_s.h index 4c91ff3..c1a70cb 100644 --- a/riscv/insns/fsgnj_s.h +++ b/riscv/insns/fsgnj_s.h @@ -1,3 +1,3 @@ require_extension('F'); require_fp; -WRITE_FRD((FRS1 &~ (uint32_t)INT32_MIN) | (FRS2 & (uint32_t)INT32_MIN)); +WRITE_FRD(fsgnj32(FRS1, FRS2, false, false)); diff --git a/riscv/insns/fsgnjn_d.h b/riscv/insns/fsgnjn_d.h index cdec924..f02c311 100644 --- a/riscv/insns/fsgnjn_d.h +++ b/riscv/insns/fsgnjn_d.h @@ -1,3 +1,3 @@ require_extension('D'); require_fp; -WRITE_FRD((FRS1 &~ INT64_MIN) | ((~FRS2) & INT64_MIN)); +WRITE_FRD(fsgnj64(FRS1, FRS2, true, false)); diff --git a/riscv/insns/fsgnjn_s.h b/riscv/insns/fsgnjn_s.h index f91a7b0..35906d6 100644 --- a/riscv/insns/fsgnjn_s.h +++ b/riscv/insns/fsgnjn_s.h @@ -1,3 +1,3 @@ require_extension('F'); require_fp; -WRITE_FRD((FRS1 &~ (uint32_t)INT32_MIN) | ((~FRS2) & (uint32_t)INT32_MIN)); +WRITE_FRD(fsgnj32(FRS1, FRS2, true, false)); diff --git a/riscv/insns/fsgnjx_d.h b/riscv/insns/fsgnjx_d.h index b09d24c..c121737 100644 --- a/riscv/insns/fsgnjx_d.h +++ b/riscv/insns/fsgnjx_d.h @@ -1,3 +1,3 @@ require_extension('D'); require_fp; -WRITE_FRD(FRS1 ^ (FRS2 & INT64_MIN)); +WRITE_FRD(fsgnj64(FRS1, FRS2, false, true)); diff --git a/riscv/insns/fsgnjx_s.h b/riscv/insns/fsgnjx_s.h index 1fd2de6..4d5c624 100644 --- a/riscv/insns/fsgnjx_s.h +++ b/riscv/insns/fsgnjx_s.h @@ -1,3 +1,3 @@ require_extension('F'); require_fp; -WRITE_FRD(FRS1 ^ (FRS2 & (uint32_t)INT32_MIN)); +WRITE_FRD(fsgnj32(FRS1, FRS2, false, true)); diff --git a/riscv/insns/fsqrt_d.h b/riscv/insns/fsqrt_d.h index 45f37ce..da138ba 100644 --- a/riscv/insns/fsqrt_d.h +++ b/riscv/insns/fsqrt_d.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f64_sqrt(f64(FRS1)).v); +WRITE_FRD(f64_sqrt(f64(FRS1))); set_fp_exceptions; diff --git a/riscv/insns/fsqrt_s.h b/riscv/insns/fsqrt_s.h index f3b3956..7476846 100644 --- a/riscv/insns/fsqrt_s.h +++ b/riscv/insns/fsqrt_s.h @@ -1,5 +1,5 @@ require_extension('F'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f32_sqrt(f32(FRS1)).v); +WRITE_FRD(f32_sqrt(f32(FRS1))); set_fp_exceptions; diff --git a/riscv/insns/fsub_d.h b/riscv/insns/fsub_d.h index 487743e..1418a06 100644 --- a/riscv/insns/fsub_d.h +++ b/riscv/insns/fsub_d.h @@ -1,5 +1,5 @@ require_extension('D'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f64_sub(f64(FRS1), f64(FRS2)).v); +WRITE_FRD(f64_sub(f64(FRS1), f64(FRS2))); set_fp_exceptions; diff --git a/riscv/insns/fsub_s.h b/riscv/insns/fsub_s.h index e7a7cf1..f6183ea 100644 --- a/riscv/insns/fsub_s.h +++ b/riscv/insns/fsub_s.h @@ -1,5 +1,5 @@ require_extension('F'); require_fp; softfloat_roundingMode = RM; -WRITE_FRD(f32_sub(f32(FRS1), f32(FRS2)).v); +WRITE_FRD(f32_sub(f32(FRS1), f32(FRS2))); set_fp_exceptions; diff --git a/riscv/insns/fsw.h b/riscv/insns/fsw.h index 3135e9b..42fc683 100644 --- a/riscv/insns/fsw.h +++ b/riscv/insns/fsw.h @@ -1,3 +1,3 @@ require_extension('F'); require_fp; -MMU.store_uint32(RS1 + insn.s_imm(), FRS2); +MMU.store_uint32(RS1 + insn.s_imm(), FRS2.v); diff --git a/riscv/insns/mret.h b/riscv/insns/mret.h index fa97b2c..96933cf 100644 --- a/riscv/insns/mret.h +++ b/riscv/insns/mret.h @@ -2,8 +2,8 @@ require_privilege(PRV_M); set_pc_and_serialize(p->get_state()->mepc); reg_t s = STATE.mstatus; reg_t prev_prv = get_field(s, MSTATUS_MPP); -s = set_field(s, MSTATUS_UIE << prev_prv, get_field(s, MSTATUS_MPIE)); -s = set_field(s, MSTATUS_MPIE, 0); +s = set_field(s, MSTATUS_MIE, get_field(s, MSTATUS_MPIE)); +s = set_field(s, MSTATUS_MPIE, 1); s = set_field(s, MSTATUS_MPP, PRV_U); p->set_privilege(prev_prv); p->set_csr(CSR_MSTATUS, s); diff --git a/riscv/insns/sfence_vm.h b/riscv/insns/sfence_vm.h deleted file mode 100644 index 35ff5dd..0000000 --- a/riscv/insns/sfence_vm.h +++ /dev/null @@ -1,2 +0,0 @@ -require_privilege(PRV_S); -MMU.flush_tlb(); diff --git a/riscv/insns/sfence_vma.h b/riscv/insns/sfence_vma.h new file mode 100644 index 0000000..fc4625f --- /dev/null +++ b/riscv/insns/sfence_vma.h @@ -0,0 +1,2 @@ +require_privilege(get_field(STATE.mstatus, MSTATUS_TVM) ? PRV_M : PRV_S); +MMU.flush_tlb(); diff --git a/riscv/insns/sret.h b/riscv/insns/sret.h index f5e89e4..ae841de 100644 --- a/riscv/insns/sret.h +++ b/riscv/insns/sret.h @@ -1,9 +1,9 @@ -require_privilege(PRV_S); +require_privilege(get_field(STATE.mstatus, MSTATUS_TSR) ? PRV_M : PRV_S); set_pc_and_serialize(p->get_state()->sepc); reg_t s = STATE.mstatus; reg_t prev_prv = get_field(s, MSTATUS_SPP); -s = set_field(s, MSTATUS_UIE << prev_prv, get_field(s, MSTATUS_SPIE)); -s = set_field(s, MSTATUS_SPIE, 0); +s = set_field(s, MSTATUS_SIE, get_field(s, MSTATUS_SPIE)); +s = set_field(s, MSTATUS_SPIE, 1); s = set_field(s, MSTATUS_SPP, PRV_U); p->set_privilege(prev_prv); p->set_csr(CSR_MSTATUS, s); diff --git a/riscv/insns/wfi.h b/riscv/insns/wfi.h index 6f037f8..16de594 100644 --- a/riscv/insns/wfi.h +++ b/riscv/insns/wfi.h @@ -1 +1,2 @@ -// nop +require_privilege(get_field(STATE.mstatus, MSTATUS_TW) ? PRV_M : PRV_S); +set_pc_and_serialize(npc); diff --git a/riscv/interactive.cc b/riscv/interactive.cc index 748f454..31b9162 100644 --- a/riscv/interactive.cc +++ b/riscv/interactive.cc @@ -18,12 +18,14 @@ #include #include +DECLARE_TRAP(-1, interactive) + processor_t *sim_t::get_core(const std::string& i) { char *ptr; unsigned long p = strtoul(i.c_str(), &ptr, 10); - if (*ptr || p >= num_cores()) - throw trap_illegal_instruction(); + if (*ptr || p >= procs.size()) + throw trap_interactive(); return get_core(p); } @@ -64,6 +66,7 @@ void sim_t::interactive() funcs["r"] = funcs["run"]; funcs["rs"] = &sim_t::interactive_run_silent; funcs["reg"] = &sim_t::interactive_reg; + funcs["freg"] = &sim_t::interactive_freg; funcs["fregs"] = &sim_t::interactive_fregs; funcs["fregd"] = &sim_t::interactive_fregd; funcs["pc"] = &sim_t::interactive_pc; @@ -161,7 +164,7 @@ void sim_t::interactive_quit(const std::string& cmd, const std::vector& args) { if(args.size() != 1) - throw trap_illegal_instruction(); + throw trap_interactive(); processor_t *p = get_core(args[0]); return p->state.pc; @@ -175,7 +178,7 @@ void sim_t::interactive_pc(const std::string& cmd, const std::vector& args) { if(args.size() != 2) - throw trap_illegal_instruction(); + throw trap_interactive(); processor_t *p = get_core(args[0]); @@ -192,22 +195,22 @@ reg_t sim_t::get_reg(const std::vector& args) } if (r >= NXPR) - throw trap_illegal_instruction(); + throw trap_interactive(); return p->state.XPR[r]; } -reg_t sim_t::get_freg(const std::vector& args) +freg_t sim_t::get_freg(const std::vector& args) { if(args.size() != 2) - throw trap_illegal_instruction(); + throw trap_interactive(); processor_t *p = get_core(args[0]); int r = std::find(fpr_name, fpr_name + NFPR, args[1]) - fpr_name; if (r == NFPR) r = atoi(args[1].c_str()); if (r >= NFPR) - throw trap_illegal_instruction(); + throw trap_interactive(); return p->state.FPR[r]; } @@ -229,11 +232,16 @@ void sim_t::interactive_reg(const std::string& cmd, const std::vector& args) +{ + fprintf(stderr, "0x%016" PRIx64 "\n", get_freg(args).v); +} + void sim_t::interactive_fregs(const std::string& cmd, const std::vector& args) { fpr f; @@ -251,7 +259,7 @@ void sim_t::interactive_fregd(const std::string& cmd, const std::vector& args) { if(args.size() != 1 && args.size() != 2) - throw trap_illegal_instruction(); + throw trap_interactive(); std::string addr_str = args[0]; mmu_t* mmu = debug_mmu; @@ -293,7 +301,7 @@ void sim_t::interactive_mem(const std::string& cmd, const std::vector& args) { if(args.size() != 1) - throw trap_illegal_instruction(); + throw trap_interactive(); reg_t addr = strtol(args[0].c_str(),NULL,16); diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 878d849..8df38e5 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -43,13 +43,7 @@ reg_t mmu_t::translate(reg_t addr, access_type type) if (!proc->state.dcsr.cause && get_field(proc->state.mstatus, MSTATUS_MPRV)) mode = get_field(proc->state.mstatus, MSTATUS_MPP); } - if (get_field(proc->state.mstatus, MSTATUS_VM) == VM_MBARE) - mode = PRV_M; - if (mode == PRV_M) { - reg_t msb_mask = (reg_t(2) << (proc->xlen-1))-1; // zero-extend from xlen - return addr & msb_mask; - } return walk(addr, type, mode) | (addr & (PGSIZE-1)); } @@ -57,12 +51,6 @@ const uint16_t* mmu_t::fetch_slow_path(reg_t vaddr) { reg_t paddr = translate(vaddr, FETCH); - // mmu_t::walk() returns -1 if it can't find a match. Of course -1 could also - // be a valid address. - if (paddr == ~(reg_t) 0 && vaddr != ~(reg_t) 0) { - throw trap_instruction_access_fault(vaddr); - } - if (sim->addr_is_mem(paddr)) { refill_tlb(vaddr, paddr, FETCH); return (const uint16_t*)sim->addr_to_mem(paddr); @@ -169,43 +157,38 @@ void mmu_t::refill_tlb(reg_t vaddr, reg_t paddr, access_type type) reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode) { - int levels, ptidxbits, ptesize; - switch (get_field(proc->get_state()->mstatus, MSTATUS_VM)) - { - case VM_SV32: levels = 2; ptidxbits = 10; ptesize = 4; break; - case VM_SV39: levels = 3; ptidxbits = 9; ptesize = 8; break; - case VM_SV48: levels = 4; ptidxbits = 9; ptesize = 8; break; - default: abort(); - } + vm_info vm = decode_vm_info(proc->max_xlen, mode, proc->get_state()->sptbr); + if (vm.levels == 0) + return addr & ((reg_t(2) << (proc->xlen-1))-1); // zero-extend from xlen bool supervisor = mode == PRV_S; - bool pum = get_field(proc->state.mstatus, MSTATUS_PUM); + bool sum = get_field(proc->state.mstatus, MSTATUS_SUM); bool mxr = get_field(proc->state.mstatus, MSTATUS_MXR); // verify bits xlen-1:va_bits-1 are all equal - int va_bits = PGSHIFT + levels * ptidxbits; + int va_bits = PGSHIFT + vm.levels * vm.idxbits; reg_t mask = (reg_t(1) << (proc->xlen - (va_bits-1))) - 1; reg_t masked_msbs = (addr >> (va_bits-1)) & mask; if (masked_msbs != 0 && masked_msbs != mask) - return -1; + vm.levels = 0; - reg_t base = proc->get_state()->sptbr << PGSHIFT; - int ptshift = (levels - 1) * ptidxbits; - for (int i = 0; i < levels; i++, ptshift -= ptidxbits) { - reg_t idx = (addr >> (PGSHIFT + ptshift)) & ((1 << ptidxbits) - 1); + reg_t base = vm.ptbase; + for (int i = vm.levels - 1; i >= 0; i--) { + int ptshift = i * vm.idxbits; + reg_t idx = (addr >> (PGSHIFT + ptshift)) & ((1 << vm.idxbits) - 1); // check that physical address of PTE is legal - reg_t pte_addr = base + idx * ptesize; + reg_t pte_addr = base + idx * vm.ptesize; if (!sim->addr_is_mem(pte_addr)) - break; + throw trap_load_access_fault(addr); void* ppte = sim->addr_to_mem(pte_addr); - reg_t pte = ptesize == 4 ? *(uint32_t*)ppte : *(uint64_t*)ppte; + reg_t pte = vm.ptesize == 4 ? *(uint32_t*)ppte : *(uint64_t*)ppte; reg_t ppn = pte >> PTE_PPN_SHIFT; if (PTE_TABLE(pte)) { // next level of page table base = ppn << PGSHIFT; - } else if ((pte & PTE_U) ? supervisor && pum : !supervisor) { + } else if ((pte & PTE_U) ? supervisor && !sum : !supervisor) { break; } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) { break; @@ -214,8 +197,15 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode) !((pte & PTE_R) && (pte & PTE_W))) { break; } else { + reg_t ad = PTE_A | ((type == STORE) * PTE_D); +#ifdef RISCV_ENABLE_DIRTY // set accessed and possibly dirty bits. - *(uint32_t*)ppte |= PTE_A | ((type == STORE) * PTE_D); + *(uint32_t*)ppte |= ad; +#else + // take exception if access or possibly dirty bit is not set. + if ((pte & ad) != ad) + break; +#endif // for superpage mappings, make a fake leaf PTE for the TLB's benefit. reg_t vpn = addr >> PGSHIFT; reg_t value = (ppn | (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT; @@ -223,7 +213,13 @@ reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode) } } - return -1; +fail: + switch (type) { + case FETCH: throw trap_instruction_page_fault(addr); + case LOAD: throw trap_load_page_fault(addr); + case STORE: throw trap_store_page_fault(addr); + default: abort(); + } } void mmu_t::register_memtracer(memtracer_t* t) diff --git a/riscv/mmu.h b/riscv/mmu.h index 34bcf99..a8d9675 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -51,11 +51,33 @@ public: mmu_t(sim_t* sim, processor_t* proc); ~mmu_t(); + inline reg_t misaligned_load(reg_t addr, size_t size) + { +#ifdef RISCV_ENABLE_MISALIGNED + reg_t res = 0; + for (size_t i = 0; i < size; i++) + res += (reg_t)load_uint8(addr + i) << (i * 8); + return res; +#else + throw trap_load_address_misaligned(addr); +#endif + } + + inline void misaligned_store(reg_t addr, reg_t data, size_t size) + { +#ifdef RISCV_ENABLE_MISALIGNED + for (size_t i = 0; i < size; i++) + store_uint8(addr + i, data >> (i * 8)); +#else + throw trap_store_address_misaligned(addr); +#endif + } + // template for functions that load an aligned value from memory #define load_func(type) \ inline type##_t load_##type(reg_t addr) { \ - if (addr & (sizeof(type##_t)-1)) \ - throw trap_load_address_misaligned(addr); \ + if (unlikely(addr & (sizeof(type##_t)-1))) \ + return misaligned_load(addr, sizeof(type##_t)); \ reg_t vpn = addr >> PGSHIFT; \ if (likely(tlb_load_tag[vpn % TLB_ENTRIES] == vpn)) \ return *(type##_t*)(tlb_data[vpn % TLB_ENTRIES] + addr); \ @@ -88,8 +110,8 @@ public: // template for functions that store an aligned value to memory #define store_func(type) \ void store_##type(reg_t addr, type##_t val) { \ - if (addr & (sizeof(type##_t)-1)) \ - throw trap_store_address_misaligned(addr); \ + if (unlikely(addr & (sizeof(type##_t)-1))) \ + return misaligned_store(addr, val, sizeof(type##_t)); \ reg_t vpn = addr >> PGSHIFT; \ if (likely(tlb_store_tag[vpn % TLB_ENTRIES] == vpn)) \ *(type##_t*)(tlb_data[vpn % TLB_ENTRIES] + addr) = val; \ @@ -115,6 +137,9 @@ public: auto lhs = load_##type(addr); \ store_##type(addr, f(lhs)); \ return lhs; \ + } catch (trap_load_page_fault& t) { \ + /* AMO faults should be reported as store faults */ \ + throw trap_store_page_fault(t.get_badaddr()); \ } catch (trap_load_access_fault& t) { \ /* AMO faults should be reported as store faults */ \ throw trap_store_access_fault(t.get_badaddr()); \ @@ -260,4 +285,35 @@ private: friend class processor_t; }; +struct vm_info { + int levels; + int idxbits; + int ptesize; + reg_t ptbase; +}; + +inline vm_info decode_vm_info(int xlen, reg_t prv, reg_t sptbr) +{ + if (prv == PRV_M) { + return {0, 0, 0, 0}; + } else if (prv <= PRV_S && xlen == 32) { + switch (get_field(sptbr, SPTBR32_MODE)) { + case SPTBR_MODE_OFF: return {0, 0, 0, 0}; + case SPTBR_MODE_SV32: return {2, 10, 4, (sptbr & SPTBR32_PPN) << PGSHIFT}; + default: abort(); + } + } else if (prv <= PRV_S && xlen == 64) { + switch (get_field(sptbr, SPTBR64_MODE)) { + case SPTBR_MODE_OFF: return {0, 0, 0, 0}; + case SPTBR_MODE_SV39: return {3, 9, 8, (sptbr & SPTBR64_PPN) << PGSHIFT}; + case SPTBR_MODE_SV48: return {4, 9, 8, (sptbr & SPTBR64_PPN) << PGSHIFT}; + case SPTBR_MODE_SV57: return {5, 9, 8, (sptbr & SPTBR64_PPN) << PGSHIFT}; + case SPTBR_MODE_SV64: return {6, 9, 8, (sptbr & SPTBR64_PPN) << PGSHIFT}; + default: abort(); + } + } else { + abort(); + } +} + #endif diff --git a/riscv/processor.cc b/riscv/processor.cc index 58837d1..ef529fc 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -118,7 +118,6 @@ void state_t::reset() memset(this, 0, sizeof(*this)); prv = PRV_M; pc = DEFAULT_RSTVEC; - mtvec = DEFAULT_MTVEC; load_reservation = -1; tselect = 0; for (unsigned int i = 0; i < num_triggers; i++) @@ -154,11 +153,6 @@ void processor_t::reset() ext->reset(); // reset the extension } -void processor_t::raise_interrupt(reg_t which) -{ - throw trap_t(((reg_t)1 << (max_xlen-1)) | which); -} - // Count number of contiguous 0 bits starting from the LSB. static int ctz(reg_t val) { @@ -169,20 +163,19 @@ static int ctz(reg_t val) return res; } -void processor_t::take_interrupt() +void processor_t::take_interrupt(reg_t pending_interrupts) { - reg_t pending_interrupts = state.mip & state.mie; - reg_t mie = get_field(state.mstatus, MSTATUS_MIE); reg_t m_enabled = state.prv < PRV_M || (state.prv == PRV_M && mie); reg_t enabled_interrupts = pending_interrupts & ~state.mideleg & -m_enabled; reg_t sie = get_field(state.mstatus, MSTATUS_SIE); reg_t s_enabled = state.prv < PRV_S || (state.prv == PRV_S && sie); - enabled_interrupts |= pending_interrupts & state.mideleg & -s_enabled; + if (enabled_interrupts == 0) + enabled_interrupts = pending_interrupts & state.mideleg & -s_enabled; if (enabled_interrupts) - raise_interrupt(ctz(enabled_interrupts)); + throw trap_t(((reg_t)1 << (max_xlen-1)) | ctz(enabled_interrupts)); } void processor_t::set_privilege(reg_t prv) @@ -234,7 +227,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc) // by default, trap to M-mode, unless delegated to S-mode reg_t bit = t.cause(); reg_t deleg = state.medeleg; - if (bit & ((reg_t)1 << (max_xlen-1))) + bool interrupt = (bit & ((reg_t)1 << (max_xlen-1))) != 0; + if (interrupt) deleg = state.mideleg, bit &= ~((reg_t)1 << (max_xlen-1)); if (state.prv <= PRV_S && bit < max_xlen && ((deleg >> bit) & 1)) { // handle the trap in S-mode @@ -245,20 +239,21 @@ void processor_t::take_trap(trap_t& t, reg_t epc) state.sbadaddr = t.get_badaddr(); reg_t s = state.mstatus; - s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_UIE << state.prv)); + s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_SIE)); s = set_field(s, MSTATUS_SPP, state.prv); s = set_field(s, MSTATUS_SIE, 0); set_csr(CSR_MSTATUS, s); set_privilege(PRV_S); } else { - state.pc = state.mtvec; + reg_t vector = (state.mtvec & 1) && interrupt ? 4*bit : 0; + state.pc = (state.mtvec & ~(reg_t)1) + vector; state.mepc = epc; state.mcause = t.cause(); if (t.has_badaddr()) state.mbadaddr = t.get_badaddr(); reg_t s = state.mstatus; - s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_UIE << state.prv)); + s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE)); s = set_field(s, MSTATUS_MPP, state.prv); s = set_field(s, MSTATUS_MIE, 0); set_csr(CSR_MSTATUS, s); @@ -289,15 +284,6 @@ void processor_t::disasm(insn_t insn) } } -static bool validate_vm(int max_xlen, reg_t vm) -{ - if (max_xlen == 64 && (vm == VM_SV39 || vm == VM_SV48)) - return true; - if (max_xlen == 32 && vm == VM_SV32) - return true; - return vm == VM_MBARE; -} - int processor_t::paddr_bits() { assert(xlen == max_xlen); @@ -326,15 +312,13 @@ void processor_t::set_csr(int which, reg_t val) break; case CSR_MSTATUS: { if ((val ^ state.mstatus) & - (MSTATUS_VM | MSTATUS_MPP | MSTATUS_MPRV | MSTATUS_PUM | MSTATUS_MXR)) + (MSTATUS_MPP | MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_MXR)) mmu->flush_tlb(); reg_t mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE - | MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_PUM - | MSTATUS_MPP | MSTATUS_MXR | (ext ? MSTATUS_XS : 0); - - if (validate_vm(max_xlen, get_field(val, MSTATUS_VM))) - mask |= MSTATUS_VM; + | MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM + | MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TW | MSTATUS_TVM + | MSTATUS_TSR | (ext ? MSTATUS_XS : 0); state.mstatus = (state.mstatus & ~mask) | (val & mask); @@ -380,15 +364,15 @@ void processor_t::set_csr(int which, reg_t val) case CSR_MCYCLEH: state.minstret = (val << 32) | (state.minstret << 32 >> 32); break; - case CSR_MUCOUNTEREN: - state.mucounteren = val; + case CSR_SCOUNTEREN: + state.scounteren = val; break; - case CSR_MSCOUNTEREN: - state.mscounteren = val; + case CSR_MCOUNTEREN: + state.mcounteren = val; break; case CSR_SSTATUS: { reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS - | SSTATUS_XS | SSTATUS_PUM; + | SSTATUS_XS | SSTATUS_SUM | SSTATUS_MXR; return set_csr(CSR_MSTATUS, (state.mstatus & ~mask) | (val & mask)); } case CSR_SIP: { @@ -399,8 +383,13 @@ void processor_t::set_csr(int which, reg_t val) return set_csr(CSR_MIE, (state.mie & ~state.mideleg) | (val & state.mideleg)); case CSR_SPTBR: { - // upper bits of sptbr are the ASID; we only support ASID = 0 - state.sptbr = val & (((reg_t)1 << (paddr_bits() - PGSHIFT)) - 1); + mmu->flush_tlb(); + if (max_xlen == 32) + state.sptbr = val & (SPTBR32_PPN | SPTBR32_MODE); + if (max_xlen == 64 && (get_field(val, SPTBR64_MODE) == SPTBR_MODE_OFF || + get_field(val, SPTBR64_MODE) == SPTBR_MODE_SV39 || + get_field(val, SPTBR64_MODE) == SPTBR_MODE_SV48)) + state.sptbr = val & (SPTBR64_PPN | SPTBR64_MODE); break; } case CSR_SEPC: state.sepc = val; break; @@ -409,7 +398,7 @@ void processor_t::set_csr(int which, reg_t val) case CSR_SCAUSE: state.scause = val; break; case CSR_SBADADDR: state.sbadaddr = val; break; case CSR_MEPC: state.mepc = val; break; - case CSR_MTVEC: state.mtvec = val >> 2 << 2; break; + case CSR_MTVEC: state.mtvec = val & ~(reg_t)2; break; case CSR_MSCRATCH: state.mscratch = val; break; case CSR_MCAUSE: state.mcause = val; break; case CSR_MBADADDR: state.mbadaddr = val; break; @@ -488,8 +477,11 @@ void processor_t::set_csr(int which, reg_t val) reg_t processor_t::get_csr(int which) { - reg_t ctr_en = state.prv == PRV_U ? state.mucounteren : - state.prv == PRV_S ? state.mscounteren : -1U; + uint32_t ctr_en = -1; + if (state.prv < PRV_M) + ctr_en &= state.mcounteren; + if (state.prv < PRV_S) + ctr_en &= state.scounteren; bool ctr_ok = (ctr_en >> (which & 31)) & 1; if (ctr_ok) { @@ -500,7 +492,7 @@ reg_t processor_t::get_csr(int which) } if (which >= CSR_MHPMCOUNTER3 && which <= CSR_MHPMCOUNTER31) return 0; - if (xlen == 32 && which >= CSR_MHPMCOUNTER3 && which <= CSR_MHPMCOUNTER31) + if (xlen == 32 && which >= CSR_MHPMCOUNTER3H && which <= CSR_MHPMCOUNTER31H) return 0; if (which >= CSR_MHPMEVENT3 && which <= CSR_MHPMEVENT31) return 0; @@ -535,11 +527,11 @@ reg_t processor_t::get_csr(int which) if (xlen == 32) return state.minstret >> 32; break; - case CSR_MUCOUNTEREN: return state.mucounteren; - case CSR_MSCOUNTEREN: return state.mscounteren; + case CSR_SCOUNTEREN: return state.scounteren; + case CSR_MCOUNTEREN: return state.mcounteren; case CSR_SSTATUS: { reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS - | SSTATUS_XS | SSTATUS_PUM; + | SSTATUS_XS | SSTATUS_SUM; reg_t sstatus = state.mstatus & mask; if ((sstatus & SSTATUS_FS) == SSTATUS_FS || (sstatus & SSTATUS_XS) == SSTATUS_XS) @@ -555,7 +547,10 @@ reg_t processor_t::get_csr(int which) if (max_xlen > xlen) return state.scause | ((state.scause >> (max_xlen-1)) << (xlen-1)); return state.scause; - case CSR_SPTBR: return state.sptbr; + case CSR_SPTBR: + if (get_field(state.mstatus, MSTATUS_TVM)) + require_privilege(PRV_M); + return state.sptbr; case CSR_SSCRATCH: return state.sscratch; case CSR_MSTATUS: return state.mstatus; case CSR_MIP: return state.mip; @@ -625,12 +620,12 @@ reg_t processor_t::get_csr(int which) case CSR_DSCRATCH: return state.dscratch; } - throw trap_illegal_instruction(); + throw trap_illegal_instruction(0); } reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc) { - throw trap_illegal_instruction(); + throw trap_illegal_instruction(0); } insn_func_t processor_t::decode_insn(insn_t insn) @@ -713,6 +708,17 @@ void processor_t::register_base_instructions() bool processor_t::load(reg_t addr, size_t len, uint8_t* bytes) { + switch (addr) + { + case 0: + if (len <= 4) { + memset(bytes, 0, len); + bytes[0] = get_field(state.mip, MIP_MSIP); + return true; + } + break; + } + return false; } @@ -721,14 +727,14 @@ bool processor_t::store(reg_t addr, size_t len, const uint8_t* bytes) switch (addr) { case 0: - state.mip &= ~MIP_MSIP; - if (bytes[0] & 1) - state.mip |= MIP_MSIP; - return true; - - default: - return false; + if (len <= 4) { + state.mip = set_field(state.mip, MIP_MSIP, bytes[0]); + return true; + } + break; } + + return false; } void processor_t::trigger_updated() diff --git a/riscv/processor.h b/riscv/processor.h index 3268029..4d94d5b 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -105,8 +105,8 @@ struct state_t reg_t mip; reg_t medeleg; reg_t mideleg; - uint32_t mucounteren; - uint32_t mscounteren; + uint32_t mcounteren; + uint32_t scounteren; reg_t sepc; reg_t sbadaddr; reg_t sscratch; @@ -167,7 +167,6 @@ public: void reset(); void step(size_t n); // run for n cycles void set_csr(int which, reg_t val); - void raise_interrupt(reg_t which); reg_t get_csr(int which); mmu_t* get_mmu() { return mmu; } state_t* get_state() { return &state; } @@ -304,8 +303,8 @@ private: static const size_t OPCODE_CACHE_SIZE = 8191; insn_desc_t opcode_cache[OPCODE_CACHE_SIZE]; - void check_timer(); - void take_interrupt(); // take a trap if any interrupts are pending + void take_pending_interrupt() { take_interrupt(state.mip & state.mie); } + void take_interrupt(reg_t mask); // take first enabled interrupt in mask void take_trap(trap_t& t, reg_t epc); // take an exception void disasm(insn_t insn); // disassemble and print an instruction int paddr_bits(); @@ -314,7 +313,7 @@ private: friend class sim_t; friend class mmu_t; - friend class rtc_t; + friend class clint_t; friend class extension_t; void parse_isa_string(const char* isa); diff --git a/riscv/riscv.ac b/riscv/riscv.ac index 7b48be6..68bcdb5 100644 --- a/riscv/riscv.ac +++ b/riscv/riscv.ac @@ -32,3 +32,13 @@ AC_ARG_ENABLE([histogram], AS_HELP_STRING([--enable-histogram], [Enable PC histo AS_IF([test "x$enable_histogram" = "xyes"], [ AC_DEFINE([RISCV_ENABLE_HISTOGRAM],,[Enable PC histogram generation]) ]) + +AC_ARG_ENABLE([dirty], AS_HELP_STRING([--enable-dirty], [Enable hardware management of PTE accessed and dirty bits])) +AS_IF([test "x$enable_dirty" = "xyes"], [ + AC_DEFINE([RISCV_ENABLE_DIRTY],,[Enable hardware management of PTE accessed and dirty bits]) +]) + +AC_ARG_ENABLE([misaligned], AS_HELP_STRING([--enable-misaligned], [Enable hardware support for misaligned loads and stores])) +AS_IF([test "x$enable_misaligned" = "xyes"], [ + AC_DEFINE([RISCV_ENABLE_MISALIGNED],,[Enable hardware support for misaligned loads and stores]) +]) diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 6f12b84..9cd8f4d 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -46,6 +46,8 @@ riscv_srcs = \ devices.cc \ rom.cc \ rtc.cc \ + clint.cc \ + gdbserver.cc \ debug_module.cc \ remote_bitbang.cc \ jtag_dtm.cc \ @@ -229,7 +231,7 @@ riscv_insn_list = \ sc_d \ sc_w \ sd \ - sfence_vm \ + sfence_vma \ sh \ sll \ slli \ diff --git a/riscv/rtc.cc b/riscv/rtc.cc deleted file mode 100644 index 22f318c..0000000 --- a/riscv/rtc.cc +++ /dev/null @@ -1,34 +0,0 @@ -#include "devices.h" -#include "processor.h" - -rtc_t::rtc_t(std::vector& procs) - : procs(procs), regs(1 + procs.size()) -{ -} - -bool rtc_t::load(reg_t addr, size_t len, uint8_t* bytes) -{ - if (addr + len > size()) - return false; - memcpy(bytes, (uint8_t*)®s[0] + addr, len); - return true; -} - -bool rtc_t::store(reg_t addr, size_t len, const uint8_t* bytes) -{ - if (addr + len > size() || addr < 8) - return false; - memcpy((uint8_t*)®s[0] + addr, bytes, len); - increment(0); - return true; -} - -void rtc_t::increment(reg_t inc) -{ - regs[0] += inc; - for (size_t i = 0; i < procs.size(); i++) { - procs[i]->state.mip &= ~MIP_MTIP; - if (regs[0] >= regs[1+i]) - procs[i]->state.mip |= MIP_MTIP; - } -} diff --git a/riscv/sim.cc b/riscv/sim.cc index 033f12b..a44ced6 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include volatile bool ctrlc_pressed = false; static void handle_signal(int sig) @@ -31,7 +34,7 @@ sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, bool halted, size_t memsz0 = (size_t)mem_mb << 20; size_t quantum = 1L << 20; if (memsz0 == 0) - memsz0 = (size_t)((sizeof(size_t) == 8 ? 4096 : 2048) - 256) << 20; + memsz0 = (size_t)2048 << 20; memsz = memsz0; while ((mem = (char*)calloc(1, memsz)) == NULL) @@ -49,8 +52,10 @@ sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, bool halted, procs[i] = new processor_t(isa, this, i, halted); } - rtc.reset(new rtc_t(procs)); - make_config_string(); + clint.reset(new clint_t(procs)); + bus.add_device(CLINT_BASE, clint.get()); + + make_dtb(); } sim_t::~sim_t() @@ -104,7 +109,7 @@ void sim_t::step(size_t n) procs[current_proc]->yield_load_reservation(); if (++current_proc == procs.size()) { current_proc = 0; - rtc->increment(INTERLEAVE / INSNS_PER_RTC_TICK); + clint->increment(INTERLEAVE / INSNS_PER_RTC_TICK); } host->switch_to(); @@ -150,59 +155,162 @@ bool sim_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes) return bus.store(addr, len, bytes); } -void sim_t::make_config_string() +static std::string dts_compile(const std::string& dts) { - reg_t rtc_addr = EXT_IO_BASE; - bus.add_device(rtc_addr, rtc.get()); + // Convert the DTS to DTB + int dts_pipe[2]; + pid_t dts_pid; - const int align = 0x1000; - reg_t cpu_addr = rtc_addr + ((rtc->size() - 1) / align + 1) * align; - reg_t cpu_size = align; - - uint32_t reset_vec[8] = { - 0x297 + DRAM_BASE - DEFAULT_RSTVEC, // reset vector - 0x00028067, // jump straight to DRAM_BASE - 0x00000000, // reserved - 0, // config string pointer - 0, 0, 0, 0 // trap vector + if (pipe(dts_pipe) != 0 || (dts_pid = fork()) < 0) { + std::cerr << "Failed to fork dts child: " << strerror(errno) << std::endl; + exit(1); + } + + // Child process to output dts + if (dts_pid == 0) { + close(dts_pipe[0]); + int step, len = dts.length(); + const char *buf = dts.c_str(); + for (int done = 0; done < len; done += step) { + step = write(dts_pipe[1], buf+done, len-done); + if (step == -1) { + std::cerr << "Failed to write dts: " << strerror(errno) << std::endl; + exit(1); + } + } + close(dts_pipe[1]); + exit(0); + } + + pid_t dtb_pid; + int dtb_pipe[2]; + if (pipe(dtb_pipe) != 0 || (dtb_pid = fork()) < 0) { + std::cerr << "Failed to fork dtb child: " << strerror(errno) << std::endl; + exit(1); + } + + // Child process to output dtb + if (dtb_pid == 0) { + dup2(dts_pipe[0], 0); + dup2(dtb_pipe[1], 1); + close(dts_pipe[0]); + close(dts_pipe[1]); + close(dtb_pipe[0]); + close(dtb_pipe[1]); + execl(DTC, DTC, "-O", "dtb", 0); + std::cerr << "Failed to run " DTC ": " << strerror(errno) << std::endl; + exit(1); + } + + close(dts_pipe[1]); + close(dts_pipe[0]); + close(dtb_pipe[1]); + + // Read-out dtb + std::stringstream dtb; + + int got; + char buf[4096]; + while ((got = read(dtb_pipe[0], buf, sizeof(buf))) > 0) { + dtb.write(buf, got); + } + if (got == -1) { + std::cerr << "Failed to read dtb: " << strerror(errno) << std::endl; + exit(1); + } + close(dtb_pipe[0]); + + // Reap children + int status; + waitpid(dts_pid, &status, 0); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + std::cerr << "Child dts process failed" << std::endl; + exit(1); + } + waitpid(dtb_pid, &status, 0); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + std::cerr << "Child dtb process failed" << std::endl; + exit(1); + } + + return dtb.str(); +} + +void sim_t::make_dtb() +{ + uint32_t reset_vec[] = { + 0x297 + DRAM_BASE - DEFAULT_RSTVEC, // auipc t0, DRAM_BASE + 0x597, // auipc a1, 0 + 0x58593, // addi a1, a1, 0 + 0xf1402573, // csrr a0,mhartid + 0x00028067 // jalr zero, t0, 0 (jump straight to DRAM_BASE) }; - reset_vec[3] = DEFAULT_RSTVEC + sizeof(reset_vec); // config string pointer + reset_vec[2] += (sizeof(reset_vec) - 4) << 20; // addi a1, a1, sizeof(reset_vec) - 4 = DTB start std::vector rom((char*)reset_vec, (char*)reset_vec + sizeof(reset_vec)); std::stringstream s; - s << std::hex << - "platform {\n" - " vendor ucb;\n" - " arch spike;\n" - "};\n" - "rtc {\n" - " addr 0x" << rtc_addr << ";\n" - "};\n" - "ram {\n" - " 0 {\n" - " addr 0x" << DRAM_BASE << ";\n" - " size 0x" << memsz << ";\n" - " };\n" - "};\n" - "core {\n"; + s << std::dec << + "/dts-v1/;\n" + "\n" + "/ {\n" + " #address-cells = <2>;\n" + " #size-cells = <2>;\n" + " compatible = \"ucbbar,spike-bare-dev\";\n" + " model = \"ucbbar,spike-bare\";\n" + " cpus {\n" + " #address-cells = <1>;\n" + " #size-cells = <0>;\n" + " timebase-frequency = <" << (CPU_HZ/INSNS_PER_RTC_TICK) << ">;\n"; for (size_t i = 0; i < procs.size(); i++) { - s << - " " << i << " {\n" - " " << "0 {\n" << // hart 0 on core i - " isa " << procs[i]->isa_string << ";\n" - " timecmp 0x" << (rtc_addr + 8*(1+i)) << ";\n" - " ipi 0x" << cpu_addr << ";\n" - " };\n" - " };\n"; - bus.add_device(cpu_addr, procs[i]); - cpu_addr += cpu_size; + s << " CPU" << i << ": cpu@" << i << " {\n" + " device_type = \"cpu\";\n" + " reg = <" << i << ">;\n" + " status = \"okay\";\n" + " compatible = \"riscv\";\n" + " riscv,isa = \"" << procs[i]->isa_string << "\";\n" + " mmu-type = \"riscv," << (procs[i]->max_xlen <= 32 ? "sv32" : "sv48") << "\";\n" + " clock-frequency = <" << CPU_HZ << ">;\n" + " CPU" << i << "_intc: interrupt-controller {\n" + " #interrupt-cells = <1>;\n" + " interrupt-controller;\n" + " compatible = \"riscv,cpu-intc\";\n" + " };\n" + " };\n"; } - s << "};\n"; - - config_string = s.str(); - rom.insert(rom.end(), config_string.begin(), config_string.end()); - rom.resize((rom.size() / align + 1) * align); + reg_t membs = DRAM_BASE; + s << std::hex << + " };\n" + " memory@" << DRAM_BASE << " {\n" + " device_type = \"memory\";\n" + " reg = <0x" << (membs >> 32) << " 0x" << (membs & (uint32_t)-1) << + " 0x" << (memsz >> 32) << " 0x" << (memsz & (uint32_t)-1) << ">;\n" + " };\n" + " soc {\n" + " #address-cells = <2>;\n" + " #size-cells = <2>;\n" + " compatible = \"ucbbar,spike-bare-soc\", \"simple-bus\";\n" + " ranges;\n" + " clint@" << CLINT_BASE << " {\n" + " compatible = \"riscv,clint0\";\n" + " interrupts-extended = <" << std::dec; + for (size_t i = 0; i < procs.size(); i++) + s << "&CPU" << i << "_intc 3 &CPU" << i << "_intc 7 "; + reg_t clintbs = CLINT_BASE; + reg_t clintsz = CLINT_SIZE; + s << std::hex << ">;\n" + " reg = <0x" << (clintbs >> 32) << " 0x" << (clintbs & (uint32_t)-1) << + " 0x" << (clintsz >> 32) << " 0x" << (clintsz & (uint32_t)-1) << ">;\n" + " };\n" + " };\n" + "};\n"; + + dts = s.str(); + std::string dtb = dts_compile(dts); + + rom.insert(rom.end(), dtb.begin(), dtb.end()); + const int align = 0x1000; + rom.resize((rom.size() + align - 1) / align * align); boot_rom.reset(new rom_device_t(rom)); bus.add_device(DEFAULT_RSTVEC, boot_rom.get()); diff --git a/riscv/sim.h b/riscv/sim.h index 4cb70b4..d3353a1 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -32,7 +32,7 @@ public: void set_remote_bitbang(remote_bitbang_t* remote_bitbang) { this->remote_bitbang = remote_bitbang; } - const char* get_config_string() { return config_string.c_str(); } + const char* get_dts() { return dts.c_str(); } processor_t* get_core(size_t i) { return procs.at(i); } unsigned nprocs() const { return procs.size(); } @@ -43,15 +43,16 @@ private: size_t memsz; // memory size in bytes mmu_t* debug_mmu; // debug port into main memory std::vector procs; - std::string config_string; + std::string dts; std::unique_ptr boot_rom; - std::unique_ptr rtc; + std::unique_ptr clint; bus_t bus; processor_t* get_core(const std::string& i); void step(size_t n); // step through simulation static const size_t INTERLEAVE = 5000; static const size_t INSNS_PER_RTC_TICK = 100; // 10 MHz clock for 1 BIPS core + static const size_t CPU_HZ = 1000000000; // 1GHz CPU size_t current_step; size_t current_proc; bool debug; @@ -67,7 +68,7 @@ private: reg_t mem_to_addr(char* x) { return x - mem + DRAM_BASE; } bool mmio_load(reg_t addr, size_t len, uint8_t* bytes); bool mmio_store(reg_t addr, size_t len, const uint8_t* bytes); - void make_config_string(); + void make_dtb(); // presents a prompt for introspection into the simulation void interactive(); @@ -79,6 +80,7 @@ private: void interactive_run_noisy(const std::string& cmd, const std::vector& args); void interactive_run_silent(const std::string& cmd, const std::vector& args); void interactive_reg(const std::string& cmd, const std::vector& args); + void interactive_freg(const std::string& cmd, const std::vector& args); void interactive_fregs(const std::string& cmd, const std::vector& args); void interactive_fregd(const std::string& cmd, const std::vector& args); void interactive_pc(const std::string& cmd, const std::vector& args); @@ -86,7 +88,7 @@ private: void interactive_str(const std::string& cmd, const std::vector& args); void interactive_until(const std::string& cmd, const std::vector& args); reg_t get_reg(const std::vector& args); - reg_t get_freg(const std::vector& args); + freg_t get_freg(const std::vector& args); reg_t get_mem(const std::vector& args); reg_t get_pc(const std::vector& args); diff --git a/riscv/trap.h b/riscv/trap.h index 7f35c5f..91e5223 100644 --- a/riscv/trap.h +++ b/riscv/trap.h @@ -45,16 +45,19 @@ class mem_trap_t : public trap_t }; DECLARE_MEM_TRAP(CAUSE_MISALIGNED_FETCH, instruction_address_misaligned) -DECLARE_MEM_TRAP(CAUSE_FAULT_FETCH, instruction_access_fault) -DECLARE_TRAP(CAUSE_ILLEGAL_INSTRUCTION, illegal_instruction) -DECLARE_TRAP(CAUSE_BREAKPOINT, breakpoint) +DECLARE_MEM_TRAP(CAUSE_FETCH_ACCESS, instruction_access_fault) +DECLARE_MEM_TRAP(CAUSE_ILLEGAL_INSTRUCTION, illegal_instruction) +DECLARE_MEM_TRAP(CAUSE_BREAKPOINT, breakpoint) DECLARE_MEM_TRAP(CAUSE_MISALIGNED_LOAD, load_address_misaligned) DECLARE_MEM_TRAP(CAUSE_MISALIGNED_STORE, store_address_misaligned) -DECLARE_MEM_TRAP(CAUSE_FAULT_LOAD, load_access_fault) -DECLARE_MEM_TRAP(CAUSE_FAULT_STORE, store_access_fault) +DECLARE_MEM_TRAP(CAUSE_LOAD_ACCESS, load_access_fault) +DECLARE_MEM_TRAP(CAUSE_STORE_ACCESS, store_access_fault) DECLARE_TRAP(CAUSE_USER_ECALL, user_ecall) DECLARE_TRAP(CAUSE_SUPERVISOR_ECALL, supervisor_ecall) DECLARE_TRAP(CAUSE_HYPERVISOR_ECALL, hypervisor_ecall) DECLARE_TRAP(CAUSE_MACHINE_ECALL, machine_ecall) +DECLARE_MEM_TRAP(CAUSE_FETCH_PAGE_FAULT, instruction_page_fault) +DECLARE_MEM_TRAP(CAUSE_LOAD_PAGE_FAULT, load_page_fault) +DECLARE_MEM_TRAP(CAUSE_STORE_PAGE_FAULT, store_page_fault) #endif diff --git a/spike_main/spike.cc b/spike_main/spike.cc index 846b1d9..38529b2 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -31,7 +31,7 @@ static void help() fprintf(stderr, " --extension= Specify RoCC Extension\n"); fprintf(stderr, " --extlib= Shared library to load\n"); fprintf(stderr, " --rbb-port= Listen on for remote bitbang connection\n"); - fprintf(stderr, " --dump-config-string Print platform configuration string and exit\n"); + fprintf(stderr, " --dump-dts Print device tree string and exit\n"); exit(1); } @@ -41,7 +41,7 @@ int main(int argc, char** argv) bool halted = false; bool histogram = false; bool log = false; - bool dump_config_string = false; + bool dump_dts = false; size_t nprocs = 1; size_t mem_mb = 0; std::unique_ptr ic; @@ -68,7 +68,7 @@ int main(int argc, char** argv) parser.option(0, "l2", 1, [&](const char* s){l2.reset(cache_sim_t::construct(s, "L2$"));}); parser.option(0, "isa", 1, [&](const char* s){isa = s;}); parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);}); - parser.option(0, "dump-config-string", 0, [&](const char *s){dump_config_string = true;}); + parser.option(0, "dump-dts", 0, [&](const char *s){dump_dts = true;}); parser.option(0, "extlib", 1, [&](const char *s){ void *lib = dlopen(s, RTLD_NOW | RTLD_GLOBAL); if (lib == NULL) { @@ -87,8 +87,8 @@ int main(int argc, char** argv) s.set_remote_bitbang(&(*remote_bitbang)); } - if (dump_config_string) { - printf("%s", s.get_config_string()); + if (dump_dts) { + printf("%s", s.get_dts()); return 0; }