aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2013-08-11 19:10:51 -0700
committerAndrew Waterman <waterman@cs.berkeley.edu>2013-08-11 19:10:51 -0700
commit04c2d491c4bbb424a59273d4ebee62ddfe3379f9 (patch)
treeadbbe9bc3d7694c289aa7d18cf4a425d106a1c4a /riscv
parentb0af18ed449fb433ae5fce1cf8eb5e1e25ae9190 (diff)
downloadriscv-isa-sim-04c2d491c4bbb424a59273d4ebee62ddfe3379f9.zip
riscv-isa-sim-04c2d491c4bbb424a59273d4ebee62ddfe3379f9.tar.gz
riscv-isa-sim-04c2d491c4bbb424a59273d4ebee62ddfe3379f9.tar.bz2
Instructions are no longer member functions
Diffstat (limited to 'riscv')
-rw-r--r--riscv/decode.h35
-rw-r--r--riscv/htif.cc6
-rw-r--r--riscv/insn_template.cc4
-rw-r--r--riscv/insns/amoadd_d.h4
-rw-r--r--riscv/insns/amoadd_w.h4
-rw-r--r--riscv/insns/amoand_d.h4
-rw-r--r--riscv/insns/amoand_w.h4
-rw-r--r--riscv/insns/amomax_d.h4
-rw-r--r--riscv/insns/amomax_w.h4
-rw-r--r--riscv/insns/amomaxu_d.h4
-rw-r--r--riscv/insns/amomaxu_w.h4
-rw-r--r--riscv/insns/amomin_d.h4
-rw-r--r--riscv/insns/amomin_w.h4
-rw-r--r--riscv/insns/amominu_d.h4
-rw-r--r--riscv/insns/amominu_w.h4
-rw-r--r--riscv/insns/amoor_d.h4
-rw-r--r--riscv/insns/amoor_w.h4
-rw-r--r--riscv/insns/amoswap_d.h4
-rw-r--r--riscv/insns/amoswap_w.h4
-rw-r--r--riscv/insns/break.h2
-rw-r--r--riscv/insns/clearpcr.h4
-rw-r--r--riscv/insns/eret.h8
-rw-r--r--riscv/insns/fence_i.h2
-rw-r--r--riscv/insns/fld.h2
-rw-r--r--riscv/insns/flw.h2
-rw-r--r--riscv/insns/frsr.h2
-rw-r--r--riscv/insns/fsd.h2
-rw-r--r--riscv/insns/fssr.h4
-rw-r--r--riscv/insns/fsw.h2
-rw-r--r--riscv/insns/lb.h2
-rw-r--r--riscv/insns/lbu.h2
-rw-r--r--riscv/insns/ld.h2
-rw-r--r--riscv/insns/lh.h2
-rw-r--r--riscv/insns/lhu.h2
-rw-r--r--riscv/insns/lr_d.h3
-rw-r--r--riscv/insns/lr_w.h3
-rw-r--r--riscv/insns/lw.h2
-rw-r--r--riscv/insns/lwu.h2
-rw-r--r--riscv/insns/mfpcr.h2
-rw-r--r--riscv/insns/mtpcr.h4
-rw-r--r--riscv/insns/rdcycle.h2
-rw-r--r--riscv/insns/rdinstret.h2
-rw-r--r--riscv/insns/rdtime.h2
-rw-r--r--riscv/insns/sb.h2
-rw-r--r--riscv/insns/sc_d.h8
-rw-r--r--riscv/insns/sc_w.h8
-rw-r--r--riscv/insns/sd.h2
-rw-r--r--riscv/insns/setpcr.h4
-rw-r--r--riscv/insns/sh.h2
-rw-r--r--riscv/insns/slli.h2
-rw-r--r--riscv/insns/srai.h2
-rw-r--r--riscv/insns/srli.h2
-rw-r--r--riscv/insns/sw.h2
-rw-r--r--riscv/insns/syscall.h2
-rw-r--r--riscv/interactive.cc29
-rw-r--r--riscv/mmu.cc17
-rw-r--r--riscv/mmu.h27
-rw-r--r--riscv/processor.cc181
-rw-r--r--riscv/processor.h69
-rw-r--r--riscv/sim.cc18
-rw-r--r--riscv/sim.h2
-rw-r--r--riscv/trap.cc17
-rw-r--r--riscv/trap.h75
63 files changed, 335 insertions, 307 deletions
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 <assert.h>
-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<std::stri
reg_t sim_t::get_pc(const std::vector<std::string>& 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<std::string>& 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<std::string>& 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<std::string>& args)
@@ -177,15 +177,16 @@ void sim_t::interactive_fregd(const std::string& cmd, const std::vector<std::str
reg_t sim_t::get_mem(const std::vector<std::string>& 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<std::strin
void sim_t::interactive_str(const std::string& cmd, const std::vector<std::string>& 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 <cstring>
-#include "trap.h"
#include "config.h"
#include <map>
@@ -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<reg_t, NXPR, true> XPR;
regfile_t<freg_t, NFPR, false> 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<uint32_t, opcode_map_entry_t> 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<std::string>& 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<std::string>& 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<std::string>& 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_isasim_t> 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<processor_t*> 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 <cstdio>
-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