From 04c2d491c4bbb424a59273d4ebee62ddfe3379f9 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 11 Aug 2013 19:10:51 -0700 Subject: [PATCH] Instructions are no longer member functions --- configure | 2 +- configure.ac | 2 +- riscv/decode.h | 35 ++++---- riscv/htif.cc | 6 +- riscv/insn_template.cc | 4 +- riscv/insns/amoadd_d.h | 4 +- riscv/insns/amoadd_w.h | 4 +- riscv/insns/amoand_d.h | 4 +- riscv/insns/amoand_w.h | 4 +- riscv/insns/amomax_d.h | 4 +- riscv/insns/amomax_w.h | 4 +- riscv/insns/amomaxu_d.h | 4 +- riscv/insns/amomaxu_w.h | 4 +- riscv/insns/amomin_d.h | 4 +- riscv/insns/amomin_w.h | 4 +- riscv/insns/amominu_d.h | 4 +- riscv/insns/amominu_w.h | 4 +- riscv/insns/amoor_d.h | 4 +- riscv/insns/amoor_w.h | 4 +- riscv/insns/amoswap_d.h | 4 +- riscv/insns/amoswap_w.h | 4 +- riscv/insns/break.h | 2 +- riscv/insns/clearpcr.h | 4 +- riscv/insns/eret.h | 8 +- riscv/insns/fence_i.h | 2 +- riscv/insns/fld.h | 2 +- riscv/insns/flw.h | 2 +- riscv/insns/frsr.h | 2 +- riscv/insns/fsd.h | 2 +- riscv/insns/fssr.h | 4 +- riscv/insns/fsw.h | 2 +- riscv/insns/lb.h | 2 +- riscv/insns/lbu.h | 2 +- riscv/insns/ld.h | 2 +- riscv/insns/lh.h | 2 +- riscv/insns/lhu.h | 2 +- riscv/insns/lr_d.h | 3 +- riscv/insns/lr_w.h | 3 +- riscv/insns/lw.h | 2 +- riscv/insns/lwu.h | 2 +- riscv/insns/mfpcr.h | 2 +- riscv/insns/mtpcr.h | 4 +- riscv/insns/rdcycle.h | 2 +- riscv/insns/rdinstret.h | 2 +- riscv/insns/rdtime.h | 2 +- riscv/insns/sb.h | 2 +- riscv/insns/sc_d.h | 8 +- riscv/insns/sc_w.h | 8 +- riscv/insns/sd.h | 2 +- riscv/insns/setpcr.h | 4 +- riscv/insns/sh.h | 2 +- riscv/insns/slli.h | 2 +- riscv/insns/srai.h | 2 +- riscv/insns/srli.h | 2 +- riscv/insns/sw.h | 2 +- riscv/insns/syscall.h | 2 +- riscv/interactive.cc | 29 +++---- riscv/mmu.cc | 17 ++-- riscv/mmu.h | 27 +----- riscv/processor.cc | 181 ++++++++++++++++++++++------------------ riscv/processor.h | 69 ++++++++------- riscv/sim.cc | 18 ++-- riscv/sim.h | 2 +- riscv/trap.cc | 17 ++-- riscv/trap.h | 75 +++++++++++------ 65 files changed, 337 insertions(+), 309 deletions(-) diff --git a/configure b/configure index 32f29c2..9340bfb 100755 --- a/configure +++ b/configure @@ -4004,7 +4004,7 @@ fi CFLAGS="-Wall -O2 -Wno-unused" -CXXFLAGS="-Wall -O2 -std=c++0x -Wno-pmf-conversions" +CXXFLAGS="-Wall -O2 -std=c++0x" #------------------------------------------------------------------------- diff --git a/configure.ac b/configure.ac index bb672e6..335100b 100644 --- a/configure.ac +++ b/configure.ac @@ -72,7 +72,7 @@ AC_HEADER_STDC #------------------------------------------------------------------------- AC_SUBST([CFLAGS], ["-Wall -O2 -Wno-unused"]) -AC_SUBST([CXXFLAGS],["-Wall -O2 -std=c++0x -Wno-pmf-conversions"]) +AC_SUBST([CXXFLAGS],["-Wall -O2 -std=c++0x"]) #------------------------------------------------------------------------- # MCPPBS subproject list diff --git a/riscv/decode.h b/riscv/decode.h index 5f65c27..1529927 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -168,14 +168,15 @@ private: }; // helpful macros, etc -#define RS1 XPR[insn.rtype.rs1] -#define RS2 XPR[insn.rtype.rs2] -#define RD XPR.write_port(insn.rtype.rd) -#define RA XPR.write_port(1) -#define FRS1 FPR[insn.ftype.rs1] -#define FRS2 FPR[insn.ftype.rs2] -#define FRS3 FPR[insn.ftype.rs3] -#define FRD FPR.write_port(insn.ftype.rd) +#define MMU (*p->get_mmu()) +#define RS1 p->get_state()->XPR[insn.rtype.rs1] +#define RS2 p->get_state()->XPR[insn.rtype.rs2] +#define RD p->get_state()->XPR.write_port(insn.rtype.rd) +#define RA p->get_state()->XPR.write_port(1) +#define FRS1 p->get_state()->FPR[insn.ftype.rs1] +#define FRS2 p->get_state()->FPR[insn.ftype.rs2] +#define FRS3 p->get_state()->FPR[insn.ftype.rs3] +#define FRD p->get_state()->FPR.write_port(insn.ftype.rd) #define BIGIMM insn.ltype.bigimm #define SIMM insn.itype.imm12 #define BIMM ((signed)insn.btype.immlo | (insn.btype.immhi << IMMLO_BITS)) @@ -187,23 +188,23 @@ private: #define ITYPE_EADDR sext_xprlen(RS1 + SIMM) #define BTYPE_EADDR sext_xprlen(RS1 + BIMM) #define RM ({ int rm = insn.ftype.rm; \ - if(rm == 7) rm = (fsr & FSR_RD) >> FSR_RD_SHIFT; \ - if(rm > 4) throw trap_illegal_instruction; \ + if(rm == 7) rm = (p->get_state()->fsr & FSR_RD) >> FSR_RD_SHIFT; \ + if(rm > 4) throw trap_illegal_instruction(); \ rm; }) #define xpr64 (xprlen == 64) -#define require_supervisor if(unlikely(!(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 +#define require_supervisor if(unlikely(!(p->get_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 +# define require_fp throw trap_illegal_instruction() #else -# define require_fp if(unlikely(!(sr & SR_EF))) throw trap_fp_disabled +# define require_fp if(unlikely(!(p->get_state()->sr & SR_EF))) throw trap_fp_disabled() #endif #define cmp_trunc(reg) (reg_t(reg) << (64-xprlen)) -#define set_fp_exceptions ({ set_fsr(fsr | \ +#define set_fp_exceptions ({ p->set_fsr(p->get_state()->fsr | \ (softfloat_exceptionFlags << FSR_AEXC_SHIFT)); \ softfloat_exceptionFlags = 0; }) @@ -220,7 +221,7 @@ private: #define set_pc(x) \ do { if ((x) & 3 /* For now... */) \ - throw trap_instruction_address_misaligned; \ + throw trap_instruction_address_misaligned(); \ npc = (x); \ } while(0) diff --git a/riscv/htif.cc b/riscv/htif.cc index fc90375..679ef93 100644 --- a/riscv/htif.cc +++ b/riscv/htif.cc @@ -41,7 +41,7 @@ void htif_isasim_t::tick_once() uint64_t buf[hdr.data_size]; for (size_t i = 0; i < hdr.data_size; i++) - buf[i] = sim->mmu->load_uint64((hdr.addr+i)*HTIF_DATA_ALIGN); + buf[i] = sim->debug_mmu->load_uint64((hdr.addr+i)*HTIF_DATA_ALIGN); send(buf, hdr.data_size * sizeof(buf[0])); break; } @@ -49,7 +49,7 @@ void htif_isasim_t::tick_once() { const uint64_t* buf = (const uint64_t*)p.get_payload(); for (size_t i = 0; i < hdr.data_size; i++) - sim->mmu->store_uint64((hdr.addr+i)*HTIF_DATA_ALIGN, buf[i]); + sim->debug_mmu->store_uint64((hdr.addr+i)*HTIF_DATA_ALIGN, buf[i]); packet_header_t ack(HTIF_CMD_ACK, seqno, 0, 0); send(&ack, sizeof(ack)); @@ -77,7 +77,7 @@ void htif_isasim_t::tick_once() send(&old_val, sizeof(old_val)); if (regno == PCR_TOHOST) - sim->procs[coreid]->tohost = 0; + sim->procs[coreid]->state.tohost = 0; if (hdr.cmd == HTIF_CMD_WRITE_CONTROL_REG) { diff --git a/riscv/insn_template.cc b/riscv/insn_template.cc index 5bd986e..a901077 100644 --- a/riscv/insn_template.cc +++ b/riscv/insn_template.cc @@ -8,7 +8,7 @@ #include "internals.h" // ditto #include -reg_t processor_t::rv32_NAME(insn_t insn, reg_t pc) +reg_t rv32_NAME(processor_t* p, insn_t insn, reg_t pc) { int xprlen = 32; reg_t npc = sext_xprlen(pc + insn_length(OPCODE)); @@ -16,7 +16,7 @@ reg_t processor_t::rv32_NAME(insn_t insn, reg_t pc) return npc; } -reg_t processor_t::rv64_NAME(insn_t insn, reg_t pc) +reg_t rv64_NAME(processor_t* p, insn_t insn, reg_t pc) { int xprlen = 64; reg_t npc = sext_xprlen(pc + insn_length(OPCODE)); diff --git a/riscv/insns/amoadd_d.h b/riscv/insns/amoadd_d.h index b8450bf..bba975c 100644 --- a/riscv/insns/amoadd_d.h +++ b/riscv/insns/amoadd_d.h @@ -1,4 +1,4 @@ require_xpr64; -reg_t v = mmu.load_uint64(RS1); -mmu.store_uint64(RS1, RS2 + v); +reg_t v = MMU.load_uint64(RS1); +MMU.store_uint64(RS1, RS2 + v); RD = v; diff --git a/riscv/insns/amoadd_w.h b/riscv/insns/amoadd_w.h index 033b3c8..07c9c9a 100644 --- a/riscv/insns/amoadd_w.h +++ b/riscv/insns/amoadd_w.h @@ -1,3 +1,3 @@ -reg_t v = mmu.load_int32(RS1); -mmu.store_uint32(RS1, RS2 + v); +reg_t v = MMU.load_int32(RS1); +MMU.store_uint32(RS1, RS2 + v); RD = v; diff --git a/riscv/insns/amoand_d.h b/riscv/insns/amoand_d.h index 586eb7f..1bb3402 100644 --- a/riscv/insns/amoand_d.h +++ b/riscv/insns/amoand_d.h @@ -1,4 +1,4 @@ require_xpr64; -reg_t v = mmu.load_uint64(RS1); -mmu.store_uint64(RS1, RS2 & v); +reg_t v = MMU.load_uint64(RS1); +MMU.store_uint64(RS1, RS2 & v); RD = v; diff --git a/riscv/insns/amoand_w.h b/riscv/insns/amoand_w.h index 18a9249..91866dc 100644 --- a/riscv/insns/amoand_w.h +++ b/riscv/insns/amoand_w.h @@ -1,3 +1,3 @@ -reg_t v = mmu.load_int32(RS1); -mmu.store_uint32(RS1, RS2 & v); +reg_t v = MMU.load_int32(RS1); +MMU.store_uint32(RS1, RS2 & v); RD = v; diff --git a/riscv/insns/amomax_d.h b/riscv/insns/amomax_d.h index 1a0bc8a..dfd2b33 100644 --- a/riscv/insns/amomax_d.h +++ b/riscv/insns/amomax_d.h @@ -1,4 +1,4 @@ require_xpr64; -sreg_t v = mmu.load_int64(RS1); -mmu.store_uint64(RS1, std::max(sreg_t(RS2),v)); +sreg_t v = MMU.load_int64(RS1); +MMU.store_uint64(RS1, std::max(sreg_t(RS2),v)); RD = v; diff --git a/riscv/insns/amomax_w.h b/riscv/insns/amomax_w.h index ff9c2da..1f68a8b 100644 --- a/riscv/insns/amomax_w.h +++ b/riscv/insns/amomax_w.h @@ -1,3 +1,3 @@ -int32_t v = mmu.load_int32(RS1); -mmu.store_uint32(RS1, std::max(int32_t(RS2),v)); +int32_t v = MMU.load_int32(RS1); +MMU.store_uint32(RS1, std::max(int32_t(RS2),v)); RD = v; diff --git a/riscv/insns/amomaxu_d.h b/riscv/insns/amomaxu_d.h index ccfaf1d..8d50a0a 100644 --- a/riscv/insns/amomaxu_d.h +++ b/riscv/insns/amomaxu_d.h @@ -1,4 +1,4 @@ require_xpr64; -reg_t v = mmu.load_uint64(RS1); -mmu.store_uint64(RS1, std::max(RS2,v)); +reg_t v = MMU.load_uint64(RS1); +MMU.store_uint64(RS1, std::max(RS2,v)); RD = v; diff --git a/riscv/insns/amomaxu_w.h b/riscv/insns/amomaxu_w.h index 075847d..d507e4f 100644 --- a/riscv/insns/amomaxu_w.h +++ b/riscv/insns/amomaxu_w.h @@ -1,3 +1,3 @@ -uint32_t v = mmu.load_int32(RS1); -mmu.store_uint32(RS1, std::max(uint32_t(RS2),v)); +uint32_t v = MMU.load_int32(RS1); +MMU.store_uint32(RS1, std::max(uint32_t(RS2),v)); RD = (int32_t)v; diff --git a/riscv/insns/amomin_d.h b/riscv/insns/amomin_d.h index 4f3b6d6..a20ace8 100644 --- a/riscv/insns/amomin_d.h +++ b/riscv/insns/amomin_d.h @@ -1,4 +1,4 @@ require_xpr64; -sreg_t v = mmu.load_int64(RS1); -mmu.store_uint64(RS1, std::min(sreg_t(RS2),v)); +sreg_t v = MMU.load_int64(RS1); +MMU.store_uint64(RS1, std::min(sreg_t(RS2),v)); RD = v; diff --git a/riscv/insns/amomin_w.h b/riscv/insns/amomin_w.h index 529ad50..d8f95af 100644 --- a/riscv/insns/amomin_w.h +++ b/riscv/insns/amomin_w.h @@ -1,3 +1,3 @@ -int32_t v = mmu.load_int32(RS1); -mmu.store_uint32(RS1, std::min(int32_t(RS2),v)); +int32_t v = MMU.load_int32(RS1); +MMU.store_uint32(RS1, std::min(int32_t(RS2),v)); RD = v; diff --git a/riscv/insns/amominu_d.h b/riscv/insns/amominu_d.h index c09c51a..4f83c0f 100644 --- a/riscv/insns/amominu_d.h +++ b/riscv/insns/amominu_d.h @@ -1,4 +1,4 @@ require_xpr64; -reg_t v = mmu.load_uint64(RS1); -mmu.store_uint64(RS1, std::min(RS2,v)); +reg_t v = MMU.load_uint64(RS1); +MMU.store_uint64(RS1, std::min(RS2,v)); RD = v; diff --git a/riscv/insns/amominu_w.h b/riscv/insns/amominu_w.h index d8d6377..a3a537a 100644 --- a/riscv/insns/amominu_w.h +++ b/riscv/insns/amominu_w.h @@ -1,3 +1,3 @@ -uint32_t v = mmu.load_int32(RS1); -mmu.store_uint32(RS1, std::min(uint32_t(RS2),v)); +uint32_t v = MMU.load_int32(RS1); +MMU.store_uint32(RS1, std::min(uint32_t(RS2),v)); RD = (int32_t)v; diff --git a/riscv/insns/amoor_d.h b/riscv/insns/amoor_d.h index 76a4508..87b6f2a 100644 --- a/riscv/insns/amoor_d.h +++ b/riscv/insns/amoor_d.h @@ -1,4 +1,4 @@ require_xpr64; -reg_t v = mmu.load_uint64(RS1); -mmu.store_uint64(RS1, RS2 | v); +reg_t v = MMU.load_uint64(RS1); +MMU.store_uint64(RS1, RS2 | v); RD = v; diff --git a/riscv/insns/amoor_w.h b/riscv/insns/amoor_w.h index 741fbef..0733fad 100644 --- a/riscv/insns/amoor_w.h +++ b/riscv/insns/amoor_w.h @@ -1,3 +1,3 @@ -reg_t v = mmu.load_int32(RS1); -mmu.store_uint32(RS1, RS2 | v); +reg_t v = MMU.load_int32(RS1); +MMU.store_uint32(RS1, RS2 | v); RD = v; diff --git a/riscv/insns/amoswap_d.h b/riscv/insns/amoswap_d.h index 43e3538..3423b91 100644 --- a/riscv/insns/amoswap_d.h +++ b/riscv/insns/amoswap_d.h @@ -1,4 +1,4 @@ require_xpr64; -reg_t v = mmu.load_uint64(RS1); -mmu.store_uint64(RS1, RS2); +reg_t v = MMU.load_uint64(RS1); +MMU.store_uint64(RS1, RS2); RD = v; diff --git a/riscv/insns/amoswap_w.h b/riscv/insns/amoswap_w.h index 30e6102..b888235 100644 --- a/riscv/insns/amoswap_w.h +++ b/riscv/insns/amoswap_w.h @@ -1,3 +1,3 @@ -reg_t v = mmu.load_int32(RS1); -mmu.store_uint32(RS1, RS2); +reg_t v = MMU.load_int32(RS1); +MMU.store_uint32(RS1, RS2); RD = v; diff --git a/riscv/insns/break.h b/riscv/insns/break.h index 7fd3d66..c22776c 100644 --- a/riscv/insns/break.h +++ b/riscv/insns/break.h @@ -1 +1 @@ -throw trap_breakpoint; +throw trap_breakpoint(); diff --git a/riscv/insns/clearpcr.h b/riscv/insns/clearpcr.h index 7acf221..56c3584 100644 --- a/riscv/insns/clearpcr.h +++ b/riscv/insns/clearpcr.h @@ -1,4 +1,2 @@ require_supervisor; -reg_t temp = get_pcr(insn.rtype.rs1); -set_pcr(insn.rtype.rs1, temp & ~SIMM); -RD = temp; +RD = p->set_pcr(insn.rtype.rs1, p->get_pcr(insn.rtype.rs1) & ~SIMM); diff --git a/riscv/insns/eret.h b/riscv/insns/eret.h index 9ea8baf..d4517ee 100644 --- a/riscv/insns/eret.h +++ b/riscv/insns/eret.h @@ -1,5 +1,5 @@ require_supervisor; -set_pcr(PCR_SR, ((sr & ~(SR_S | SR_EI)) | - ((sr & SR_PS) ? SR_S : 0)) | - ((sr & SR_PEI) ? SR_EI : 0)); -set_pc(epc); +p->set_pcr(PCR_SR, ((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); diff --git a/riscv/insns/fence_i.h b/riscv/insns/fence_i.h index a2dbffe..38dcaf3 100644 --- a/riscv/insns/fence_i.h +++ b/riscv/insns/fence_i.h @@ -1 +1 @@ -mmu.flush_icache(); +MMU.flush_icache(); diff --git a/riscv/insns/fld.h b/riscv/insns/fld.h index bc8b9c7..2704a4d 100644 --- a/riscv/insns/fld.h +++ b/riscv/insns/fld.h @@ -1,2 +1,2 @@ require_fp; -FRD = mmu.load_int64(ITYPE_EADDR); +FRD = MMU.load_int64(ITYPE_EADDR); diff --git a/riscv/insns/flw.h b/riscv/insns/flw.h index 74374b9..afab636 100644 --- a/riscv/insns/flw.h +++ b/riscv/insns/flw.h @@ -1,2 +1,2 @@ require_fp; -FRD = mmu.load_int32(ITYPE_EADDR); +FRD = MMU.load_int32(ITYPE_EADDR); diff --git a/riscv/insns/frsr.h b/riscv/insns/frsr.h index 29debc4..ef121e3 100644 --- a/riscv/insns/frsr.h +++ b/riscv/insns/frsr.h @@ -1,2 +1,2 @@ require_fp; -RD = fsr; +RD = p->get_fsr(); diff --git a/riscv/insns/fsd.h b/riscv/insns/fsd.h index 95fbd26..0e1c38a 100644 --- a/riscv/insns/fsd.h +++ b/riscv/insns/fsd.h @@ -1,2 +1,2 @@ require_fp; -mmu.store_uint64(BTYPE_EADDR, FRS2); +MMU.store_uint64(BTYPE_EADDR, FRS2); diff --git a/riscv/insns/fssr.h b/riscv/insns/fssr.h index cc6f9ea..a9acca6 100644 --- a/riscv/insns/fssr.h +++ b/riscv/insns/fssr.h @@ -1,4 +1,2 @@ require_fp; -uint32_t tmp = fsr; -set_fsr(RS1); -RD = tmp; +RD = p->set_fsr(RS1); diff --git a/riscv/insns/fsw.h b/riscv/insns/fsw.h index 59d9066..c921123 100644 --- a/riscv/insns/fsw.h +++ b/riscv/insns/fsw.h @@ -1,2 +1,2 @@ require_fp; -mmu.store_uint32(BTYPE_EADDR, FRS2); +MMU.store_uint32(BTYPE_EADDR, FRS2); diff --git a/riscv/insns/lb.h b/riscv/insns/lb.h index c88ee2d..56a5f32 100644 --- a/riscv/insns/lb.h +++ b/riscv/insns/lb.h @@ -1 +1 @@ -RD = mmu.load_int8(ITYPE_EADDR); +RD = MMU.load_int8(ITYPE_EADDR); diff --git a/riscv/insns/lbu.h b/riscv/insns/lbu.h index bcef96b..66621c0 100644 --- a/riscv/insns/lbu.h +++ b/riscv/insns/lbu.h @@ -1 +1 @@ -RD = mmu.load_uint8(ITYPE_EADDR); +RD = MMU.load_uint8(ITYPE_EADDR); diff --git a/riscv/insns/ld.h b/riscv/insns/ld.h index 2bbe5c3..f214294 100644 --- a/riscv/insns/ld.h +++ b/riscv/insns/ld.h @@ -1,2 +1,2 @@ require_xpr64; -RD = mmu.load_int64(ITYPE_EADDR); +RD = MMU.load_int64(ITYPE_EADDR); diff --git a/riscv/insns/lh.h b/riscv/insns/lh.h index c04302c..fea2a8e 100644 --- a/riscv/insns/lh.h +++ b/riscv/insns/lh.h @@ -1 +1 @@ -RD = mmu.load_int16(ITYPE_EADDR); +RD = MMU.load_int16(ITYPE_EADDR); diff --git a/riscv/insns/lhu.h b/riscv/insns/lhu.h index 99d0985..71c21be 100644 --- a/riscv/insns/lhu.h +++ b/riscv/insns/lhu.h @@ -1 +1 @@ -RD = mmu.load_uint16(ITYPE_EADDR); +RD = MMU.load_uint16(ITYPE_EADDR); diff --git a/riscv/insns/lr_d.h b/riscv/insns/lr_d.h index 5c8eff1..3d2aace 100644 --- a/riscv/insns/lr_d.h +++ b/riscv/insns/lr_d.h @@ -1,2 +1,3 @@ require_xpr64; -RD = mmu.load_reserved_int64(RS1); +p->get_state()->load_reservation = RS1; +RD = MMU.load_int64(RS1); diff --git a/riscv/insns/lr_w.h b/riscv/insns/lr_w.h index 3ac4746..7ff48ea 100644 --- a/riscv/insns/lr_w.h +++ b/riscv/insns/lr_w.h @@ -1 +1,2 @@ -RD = mmu.load_reserved_int32(RS1); +p->get_state()->load_reservation = RS1; +RD = MMU.load_int32(RS1); diff --git a/riscv/insns/lw.h b/riscv/insns/lw.h index 639d0e7..77f735e 100644 --- a/riscv/insns/lw.h +++ b/riscv/insns/lw.h @@ -1 +1 @@ -RD = mmu.load_int32(ITYPE_EADDR); +RD = MMU.load_int32(ITYPE_EADDR); diff --git a/riscv/insns/lwu.h b/riscv/insns/lwu.h index b3ebc0c..e731178 100644 --- a/riscv/insns/lwu.h +++ b/riscv/insns/lwu.h @@ -1,2 +1,2 @@ require_xpr64; -RD = mmu.load_uint32(ITYPE_EADDR); +RD = MMU.load_uint32(ITYPE_EADDR); diff --git a/riscv/insns/mfpcr.h b/riscv/insns/mfpcr.h index f7aea9f..0f23426 100644 --- a/riscv/insns/mfpcr.h +++ b/riscv/insns/mfpcr.h @@ -1,2 +1,2 @@ require_supervisor; -RD = get_pcr(insn.rtype.rs1); +RD = p->get_pcr(insn.rtype.rs1); diff --git a/riscv/insns/mtpcr.h b/riscv/insns/mtpcr.h index 5cd0134..770dfd5 100644 --- a/riscv/insns/mtpcr.h +++ b/riscv/insns/mtpcr.h @@ -1,4 +1,2 @@ require_supervisor; -reg_t val = get_pcr(insn.rtype.rs1); -set_pcr(insn.rtype.rs1, RS2); -RD = val; +RD = p->set_pcr(insn.rtype.rs1, RS2); diff --git a/riscv/insns/rdcycle.h b/riscv/insns/rdcycle.h index 9b966a6..7ebe986 100644 --- a/riscv/insns/rdcycle.h +++ b/riscv/insns/rdcycle.h @@ -1 +1 @@ -RD = cycle; +RD = sext_xprlen(p->get_state()->cycle); diff --git a/riscv/insns/rdinstret.h b/riscv/insns/rdinstret.h index 9b966a6..df56cb7 100644 --- a/riscv/insns/rdinstret.h +++ b/riscv/insns/rdinstret.h @@ -1 +1 @@ -RD = cycle; +#include "insns/rdcycle.h" diff --git a/riscv/insns/rdtime.h b/riscv/insns/rdtime.h index 9b966a6..df56cb7 100644 --- a/riscv/insns/rdtime.h +++ b/riscv/insns/rdtime.h @@ -1 +1 @@ -RD = cycle; +#include "insns/rdcycle.h" diff --git a/riscv/insns/sb.h b/riscv/insns/sb.h index 54176c0..db4d523 100644 --- a/riscv/insns/sb.h +++ b/riscv/insns/sb.h @@ -1 +1 @@ -mmu.store_uint8(BTYPE_EADDR, RS2); +MMU.store_uint8(BTYPE_EADDR, RS2); diff --git a/riscv/insns/sc_d.h b/riscv/insns/sc_d.h index a29b9f7..9ad962c 100644 --- a/riscv/insns/sc_d.h +++ b/riscv/insns/sc_d.h @@ -1,2 +1,8 @@ require_xpr64; -RD = mmu.store_conditional_uint64(RS1, RS2); +if (RS1 == p->get_state()->load_reservation) +{ + MMU.store_uint64(RS1, RS2); + RD = 0; +} +else + RD = 1; diff --git a/riscv/insns/sc_w.h b/riscv/insns/sc_w.h index caf7683..3ad79ac 100644 --- a/riscv/insns/sc_w.h +++ b/riscv/insns/sc_w.h @@ -1 +1,7 @@ -RD = mmu.store_conditional_uint32(RS1, RS2); +if (RS1 == p->get_state()->load_reservation) +{ + MMU.store_uint32(RS1, RS2); + RD = 0; +} +else + RD = 1; diff --git a/riscv/insns/sd.h b/riscv/insns/sd.h index 558428e..24c0de9 100644 --- a/riscv/insns/sd.h +++ b/riscv/insns/sd.h @@ -1,2 +1,2 @@ require_xpr64; -mmu.store_uint64(BTYPE_EADDR, RS2); +MMU.store_uint64(BTYPE_EADDR, RS2); diff --git a/riscv/insns/setpcr.h b/riscv/insns/setpcr.h index d645626..4a25d80 100644 --- a/riscv/insns/setpcr.h +++ b/riscv/insns/setpcr.h @@ -1,4 +1,2 @@ require_supervisor; -reg_t temp = get_pcr(insn.rtype.rs1); -set_pcr(insn.rtype.rs1, temp | SIMM); -RD = temp; +RD = p->set_pcr(insn.rtype.rs1, p->get_pcr(insn.rtype.rs1) | SIMM); diff --git a/riscv/insns/sh.h b/riscv/insns/sh.h index 235e50e..69234dc 100644 --- a/riscv/insns/sh.h +++ b/riscv/insns/sh.h @@ -1 +1 @@ -mmu.store_uint16(BTYPE_EADDR, RS2); +MMU.store_uint16(BTYPE_EADDR, RS2); diff --git a/riscv/insns/slli.h b/riscv/insns/slli.h index bfaf430..151d970 100644 --- a/riscv/insns/slli.h +++ b/riscv/insns/slli.h @@ -3,6 +3,6 @@ if(xpr64) else { if(SHAMT & 0x20) - throw trap_illegal_instruction; + throw trap_illegal_instruction(); RD = sext32(RS1 << SHAMT); } diff --git a/riscv/insns/srai.h b/riscv/insns/srai.h index bb17d27..7360d5f 100644 --- a/riscv/insns/srai.h +++ b/riscv/insns/srai.h @@ -3,6 +3,6 @@ if(xpr64) else { if(SHAMT & 0x20) - throw trap_illegal_instruction; + throw trap_illegal_instruction(); RD = sext32(int32_t(RS1) >> SHAMT); } diff --git a/riscv/insns/srli.h b/riscv/insns/srli.h index 5378fd1..f5b8c02 100644 --- a/riscv/insns/srli.h +++ b/riscv/insns/srli.h @@ -3,6 +3,6 @@ if(xpr64) else { if(SHAMT & 0x20) - throw trap_illegal_instruction; + throw trap_illegal_instruction(); RD = sext32((uint32_t)RS1 >> SHAMT); } diff --git a/riscv/insns/sw.h b/riscv/insns/sw.h index 008d8c0..81ca71d 100644 --- a/riscv/insns/sw.h +++ b/riscv/insns/sw.h @@ -1 +1 @@ -mmu.store_uint32(BTYPE_EADDR, RS2); +MMU.store_uint32(BTYPE_EADDR, RS2); diff --git a/riscv/insns/syscall.h b/riscv/insns/syscall.h index 2c7199d..b31b7e6 100644 --- a/riscv/insns/syscall.h +++ b/riscv/insns/syscall.h @@ -1 +1 @@ -throw trap_syscall; +throw trap_syscall(); diff --git a/riscv/interactive.cc b/riscv/interactive.cc index fe70760..33efcfb 100644 --- a/riscv/interactive.cc +++ b/riscv/interactive.cc @@ -113,39 +113,39 @@ void sim_t::interactive_quit(const std::string& cmd, const std::vector& args) { if(args.size() != 1) - throw trap_illegal_instruction; + throw trap_illegal_instruction(); int p = atoi(args[0].c_str()); if(p >= (int)num_cores()) - throw trap_illegal_instruction; + throw trap_illegal_instruction(); - return procs[p]->pc; + return procs[p]->state.pc; } reg_t sim_t::get_reg(const std::vector& args) { if(args.size() != 2) - throw trap_illegal_instruction; + throw trap_illegal_instruction(); int p = atoi(args[0].c_str()); int r = atoi(args[1].c_str()); if(p >= (int)num_cores() || r >= NXPR) - throw trap_illegal_instruction; + throw trap_illegal_instruction(); - return procs[p]->XPR[r]; + return procs[p]->state.XPR[r]; } reg_t sim_t::get_freg(const std::vector& args) { if(args.size() != 2) - throw trap_illegal_instruction; + throw trap_illegal_instruction(); int p = atoi(args[0].c_str()); int r = atoi(args[1].c_str()); if(p >= (int)num_cores() || r >= NFPR) - throw trap_illegal_instruction; + throw trap_illegal_instruction(); - return procs[p]->FPR[r]; + return procs[p]->state.FPR[r]; } void sim_t::interactive_reg(const std::string& cmd, const std::vector& args) @@ -177,15 +177,16 @@ 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_illegal_instruction(); std::string addr_str = args[0]; + mmu_t* mmu = debug_mmu; if(args.size() == 2) { int p = atoi(args[0].c_str()); if(p >= (int)num_cores()) - throw trap_illegal_instruction; - mmu->set_ptbr(procs[p]->mmu.get_ptbr()); + throw trap_illegal_instruction(); + mmu = procs[p]->get_mmu(); addr_str = args[1]; } @@ -220,12 +221,12 @@ void sim_t::interactive_mem(const std::string& cmd, const std::vector& args) { if(args.size() != 1) - throw trap_illegal_instruction; + throw trap_illegal_instruction(); reg_t addr = strtol(args[0].c_str(),NULL,16); char ch; - while((ch = mmu->load_uint8(addr++))) + while((ch = debug_mmu->load_uint8(addr++))) putchar(ch); putchar('\n'); diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 01cbb97..96884d6 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -5,8 +5,7 @@ #include "processor.h" mmu_t::mmu_t(char* _mem, size_t _memsz) - : mem(_mem), memsz(_memsz), badvaddr(0), - ptbr(0), proc(NULL) + : mem(_mem), memsz(_memsz), proc(NULL) { flush_tlb(); } @@ -27,7 +26,6 @@ void mmu_t::flush_tlb() memset(tlb_store_tag, -1, sizeof(tlb_store_tag)); flush_icache(); - yield_load_reservation(); } reg_t mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch) @@ -38,7 +36,7 @@ reg_t mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch) reg_t pte = walk(addr); reg_t pte_perm = pte & PTE_PERM; - if (proc == NULL || (proc->sr & SR_S)) + if (proc == NULL || (proc->state.sr & SR_S)) pte_perm = (pte_perm/(PTE_SX/PTE_UX)) & PTE_PERM; pte_perm |= pte & PTE_V; @@ -46,10 +44,11 @@ reg_t mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch) if(unlikely((pte_perm & perm) != perm)) { if (fetch) - throw trap_instruction_access_fault; + throw trap_instruction_access_fault(); - badvaddr = addr; - throw store ? trap_store_access_fault : trap_load_access_fault; + if (store) + throw trap_store_access_fault(addr); + throw trap_load_access_fault(addr); } reg_t pgoff = addr & (PGSIZE-1); @@ -77,14 +76,14 @@ pte_t mmu_t::walk(reg_t addr) int shift = 8*sizeof(reg_t) - VA_BITS; if (((sreg_t)addr << shift >> shift) != (sreg_t)addr) ; - else if (proc == NULL || !(proc->sr & SR_VM)) + else if (proc == NULL || !(proc->state.sr & SR_VM)) { if(addr < memsz) pte = PTE_V | PTE_PERM | ((addr >> PGSHIFT) << PGSHIFT); } else { - reg_t base = ptbr; + reg_t base = proc->get_state()->ptbr; reg_t ptd; int ptshift = (LEVELS-1)*PTIDXBITS; diff --git a/riscv/mmu.h b/riscv/mmu.h index bb35f70..b69de9c 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -33,16 +33,9 @@ public: #define load_func(type) \ type##_t load_##type(reg_t addr) { \ if(unlikely(addr % sizeof(type##_t))) \ - { \ - badvaddr = addr; \ - throw trap_load_address_misaligned; \ - } \ + throw trap_load_address_misaligned(addr); \ reg_t paddr = translate(addr, sizeof(type##_t), false, false); \ return *(type##_t*)(mem + paddr); \ - } \ - type##_t load_reserved_##type(reg_t addr) { \ - load_reservation = addr; \ - return load_##type(addr); \ } // load value from memory at aligned address; zero extend to register width @@ -61,18 +54,9 @@ public: #define store_func(type) \ void store_##type(reg_t addr, type##_t val) { \ if(unlikely(addr % sizeof(type##_t))) \ - { \ - badvaddr = addr; \ - throw trap_store_address_misaligned; \ - } \ + throw trap_store_address_misaligned(addr); \ reg_t paddr = translate(addr, sizeof(type##_t), true, false); \ *(type##_t*)(mem + paddr) = val; \ - } \ - reg_t store_conditional_##type(reg_t addr, type##_t val) { \ - if (addr == load_reservation) { \ - store_##type(addr, val); \ - return 0; \ - } else return 1; \ } // store value to memory at aligned address @@ -111,23 +95,16 @@ public: return icache_data[idx]; } - reg_t get_badvaddr() { return badvaddr; } - reg_t get_ptbr() { return ptbr; } - void set_ptbr(reg_t addr) { ptbr = addr & ~(PGSIZE-1); } void set_processor(processor_t* p) { proc = p; flush_tlb(); } void flush_tlb(); void flush_icache(); - void yield_load_reservation() { load_reservation = -1; } void register_memtracer(memtracer_t*); private: char* mem; size_t memsz; - reg_t load_reservation; - reg_t badvaddr; - reg_t ptbr; processor_t* proc; memtracer_list_t tracer; diff --git a/riscv/processor.cc b/riscv/processor.cc index 4dff486..0510a3d 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -19,7 +19,9 @@ processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id) mmu.set_processor(this); #define DECLARE_INSN(name, match, mask) \ - register_insn(match, mask, (insn_func_t)&processor_t::rv32_##name, (insn_func_t)&processor_t::rv64_##name); + extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \ + extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \ + register_insn(match, mask, rv32_##name, rv64_##name); #include "opcodes.h" #undef DECLARE_INSN } @@ -28,17 +30,15 @@ processor_t::~processor_t() { } -void processor_t::reset(bool value) +void state_t::reset() { - if (run == !value) - return; - run = !value; - // 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 = 0; - set_pcr(PCR_SR, SR_S | SR_S64 | SR_IM); + sr = SR_S; +#ifdef RISCV_ENABLE_64BIT + sr |= SR_S64; +#endif pc = 0x2000; // the following state is undefined upon boot-up, @@ -55,23 +55,36 @@ void processor_t::reset(bool value) count = 0; compare = 0; cycle = 0; - set_fsr(0); + fsr = 0; + + load_reservation = -1; +} + +void processor_t::reset(bool value) +{ + if (run == !value) + return; + run = !value; + + state.reset(); } -void processor_t::set_fsr(uint32_t val) +uint32_t processor_t::set_fsr(uint32_t val) { - fsr = val & ~FSR_ZERO; // clear FSR bits that read as zero + uint32_t old_fsr = state.fsr; + state.fsr = val & ~FSR_ZERO; // clear FSR bits that read as zero + return old_fsr; } void processor_t::take_interrupt() { - uint32_t interrupts = (sr & SR_IP) >> SR_IP_SHIFT; - interrupts &= (sr & SR_IM) >> SR_IM_SHIFT; + uint32_t interrupts = (state.sr & SR_IP) >> SR_IP_SHIFT; + interrupts &= (state.sr & SR_IM) >> SR_IM_SHIFT; - if(interrupts && (sr & SR_EI)) - for(int i = 0; ; i++, interrupts >>= 1) - if(interrupts & 1) - throw interrupt_t(i); + if (interrupts && (state.sr & SR_EI)) + for (int i = 0; ; i++, interrupts >>= 1) + if (interrupts & 1) + throw trap_t((1ULL << ((state.sr & SR_S64) ? 63 : 31)) + i); } void processor_t::step(size_t n, bool noisy) @@ -80,20 +93,19 @@ void processor_t::step(size_t n, bool noisy) return; size_t i = 0; + reg_t npc = state.pc; + mmu_t& _mmu = mmu; + try { take_interrupt(); - mmu_t& _mmu = mmu; - reg_t npc = pc; - // execute_insn fetches and executes one instruction #define execute_insn(noisy) \ do { \ mmu_t::insn_fetch_t fetch = _mmu.load_insn(npc); \ if(noisy) disasm(fetch.insn, npc); \ npc = fetch.func(this, fetch.insn, npc); \ - pc = npc; \ } while(0) if(noisy) for( ; i < n; i++) // print out instructions as we go @@ -111,46 +123,45 @@ void processor_t::step(size_t n, bool noisy) for( ; i < n; i++) execute_insn(false); } + + state.pc = npc; } - catch(trap_t t) - { - // an exception occurred in the target processor - take_trap(t,noisy); - } - catch(interrupt_t t) + catch(trap_t& t) { - take_trap((1ULL << ((sr & SR_S64) ? 63 : 31)) + t.i, noisy); + take_trap(npc, t, noisy); } - cycle += i; + state.cycle += i; // update timer and possibly register a timer interrupt - uint32_t old_count = count; - count += i; - if(old_count < compare && uint64_t(old_count) + i >= compare) + uint32_t old_count = state.count; + state.count += i; + if(old_count < state.compare && uint64_t(old_count) + i >= state.compare) set_interrupt(IRQ_TIMER, true); } -void processor_t::take_trap(reg_t t, bool noisy) +void processor_t::take_trap(reg_t pc, trap_t& t, bool noisy) { if(noisy) { - if ((sreg_t)t < 0) + if ((sreg_t)t.cause() < 0) fprintf(stderr, "core %3d: interrupt %d, epc 0x%016" PRIx64 "\n", - id, uint8_t(t), pc); + id, uint8_t(t.cause()), pc); else fprintf(stderr, "core %3d: trap %s, epc 0x%016" PRIx64 "\n", - id, trap_name(trap_t(t)), pc); + id, t.name(), pc); } - // switch to supervisor, set previous supervisor bit, disable traps - set_pcr(PCR_SR, (((sr & ~SR_EI) | SR_S) & ~SR_PS & ~SR_PEI) | - ((sr & SR_S) ? SR_PS : 0) | - ((sr & SR_EI) ? SR_PEI : 0)); - cause = t; - epc = pc; - pc = evec; - badvaddr = mmu.get_badvaddr(); + // switch to supervisor, set previous supervisor bit, disable interrupts + set_pcr(PCR_SR, (((state.sr & ~SR_EI) | SR_S) & ~SR_PS & ~SR_PEI) | + ((state.sr & SR_S) ? SR_PS : 0) | + ((state.sr & SR_EI) ? SR_PEI : 0)); + yield_load_reservation(); + state.cause = t.cause(); + state.epc = pc; + state.pc = state.evec; + + t.side_effects(&state); // might set badvaddr etc. } void processor_t::deliver_ipi() @@ -164,42 +175,44 @@ void processor_t::disasm(insn_t insn, reg_t pc) // the disassembler is stateless, so we share it static disassembler disasm; fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIxFAST32 ") %s\n", - id, pc, insn.bits, disasm.disassemble(insn).c_str()); + id, state.pc, insn.bits, disasm.disassemble(insn).c_str()); } -void processor_t::set_pcr(int which, reg_t val) +reg_t processor_t::set_pcr(int which, reg_t val) { + reg_t old_pcr = get_pcr(which); + switch (which) { case PCR_SR: - sr = (val & ~SR_IP) | (sr & SR_IP); + state.sr = (val & ~SR_IP) | (state.sr & SR_IP); #ifndef RISCV_ENABLE_64BIT - sr &= ~(SR_S64 | SR_U64); + state.sr &= ~(SR_S64 | SR_U64); #endif #ifndef RISCV_ENABLE_FPU - sr &= ~SR_EF; + state.sr &= ~SR_EF; #endif #ifndef RISCV_ENABLE_VEC - sr &= ~SR_EV; + state.sr &= ~SR_EV; #endif - sr &= ~SR_ZERO; + state.sr &= ~SR_ZERO; mmu.flush_tlb(); break; case PCR_EPC: - epc = val; + state.epc = val; break; case PCR_EVEC: - evec = val; + state.evec = val; break; case PCR_COUNT: - count = val; + state.count = val; break; case PCR_COMPARE: set_interrupt(IRQ_TIMER, false); - compare = val; + state.compare = val; break; case PCR_PTBR: - mmu.set_ptbr(val); + state.ptbr = val & ~(PGSIZE-1); break; case PCR_SEND_IPI: sim.send_ipi(val); @@ -208,20 +221,22 @@ void processor_t::set_pcr(int which, reg_t val) set_interrupt(IRQ_IPI, val & 1); break; case PCR_K0: - pcr_k0 = val; + state.pcr_k0 = val; break; case PCR_K1: - pcr_k1 = val; + state.pcr_k1 = val; break; case PCR_TOHOST: - if (tohost == 0) - tohost = val; + if (state.tohost == 0) + state.tohost = val; break; case PCR_FROMHOST: set_interrupt(IRQ_HOST, val != 0); - fromhost = val; + state.fromhost = val; break; } + + return old_pcr; } reg_t processor_t::get_pcr(int which) @@ -229,37 +244,38 @@ reg_t processor_t::get_pcr(int which) switch (which) { case PCR_SR: - return sr; + return state.sr; case PCR_EPC: - return epc; + return state.epc; case PCR_BADVADDR: - return badvaddr; + return state.badvaddr; case PCR_EVEC: - return evec; + return state.evec; case PCR_COUNT: - return count; + return state.count; case PCR_COMPARE: - return compare; + return state.compare; case PCR_CAUSE: - return cause; + return state.cause; case PCR_PTBR: - return mmu.get_ptbr(); + return state.ptbr; case PCR_ASID: return 0; case PCR_FATC: mmu.flush_tlb(); + return 0; case PCR_HARTID: return id; case PCR_IMPL: return 1; case PCR_K0: - return pcr_k0; + return state.pcr_k0; case PCR_K1: - return pcr_k1; + return state.pcr_k1; case PCR_TOHOST: - return tohost; + return state.tohost; case PCR_FROMHOST: - return fromhost; + return state.fromhost; } return -1; } @@ -268,27 +284,26 @@ void processor_t::set_interrupt(int which, bool on) { uint32_t mask = (1 << (which + SR_IP_SHIFT)) & SR_IP; if (on) - sr |= mask; + state.sr |= mask; else - sr &= ~mask; + state.sr &= ~mask; +} + +static reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc) +{ + throw trap_illegal_instruction(); } insn_func_t processor_t::decode_insn(insn_t insn) { - bool rv64 = (sr & SR_S) ? (sr & SR_S64) : (sr & SR_U64); + bool rv64 = (state.sr & SR_S) ? (state.sr & SR_S64) : (state.sr & SR_U64); auto key = insn.bits & ((1L << opcode_bits)-1); - auto it = opcode_map.find(key); for (auto it = opcode_map.find(key); it != opcode_map.end() && it->first == key; ++it) if ((insn.bits & it->second.mask) == it->second.match) return rv64 ? it->second.rv64 : it->second.rv32; - return &processor_t::illegal_instruction; -} - -reg_t processor_t::illegal_instruction(insn_t insn, reg_t pc) -{ - throw trap_illegal_instruction; + return &illegal_instruction; } void processor_t::register_insn(uint32_t match, uint32_t mask, insn_func_t rv32, insn_func_t rv64) diff --git a/riscv/processor.h b/riscv/processor.h index e21901c..7b7f314 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -5,7 +5,6 @@ #include "decode.h" #include -#include "trap.h" #include "config.h" #include @@ -13,30 +12,14 @@ class processor_t; class mmu_t; typedef reg_t (*insn_func_t)(processor_t*, insn_t, reg_t); class sim_t; +class trap_t; -// this class represents one processor in a RISC-V machine. -class processor_t +// architectural state of a RISC-V hart +struct state_t { -public: - processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id); - ~processor_t(); - - void reset(bool value); - void step(size_t n, bool noisy); // 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_interrupt(int which, bool on); - reg_t get_pcr(int which); - mmu_t* get_mmu() { return &mmu; } - - void register_insn(uint32_t match, uint32_t mask, insn_func_t rv32, insn_func_t rv64); + void reset(); -private: - sim_t& sim; - mmu_t& mmu; // main memory is always accessed via the mmu - - // user-visible architected state + // user-visible state reg_t pc; regfile_t XPR; regfile_t FPR; @@ -46,17 +29,47 @@ private: 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 tohost; reg_t fromhost; - uint32_t id; uint32_t sr; // only modify the status register using set_pcr() uint32_t fsr; uint32_t count; uint32_t compare; + reg_t load_reservation; +}; + +// this class represents one processor in a RISC-V machine. +class processor_t +{ +public: + processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id); + ~processor_t(); + + void reset(bool value); + void step(size_t n, bool noisy); // run for n cycles + void deliver_ipi(); // register an interprocessor interrupt + bool running() { return run; } + reg_t set_pcr(int which, reg_t val); + uint32_t set_fsr(uint32_t val); // set the floating-point status register + void set_interrupt(int which, bool on); + reg_t get_pcr(int which); + uint32_t get_fsr() { return state.fsr; } + mmu_t* get_mmu() { return &mmu; } + state_t* get_state() { return &state; } + void yield_load_reservation() { state.load_reservation = (reg_t)-1; } + + void register_insn(uint32_t match, uint32_t mask, insn_func_t rv32, insn_func_t rv64); + +private: + sim_t& sim; + mmu_t& mmu; // main memory is always accessed via the mmu + state_t state; + uint32_t id; bool run; // !reset struct opcode_map_entry_t @@ -70,22 +83,14 @@ private: std::multimap opcode_map; void take_interrupt(); // take a trap if any interrupts are pending - void set_fsr(uint32_t val); // set the floating-point status register - void take_trap(reg_t t, bool noisy); // take an exception + void take_trap(reg_t pc, trap_t& t, bool noisy); // take an exception void disasm(insn_t insn, reg_t pc); // disassemble and print an instruction friend class sim_t; friend class mmu_t; friend class htif_isasim_t; - #define DECLARE_INSN(name, match, mask) \ - reg_t rv32_ ## name(insn_t insn, reg_t pc); \ - reg_t rv64_ ## name(insn_t insn, reg_t pc); - #include "opcodes.h" - #undef DECLARE_INSN - insn_func_t decode_insn(insn_t insn); - reg_t illegal_instruction(insn_t insn, reg_t pc); }; #endif diff --git a/riscv/sim.cc b/riscv/sim.cc index 6534900..2ac3266 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -18,9 +18,9 @@ static void handle_signal(int sig) signal(sig, &handle_signal); } -sim_t::sim_t(size_t _nprocs, size_t mem_mb, const std::vector& args) - : htif(new htif_isasim_t(this, args)), - procs(_nprocs), current_step(0), current_proc(0), debug(false) +sim_t::sim_t(size_t nprocs, size_t mem_mb, const std::vector& args) + : htif(new htif_isasim_t(this, args)), procs(std::max(nprocs, size_t(1))), + current_step(0), current_proc(0), debug(false) { signal(SIGINT, &handle_signal); // allocate target machine's memory, shrinking it as necessary @@ -38,11 +38,9 @@ sim_t::sim_t(size_t _nprocs, size_t mem_mb, const std::vector& args fprintf(stderr, "warning: only got %lu bytes of target mem (wanted %lu)\n", (unsigned long)memsz, (unsigned long)memsz0); - mmu = new mmu_t(mem, memsz); + debug_mmu = new mmu_t(mem, memsz); - if (_nprocs == 0) - _nprocs = 1; - for (size_t i = 0; i < _nprocs; i++) + for (size_t i = 0; i < procs.size(); i++) procs[i] = new processor_t(this, new mmu_t(mem, memsz), i); } @@ -54,7 +52,7 @@ sim_t::~sim_t() delete procs[i]; delete pmmu; } - delete mmu; + delete debug_mmu; free(mem); } @@ -100,7 +98,7 @@ void sim_t::step(size_t n, bool noisy) if (current_step == INTERLEAVE) { current_step = 0; - procs[current_proc]->mmu.yield_load_reservation(); + procs[current_proc]->yield_load_reservation(); if (++current_proc == procs.size()) current_proc = 0; } @@ -117,7 +115,7 @@ bool sim_t::running() void sim_t::stop() { - procs[0]->tohost = 1; + procs[0]->state.tohost = 1; while (!htif->done()) htif->tick(); } diff --git a/riscv/sim.h b/riscv/sim.h index a53f3f0..bcb7c1c 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -38,7 +38,7 @@ private: std::auto_ptr htif; char* mem; // main memory size_t memsz; // memory size in bytes - mmu_t* mmu; // debug port into main memory + mmu_t* debug_mmu; // debug port into main memory std::vector procs; void step(size_t n, bool noisy); // step through simulation diff --git a/riscv/trap.cc b/riscv/trap.cc index ba0d867..ead3a00 100644 --- a/riscv/trap.cc +++ b/riscv/trap.cc @@ -1,12 +1,15 @@ -// See LICENSE for license details. - #include "trap.h" +#include "processor.h" +#include -const char* trap_name(trap_t t) +const char* trap_t::name() { - #define DECLARE_TRAP(x) "trap_"#x - static const char* names[] = { TRAP_LIST }; - #undef DECLARE_TRAP + const char* fmt = uint8_t(which) == which ? "trap #%u" : "interrupt #%u"; + sprintf(_name, fmt, uint8_t(which)); + return _name; +} - return (unsigned)t >= sizeof(names)/sizeof(names[0]) ? "unknown" : names[t]; +void mem_trap_t::side_effects(state_t* state) +{ + state->badvaddr = badvaddr; } diff --git a/riscv/trap.h b/riscv/trap.h index 6448e51..a7a823b 100644 --- a/riscv/trap.h +++ b/riscv/trap.h @@ -3,35 +3,58 @@ #ifndef _RISCV_TRAP_H #define _RISCV_TRAP_H -#define TRAP_LIST \ - DECLARE_TRAP(instruction_address_misaligned), \ - DECLARE_TRAP(instruction_access_fault), \ - DECLARE_TRAP(illegal_instruction), \ - DECLARE_TRAP(privileged_instruction), \ - DECLARE_TRAP(fp_disabled), \ - DECLARE_TRAP(reserved0), \ - DECLARE_TRAP(syscall), \ - DECLARE_TRAP(breakpoint), \ - DECLARE_TRAP(load_address_misaligned), \ - DECLARE_TRAP(store_address_misaligned), \ - DECLARE_TRAP(load_access_fault), \ - DECLARE_TRAP(store_access_fault), \ - DECLARE_TRAP(vector_disabled), \ - DECLARE_TRAP(vector_bank), \ - DECLARE_TRAP(vector_illegal_instruction), \ - DECLARE_TRAP(reserved1), \ - -#define DECLARE_TRAP(x) trap_##x -enum trap_t +#include "decode.h" + +class state_t; + +class trap_t +{ + public: + trap_t(reg_t which) : which(which) {} + virtual const char* name(); + virtual void side_effects(state_t* state) {} + reg_t cause() { return which; } + private: + char _name[16]; + reg_t which; +}; + +class mem_trap_t : public trap_t { - TRAP_LIST - NUM_TRAPS + public: + mem_trap_t(reg_t which, reg_t badvaddr) + : trap_t(which), badvaddr(badvaddr) {} + void side_effects(state_t* state); + private: + reg_t badvaddr; +}; + +#define DECLARE_TRAP(n, x) class trap_##x : public trap_t { \ + public: \ + trap_##x() : trap_t(n) {} \ + const char* name() { return "trap_"#x; } \ }; -#undef DECLARE_TRAP -struct interrupt_t { interrupt_t(int which) : i(which) {} int i; }; -struct halt_t {}; // thrown to stop the processor from running +#define DECLARE_MEM_TRAP(n, x) class trap_##x : public mem_trap_t { \ + public: \ + trap_##x(reg_t badvaddr) : mem_trap_t(n, badvaddr) {} \ + const char* name() { return "trap_"#x; } \ +}; -extern "C" const char* trap_name(trap_t t); +DECLARE_TRAP(0, instruction_address_misaligned) +DECLARE_TRAP(1, instruction_access_fault) +DECLARE_TRAP(2, illegal_instruction) +DECLARE_TRAP(3, privileged_instruction) +DECLARE_TRAP(4, fp_disabled) +DECLARE_TRAP(5, reserved0) +DECLARE_TRAP(6, syscall) +DECLARE_TRAP(7, breakpoint) +DECLARE_MEM_TRAP(8, load_address_misaligned) +DECLARE_MEM_TRAP(9, store_address_misaligned) +DECLARE_MEM_TRAP(10, load_access_fault) +DECLARE_MEM_TRAP(11, store_access_fault) +DECLARE_TRAP(12, vector_disabled) +DECLARE_TRAP(13, vector_bank) +DECLARE_TRAP(14, vector_illegal_instruction) #endif -- 2.30.2