diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2015-03-12 17:32:43 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2015-03-12 17:32:43 -0700 |
commit | ea58df801f36605b462783a61b5266bdd9a40eb0 (patch) | |
tree | ec6c4736f29e9f2021a9e448946e0a0169639cc1 | |
parent | 9af855a28e7dc4009ad31312840ca6f9396d572e (diff) | |
download | spike-ea58df801f36605b462783a61b5266bdd9a40eb0.zip spike-ea58df801f36605b462783a61b5266bdd9a40eb0.tar.gz spike-ea58df801f36605b462783a61b5266bdd9a40eb0.tar.bz2 |
Update to new privileged spec
Sorry, everyone.
74 files changed, 589 insertions, 430 deletions
diff --git a/hwacha/decode_hwacha.h b/hwacha/decode_hwacha.h index 5e85bf6..b00c6af 100644 --- a/hwacha/decode_hwacha.h +++ b/hwacha/decode_hwacha.h @@ -99,7 +99,7 @@ static inline void write_fpr(hwacha_t* h, insn_t insn, uint32_t idx, size_t dst, } #define require_supervisor_hwacha \ - if (unlikely(!(p->get_state()->sr & SR_S))) \ + if (get_field(p->get_state()->mstatus, MSTATUS_PRV) < PRV_S) \ h->take_exception(HWACHA_CAUSE_PRIVILEGED_INSTRUCTION, uint32_t(insn.bits())); #endif diff --git a/hwacha/hwacha.cc b/hwacha/hwacha.cc index a56db12..972e151 100644 --- a/hwacha/hwacha.cc +++ b/hwacha/hwacha.cc @@ -20,9 +20,7 @@ void ct_state_t::reset() void ut_state_t::reset() { - run = false; - XPR.reset(); - FPR.reset(); + memset(this, 0, sizeof(*this)); } void hwacha_t::reset() @@ -105,7 +103,5 @@ void hwacha_t::take_exception(reg_t c, reg_t a) cause = c; aux = a; raise_interrupt(); - if (!(p->get_state()->sr & SR_EI)) - throw std::logic_error("hwacha exception posted, but SR_EI bit not set!"); - throw std::logic_error("hwacha exception posted, but IM[COP] bit not set!"); + throw std::logic_error("a hwacha exception was posted, but interrupts are disabled!"); } diff --git a/hwacha/insns_ut/ut_fcvt_h_l.h b/hwacha/insns_ut/ut_fcvt_h_l.h index fe75c27..69f39ec 100644 --- a/hwacha/insns_ut/ut_fcvt_h_l.h +++ b/hwacha/insns_ut/ut_fcvt_h_l.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; require_fp; softfloat_roundingMode = RM; WRITE_HFRD(i64_to_f32(RS1)); diff --git a/hwacha/insns_ut/ut_fcvt_h_lu.h b/hwacha/insns_ut/ut_fcvt_h_lu.h index 38fc8a7..ab74977 100644 --- a/hwacha/insns_ut/ut_fcvt_h_lu.h +++ b/hwacha/insns_ut/ut_fcvt_h_lu.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; require_fp; softfloat_roundingMode = RM; WRITE_HFRD(ui64_to_f32(RS1)); diff --git a/hwacha/insns_ut/ut_fcvt_l_h.h b/hwacha/insns_ut/ut_fcvt_l_h.h index 1551ce2..d3128d6 100644 --- a/hwacha/insns_ut/ut_fcvt_l_h.h +++ b/hwacha/insns_ut/ut_fcvt_l_h.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; require_fp; softfloat_roundingMode = RM; WRITE_RD(f32_to_i64(HFRS1, RM, true)); diff --git a/hwacha/insns_ut/ut_fcvt_lu_h.h b/hwacha/insns_ut/ut_fcvt_lu_h.h index b2fc5fd..a1cedea 100644 --- a/hwacha/insns_ut/ut_fcvt_lu_h.h +++ b/hwacha/insns_ut/ut_fcvt_lu_h.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; require_fp; softfloat_roundingMode = RM; WRITE_RD(f32_to_ui64(HFRS1, RM, true)); diff --git a/riscv/decode.h b/riscv/decode.h index 6ac465a..2fdb042 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -9,6 +9,7 @@ #include <cstdint> #include <string.h> +#include <strings.h> #include "encoding.h" #include "config.h" #include "common.h" @@ -80,10 +81,6 @@ template <class T, size_t N, bool zero_reg> class regfile_t { public: - void reset() - { - memset(data, 0, sizeof(data)); - } void write(size_t i, T value) { if (!zero_reg || i != 0) @@ -116,14 +113,17 @@ private: #define FRS1 STATE.FPR[insn.rs1()] #define FRS2 STATE.FPR[insn.rs2()] #define FRS3 STATE.FPR[insn.rs3()] -#define WRITE_FRD(value) STATE.FPR.write(insn.rd(), value) +#define dirty_fp_state (STATE.mstatus |= MSTATUS_FS | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD)) +#define dirty_ext_state (STATE.mstatus |= MSTATUS_XS | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD)) +#define do_write_frd(value) (STATE.FPR.write(insn.rd(), value), dirty_fp_state) -#ifdef RISCV_ENABLE_COMMITLOG - #undef WRITE_FRD - #define WRITE_FRD(value) ({ \ - freg_t wdata = value; /* value is a func with side-effects */ \ +#ifndef RISCV_ENABLE_COMMITLOG +# define WRITE_FRD(value) do_write_frd(value) +#else +# define WRITE_FRD(value) ({ \ + freg_t wdata = (value); /* value may have side effects */ \ STATE.log_reg_write = (commit_log_reg_t){(insn.rd() << 1) | 1, wdata}; \ - STATE.FPR.write(insn.rd(), wdata); \ + do_write_frd(wdata); \ }) #endif @@ -135,17 +135,14 @@ private: if(rm > 4) throw trap_illegal_instruction(); \ rm; }) -#define xpr64 (xlen == 64) +#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_supervisor if(unlikely(!(STATE.sr & SR_S))) throw trap_privileged_instruction() -#define require_xpr64 if(unlikely(!xpr64)) throw trap_illegal_instruction() -#define require_xpr32 if(unlikely(xpr64)) throw trap_illegal_instruction() -#ifndef RISCV_ENABLE_FPU -# define require_fp throw trap_illegal_instruction() -#else -# define require_fp if(unlikely(!(STATE.sr & SR_EF))) throw trap_fp_disabled() -#endif -#define require_accelerator if(unlikely(!(STATE.sr & SR_EA))) throw trap_accelerator_disabled() +#define require_privilege(p) if (get_field(STATE.mstatus, MSTATUS_PRV) < (p)) throw trap_illegal_instruction() +#define require_rv64 if(unlikely(xlen != 64)) throw trap_illegal_instruction() +#define require_rv32 if(unlikely(xlen != 32)) throw trap_illegal_instruction() +#define require_fp if (unlikely((STATE.mstatus & MSTATUS_FS) == 0)) throw trap_illegal_instruction() +#define require_accelerator if (unlikely((STATE.mstatus & MSTATUS_XS) == 0)) throw trap_illegal_instruction() #define cmp_trunc(reg) (reg_t(reg) << (64-xlen)) #define set_fp_exceptions ({ STATE.fflags |= softfloat_exceptionFlags; \ @@ -159,12 +156,11 @@ private: #define set_pc(x) (npc = sext_xlen(x)) #define validate_csr(which, write) ({ \ - unsigned my_priv = (STATE.sr & SR_S) ? 1 : 0; \ - unsigned read_priv = ((which) >> 10) & 3; \ - unsigned write_priv = (((which) >> 8) & 3); \ - if (read_priv == 3) read_priv = write_priv, write_priv = -1; \ - if (my_priv < ((write) ? write_priv : read_priv)) \ - throw trap_privileged_instruction(); \ + unsigned my_priv = get_field(STATE.mstatus, MSTATUS_PRV); \ + unsigned csr_priv = get_field((which), 0x300); \ + unsigned csr_read_only = get_field((which), 0xC00) == 3; \ + if (((write) && csr_read_only) || my_priv < csr_priv) \ + throw trap_illegal_instruction(); \ (which); }) #endif diff --git a/riscv/encoding.h b/riscv/encoding.h index 089a8a9..4b929d3 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -3,25 +3,61 @@ #ifndef RISCV_CSR_ENCODING_H #define RISCV_CSR_ENCODING_H -#define SR_S 0x00000001 -#define SR_PS 0x00000002 -#define SR_EI 0x00000004 -#define SR_PEI 0x00000008 -#define SR_EF 0x00000010 -#define SR_U64 0x00000020 -#define SR_S64 0x00000040 -#define SR_VM 0x00000080 -#define SR_EA 0x00000100 -#define SR_IM 0x00FF0000 -#define SR_IP 0xFF000000 -#define SR_ZERO ~(SR_S|SR_PS|SR_EI|SR_PEI|SR_EF|SR_U64|SR_S64|SR_VM|SR_EA|SR_IM|SR_IP) -#define SR_IM_SHIFT 16 -#define SR_IP_SHIFT 24 +#define MSTATUS_SSIP 0x00000002 +#define MSTATUS_HSIP 0x00000004 +#define MSTATUS_MSIP 0x00000008 +#define MSTATUS_IE 0x00000010 +#define MSTATUS_PRV 0x00000060 +#define MSTATUS_IE1 0x00000080 +#define MSTATUS_PRV1 0x00000300 +#define MSTATUS_IE2 0x00000400 +#define MSTATUS_PRV2 0x00001800 +#define MSTATUS_IE3 0x00002000 +#define MSTATUS_PRV3 0x0000C000 +#define MSTATUS_MPRV 0x00030000 +#define MSTATUS_VM 0x00780000 +#define MSTATUS_STIE 0x01000000 +#define MSTATUS_HTIE 0x02000000 +#define MSTATUS_MTIE 0x04000000 +#define MSTATUS_FS 0x18000000 +#define MSTATUS_XS 0x60000000 +#define MSTATUS32_SD 0x80000000 +#define MSTATUS64_UA 0x0000000F00000000 +#define MSTATUS64_SA 0x000000F000000000 +#define MSTATUS64_HA 0x00000F0000000000 +#define MSTATUS64_SD 0x8000000000000000 -#define IRQ_COP 2 -#define IRQ_IPI 5 -#define IRQ_HOST 6 -#define IRQ_TIMER 7 +#define SSTATUS_SIP 0x00000002 +#define SSTATUS_IE 0x00000010 +#define SSTATUS_PIE 0x00000080 +#define SSTATUS_PS 0x00000100 +#define SSTATUS_UA 0x000F0000 +#define SSTATUS_TIE 0x01000000 +#define SSTATUS_TIP 0x04000000 +#define SSTATUS_FS 0x18000000 +#define SSTATUS_XS 0x60000000 +#define SSTATUS32_SD 0x80000000 +#define SSTATUS64_SD 0x8000000000000000 + +#define PRV_U 0 +#define PRV_S 1 +#define PRV_H 2 +#define PRV_M 3 + +#define VM_MBARE 0 +#define VM_MBB 1 +#define VM_MBBID 2 +#define VM_SV32 4 +#define VM_SV43 5 + +#define UA_RV32 0 +#define UA_RV64 4 +#define UA_RV128 8 + +#define IRQ_TIMER 0 +#define IRQ_IPI 1 +#define IRQ_HOST 2 +#define IRQ_COP 3 #define IMPL_SPIKE 1 #define IMPL_ROCKET 2 @@ -41,9 +77,16 @@ #ifdef __riscv #ifdef __riscv64 +# define MSTATUS_UA MSTATUS64_UA +# define MSTATUS_SA MSTATUS64_SA +# define MSTATUS_HA MSTATUS64_HA +# define MSTATUS_SD MSTATUS64_SD +# define SSTATUS_SD SSTATUS64_SD # define RISCV_PGLEVELS 3 # define RISCV_PGSHIFT 13 #else +# define MSTATUS_SD MSTATUS32_SD +# define SSTATUS_SD SSTATUS32_SD # define RISCV_PGLEVELS 2 # define RISCV_PGSHIFT 12 #endif @@ -52,7 +95,9 @@ #ifndef __ASSEMBLER__ -#define read_csr(reg) ({ long __tmp; \ +#ifdef __GNUC__ + +#define read_csr(reg) ({ unsigned long __tmp; \ asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ __tmp; }) @@ -63,31 +108,25 @@ asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \ __tmp; }) -#define set_csr(reg, bit) ({ long __tmp; \ +#define set_csr(reg, bit) ({ unsigned long __tmp; \ if (__builtin_constant_p(bit) && (bit) < 32) \ asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ else \ asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ __tmp; }) -#define clear_csr(reg, bit) ({ long __tmp; \ +#define clear_csr(reg, bit) ({ unsigned long __tmp; \ if (__builtin_constant_p(bit) && (bit) < 32) \ asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ else \ asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ __tmp; }) -#define rdtime() ({ unsigned long __tmp; \ - asm volatile ("rdtime %0" : "=r"(__tmp)); \ - __tmp; }) - -#define rdcycle() ({ unsigned long __tmp; \ - asm volatile ("rdcycle %0" : "=r"(__tmp)); \ - __tmp; }) +#define rdtime() read_csr(time) +#define rdcycle() read_csr(cycle) +#define rdinstret() read_csr(instret) -#define rdinstret() ({ unsigned long __tmp; \ - asm volatile ("rdinstret %0" : "=r"(__tmp)); \ - __tmp; }) +#endif #endif @@ -113,6 +152,8 @@ #define MASK_FSGNJN_D 0xfe00707f #define MATCH_FMIN_S 0x28000053 #define MASK_FMIN_S 0xfe00707f +#define MATCH_MRET 0x30200073 +#define MASK_MRET 0xffffffff #define MATCH_CSRRW 0x1073 #define MASK_CSRRW 0x707f #define MATCH_SLLIW 0x101b @@ -201,6 +242,8 @@ #define MASK_SCALL 0xffffffff #define MATCH_FCLASS_S 0xe0001053 #define MASK_FCLASS_S 0xfff0707f +#define MATCH_SFENCE_VM 0x10400073 +#define MASK_SFENCE_VM 0xfff07fff #define MATCH_SC_W 0x1800202f #define MASK_SC_W 0xf800707f #define MATCH_REM 0x2006033 @@ -217,6 +260,8 @@ #define MASK_MULH 0xfe00707f #define MATCH_FMUL_S 0x10000053 #define MASK_FMUL_S 0xfe00007f +#define MATCH_MCALL 0x20000073 +#define MASK_MCALL 0xffffffff #define MATCH_CSRRSI 0x6073 #define MASK_CSRRSI 0x707f #define MATCH_SRAI 0x40005013 @@ -257,6 +302,8 @@ #define MASK_FSUB_D 0xfe00007f #define MATCH_FSGNJX_S 0x20002053 #define MASK_FSGNJX_S 0xfe00707f +#define MATCH_MRTS 0x30900073 +#define MASK_MRTS 0xffffffff #define MATCH_FEQ_D 0xa2002053 #define MASK_FEQ_D 0xfe00707f #define MATCH_FCVT_D_WU 0xd2100053 @@ -283,7 +330,7 @@ #define MASK_ANDI 0x707f #define MATCH_FMV_X_S 0xe0000053 #define MASK_FMV_X_S 0xfff0707f -#define MATCH_SRET 0x80000073 +#define MATCH_SRET 0x10200073 #define MASK_SRET 0xffffffff #define MATCH_FNMADD_S 0x4f #define MASK_FNMADD_S 0x600007f @@ -414,29 +461,10 @@ #define CSR_FFLAGS 0x1 #define CSR_FRM 0x2 #define CSR_FCSR 0x3 -#define CSR_STATS 0xc0 -#define CSR_SUP0 0x500 -#define CSR_SUP1 0x501 -#define CSR_EPC 0x502 -#define CSR_BADVADDR 0x503 -#define CSR_PTBR 0x504 -#define CSR_ASID 0x505 -#define CSR_COUNT 0x506 -#define CSR_COMPARE 0x507 -#define CSR_EVEC 0x508 -#define CSR_CAUSE 0x509 -#define CSR_STATUS 0x50a -#define CSR_HARTID 0x50b -#define CSR_IMPL 0x50c -#define CSR_FATC 0x50d -#define CSR_SEND_IPI 0x50e -#define CSR_CLEAR_IPI 0x50f -#define CSR_RESET 0x51d -#define CSR_TOHOST 0x51e -#define CSR_FROMHOST 0x51f #define CSR_CYCLE 0xc00 #define CSR_TIME 0xc01 #define CSR_INSTRET 0xc02 +#define CSR_STATS 0xc0 #define CSR_UARCH0 0xcc0 #define CSR_UARCH1 0xcc1 #define CSR_UARCH2 0xcc2 @@ -453,22 +481,45 @@ #define CSR_UARCH13 0xccd #define CSR_UARCH14 0xcce #define CSR_UARCH15 0xccf -#define CSR_COUNTH 0x586 +#define CSR_SSTATUS 0x100 +#define CSR_STVEC 0x101 +#define CSR_STIMECMP 0x121 +#define CSR_SSCRATCH 0x140 +#define CSR_SEPC 0x141 +#define CSR_SPTBR 0x188 +#define CSR_SASID 0x189 +#define CSR_SCYCLE 0x900 +#define CSR_STIME 0x901 +#define CSR_SINSTRET 0x902 +#define CSR_SCAUSE 0xd40 +#define CSR_SBADADDR 0xd41 +#define CSR_MSTATUS 0x300 +#define CSR_MSCRATCH 0x340 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MBADADDR 0x343 +#define CSR_RESET 0x780 +#define CSR_TOHOST 0x781 +#define CSR_FROMHOST 0x782 +#define CSR_SEND_IPI 0x783 +#define CSR_HARTID 0xfc0 #define CSR_CYCLEH 0xc80 #define CSR_TIMEH 0xc81 #define CSR_INSTRETH 0xc82 +#define CSR_SCYCLEH 0x980 +#define CSR_STIMEH 0x981 +#define CSR_SINSTRETH 0x982 #define CAUSE_MISALIGNED_FETCH 0x0 #define CAUSE_FAULT_FETCH 0x1 #define CAUSE_ILLEGAL_INSTRUCTION 0x2 -#define CAUSE_PRIVILEGED_INSTRUCTION 0x3 -#define CAUSE_FP_DISABLED 0x4 -#define CAUSE_SYSCALL 0x6 +#define CAUSE_SCALL 0x4 +#define CAUSE_HCALL 0x5 +#define CAUSE_MCALL 0x6 #define CAUSE_BREAKPOINT 0x7 #define CAUSE_MISALIGNED_LOAD 0x8 -#define CAUSE_MISALIGNED_STORE 0x9 -#define CAUSE_FAULT_LOAD 0xa +#define CAUSE_FAULT_LOAD 0x9 +#define CAUSE_MISALIGNED_STORE 0xa #define CAUSE_FAULT_STORE 0xb -#define CAUSE_ACCELERATOR_DISABLED 0xc #endif #ifdef DECLARE_INSN DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X) @@ -479,6 +530,7 @@ DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D) DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU) DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D) DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S) +DECLARE_INSN(mret, MATCH_MRET, MASK_MRET) DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW) DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW) DECLARE_INSN(lb, MATCH_LB, MASK_LB) @@ -523,6 +575,7 @@ DECLARE_INSN(sub, MATCH_SUB, MASK_SUB) DECLARE_INSN(blt, MATCH_BLT, MASK_BLT) DECLARE_INSN(scall, MATCH_SCALL, MASK_SCALL) DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S) +DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM) DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W) DECLARE_INSN(rem, MATCH_REM, MASK_REM) DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW) @@ -531,6 +584,7 @@ DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI) DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI) DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH) DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S) +DECLARE_INSN(mcall, MATCH_MCALL, MASK_MCALL) DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI) DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI) DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D) @@ -551,6 +605,7 @@ DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW) DECLARE_INSN(srl, MATCH_SRL, MASK_SRL) DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D) DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S) +DECLARE_INSN(mrts, MATCH_MRTS, MASK_MRTS) DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D) DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU) DECLARE_INSN(or, MATCH_OR, MASK_OR) @@ -633,29 +688,10 @@ DECLARE_INSN(sd, MATCH_SD, MASK_SD) DECLARE_CSR(fflags, CSR_FFLAGS) DECLARE_CSR(frm, CSR_FRM) DECLARE_CSR(fcsr, CSR_FCSR) -DECLARE_CSR(stats, CSR_STATS) -DECLARE_CSR(sup0, CSR_SUP0) -DECLARE_CSR(sup1, CSR_SUP1) -DECLARE_CSR(epc, CSR_EPC) -DECLARE_CSR(badvaddr, CSR_BADVADDR) -DECLARE_CSR(ptbr, CSR_PTBR) -DECLARE_CSR(asid, CSR_ASID) -DECLARE_CSR(count, CSR_COUNT) -DECLARE_CSR(compare, CSR_COMPARE) -DECLARE_CSR(evec, CSR_EVEC) -DECLARE_CSR(cause, CSR_CAUSE) -DECLARE_CSR(status, CSR_STATUS) -DECLARE_CSR(hartid, CSR_HARTID) -DECLARE_CSR(impl, CSR_IMPL) -DECLARE_CSR(fatc, CSR_FATC) -DECLARE_CSR(send_ipi, CSR_SEND_IPI) -DECLARE_CSR(clear_ipi, CSR_CLEAR_IPI) -DECLARE_CSR(reset, CSR_RESET) -DECLARE_CSR(tohost, CSR_TOHOST) -DECLARE_CSR(fromhost, CSR_FROMHOST) DECLARE_CSR(cycle, CSR_CYCLE) DECLARE_CSR(time, CSR_TIME) DECLARE_CSR(instret, CSR_INSTRET) +DECLARE_CSR(stats, CSR_STATS) DECLARE_CSR(uarch0, CSR_UARCH0) DECLARE_CSR(uarch1, CSR_UARCH1) DECLARE_CSR(uarch2, CSR_UARCH2) @@ -672,38 +708,43 @@ DECLARE_CSR(uarch12, CSR_UARCH12) DECLARE_CSR(uarch13, CSR_UARCH13) DECLARE_CSR(uarch14, CSR_UARCH14) DECLARE_CSR(uarch15, CSR_UARCH15) -DECLARE_CSR(counth, CSR_COUNTH) +DECLARE_CSR(sstatus, CSR_SSTATUS) +DECLARE_CSR(stvec, CSR_STVEC) +DECLARE_CSR(stimecmp, CSR_STIMECMP) +DECLARE_CSR(sscratch, CSR_SSCRATCH) +DECLARE_CSR(sepc, CSR_SEPC) +DECLARE_CSR(sptbr, CSR_SPTBR) +DECLARE_CSR(sasid, CSR_SASID) +DECLARE_CSR(scycle, CSR_SCYCLE) +DECLARE_CSR(stime, CSR_STIME) +DECLARE_CSR(sinstret, CSR_SINSTRET) +DECLARE_CSR(scause, CSR_SCAUSE) +DECLARE_CSR(sbadaddr, CSR_SBADADDR) +DECLARE_CSR(mstatus, CSR_MSTATUS) +DECLARE_CSR(mscratch, CSR_MSCRATCH) +DECLARE_CSR(mepc, CSR_MEPC) +DECLARE_CSR(mcause, CSR_MCAUSE) +DECLARE_CSR(mbadaddr, CSR_MBADADDR) +DECLARE_CSR(reset, CSR_RESET) +DECLARE_CSR(tohost, CSR_TOHOST) +DECLARE_CSR(fromhost, CSR_FROMHOST) +DECLARE_CSR(send_ipi, CSR_SEND_IPI) +DECLARE_CSR(hartid, CSR_HARTID) DECLARE_CSR(cycleh, CSR_CYCLEH) DECLARE_CSR(timeh, CSR_TIMEH) DECLARE_CSR(instreth, CSR_INSTRETH) +DECLARE_CSR(scycleh, CSR_SCYCLEH) +DECLARE_CSR(stimeh, CSR_STIMEH) +DECLARE_CSR(sinstreth, CSR_SINSTRETH) #endif #ifdef DECLARE_CAUSE DECLARE_CAUSE("fflags", CAUSE_FFLAGS) DECLARE_CAUSE("frm", CAUSE_FRM) DECLARE_CAUSE("fcsr", CAUSE_FCSR) -DECLARE_CAUSE("stats", CAUSE_STATS) -DECLARE_CAUSE("sup0", CAUSE_SUP0) -DECLARE_CAUSE("sup1", CAUSE_SUP1) -DECLARE_CAUSE("epc", CAUSE_EPC) -DECLARE_CAUSE("badvaddr", CAUSE_BADVADDR) -DECLARE_CAUSE("ptbr", CAUSE_PTBR) -DECLARE_CAUSE("asid", CAUSE_ASID) -DECLARE_CAUSE("count", CAUSE_COUNT) -DECLARE_CAUSE("compare", CAUSE_COMPARE) -DECLARE_CAUSE("evec", CAUSE_EVEC) -DECLARE_CAUSE("cause", CAUSE_CAUSE) -DECLARE_CAUSE("status", CAUSE_STATUS) -DECLARE_CAUSE("hartid", CAUSE_HARTID) -DECLARE_CAUSE("impl", CAUSE_IMPL) -DECLARE_CAUSE("fatc", CAUSE_FATC) -DECLARE_CAUSE("send_ipi", CAUSE_SEND_IPI) -DECLARE_CAUSE("clear_ipi", CAUSE_CLEAR_IPI) -DECLARE_CAUSE("reset", CAUSE_RESET) -DECLARE_CAUSE("tohost", CAUSE_TOHOST) -DECLARE_CAUSE("fromhost", CAUSE_FROMHOST) DECLARE_CAUSE("cycle", CAUSE_CYCLE) DECLARE_CAUSE("time", CAUSE_TIME) DECLARE_CAUSE("instret", CAUSE_INSTRET) +DECLARE_CAUSE("stats", CAUSE_STATS) DECLARE_CAUSE("uarch0", CAUSE_UARCH0) DECLARE_CAUSE("uarch1", CAUSE_UARCH1) DECLARE_CAUSE("uarch2", CAUSE_UARCH2) @@ -720,8 +761,32 @@ DECLARE_CAUSE("uarch12", CAUSE_UARCH12) DECLARE_CAUSE("uarch13", CAUSE_UARCH13) DECLARE_CAUSE("uarch14", CAUSE_UARCH14) DECLARE_CAUSE("uarch15", CAUSE_UARCH15) -DECLARE_CAUSE("counth", CAUSE_COUNTH) +DECLARE_CAUSE("sstatus", CAUSE_SSTATUS) +DECLARE_CAUSE("stvec", CAUSE_STVEC) +DECLARE_CAUSE("stimecmp", CAUSE_STIMECMP) +DECLARE_CAUSE("sscratch", CAUSE_SSCRATCH) +DECLARE_CAUSE("sepc", CAUSE_SEPC) +DECLARE_CAUSE("sptbr", CAUSE_SPTBR) +DECLARE_CAUSE("sasid", CAUSE_SASID) +DECLARE_CAUSE("scycle", CAUSE_SCYCLE) +DECLARE_CAUSE("stime", CAUSE_STIME) +DECLARE_CAUSE("sinstret", CAUSE_SINSTRET) +DECLARE_CAUSE("scause", CAUSE_SCAUSE) +DECLARE_CAUSE("sbadaddr", CAUSE_SBADADDR) +DECLARE_CAUSE("mstatus", CAUSE_MSTATUS) +DECLARE_CAUSE("mscratch", CAUSE_MSCRATCH) +DECLARE_CAUSE("mepc", CAUSE_MEPC) +DECLARE_CAUSE("mcause", CAUSE_MCAUSE) +DECLARE_CAUSE("mbadaddr", CAUSE_MBADADDR) +DECLARE_CAUSE("reset", CAUSE_RESET) +DECLARE_CAUSE("tohost", CAUSE_TOHOST) +DECLARE_CAUSE("fromhost", CAUSE_FROMHOST) +DECLARE_CAUSE("send_ipi", CAUSE_SEND_IPI) +DECLARE_CAUSE("hartid", CAUSE_HARTID) DECLARE_CAUSE("cycleh", CAUSE_CYCLEH) DECLARE_CAUSE("timeh", CAUSE_TIMEH) DECLARE_CAUSE("instreth", CAUSE_INSTRETH) +DECLARE_CAUSE("scycleh", CAUSE_SCYCLEH) +DECLARE_CAUSE("stimeh", CAUSE_STIMEH) +DECLARE_CAUSE("sinstreth", CAUSE_SINSTRETH) #endif diff --git a/riscv/extension.cc b/riscv/extension.cc index b758eef..c2bea2e 100644 --- a/riscv/extension.cc +++ b/riscv/extension.cc @@ -12,11 +12,9 @@ void extension_t::illegal_instruction() void extension_t::raise_interrupt() { - p->set_interrupt(IRQ_COP, true); - p->take_interrupt(); + p->raise_interrupt(IRQ_COP); } void extension_t::clear_interrupt() { - p->set_interrupt(IRQ_COP, false); } diff --git a/riscv/htif.cc b/riscv/htif.cc index 741a00f..5234c7b 100644 --- a/riscv/htif.cc +++ b/riscv/htif.cc @@ -84,23 +84,19 @@ void htif_isasim_t::tick_once() if (write) memcpy(&new_val, p.get_payload(), sizeof(new_val)); - // TODO mapping HTIF regno to CSR[4:0] is arbitrary; consider alternative switch (regno) { - case CSR_HARTID & 0x1f: - old_val = coreid; - break; - case CSR_TOHOST & 0x1f: + case CSR_TOHOST: old_val = proc->get_state()->tohost; if (write) proc->get_state()->tohost = new_val; break; - case CSR_FROMHOST & 0x1f: + case CSR_FROMHOST: old_val = proc->get_state()->fromhost; if (write && old_val == 0) - proc->set_fromhost(new_val); + proc->get_state()->fromhost = new_val; break; - case CSR_RESET & 0x1f: + case CSR_RESET: old_val = !proc->running(); if (write) { diff --git a/riscv/insns/addiw.h b/riscv/insns/addiw.h index 71ab292..4263ead 100644 --- a/riscv/insns/addiw.h +++ b/riscv/insns/addiw.h @@ -1,2 +1,2 @@ -require_xpr64; +require_rv64; WRITE_RD(sext32(insn.i_imm() + RS1)); diff --git a/riscv/insns/addw.h b/riscv/insns/addw.h index f2d98d9..706dc9c 100644 --- a/riscv/insns/addw.h +++ b/riscv/insns/addw.h @@ -1,2 +1,2 @@ -require_xpr64; +require_rv64; WRITE_RD(sext32(RS1 + RS2)); diff --git a/riscv/insns/amoadd_d.h b/riscv/insns/amoadd_d.h index 532902e..c6bacaf 100644 --- a/riscv/insns/amoadd_d.h +++ b/riscv/insns/amoadd_d.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; reg_t v = MMU.load_uint64(RS1); MMU.store_uint64(RS1, RS2 + v); WRITE_RD(v); diff --git a/riscv/insns/amoand_d.h b/riscv/insns/amoand_d.h index 8a672ba..d896ec1 100644 --- a/riscv/insns/amoand_d.h +++ b/riscv/insns/amoand_d.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; reg_t v = MMU.load_uint64(RS1); MMU.store_uint64(RS1, RS2 & v); WRITE_RD(v); diff --git a/riscv/insns/amomax_d.h b/riscv/insns/amomax_d.h index 7b97e7b..0a66214 100644 --- a/riscv/insns/amomax_d.h +++ b/riscv/insns/amomax_d.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; sreg_t v = MMU.load_int64(RS1); MMU.store_uint64(RS1, std::max(sreg_t(RS2),v)); WRITE_RD(v); diff --git a/riscv/insns/amomaxu_d.h b/riscv/insns/amomaxu_d.h index ef003c6..dbdb1d2 100644 --- a/riscv/insns/amomaxu_d.h +++ b/riscv/insns/amomaxu_d.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; reg_t v = MMU.load_uint64(RS1); MMU.store_uint64(RS1, std::max(RS2,v)); WRITE_RD(v); diff --git a/riscv/insns/amomin_d.h b/riscv/insns/amomin_d.h index 62915bb..2ad8eef 100644 --- a/riscv/insns/amomin_d.h +++ b/riscv/insns/amomin_d.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; sreg_t v = MMU.load_int64(RS1); MMU.store_uint64(RS1, std::min(sreg_t(RS2),v)); WRITE_RD(v); diff --git a/riscv/insns/amominu_d.h b/riscv/insns/amominu_d.h index 5543d5e..88fe724 100644 --- a/riscv/insns/amominu_d.h +++ b/riscv/insns/amominu_d.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; reg_t v = MMU.load_uint64(RS1); MMU.store_uint64(RS1, std::min(RS2,v)); WRITE_RD(v); diff --git a/riscv/insns/amoor_d.h b/riscv/insns/amoor_d.h index 500803f..58a64e0 100644 --- a/riscv/insns/amoor_d.h +++ b/riscv/insns/amoor_d.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; reg_t v = MMU.load_uint64(RS1); MMU.store_uint64(RS1, RS2 | v); WRITE_RD(v); diff --git a/riscv/insns/amoswap_d.h b/riscv/insns/amoswap_d.h index f03d2aa..9f34eaa 100644 --- a/riscv/insns/amoswap_d.h +++ b/riscv/insns/amoswap_d.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; reg_t v = MMU.load_uint64(RS1); MMU.store_uint64(RS1, RS2); WRITE_RD(v); diff --git a/riscv/insns/amoxor_d.h b/riscv/insns/amoxor_d.h index c78e7e3..acd8b61 100644 --- a/riscv/insns/amoxor_d.h +++ b/riscv/insns/amoxor_d.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; reg_t v = MMU.load_uint64(RS1); MMU.store_uint64(RS1, RS2 ^ v); WRITE_RD(v); diff --git a/riscv/insns/csrrc.h b/riscv/insns/csrrc.h index 4667fc8..74a6872 100644 --- a/riscv/insns/csrrc.h +++ b/riscv/insns/csrrc.h @@ -1,4 +1,4 @@ int csr = validate_csr(insn.csr(), true); -reg_t old = p->get_pcr(csr); -p->set_pcr(csr, old & ~RS1); +reg_t old = p->get_csr(csr); +p->set_csr(csr, old & ~RS1); WRITE_RD(sext_xlen(old)); diff --git a/riscv/insns/csrrci.h b/riscv/insns/csrrci.h index 172aea0..993f2d8 100644 --- a/riscv/insns/csrrci.h +++ b/riscv/insns/csrrci.h @@ -1,4 +1,4 @@ int csr = validate_csr(insn.csr(), true); -reg_t old = p->get_pcr(csr); -p->set_pcr(csr, old & ~(reg_t)insn.rs1()); +reg_t old = p->get_csr(csr); +p->set_csr(csr, old & ~(reg_t)insn.rs1()); WRITE_RD(sext_xlen(old)); diff --git a/riscv/insns/csrrs.h b/riscv/insns/csrrs.h index 6616855..72b49bb 100644 --- a/riscv/insns/csrrs.h +++ b/riscv/insns/csrrs.h @@ -1,4 +1,4 @@ int csr = validate_csr(insn.csr(), insn.rs1() != 0); -reg_t old = p->get_pcr(csr); -p->set_pcr(csr, old | RS1); +reg_t old = p->get_csr(csr); +p->set_csr(csr, old | RS1); WRITE_RD(sext_xlen(old)); diff --git a/riscv/insns/csrrsi.h b/riscv/insns/csrrsi.h index 913c20a..90a4436 100644 --- a/riscv/insns/csrrsi.h +++ b/riscv/insns/csrrsi.h @@ -1,4 +1,4 @@ int csr = validate_csr(insn.csr(), true); -reg_t old = p->get_pcr(csr); -p->set_pcr(csr, old | insn.rs1()); +reg_t old = p->get_csr(csr); +p->set_csr(csr, old | insn.rs1()); WRITE_RD(sext_xlen(old)); diff --git a/riscv/insns/csrrw.h b/riscv/insns/csrrw.h index b981665..9f2324f 100644 --- a/riscv/insns/csrrw.h +++ b/riscv/insns/csrrw.h @@ -1,4 +1,4 @@ int csr = validate_csr(insn.csr(), true); -reg_t old = p->get_pcr(csr); -p->set_pcr(csr, RS1); +reg_t old = p->get_csr(csr); +p->set_csr(csr, RS1); WRITE_RD(sext_xlen(old)); diff --git a/riscv/insns/csrrwi.h b/riscv/insns/csrrwi.h index cbee6b9..cf0710f 100644 --- a/riscv/insns/csrrwi.h +++ b/riscv/insns/csrrwi.h @@ -1,4 +1,4 @@ int csr = validate_csr(insn.csr(), true); -reg_t old = p->get_pcr(csr); -p->set_pcr(csr, insn.rs1()); +reg_t old = p->get_csr(csr); +p->set_csr(csr, insn.rs1()); WRITE_RD(sext_xlen(old)); diff --git a/riscv/insns/divuw.h b/riscv/insns/divuw.h index a717658..a613d95 100644 --- a/riscv/insns/divuw.h +++ b/riscv/insns/divuw.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; reg_t lhs = zext32(RS1); reg_t rhs = zext32(RS2); if(rhs == 0) diff --git a/riscv/insns/divw.h b/riscv/insns/divw.h index 24f22fd..bd4e999 100644 --- a/riscv/insns/divw.h +++ b/riscv/insns/divw.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; sreg_t lhs = sext32(RS1); sreg_t rhs = sext32(RS2); if(rhs == 0) diff --git a/riscv/insns/fcvt_d_l.h b/riscv/insns/fcvt_d_l.h index eab849a..e0e1824 100644 --- a/riscv/insns/fcvt_d_l.h +++ b/riscv/insns/fcvt_d_l.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; require_fp; softfloat_roundingMode = RM; WRITE_FRD(i64_to_f64(RS1)); diff --git a/riscv/insns/fcvt_d_lu.h b/riscv/insns/fcvt_d_lu.h index bef89eb..ee33848 100644 --- a/riscv/insns/fcvt_d_lu.h +++ b/riscv/insns/fcvt_d_lu.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; require_fp; softfloat_roundingMode = RM; WRITE_FRD(ui64_to_f64(RS1)); diff --git a/riscv/insns/fcvt_l_d.h b/riscv/insns/fcvt_l_d.h index bf03b71..55dbe27 100644 --- a/riscv/insns/fcvt_l_d.h +++ b/riscv/insns/fcvt_l_d.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; require_fp; softfloat_roundingMode = RM; WRITE_RD(f64_to_i64(FRS1, RM, true)); diff --git a/riscv/insns/fcvt_l_s.h b/riscv/insns/fcvt_l_s.h index 1259234..ea1e5a7 100644 --- a/riscv/insns/fcvt_l_s.h +++ b/riscv/insns/fcvt_l_s.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; require_fp; softfloat_roundingMode = RM; WRITE_RD(f32_to_i64(FRS1, RM, true)); diff --git a/riscv/insns/fcvt_lu_d.h b/riscv/insns/fcvt_lu_d.h index d69b36b..7be12ed 100644 --- a/riscv/insns/fcvt_lu_d.h +++ b/riscv/insns/fcvt_lu_d.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; require_fp; softfloat_roundingMode = RM; WRITE_RD(f64_to_ui64(FRS1, RM, true)); diff --git a/riscv/insns/fcvt_lu_s.h b/riscv/insns/fcvt_lu_s.h index e40605b..04501c1 100644 --- a/riscv/insns/fcvt_lu_s.h +++ b/riscv/insns/fcvt_lu_s.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; require_fp; softfloat_roundingMode = RM; WRITE_RD(f32_to_ui64(FRS1, RM, true)); diff --git a/riscv/insns/fcvt_s_l.h b/riscv/insns/fcvt_s_l.h index 98570ab..723b9e4 100644 --- a/riscv/insns/fcvt_s_l.h +++ b/riscv/insns/fcvt_s_l.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; require_fp; softfloat_roundingMode = RM; WRITE_FRD(i64_to_f32(RS1)); diff --git a/riscv/insns/fcvt_s_lu.h b/riscv/insns/fcvt_s_lu.h index 921bfcf..b58b395 100644 --- a/riscv/insns/fcvt_s_lu.h +++ b/riscv/insns/fcvt_s_lu.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; require_fp; softfloat_roundingMode = RM; WRITE_FRD(ui64_to_f32(RS1)); diff --git a/riscv/insns/fmv_d_x.h b/riscv/insns/fmv_d_x.h index 35c1977..f01811d 100644 --- a/riscv/insns/fmv_d_x.h +++ b/riscv/insns/fmv_d_x.h @@ -1,3 +1,3 @@ -require_xpr64; +require_rv64; require_fp; WRITE_FRD(RS1); diff --git a/riscv/insns/fmv_x_d.h b/riscv/insns/fmv_x_d.h index 5bcf2b5..d3c1d7a 100644 --- a/riscv/insns/fmv_x_d.h +++ b/riscv/insns/fmv_x_d.h @@ -1,3 +1,3 @@ -require_xpr64; +require_rv64; require_fp; WRITE_RD(FRS1); diff --git a/riscv/insns/ld.h b/riscv/insns/ld.h index d36e172..1122b98 100644 --- a/riscv/insns/ld.h +++ b/riscv/insns/ld.h @@ -1,2 +1,2 @@ -require_xpr64; +require_rv64; WRITE_RD(MMU.load_int64(RS1 + insn.i_imm())); diff --git a/riscv/insns/lr_d.h b/riscv/insns/lr_d.h index 4e8ac18..94c4bf7 100644 --- a/riscv/insns/lr_d.h +++ b/riscv/insns/lr_d.h @@ -1,3 +1,3 @@ -require_xpr64; +require_rv64; p->get_state()->load_reservation = RS1; WRITE_RD(MMU.load_int64(RS1)); diff --git a/riscv/insns/lwu.h b/riscv/insns/lwu.h index 5535baf..dcc4d75 100644 --- a/riscv/insns/lwu.h +++ b/riscv/insns/lwu.h @@ -1,2 +1,2 @@ -require_xpr64; +require_rv64; WRITE_RD(MMU.load_uint32(RS1 + insn.i_imm())); diff --git a/riscv/insns/mcall.h b/riscv/insns/mcall.h new file mode 100644 index 0000000..97f55f8 --- /dev/null +++ b/riscv/insns/mcall.h @@ -0,0 +1,2 @@ +require_privilege(PRV_S); // or PRV_H if implemented +throw trap_mcall(); diff --git a/riscv/insns/mret.h b/riscv/insns/mret.h new file mode 100644 index 0000000..7319a8f --- /dev/null +++ b/riscv/insns/mret.h @@ -0,0 +1,3 @@ +require_privilege(PRV_M); +p->pop_privilege_stack(); +set_pc(p->get_state()->mepc); diff --git a/riscv/insns/mrts.h b/riscv/insns/mrts.h new file mode 100644 index 0000000..34675b7 --- /dev/null +++ b/riscv/insns/mrts.h @@ -0,0 +1,6 @@ +require_privilege(PRV_M); +p->set_csr(CSR_MSTATUS, set_field(STATE.mstatus, MSTATUS_PRV, PRV_S)); +STATE.sbadaddr = STATE.mbadaddr; +STATE.scause = STATE.mcause; +STATE.sepc = STATE.mepc; +set_pc(STATE.stvec); diff --git a/riscv/insns/mulh.h b/riscv/insns/mulh.h index 8ae7520..567e213 100644 --- a/riscv/insns/mulh.h +++ b/riscv/insns/mulh.h @@ -1,4 +1,4 @@ -if (xpr64) +if (xlen == 64) WRITE_RD(mulh(RS1, RS2)); else WRITE_RD(sext32((sext32(RS1) * sext32(RS2)) >> 32)); diff --git a/riscv/insns/mulhsu.h b/riscv/insns/mulhsu.h index 3168ade..5eeb89c 100644 --- a/riscv/insns/mulhsu.h +++ b/riscv/insns/mulhsu.h @@ -1,4 +1,4 @@ -if (xpr64) +if (xlen == 64) WRITE_RD(mulhsu(RS1, RS2)); else WRITE_RD(sext32((sext32(RS1) * reg_t((uint32_t)RS2)) >> 32)); diff --git a/riscv/insns/mulhu.h b/riscv/insns/mulhu.h index b03b870..ce6a21e 100644 --- a/riscv/insns/mulhu.h +++ b/riscv/insns/mulhu.h @@ -1,4 +1,4 @@ -if (xpr64) +if (xlen == 64) WRITE_RD(mulhu(RS1, RS2)); else WRITE_RD(sext32(((uint64_t)(uint32_t)RS1 * (uint64_t)(uint32_t)RS2) >> 32)); diff --git a/riscv/insns/mulw.h b/riscv/insns/mulw.h index 9f74fcf..184dd41 100644 --- a/riscv/insns/mulw.h +++ b/riscv/insns/mulw.h @@ -1,2 +1,2 @@ -require_xpr64; +require_rv64; WRITE_RD(sext32(RS1 * RS2)); diff --git a/riscv/insns/remuw.h b/riscv/insns/remuw.h index bec7059..e487516 100644 --- a/riscv/insns/remuw.h +++ b/riscv/insns/remuw.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; reg_t lhs = zext32(RS1); reg_t rhs = zext32(RS2); if(rhs == 0) diff --git a/riscv/insns/remw.h b/riscv/insns/remw.h index b8f4597..2bae1a8 100644 --- a/riscv/insns/remw.h +++ b/riscv/insns/remw.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; sreg_t lhs = sext32(RS1); sreg_t rhs = sext32(RS2); if(rhs == 0) diff --git a/riscv/insns/sc_d.h b/riscv/insns/sc_d.h index 3b48244..2108079 100644 --- a/riscv/insns/sc_d.h +++ b/riscv/insns/sc_d.h @@ -1,4 +1,4 @@ -require_xpr64; +require_rv64; if (RS1 == p->get_state()->load_reservation) { MMU.store_uint64(RS1, RS2); diff --git a/riscv/insns/scall.h b/riscv/insns/scall.h index b31b7e6..306a160 100644 --- a/riscv/insns/scall.h +++ b/riscv/insns/scall.h @@ -1 +1 @@ -throw trap_syscall(); +throw trap_scall(); diff --git a/riscv/insns/sd.h b/riscv/insns/sd.h index 9364d87..664deb2 100644 --- a/riscv/insns/sd.h +++ b/riscv/insns/sd.h @@ -1,2 +1,2 @@ -require_xpr64; +require_rv64; MMU.store_uint64(RS1 + insn.s_imm(), RS2); diff --git a/riscv/insns/sfence_vm.h b/riscv/insns/sfence_vm.h new file mode 100644 index 0000000..35ff5dd --- /dev/null +++ b/riscv/insns/sfence_vm.h @@ -0,0 +1,2 @@ +require_privilege(PRV_S); +MMU.flush_tlb(); diff --git a/riscv/insns/slli.h b/riscv/insns/slli.h index ff9c8c3..7291276 100644 --- a/riscv/insns/slli.h +++ b/riscv/insns/slli.h @@ -1,4 +1,4 @@ -if(xpr64) +if (xlen == 64) WRITE_RD(RS1 << SHAMT); else { diff --git a/riscv/insns/slliw.h b/riscv/insns/slliw.h index fdb51be..c1fda65 100644 --- a/riscv/insns/slliw.h +++ b/riscv/insns/slliw.h @@ -1,2 +1,2 @@ -require_xpr64; +require_rv64; WRITE_RD(sext32(RS1 << SHAMT)); diff --git a/riscv/insns/sllw.h b/riscv/insns/sllw.h index 25e717a..affe894 100644 --- a/riscv/insns/sllw.h +++ b/riscv/insns/sllw.h @@ -1,2 +1,2 @@ -require_xpr64; +require_rv64; WRITE_RD(sext32(RS1 << (RS2 & 0x1F))); diff --git a/riscv/insns/srai.h b/riscv/insns/srai.h index 7fdbdf3..69066ef 100644 --- a/riscv/insns/srai.h +++ b/riscv/insns/srai.h @@ -1,4 +1,4 @@ -if(xpr64) +if (xlen == 64) WRITE_RD(sreg_t(RS1) >> SHAMT); else { diff --git a/riscv/insns/sraiw.h b/riscv/insns/sraiw.h index 242c97e..b344459 100644 --- a/riscv/insns/sraiw.h +++ b/riscv/insns/sraiw.h @@ -1,2 +1,2 @@ -require_xpr64; +require_rv64; WRITE_RD(sext32(int32_t(RS1) >> SHAMT)); diff --git a/riscv/insns/sraw.h b/riscv/insns/sraw.h index 29640bf..ca9c0c7 100644 --- a/riscv/insns/sraw.h +++ b/riscv/insns/sraw.h @@ -1,2 +1,2 @@ -require_xpr64; +require_rv64; WRITE_RD(sext32(int32_t(RS1) >> (RS2 & 0x1F))); diff --git a/riscv/insns/sret.h b/riscv/insns/sret.h index 442b00b..34fdb0d 100644 --- a/riscv/insns/sret.h +++ b/riscv/insns/sret.h @@ -1,5 +1,3 @@ -require_supervisor; -p->set_pcr(CSR_STATUS, ((p->get_state()->sr & ~(SR_S | SR_EI)) | - ((p->get_state()->sr & SR_PS) ? SR_S : 0)) | - ((p->get_state()->sr & SR_PEI) ? SR_EI : 0)); -set_pc(p->get_state()->epc); +require_privilege(PRV_S); +p->pop_privilege_stack(); +set_pc(p->get_state()->sepc); diff --git a/riscv/insns/srl.h b/riscv/insns/srl.h index 9b1eb21..0eb948b 100644 --- a/riscv/insns/srl.h +++ b/riscv/insns/srl.h @@ -1,4 +1,4 @@ -if(xpr64) +if (xlen == 64) WRITE_RD(RS1 >> (RS2 & 0x3F)); else WRITE_RD(sext32((uint32_t)RS1 >> (RS2 & 0x1F))); diff --git a/riscv/insns/srli.h b/riscv/insns/srli.h index fee136c..0cdc853 100644 --- a/riscv/insns/srli.h +++ b/riscv/insns/srli.h @@ -1,4 +1,4 @@ -if(xpr64) +if (xlen == 64) WRITE_RD(RS1 >> SHAMT); else { diff --git a/riscv/insns/srliw.h b/riscv/insns/srliw.h index 0b6f9b8..c657d3d 100644 --- a/riscv/insns/srliw.h +++ b/riscv/insns/srliw.h @@ -1,2 +1,2 @@ -require_xpr64; +require_rv64; WRITE_RD(sext32((uint32_t)RS1 >> SHAMT)); diff --git a/riscv/insns/srlw.h b/riscv/insns/srlw.h index 21ca502..a8eb451 100644 --- a/riscv/insns/srlw.h +++ b/riscv/insns/srlw.h @@ -1,2 +1,2 @@ -require_xpr64; +require_rv64; WRITE_RD(sext32((uint32_t)RS1 >> (RS2 & 0x1F))); diff --git a/riscv/insns/subw.h b/riscv/insns/subw.h index dce982f..b4168ef 100644 --- a/riscv/insns/subw.h +++ b/riscv/insns/subw.h @@ -1,3 +1,3 @@ -require_xpr64; +require_rv64; WRITE_RD(sext32(RS1 - RS2)); diff --git a/riscv/interactive.cc b/riscv/interactive.cc index 27e9ee0..2dd1cad 100644 --- a/riscv/interactive.cc +++ b/riscv/interactive.cc @@ -132,11 +132,24 @@ reg_t sim_t::get_reg(const std::vector<std::string>& args) if(args.size() != 2) throw trap_illegal_instruction(); - int p = atoi(args[0].c_str()); - int r = std::find(xpr_name, xpr_name + NXPR, args[1]) - xpr_name; - if (r == NXPR) - r = atoi(args[1].c_str()); - if(p >= (int)num_cores() || r >= NXPR) + char* ptr; + unsigned long p = strtoul(args[0].c_str(), &ptr, 10); + if (*ptr || p >= num_cores()) + throw trap_illegal_instruction(); + + unsigned long r = std::find(xpr_name, xpr_name + NXPR, args[1]) - xpr_name; + if (r == NXPR) { + r = strtoul(args[1].c_str(), &ptr, 10); + if (*ptr) { + #define DECLARE_CSR(name, number) if (args[1] == #name) return procs[p]->get_csr(number); + if (0) ; + #include "encoding.h" + else r = NXPR; + #undef DECLARE_CSR + } + } + + if (r >= NXPR) throw trap_illegal_instruction(); return procs[p]->state.XPR[r]; diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 2e5de5b..779383d 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -34,10 +34,29 @@ void* mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch) reg_t idx = (addr >> PGSHIFT) % TLB_ENTRIES; reg_t expected_tag = addr >> PGSHIFT; - reg_t pte = walk(addr); + reg_t pte = 0; + reg_t mstatus = proc ? proc->state.mstatus : 0; + + bool vm_disabled = get_field(mstatus, MSTATUS_VM) == VM_MBARE; + bool mode_m = get_field(mstatus, MSTATUS_PRV) == PRV_M; + bool mode_s = get_field(mstatus, MSTATUS_PRV) == PRV_S; + bool mprv_m = get_field(mstatus, MSTATUS_MPRV) == PRV_M; + bool mprv_s = get_field(mstatus, MSTATUS_MPRV) == PRV_S; + + if (vm_disabled || (mode_m && (mprv_m || fetch))) { + // virtual memory is disabled. merely check legality of physical address. + if (addr < memsz) { + // produce a fake PTE for the TLB's benefit. + pte = PTE_V | PTE_UX | PTE_SX | ((addr >> PGSHIFT) << PGSHIFT); + if (vm_disabled || !(mode_m && !mprv_m)) + pte |= PTE_UR | PTE_SR | PTE_UW | PTE_SW; + } + } else { + pte = walk(addr); + } reg_t pte_perm = pte & PTE_PERM; - if (proc == NULL || (proc->state.sr & SR_S)) + if (mode_s || (mode_m && mprv_s && !fetch)) pte_perm = (pte_perm/(PTE_SX/PTE_UX)) & PTE_PERM; pte_perm |= pte & PTE_V; @@ -70,53 +89,42 @@ void* mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch) pte_t mmu_t::walk(reg_t addr) { - pte_t pte = 0; - - // the address must be a canonical sign-extended VA_BITS-bit number - int shift = 8*sizeof(reg_t) - VA_BITS; - if (((sreg_t)addr << shift >> shift) != (sreg_t)addr) - ; - else if (proc == NULL || !(proc->state.sr & SR_VM)) - { - if(addr < memsz) - pte = PTE_V | PTE_PERM | ((addr >> PGSHIFT) << PGSHIFT); - } - else - { - reg_t base = proc->get_state()->ptbr; - reg_t ptd; - - int ptshift = (LEVELS-1)*PTIDXBITS; - for(reg_t i = 0; i < LEVELS; i++, ptshift -= PTIDXBITS) - { - reg_t idx = (addr >> (PGSHIFT+ptshift)) & ((1<<PTIDXBITS)-1); - - reg_t pte_addr = base + idx*sizeof(pte_t); - if(pte_addr >= memsz) - break; - - ptd = *(pte_t*)(mem+pte_addr); - - if (!(ptd & PTE_V)) // invalid mapping - break; - else if (ptd & PTE_T) // next level of page table - base = (ptd >> PGSHIFT) << PGSHIFT; - else // the actual PTE - { - // if this PTE is from a larger PT, fake a leaf - // PTE so the TLB will work right - reg_t vpn = addr >> PGSHIFT; - ptd |= (vpn & ((1<<(ptshift))-1)) << PGSHIFT; - - // fault if physical addr is out of range - if (((ptd >> PGSHIFT) << PGSHIFT) < memsz) - pte = ptd; - break; - } + reg_t msb_mask = -(reg_t(1) << (VA_BITS-1)); + if ((addr & msb_mask) != 0 && (addr & msb_mask) != msb_mask) + return 0; // address isn't properly sign-extended + + reg_t base = proc->get_state()->sptbr; + reg_t ptd; + + int ptshift = (LEVELS-1)*PTIDXBITS; + for (reg_t i = 0; i < LEVELS; i++, ptshift -= PTIDXBITS) { + reg_t idx = (addr >> (PGSHIFT+ptshift)) & ((1<<PTIDXBITS)-1); + + // check that physical address of PTE is legal + reg_t pte_addr = base + idx*sizeof(pte_t); + if (pte_addr >= memsz) + return 0; + + ptd = *(pte_t*)(mem+pte_addr); + + if (!(ptd & PTE_V)) { // invalid mapping + return 0; + } else if (ptd & PTE_T) { // next level of page table + base = (ptd >> PGSHIFT) << PGSHIFT; + } else { + // we've found the PTE. + // for superpage mappings, make a fake leaf PTE for the TLB's benefit. + reg_t vpn = addr >> PGSHIFT; + ptd |= (vpn & ((1<<(ptshift))-1)) << PGSHIFT; + + // check that physical address is legal + if (((ptd >> PGSHIFT) << PGSHIFT) >= memsz) + return 0; + + return ptd; } } - - return pte; + return 0; } void mmu_t::register_memtracer(memtracer_t* t) diff --git a/riscv/processor.cc b/riscv/processor.cc index 0a34446..335cbea 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -49,31 +49,15 @@ processor_t::~processor_t() void state_t::reset() { - // the ISA guarantees on boot that the PC is 0x2000 and the the processor - // is in supervisor mode, and in 64-bit mode, if supported, with traps - // and virtual memory disabled. - sr = SR_S | SR_S64 | SR_U64; - pc = 0x2000; - - // the following state is undefined upon boot-up, - // but we zero it for determinism - XPR.reset(); - FPR.reset(); - - epc = 0; - badvaddr = 0; - evec = 0; - ptbr = 0; - pcr_k0 = 0; - pcr_k1 = 0; - cause = 0; - tohost = 0; - fromhost = 0; - count = 0; - compare = 0; - fflags = 0; - frm = 0; - + memset(this, 0, sizeof(*this)); + mstatus = set_field(mstatus, MSTATUS_PRV, PRV_M); + mstatus = set_field(mstatus, MSTATUS_PRV1, PRV_S); + mstatus = set_field(mstatus, MSTATUS_PRV2, PRV_S); +#ifdef RISCV_ENABLE_64BIT + mstatus = set_field(mstatus, MSTATUS64_UA, UA_RV64); + mstatus = set_field(mstatus, MSTATUS64_SA, UA_RV64); +#endif + pc = 0x100; load_reservation = -1; } @@ -96,7 +80,7 @@ void processor_t::reset(bool value) run = !value; state.reset(); // reset the core - set_pcr(CSR_STATUS, state.sr); + set_csr(CSR_MSTATUS, state.mstatus); if (ext) ext->reset(); // reset the extension @@ -112,21 +96,37 @@ void processor_t::serialize() serialized = true, throw serialize_t(); } +void processor_t::raise_interrupt(reg_t which) +{ + throw trap_t(((reg_t)1 << 63) | which); +} + void processor_t::take_interrupt() { - int irqs = ((state.sr & SR_IP) >> SR_IP_SHIFT) & (state.sr >> SR_IM_SHIFT); - if (likely(!irqs) || likely(!(state.sr & SR_EI))) - return; + int priv = get_field(state.mstatus, MSTATUS_PRV); + int ie = get_field(state.mstatus, MSTATUS_IE); + + if (priv < PRV_M || (priv == PRV_M && ie)) { + if (get_field(state.mstatus, MSTATUS_MSIP)) + raise_interrupt(IRQ_IPI); + + if (state.fromhost != 0) + raise_interrupt(IRQ_HOST); + } + + if (priv < PRV_S || (priv == PRV_S && ie)) { + if (get_field(state.mstatus, MSTATUS_SSIP)) + raise_interrupt(IRQ_IPI); - for (int i = 0; ; i++) - if ((irqs >> i) & 1) - throw trap_t((1ULL << ((state.sr & SR_S64) ? 63 : 31)) + i); + if (state.stip && get_field(state.mstatus, MSTATUS_STIE)) + raise_interrupt(IRQ_TIMER); + } } static void commit_log(state_t* state, reg_t pc, insn_t insn) { #ifdef RISCV_ENABLE_COMMITLOG - if (state->sr & SR_EI) { + if (get_field(state->mstatus, MSTATUS_IE)) { uint64_t mask = (insn.length() == 8 ? uint64_t(0) : (uint64_t(1) << (insn.length() * 8))) - 1; if (state->log_reg_write.addr) { fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ") %c%2" PRIu64 " 0x%016" PRIx64 "\n", @@ -161,16 +161,16 @@ static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch) static void update_timer(state_t* state, size_t instret) { - uint64_t count0 = (uint64_t)(uint32_t)state->count; - state->count += instret; - uint64_t before = count0 - state->compare; + uint64_t count0 = (uint64_t)(uint32_t)state->scount; + state->scount += instret; + uint64_t before = count0 - state->stimecmp; if (int64_t(before ^ (before + instret)) < 0) - state->sr |= (1 << (IRQ_TIMER + SR_IP_SHIFT)); + state->stip = true; } static size_t next_timer(state_t* state) { - return state->compare - (uint32_t)state->count; + return state->stimecmp - (uint32_t)state->scount; } void processor_t::step(size_t n) @@ -225,28 +225,49 @@ void processor_t::step(size_t n) update_timer(&state, instret); } +void processor_t::push_privilege_stack() +{ + reg_t s = state.mstatus; + s = set_field(s, MSTATUS_PRV2, get_field(state.mstatus, MSTATUS_PRV1)); + s = set_field(s, MSTATUS_IE2, get_field(state.mstatus, MSTATUS_IE1)); + s = set_field(s, MSTATUS_PRV1, get_field(state.mstatus, MSTATUS_PRV)); + s = set_field(s, MSTATUS_IE1, get_field(state.mstatus, MSTATUS_IE)); + s = set_field(s, MSTATUS_PRV, PRV_M); + s = set_field(s, MSTATUS_MPRV, PRV_M); + s = set_field(s, MSTATUS_IE, 0); + set_csr(CSR_MSTATUS, s); +} + +void processor_t::pop_privilege_stack() +{ + reg_t s = state.mstatus; + s = set_field(s, MSTATUS_PRV, get_field(state.mstatus, MSTATUS_PRV1)); + s = set_field(s, MSTATUS_IE, get_field(state.mstatus, MSTATUS_IE1)); + s = set_field(s, MSTATUS_PRV1, get_field(state.mstatus, MSTATUS_PRV2)); + s = set_field(s, MSTATUS_IE1, get_field(state.mstatus, MSTATUS_IE2)); + s = set_field(s, MSTATUS_PRV2, PRV_U); + s = set_field(s, MSTATUS_IE2, 1); + set_csr(CSR_MSTATUS, s); +} + reg_t processor_t::take_trap(trap_t& t, reg_t epc) { if (debug) fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n", id, t.name(), epc); - // switch to supervisor, set previous supervisor bit, disable interrupts - set_pcr(CSR_STATUS, (((state.sr & ~SR_EI) | SR_S) & ~SR_PS & ~SR_PEI) | - ((state.sr & SR_S) ? SR_PS : 0) | - ((state.sr & SR_EI) ? SR_PEI : 0)); - + reg_t tvec = 0x40 * get_field(state.mstatus, MSTATUS_PRV); + push_privilege_stack(); yield_load_reservation(); - state.cause = t.cause(); - state.epc = epc; + state.mcause = t.cause(); + state.mepc = epc; t.side_effects(&state); // might set badvaddr etc. - return state.evec; + return tvec; } void processor_t::deliver_ipi() { - if (run) - set_pcr(CSR_CLEAR_IPI, 1); + state.mstatus |= MSTATUS_MSIP; } void processor_t::disasm(insn_t insn) @@ -256,83 +277,137 @@ void processor_t::disasm(insn_t insn) id, state.pc, bits, disassembler->disassemble(insn).c_str()); } -void processor_t::set_pcr(int which, reg_t val) +static bool validate_priv(reg_t priv) +{ + return priv == PRV_U || priv == PRV_S || priv == PRV_M; +} + +static bool validate_arch(reg_t arch) +{ +#ifdef RISCV_ENABLE_64BIT + if (arch == UA_RV64) return true; +#endif + return arch == UA_RV32; +} + +static bool validate_vm(reg_t vm) +{ + // TODO: VM_SV32 support +#ifdef RISCV_ENABLE_64BIT + if (vm == VM_SV43) return true; +#endif + return vm == VM_MBARE; +} + +void processor_t::set_csr(int which, reg_t val) { switch (which) { case CSR_FFLAGS: + dirty_fp_state; state.fflags = val & (FSR_AEXC >> FSR_AEXC_SHIFT); break; case CSR_FRM: + dirty_fp_state; state.frm = val & (FSR_RD >> FSR_RD_SHIFT); break; case CSR_FCSR: + dirty_fp_state; state.fflags = (val & FSR_AEXC) >> FSR_AEXC_SHIFT; state.frm = (val & FSR_RD) >> FSR_RD_SHIFT; break; - case CSR_STATUS: - state.sr = (val & ~SR_IP) | (state.sr & SR_IP); -#ifndef RISCV_ENABLE_64BIT - state.sr &= ~(SR_S64 | SR_U64); + case CSR_SCYCLE: + case CSR_STIME: + case CSR_SINSTRET: + state.scount = val; break; + case CSR_SCYCLEH: + case CSR_STIMEH: + case CSR_SINSTRETH: + state.scount = (val << 32) | (uint32_t)state.scount; + break; + case CSR_MSTATUS: + { + if ((val ^ state.mstatus) & (MSTATUS_VM | MSTATUS_PRV | MSTATUS_MPRV)) + mmu->flush_tlb(); + + reg_t mask = MSTATUS_SSIP | MSTATUS_MSIP | MSTATUS_IE | MSTATUS_IE1 + | MSTATUS_IE2 | MSTATUS_IE3 | MSTATUS_STIE; +#ifdef RISCV_ENABLE_FPU + mask |= MSTATUS_FS; #endif -#ifndef RISCV_ENABLE_FPU - state.sr &= ~SR_EF; + if (ext) + mask |= MSTATUS_XS; + state.mstatus = (state.mstatus & ~mask) | (val & mask); + + if (validate_vm(get_field(val, MSTATUS_VM))) + state.mstatus = (state.mstatus & ~MSTATUS_VM) | (val & MSTATUS_VM); + if (validate_priv(get_field(val, MSTATUS_MPRV))) + state.mstatus = (state.mstatus & ~MSTATUS_MPRV) | (val & MSTATUS_MPRV); + if (validate_priv(get_field(val, MSTATUS_PRV))) + state.mstatus = (state.mstatus & ~MSTATUS_PRV) | (val & MSTATUS_PRV); + if (validate_priv(get_field(val, MSTATUS_PRV1))) + state.mstatus = (state.mstatus & ~MSTATUS_PRV1) | (val & MSTATUS_PRV1); + if (validate_priv(get_field(val, MSTATUS_PRV2))) + state.mstatus = (state.mstatus & ~MSTATUS_PRV2) | (val & MSTATUS_PRV2); + if (validate_priv(get_field(val, MSTATUS_PRV3))) + state.mstatus = (state.mstatus & ~MSTATUS_PRV3) | (val & MSTATUS_PRV3); + xlen = 32; + + bool dirty = (state.mstatus & MSTATUS_FS) == MSTATUS_FS; + dirty |= (state.mstatus & MSTATUS_XS) == MSTATUS_XS; +#ifndef RISCV_ENABLE_64BIT + state.mstatus = set_field(state.mstatus, MSTATUS32_SD, dirty); +#else + state.mstatus = set_field(state.mstatus, MSTATUS64_SD, dirty); + + if (validate_arch(get_field(val, MSTATUS64_UA))) + state.mstatus = (state.mstatus & ~MSTATUS64_UA) | (val & MSTATUS64_UA); + if (validate_arch(get_field(val, MSTATUS64_SA))) + state.mstatus = (state.mstatus & ~MSTATUS64_SA) | (val & MSTATUS64_SA); + switch (get_field(state.mstatus, MSTATUS_PRV)) { + case PRV_U: if (get_field(state.mstatus, MSTATUS64_UA)) xlen = 64; break; + case PRV_S: if (get_field(state.mstatus, MSTATUS64_SA)) xlen = 64; break; + case PRV_M: xlen = 64; break; + default: abort(); + } #endif - if (!ext) - state.sr &= ~SR_EA; - state.sr &= ~SR_ZERO; - rv64 = (state.sr & SR_S) ? (state.sr & SR_S64) : (state.sr & SR_U64); - mmu->flush_tlb(); - break; - case CSR_EPC: - state.epc = val; - break; - case CSR_EVEC: - state.evec = val & ~3; - break; - case CSR_COUNT: - state.count = val; - break; - case CSR_COUNTH: - state.count = (val << 32) | (uint32_t)state.count; break; - case CSR_COMPARE: + } + case CSR_SSTATUS: + { + reg_t ms = state.mstatus; + ms = set_field(ms, MSTATUS_SSIP, get_field(val, SSTATUS_SIP)); + ms = set_field(ms, MSTATUS_IE, get_field(val, SSTATUS_IE)); + ms = set_field(ms, MSTATUS_IE1, get_field(val, SSTATUS_PIE)); + ms = set_field(ms, MSTATUS_PRV1, get_field(val, SSTATUS_PS)); + ms = set_field(ms, MSTATUS64_UA, get_field(val, SSTATUS_UA)); + ms = set_field(ms, MSTATUS_STIE, get_field(val, SSTATUS_TIE)); + ms = set_field(ms, MSTATUS_FS, get_field(val, SSTATUS_FS)); + ms = set_field(ms, MSTATUS_XS, get_field(val, SSTATUS_XS)); + return set_csr(CSR_MSTATUS, ms); + } + case CSR_SEPC: state.sepc = val; break; + case CSR_STVEC: state.stvec = val & ~3; break; + case CSR_STIMECMP: serialize(); - set_interrupt(IRQ_TIMER, false); - state.compare = val; - break; - case CSR_PTBR: - state.ptbr = val & ~(PGSIZE-1); - break; - case CSR_SEND_IPI: - sim->send_ipi(val); - break; - case CSR_CLEAR_IPI: - set_interrupt(IRQ_IPI, val & 1); - break; - case CSR_SUP0: - state.pcr_k0 = val; - break; - case CSR_SUP1: - state.pcr_k1 = val; + state.stip = false; + state.stimecmp = val; break; + case CSR_SPTBR: state.sptbr = val & ~(PGSIZE-1); break; + case CSR_SSCRATCH: state.sscratch = val; break; + case CSR_MEPC: state.mepc = val; break; + case CSR_MSCRATCH: state.mscratch = val; break; + case CSR_MCAUSE: state.mcause = val; break; + case CSR_SEND_IPI: sim->send_ipi(val); break; case CSR_TOHOST: if (state.tohost == 0) state.tohost = val; break; - case CSR_FROMHOST: - set_fromhost(val); - break; + case CSR_FROMHOST: state.fromhost = val; break; } } -void processor_t::set_fromhost(reg_t val) -{ - set_interrupt(IRQ_HOST, val != 0); - state.fromhost = val; -} - -reg_t processor_t::get_pcr(int which) +reg_t processor_t::get_csr(int which) { switch (which) { @@ -345,56 +420,64 @@ reg_t processor_t::get_pcr(int which) case CSR_FCSR: require_fp; return (state.fflags << FSR_AEXC_SHIFT) | (state.frm << FSR_RD_SHIFT); - case CSR_STATUS: - return state.sr; - case CSR_EPC: - return state.epc; - case CSR_BADVADDR: - return state.badvaddr; - case CSR_EVEC: - return state.evec; case CSR_CYCLE: case CSR_TIME: case CSR_INSTRET: - case CSR_COUNT: + case CSR_SCYCLE: + case CSR_STIME: + case CSR_SINSTRET: serialize(); - return state.count; + return state.scount; case CSR_CYCLEH: case CSR_TIMEH: case CSR_INSTRETH: - case CSR_COUNTH: - if (rv64) + case CSR_SCYCLEH: + case CSR_STIMEH: + case CSR_SINSTRETH: + if (xlen == 64) break; serialize(); - return state.count >> 32; - case CSR_COMPARE: - return state.compare; - case CSR_CAUSE: - return state.cause; - case CSR_PTBR: - return state.ptbr; - case CSR_SEND_IPI: - case CSR_CLEAR_IPI: - return 0; - case CSR_ASID: - return 0; - case CSR_FATC: - mmu->flush_tlb(); - return 0; - case CSR_HARTID: - return id; - case CSR_IMPL: - return 1; - case CSR_SUP0: - return state.pcr_k0; - case CSR_SUP1: - return state.pcr_k1; + return state.scount >> 32; + case CSR_SSTATUS: + { + reg_t ss = 0; + ss = set_field(ss, SSTATUS_SIP, get_field(state.mstatus, MSTATUS_SSIP)); + ss = set_field(ss, SSTATUS_IE, get_field(state.mstatus, MSTATUS_IE)); + ss = set_field(ss, SSTATUS_PIE, get_field(state.mstatus, MSTATUS_IE1)); + ss = set_field(ss, SSTATUS_PS, get_field(state.mstatus, MSTATUS_PRV1)); + ss = set_field(ss, SSTATUS_UA, get_field(state.mstatus, MSTATUS64_UA)); + ss = set_field(ss, SSTATUS_TIE, get_field(state.mstatus, MSTATUS_STIE)); + ss = set_field(ss, SSTATUS_TIP, state.stip); + ss = set_field(ss, SSTATUS_FS, get_field(state.mstatus, MSTATUS_FS)); + ss = set_field(ss, SSTATUS_XS, get_field(state.mstatus, MSTATUS_XS)); + if (get_field(state.mstatus, MSTATUS64_SD)) + ss = set_field(ss, (xlen == 32 ? SSTATUS32_SD : SSTATUS64_SD), 1); + return ss; + } + case CSR_SEPC: return state.sepc; + case CSR_SBADADDR: return state.sbadaddr; + case CSR_STVEC: return state.stvec; + case CSR_STIMECMP: return state.stimecmp; + case CSR_SCAUSE: + if (xlen == 32 && (state.scause >> 63) != 0) + return state.scause | ((reg_t)1 << 31); + return state.scause; + case CSR_SPTBR: return state.sptbr; + case CSR_SASID: return 0; + case CSR_SSCRATCH: return state.sscratch; + case CSR_MSTATUS: return state.mstatus; + case CSR_MEPC: return state.mepc; + case CSR_MSCRATCH: return state.mscratch; + case CSR_MCAUSE: return state.mcause; + case CSR_MBADADDR: return state.mbadaddr; case CSR_TOHOST: sim->get_htif()->tick(); // not necessary, but faster return state.tohost; case CSR_FROMHOST: sim->get_htif()->tick(); // not necessary, but faster return state.fromhost; + case CSR_SEND_IPI: return 0; + case CSR_HARTID: return id; case CSR_UARCH0: case CSR_UARCH1: case CSR_UARCH2: @@ -416,15 +499,6 @@ reg_t processor_t::get_pcr(int which) throw trap_illegal_instruction(); } -void processor_t::set_interrupt(int which, bool on) -{ - uint32_t mask = (1 << (which + SR_IP_SHIFT)) & SR_IP; - if (on) - state.sr |= mask; - else - state.sr &= ~mask; -} - reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc) { throw trap_illegal_instruction(); @@ -438,7 +512,7 @@ insn_func_t processor_t::decode_insn(insn_t insn) while ((insn.bits() & desc->mask) != desc->match) desc++; - return rv64 ? desc->rv64 : desc->rv32; + return xlen == 64 ? desc->rv64 : desc->rv32; } void processor_t::register_insn(insn_desc_t desc) diff --git a/riscv/processor.h b/riscv/processor.h index 4e5b144..4189fea 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -40,18 +40,22 @@ struct state_t regfile_t<freg_t, NFPR, false> FPR; // control and status registers - reg_t epc; - reg_t badvaddr; - reg_t evec; - reg_t ptbr; - reg_t pcr_k0; - reg_t pcr_k1; - reg_t cause; + reg_t mstatus; + reg_t mepc; + reg_t mbadaddr; + reg_t mscratch; + reg_t mcause; + reg_t sepc; + reg_t sbadaddr; + reg_t sscratch; + reg_t stvec; + reg_t sptbr; + reg_t scause; reg_t tohost; reg_t fromhost; - reg_t count; - uint32_t compare; - uint32_t sr; // only modify the status register using set_pcr() + reg_t scount; + bool stip; + uint32_t stimecmp; uint32_t fflags; uint32_t frm; @@ -75,13 +79,14 @@ public: void step(size_t n); // run for n cycles void deliver_ipi(); // register an interprocessor interrupt bool running() { return run; } - void set_pcr(int which, reg_t val); - void set_fromhost(reg_t val); - void set_interrupt(int which, bool on); - reg_t get_pcr(int which); + 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; } extension_t* get_extension() { return ext; } + void push_privilege_stack(); + void pop_privilege_stack(); void yield_load_reservation() { state.load_reservation = (reg_t)-1; } void update_histogram(size_t pc); @@ -95,10 +100,10 @@ private: disassembler_t* disassembler; state_t state; uint32_t id; + int xlen; bool run; // !reset bool debug; bool histogram_enabled; - bool rv64; bool serialized; std::vector<insn_desc_t> instructions; diff --git a/riscv/rocc.cc b/riscv/rocc.cc index e51aee5..7988c01 100644 --- a/riscv/rocc.cc +++ b/riscv/rocc.cc @@ -5,7 +5,6 @@ #define customX(n) \ static reg_t c##n(processor_t* p, insn_t insn, reg_t pc) \ { \ - require_accelerator; \ rocc_t* rocc = static_cast<rocc_t*>(p->get_extension()); \ rocc_insn_union_t u; \ u.i = insn; \ diff --git a/riscv/trap.cc b/riscv/trap.cc index ead3a00..e1346e7 100644 --- a/riscv/trap.cc +++ b/riscv/trap.cc @@ -11,5 +11,5 @@ const char* trap_t::name() void mem_trap_t::side_effects(state_t* state) { - state->badvaddr = badvaddr; + state->mbadaddr = badvaddr; } diff --git a/riscv/trap.h b/riscv/trap.h index 53df4f4..7110073 100644 --- a/riscv/trap.h +++ b/riscv/trap.h @@ -45,14 +45,12 @@ 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_PRIVILEGED_INSTRUCTION, privileged_instruction) -DECLARE_TRAP(CAUSE_FP_DISABLED, fp_disabled) -DECLARE_TRAP(CAUSE_SYSCALL, syscall) +DECLARE_TRAP(CAUSE_SCALL, scall) +DECLARE_TRAP(CAUSE_MCALL, mcall) DECLARE_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_TRAP(CAUSE_ACCELERATOR_DISABLED, accelerator_disabled) #endif |