From: Andrew Waterman Date: Sat, 24 Mar 2012 19:54:03 +0000 (-0700) Subject: new supervisor mode X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=01db50f070d576e433d2b93ad061a0d8239e7b0c;p=riscv-isa-sim.git new supervisor mode --- diff --git a/riscv/decode.h b/riscv/decode.h index d7e91f2..3256f1b 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -3,6 +3,7 @@ #define __STDC_LIMIT_MACROS #include +#include "pcr.h" typedef int int128_t __attribute__((mode(TI))); typedef unsigned int uint128_t __attribute__((mode(TI))); @@ -31,21 +32,6 @@ const int BIGIMM_BITS = 20; const int BRANCH_ALIGN_BITS = 1; const int JUMP_ALIGN_BITS = 1; -#define SR_ET 0x0000000000000001ULL -#define SR_EF 0x0000000000000002ULL -#define SR_EV 0x0000000000000004ULL -#define SR_EC 0x0000000000000008ULL -#define SR_PS 0x0000000000000010ULL -#define SR_S 0x0000000000000020ULL -#define SR_UX 0x0000000000000040ULL -#define SR_SX 0x0000000000000080ULL -#define SR_IM 0x000000000000FF00ULL -#define SR_VM 0x0000000000010000ULL -#define SR_ZERO ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_UX|SR_SX|SR_IM|SR_VM) -#define SR_IM_SHIFT 8 -#define IPI_IRQ 5 -#define TIMER_IRQ 7 - #define FP_RD_NE 0 #define FP_RD_0 1 #define FP_RD_DN 2 diff --git a/riscv/disasm.cc b/riscv/disasm.cc index 3de9741..07c7bcc 100644 --- a/riscv/disasm.cc +++ b/riscv/disasm.cc @@ -219,7 +219,7 @@ class pcr_reg_t : public arg_t virtual std::string to_string(insn_t insn) const { std::stringstream s; - s << "pcr" << insn.rtype.rs2; + s << "pcr" << insn.rtype.rs1; return s.str(); } }; @@ -565,19 +565,19 @@ disassembler::disassembler() DEFINE_DTYPE(rdtime); DEFINE_DTYPE(rdinstret); - add_insn(new disasm_insn_t("mtpcr", match_mtpcr, mask_mtpcr, xrs1_reg, pcr_reg)); + add_insn(new disasm_insn_t("mtpcr", match_mtpcr, mask_mtpcr | mask_rd, xrs2_reg, pcr_reg)); + add_insn(new disasm_insn_t("mtpcr", match_mtpcr, mask_mtpcr, xrd_reg, xrs2_reg, pcr_reg)); add_insn(new disasm_insn_t("mfpcr", match_mfpcr, mask_mfpcr, xrd_reg, pcr_reg)); - DEFINE_NOARG(cflush) + add_insn(new disasm_insn_t("setpcr", match_setpcr, mask_setpcr, xrd_reg, pcr_reg, imm)); + add_insn(new disasm_insn_t("clearpcr", match_clearpcr, mask_clearpcr, xrd_reg, pcr_reg, imm)); DEFINE_NOARG(eret) - DEFINE_DTYPE(ei) - DEFINE_DTYPE(di) + DEFINE_NOARG(cflush) DEFINE_RS1(vxcptsave); DEFINE_RS1(vxcptrestore); DEFINE_NOARG(vxcptkill); DEFINE_RS1(vxcptevac); - DEFINE_NOARG(vxcptwait); DEFINE_NOARG(vxcpthold); DEFINE_RS1_RS2(venqcmd); DEFINE_RS1_RS2(venqimm1); diff --git a/riscv/htif.cc b/riscv/htif.cc index 9aa9a7c..8a9cd30 100644 --- a/riscv/htif.cc +++ b/riscv/htif.cc @@ -135,18 +135,18 @@ int htif_t::wait_for_packet() sim->mmu->store_uint64((p.addr+i)*HTIF_DATA_ALIGN, p.data[i]); break; case APP_CMD_READ_CONTROL_REG: - assert(p.addr == 16); + assert(p.addr == PCR_TOHOST); assert(p.data_size == 1); ackpacket.data_size = 1; memcpy(ackpacket.data, &sim->tohost, sizeof(reg_t)); break; case APP_CMD_WRITE_CONTROL_REG: - assert(p.addr == 17 || p.addr == 15); + assert(p.addr == PCR_FROMHOST || p.addr == PCR_RESET); assert(p.data_size == 1); sim->tohost = 0; - if (p.addr == 17) + if (p.addr == PCR_FROMHOST) memcpy(&sim->fromhost, p.data, sizeof(reg_t)); - else if (p.addr == 15) + else if (p.addr == PCR_RESET) { bool next_reset = p.data[0] & 1; if (!reset && next_reset) diff --git a/riscv/insns/clearpcr.h b/riscv/insns/clearpcr.h new file mode 100644 index 0000000..7acf221 --- /dev/null +++ b/riscv/insns/clearpcr.h @@ -0,0 +1,4 @@ +require_supervisor; +reg_t temp = get_pcr(insn.rtype.rs1); +set_pcr(insn.rtype.rs1, temp & ~SIMM); +RD = temp; diff --git a/riscv/insns/di.h b/riscv/insns/di.h deleted file mode 100644 index 31280d5..0000000 --- a/riscv/insns/di.h +++ /dev/null @@ -1,4 +0,0 @@ -require_supervisor; -uint32_t temp = sr; -set_sr(sr & ~SR_ET); -RD = temp; diff --git a/riscv/insns/ei.h b/riscv/insns/ei.h deleted file mode 100644 index 8306aeb..0000000 --- a/riscv/insns/ei.h +++ /dev/null @@ -1,4 +0,0 @@ -require_supervisor; -uint32_t temp = sr; -set_sr(sr | SR_ET); -RD = temp; diff --git a/riscv/insns/eret.h b/riscv/insns/eret.h index 46d5bed..cd968bd 100644 --- a/riscv/insns/eret.h +++ b/riscv/insns/eret.h @@ -1,5 +1,5 @@ require_supervisor; if(sr & SR_ET) throw trap_illegal_instruction; -set_sr(((sr & SR_PS) ? sr : (sr & ~SR_S)) | SR_ET); +set_pcr(PCR_SR, ((sr & SR_PS) ? sr : (sr & ~SR_S)) | SR_ET); set_pc(epc); diff --git a/riscv/insns/mfpcr.h b/riscv/insns/mfpcr.h index c686669..f7aea9f 100644 --- a/riscv/insns/mfpcr.h +++ b/riscv/insns/mfpcr.h @@ -1,55 +1,2 @@ require_supervisor; - -reg_t val; - -switch(insn.rtype.rs2) -{ - case 0: - val = sr; - break; - case 1: - val = epc; - break; - case 2: - val = badvaddr; - break; - case 3: - val = evec; - break; - case 4: - val = count; - break; - case 5: - val = compare; - break; - case 6: - val = cause; - break; - case 7: - val = mmu.get_ptbr(); - break; - - case 10: - val = id; - break; - - case 12: - val = pcr_k0; - break; - case 13: - val = pcr_k1; - break; - - case 17: - val = sim.get_fromhost(); - break; - - case 18: - val = vecbanks; - break; - - default: - val = -1; -} - -RD = sext_xprlen(val); +RD = get_pcr(insn.rtype.rs1); diff --git a/riscv/insns/mtpcr.h b/riscv/insns/mtpcr.h index f06fcf3..5cd0134 100644 --- a/riscv/insns/mtpcr.h +++ b/riscv/insns/mtpcr.h @@ -1,47 +1,4 @@ require_supervisor; - -switch(insn.rtype.rs2) -{ - case 0: - set_sr(RS1); - break; - case 1: - epc = RS1; - break; - case 3: - evec = RS1; - break; - case 4: - count = RS1; - break; - case 5: - interrupts_pending &= ~(1 << TIMER_IRQ); - compare = RS1; - break; - case 7: - mmu.set_ptbr(RS1); - break; - - case 8: - sim.send_ipi(RS1); - break; - case 9: - interrupts_pending &= ~(1 << IPI_IRQ); - break; - - case 12: - pcr_k0 = RS1; - break; - case 13: - pcr_k1 = RS1; - break; - - case 16: - sim.set_tohost(RS1); - break; - - case 18: - vecbanks = RS1 & 0xff; - vecbanks_count = __builtin_popcountll(vecbanks); - break; -} +reg_t val = get_pcr(insn.rtype.rs1); +set_pcr(insn.rtype.rs1, RS2); +RD = val; diff --git a/riscv/insns/setpcr.h b/riscv/insns/setpcr.h new file mode 100644 index 0000000..d645626 --- /dev/null +++ b/riscv/insns/setpcr.h @@ -0,0 +1,4 @@ +require_supervisor; +reg_t temp = get_pcr(insn.rtype.rs1); +set_pcr(insn.rtype.rs1, temp | SIMM); +RD = temp; diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 55273f3..c8eec16 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -63,7 +63,7 @@ pte_t mmu_t::walk(reg_t addr) // 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) != addr) + if (((sreg_t)addr << shift >> shift) != (sreg_t)addr) ; else if(!vm_enabled) { diff --git a/riscv/opcodes.h b/riscv/opcodes.h index feeca92..52af654 100644 --- a/riscv/opcodes.h +++ b/riscv/opcodes.h @@ -23,7 +23,7 @@ DECLARE_INSN(fcvt_d_w, 0xe0d3, 0x3ff1ff) DECLARE_INSN(lw, 0x103, 0x3ff) DECLARE_INSN(add, 0x33, 0x1ffff) DECLARE_INSN(fcvt_d_s, 0x100d3, 0x3ff1ff) -DECLARE_INSN(mfpcr, 0x17b, 0x7c1ffff) +DECLARE_INSN(mfpcr, 0x17b, 0x3fffff) DECLARE_INSN(c_fsd, 0x18, 0x1f) DECLARE_INSN(fmax_d, 0x190d3, 0x1ffff) DECLARE_INSN(bne, 0xe3, 0x3ff) @@ -33,10 +33,10 @@ DECLARE_INSN(vlh, 0x8b, 0x3fffff) DECLARE_INSN(bgeu, 0x3e3, 0x3ff) DECLARE_INSN(vflstd, 0x158b, 0x1ffff) DECLARE_INSN(c_li, 0x0, 0x1f) -DECLARE_INSN(di, 0xfb, 0x7ffffff) +DECLARE_INSN(fadd_d, 0xd3, 0x1f1ff) DECLARE_INSN(sltiu, 0x193, 0x3ff) -DECLARE_INSN(mtpcr, 0x1fb, 0xf801ffff) -DECLARE_INSN(vxcptwait, 0x180fb, 0xffffffff) +DECLARE_INSN(mtpcr, 0x1fb, 0x1ffff) +DECLARE_INSN(vlb, 0xb, 0x3fffff) DECLARE_INSN(stop, 0x177, 0xffffffff) DECLARE_INSN(vld, 0x18b, 0x3fffff) DECLARE_INSN(c_slli, 0x19, 0x1c1f) @@ -46,7 +46,7 @@ DECLARE_INSN(fcvt_s_w, 0xe053, 0x3ff1ff) DECLARE_INSN(vflstw, 0x150b, 0x1ffff) DECLARE_INSN(mul, 0x433, 0x1ffff) DECLARE_INSN(c_lw, 0xa, 0x1f) -DECLARE_INSN(vxcptevac, 0x1807b, 0xf83fffff) +DECLARE_INSN(vxcptevac, 0x237b, 0xf83fffff) DECLARE_INSN(vlw, 0x10b, 0x3fffff) DECLARE_INSN(vssegstw, 0x90f, 0xfff) DECLARE_INSN(amominu_d, 0x19ab, 0x1ffff) @@ -70,7 +70,6 @@ DECLARE_INSN(mftx_s, 0x1c053, 0x3fffff) DECLARE_INSN(vssegsth, 0x88f, 0xfff) DECLARE_INSN(vvcfgivl, 0xf3, 0x3ff) DECLARE_INSN(j, 0x67, 0x7f) -DECLARE_INSN(ei, 0x7b, 0x7ffffff) DECLARE_INSN(fence, 0x12f, 0x3ff) DECLARE_INSN(vsw, 0x10f, 0x3fffff) DECLARE_INSN(fnmsub_s, 0x4b, 0x1ff) @@ -86,7 +85,6 @@ DECLARE_INSN(vsetvl, 0x2f3, 0x3fffff) DECLARE_INSN(fle_d, 0x170d3, 0x1ffff) DECLARE_INSN(fence_i, 0xaf, 0x3ff) DECLARE_INSN(vlsegbu, 0x220b, 0x1ffff) -DECLARE_INSN(vlsegstb, 0x80b, 0xfff) DECLARE_INSN(fnmsub_d, 0xcb, 0x1ff) DECLARE_INSN(addw, 0x3b, 0x1ffff) DECLARE_INSN(sll, 0xb3, 0x1ffff) @@ -127,13 +125,14 @@ DECLARE_INSN(c_add3, 0x1c, 0x31f) DECLARE_INSN(sraiw, 0x1029b, 0x3f83ff) DECLARE_INSN(vssegd, 0x218f, 0x1ffff) DECLARE_INSN(srl, 0x2b3, 0x1ffff) -DECLARE_INSN(venqcmd, 0x181fb, 0xf801ffff) +DECLARE_INSN(venqcmd, 0x2b7b, 0xf801ffff) DECLARE_INSN(vfmts, 0x1973, 0x1ffff) -DECLARE_INSN(venqimm1, 0x1827b, 0xf801ffff) +DECLARE_INSN(venqimm1, 0x2f7b, 0xf801ffff) DECLARE_INSN(fsgnjx_s, 0x7053, 0x1ffff) DECLARE_INSN(vfmsv, 0x973, 0x3fffff) -DECLARE_INSN(venqimm2, 0x182fb, 0xf801ffff) +DECLARE_INSN(venqimm2, 0x337b, 0xf801ffff) DECLARE_INSN(fcvt_d_wu, 0xf0d3, 0x3ff1ff) +DECLARE_INSN(vxcptrestore, 0x77b, 0xf83fffff) DECLARE_INSN(vmts, 0x1873, 0x1ffff) DECLARE_INSN(or, 0x333, 0x1ffff) DECLARE_INSN(rdinstret, 0xa77, 0x7ffffff) @@ -156,7 +155,8 @@ DECLARE_INSN(vlstd, 0x118b, 0x1ffff) DECLARE_INSN(c_ld0, 0x8012, 0x801f) DECLARE_INSN(rdtime, 0x677, 0x7ffffff) DECLARE_INSN(andi, 0x393, 0x3ff) -DECLARE_INSN(venqcnt, 0x1837b, 0xf801ffff) +DECLARE_INSN(clearpcr, 0x7b, 0x3ff) +DECLARE_INSN(venqcnt, 0x377b, 0xf801ffff) DECLARE_INSN(fsgnjn_d, 0x60d3, 0x1ffff) DECLARE_INSN(fnmadd_s, 0x4f, 0x1ff) DECLARE_INSN(jal, 0x6f, 0x7f) @@ -216,8 +216,8 @@ DECLARE_INSN(vfmvv, 0x173, 0x3fffff) DECLARE_INSN(vlstwu, 0x130b, 0x1ffff) DECLARE_INSN(c_sub3, 0x11c, 0x31f) DECLARE_INSN(vsh, 0x8f, 0x3fffff) -DECLARE_INSN(vlb, 0xb, 0x3fffff) -DECLARE_INSN(vxcptsave, 0x1007b, 0xf83fffff) +DECLARE_INSN(vlsegstb, 0x80b, 0xfff) +DECLARE_INSN(vxcptsave, 0x37b, 0xf83fffff) DECLARE_INSN(vlsegstd, 0x98b, 0xfff) DECLARE_INSN(vflsegd, 0x258b, 0x1ffff) DECLARE_INSN(vflsegw, 0x250b, 0x1ffff) @@ -229,10 +229,9 @@ DECLARE_INSN(mulhu, 0x5b3, 0x1ffff) DECLARE_INSN(fence_v_g, 0x2af, 0x3ff) DECLARE_INSN(vmsv, 0x873, 0x3fffff) DECLARE_INSN(vmst, 0x1073, 0x1ffff) -DECLARE_INSN(fadd_d, 0xd3, 0x1f1ff) -DECLARE_INSN(vxcptrestore, 0x100fb, 0xf83fffff) +DECLARE_INSN(setpcr, 0xfb, 0x3ff) DECLARE_INSN(rdnpc, 0x26b, 0x7ffffff) -DECLARE_INSN(vxcpthold, 0x1817b, 0xffffffff) +DECLARE_INSN(vxcpthold, 0x277b, 0xffffffff) DECLARE_INSN(fcvt_s_l, 0xc053, 0x3ff1ff) DECLARE_INSN(vflsegstd, 0xd8b, 0xfff) DECLARE_INSN(c_add, 0x1a, 0x801f) @@ -243,7 +242,7 @@ DECLARE_INSN(fmadd_s, 0x43, 0x1ff) DECLARE_INSN(fcvt_w_s, 0xa053, 0x3ff1ff) DECLARE_INSN(vssegh, 0x208f, 0x1ffff) DECLARE_INSN(fsqrt_s, 0x4053, 0x3ff1ff) -DECLARE_INSN(vxcptkill, 0x1017b, 0xffffffff) +DECLARE_INSN(vxcptkill, 0xb7b, 0xffffffff) DECLARE_INSN(c_srai, 0x1019, 0x1c1f) DECLARE_INSN(amomin_w, 0x112b, 0x1ffff) DECLARE_INSN(fsgnjn_s, 0x6053, 0x1ffff) diff --git a/riscv/pcr.h b/riscv/pcr.h new file mode 100644 index 0000000..7659a97 --- /dev/null +++ b/riscv/pcr.h @@ -0,0 +1,90 @@ +#ifndef _RISCV_PCR_H +#define _RISCV_PCR_H + +#define SR_ET 0x00000001 +#define SR_EF 0x00000002 +#define SR_EV 0x00000004 +#define SR_EC 0x00000008 +#define SR_PS 0x00000010 +#define SR_S 0x00000020 +#define SR_U64 0x00000040 +#define SR_S64 0x00000080 +#define SR_VM 0x00000100 +#define SR_IM 0x00FF0000 +#define SR_ZERO ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_U64|SR_S64|SR_VM|SR_IM) +#define SR_IM_SHIFT 16 + +#define PCR_SR 0 +#define PCR_EPC 1 +#define PCR_BADVADDR 2 +#define PCR_EVEC 3 +#define PCR_COUNT 4 +#define PCR_COMPARE 5 +#define PCR_CAUSE 6 +#define PCR_PTBR 7 +#define PCR_SEND_IPI 8 +#define PCR_CLR_IPI 9 +#define PCR_COREID 10 +#define PCR_IMPL 11 +#define PCR_K0 12 +#define PCR_K1 13 +#define PCR_VECBANK 18 +#define PCR_VECCFG 19 +#define PCR_RESET 29 +#define PCR_TOHOST 30 +#define PCR_FROMHOST 31 + +#define IRQ_IPI 5 +#define IRQ_TIMER 7 + +#define CAUSE_MISALIGNED_FETCH 0 +#define CAUSE_FAULT_FETCH 1 +#define CAUSE_ILLEGAL_INSTRUCTION 2 +#define CAUSE_PRIVILEGED_INSTRUCTION 3 +#define CAUSE_FP_DISABLED 4 +#define CAUSE_SYSCALL 6 +#define CAUSE_BREAKPOINT 7 +#define CAUSE_MISALIGNED_LOAD 8 +#define CAUSE_MISALIGNED_STORE 9 +#define CAUSE_FAULT_LOAD 10 +#define CAUSE_FAULT_STORE 11 +#define CAUSE_VECTOR_DISABLED 12 +#define CAUSE_VECTOR_BANK 13 + +#define CAUSE_VECTOR_MISALIGNED_FETCH 24 +#define CAUSE_VECTOR_FAULT_FETCH 25 +#define CAUSE_VECTOR_ILLEGAL_INSTRUCTION 26 +#define CAUSE_VECTOR_ILLEGAL_COMMAND 27 +#define CAUSE_VECTOR_MISALIGNED_LOAD 28 +#define CAUSE_VECTOR_MISALIGNED_STORE 29 +#define CAUSE_VECTOR_FAULT_LOAD 30 +#define CAUSE_VECTOR_FAULT_STORE 31 + +#ifdef __riscv + +#define ASM_CR(r) _ASM_CR(r) +#define _ASM_CR(r) cr##r + +#ifndef __ASSEMBLER__ + +#define mtpcr(reg,val) ({ long __tmp = (long)(val), __tmp2; \ + asm volatile ("mtpcr %0,%1,cr%2" : "=r"(__tmp2) : "r"(__tmp),"i"(reg)); \ + __tmp2; }) + +#define mfpcr(reg) ({ long __tmp; \ + asm volatile ("mfpcr %0,cr%1" : "=r"(__tmp) : "i"(reg)); \ + __tmp; }) + +#define setpcr(reg,val) ({ long __tmp; \ + asm volatile ("setpcr %0,cr%2,%1" : "=r"(__tmp) : "i"(val), "i"(reg)); \ + __tmp; }) + +#define clearpcr(reg,val) ({ long __tmp; \ + asm volatile ("clearpcr %0,cr%2,%1" : "=r"(__tmp) : "i"(val), "i"(reg)); \ + __tmp; }) + +#endif + +#endif + +#endif diff --git a/riscv/processor.cc b/riscv/processor.cc index 9785799..322bf32 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -23,7 +23,7 @@ processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id, : sim(*_sim), mmu(*_mmu), id(_id) { reset(); - set_sr(sr | SR_EF | SR_EV); + set_pcr(PCR_SR, sr | SR_EF | SR_EV); utidx = _utidx; // microthreads don't possess their own microthreads @@ -43,7 +43,7 @@ void processor_t::reset() // is in supervisor mode, and in 64-bit mode, if supported, with traps // and virtual memory disabled. we accomplish this by setting EVEC to // 0x2000 and *enabling* traps, then sending the core an IPI. - set_sr(SR_S | SR_SX | SR_ET | SR_IM); + set_pcr(PCR_SR, SR_S | SR_S64 | SR_ET | SR_IM); evec = 0x2000; // the following state is undefined upon boot-up, @@ -73,32 +73,6 @@ void processor_t::reset() nfpr_use = 32; } -void processor_t::set_sr(uint32_t val) -{ - sr = val & ~SR_ZERO; // clear SR bits that read as zero - -#ifndef RISCV_ENABLE_64BIT - sr &= ~(SR_SX | SR_UX); // SX=UX=0 for RV32 implementations -#endif -#ifndef RISCV_ENABLE_FPU - sr &= ~SR_EF; -#endif -#ifndef RISCV_ENABLE_RVC - sr &= ~SR_EC; -#endif -#ifndef RISCV_ENABLE_VEC - sr &= ~SR_EV; -#endif - - // update MMU state and flush TLB - mmu.set_vm_enabled(sr & SR_VM); - mmu.set_supervisor(sr & SR_S); - mmu.flush_tlb(); - - // set the fixed-point register length - xprlen = ((sr & SR_S) ? (sr & SR_SX) : (sr & SR_UX)) ? 64 : 32; -} - void processor_t::set_fsr(uint32_t val) { fsr = val & ~FSR_ZERO; // clear FSR bits that read as zero @@ -127,7 +101,7 @@ void processor_t::take_interrupt() if(interrupts && (sr & SR_ET)) for(int i = 0; ; i++, interrupts >>= 1) if(interrupts & 1) - throw (trap_t)(trap_irq0 + i); + throw interrupt_t(i); } void processor_t::step(size_t n, bool noisy) @@ -178,6 +152,11 @@ void processor_t::step(size_t n, bool noisy) i++; take_trap(t,noisy); } + catch(interrupt_t t) + { + i++; + take_trap((1ULL << (8*sizeof(reg_t)-1)) + t.i, noisy); + } catch(vt_command_t cmd) { // this microthread has finished @@ -198,17 +177,17 @@ void processor_t::step(size_t n, bool noisy) uint32_t old_count = count; count += i; if(old_count < compare && uint64_t(old_count) + i >= compare) - interrupts_pending |= 1 << TIMER_IRQ; + interrupts_pending |= 1 << IRQ_TIMER; } -void processor_t::take_trap(trap_t t, bool noisy) +void processor_t::take_trap(reg_t t, bool noisy) { if(noisy) printf("core %3d: trap %s, pc 0x%016llx\n", - id, trap_name(t), (unsigned long long)pc); + id, trap_name(trap_t(t)), (unsigned long long)pc); // switch to supervisor, set previous supervisor bit, disable traps - set_sr((((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0)); + set_pcr(PCR_SR, (((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0)); cause = t; epc = pc; pc = evec; @@ -217,7 +196,7 @@ void processor_t::take_trap(trap_t t, bool noisy) void processor_t::deliver_ipi() { - interrupts_pending |= 1 << IPI_IRQ; + interrupts_pending |= 1 << IRQ_IPI; run = true; } @@ -228,3 +207,104 @@ void processor_t::disasm(insn_t insn, reg_t pc) printf("core %3d: 0x%016llx (0x%08x) %s\n", id, (unsigned long long)pc, insn.bits, disasm.disassemble(insn).c_str()); } + +void processor_t::set_pcr(int which, reg_t val) +{ + switch (which) + { + case PCR_SR: + sr = val & ~SR_ZERO; // clear SR bits that read as zero +#ifndef RISCV_ENABLE_64BIT + sr &= ~(SR_S64 | SR_U64); +#endif +#ifndef RISCV_ENABLE_FPU + sr &= ~SR_EF; +#endif +#ifndef RISCV_ENABLE_RVC + sr &= ~SR_EC; +#endif +#ifndef RISCV_ENABLE_VEC + sr &= ~SR_EV; +#endif + // update MMU state and flush TLB + mmu.set_vm_enabled(sr & SR_VM); + mmu.set_supervisor(sr & SR_S); + mmu.flush_tlb(); + // set the fixed-point register length + xprlen = ((sr & SR_S) ? (sr & SR_S64) : (sr & SR_U64)) ? 64 : 32; + break; + case PCR_EPC: + epc = val; + break; + case PCR_EVEC: + evec = val; + break; + case PCR_COUNT: + count = val; + break; + case PCR_COMPARE: + interrupts_pending &= ~(1 << IRQ_TIMER); + compare = val; + break; + case PCR_PTBR: + mmu.set_ptbr(val); + break; + case PCR_SEND_IPI: + sim.send_ipi(val); + break; + case PCR_CLR_IPI: + interrupts_pending &= ~(1 << IRQ_IPI); + break; + case PCR_K0: + pcr_k0 = val; + break; + case PCR_K1: + pcr_k1 = val; + break; + case PCR_VECBANK: + vecbanks = val & 0xff; + vecbanks_count = __builtin_popcountll(vecbanks); + break; + case PCR_TOHOST: + sim.set_tohost(val); + break; + } +} + +reg_t processor_t::get_pcr(int which) +{ + switch (which) + { + case PCR_SR: + return sr; + case PCR_EPC: + return epc; + case PCR_BADVADDR: + return badvaddr; + case PCR_EVEC: + return evec; + case PCR_COUNT: + return count; + case PCR_COMPARE: + return compare; + case PCR_CAUSE: + return cause; + case PCR_PTBR: + return mmu.get_ptbr(); + case PCR_COREID: + return id; + case PCR_IMPL: + return 1; + case PCR_K0: + return pcr_k0; + case PCR_K1: + return pcr_k1; + case PCR_VECBANK: + return vecbanks; + case PCR_TOHOST: + return sim.get_tohost(); + case PCR_FROMHOST: + return sim.get_fromhost(); + } + return -1; +} diff --git a/riscv/processor.h b/riscv/processor.h index 09fac00..db26f7e 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -41,10 +41,10 @@ private: reg_t evec; reg_t pcr_k0; reg_t pcr_k1; - uint32_t cause; + reg_t cause; uint32_t interrupts_pending; uint32_t id; - uint32_t sr; // only modify the status register using set_sr() + uint32_t sr; // only modify the status register using set_pcr() uint32_t fsr; uint32_t count; uint32_t compare; @@ -58,9 +58,10 @@ private: // functions void reset(); // resets architected state; halts processor if it was running void take_interrupt(); // take a trap if any interrupts are pending - void set_sr(uint32_t val); // set the status register + void set_pcr(int which, reg_t val); + reg_t get_pcr(int which); void set_fsr(uint32_t val); // set the floating-point status register - void take_trap(trap_t t, bool noisy); // take an exception + void take_trap(reg_t t, bool noisy); // take an exception void disasm(insn_t insn, reg_t pc); // disassemble and print an instruction // vector stuff diff --git a/riscv/sim.cc b/riscv/sim.cc index fb533a8..0d0b555 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -63,6 +63,11 @@ void sim_t::set_tohost(reg_t val) htif->wait_for_tohost_write(); } +reg_t sim_t::get_tohost() +{ + return tohost; +} + reg_t sim_t::get_fromhost() { htif->wait_for_fromhost_write(); diff --git a/riscv/sim.h b/riscv/sim.h index c4058d3..0d384c4 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -20,6 +20,7 @@ public: // communicate with the host machine void set_tohost(reg_t val); + reg_t get_tohost(); reg_t get_fromhost(); // deliver an IPI to a specific processor diff --git a/riscv/trap.h b/riscv/trap.h index 8e43c2c..d09da3f 100644 --- a/riscv/trap.h +++ b/riscv/trap.h @@ -18,14 +18,6 @@ DECLARE_TRAP(vector_bank), \ DECLARE_TRAP(vector_illegal_instruction), \ DECLARE_TRAP(reserved1), \ - DECLARE_TRAP(irq0), \ - DECLARE_TRAP(irq1), \ - DECLARE_TRAP(irq2), \ - DECLARE_TRAP(irq3), \ - DECLARE_TRAP(irq4), \ - DECLARE_TRAP(irq5), \ - DECLARE_TRAP(irq6), \ - DECLARE_TRAP(irq7), \ #define DECLARE_TRAP(x) trap_##x enum trap_t @@ -35,6 +27,7 @@ enum trap_t }; #undef DECLARE_TRAP +struct interrupt_t { interrupt_t(int which) : i(which) {} int i; }; struct halt_t {}; // thrown to stop the processor from running extern "C" const char* trap_name(trap_t t);