aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYunsup Lee <yunsup@cs.berkeley.edu>2013-10-17 19:34:26 -0700
committerYunsup Lee <yunsup@cs.berkeley.edu>2013-10-17 19:34:26 -0700
commit0f140bcde46a940f76d3e06857d3f572ab6966c4 (patch)
treeb6f8bb4215691c4a730d323d62ec82282f90e4ff
parent289e2118cb35c023c04085e731952edb70fc18a9 (diff)
downloadriscv-isa-sim-0f140bcde46a940f76d3e06857d3f572ab6966c4.zip
riscv-isa-sim-0f140bcde46a940f76d3e06857d3f572ab6966c4.tar.gz
riscv-isa-sim-0f140bcde46a940f76d3e06857d3f572ab6966c4.tar.bz2
add hwacha exception support
-rw-r--r--config.h.in3
-rw-r--r--hwacha/decode_hwacha.h45
-rw-r--r--hwacha/decode_hwacha_ut.h66
-rw-r--r--hwacha/hwacha.cc69
-rw-r--r--hwacha/hwacha.h5
-rw-r--r--hwacha/hwacha_xcpt.h17
-rw-r--r--hwacha/insns/vf.h13
-rw-r--r--hwacha/insns/vsetcfg.h6
-rw-r--r--hwacha/insns/vxcptaux.h2
-rw-r--r--hwacha/insns/vxcptcause.h3
-rw-r--r--hwacha/insns/vxcptkill.h3
-rw-r--r--hwacha/insns/vxcptrestore.h1
-rw-r--r--hwacha/insns/vxcptsave.h1
-rw-r--r--hwacha/opcodes_hwacha.h2
-rw-r--r--riscv/pcr.h11
-rw-r--r--riscv/trap.h4
16 files changed, 213 insertions, 38 deletions
diff --git a/config.h.in b/config.h.in
index cac4655..43d6cec 100644
--- a/config.h.in
+++ b/config.h.in
@@ -6,6 +6,9 @@
/* Define to 1 if you have the `pthread' library (-lpthread). */
#undef HAVE_LIBPTHREAD
+/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
+#undef HWACHA_ENABLED
+
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
diff --git a/hwacha/decode_hwacha.h b/hwacha/decode_hwacha.h
index a99736e..9353cb9 100644
--- a/hwacha/decode_hwacha.h
+++ b/hwacha/decode_hwacha.h
@@ -1,6 +1,9 @@
#ifndef _DECODE_HWACHA_H
#define _DECODE_HWACHA_H
+#include "hwacha.h"
+#include "hwacha_xcpt.h"
+
#define XS1 (xs1)
#define XS2 (xs2)
#define WRITE_XRD(value) (xd = value)
@@ -9,10 +12,12 @@
#define NFPR (h->get_ct_state()->nfpr)
#define MAXVL (h->get_ct_state()->maxvl)
#define VL (h->get_ct_state()->vl)
+#define VF_PC (h->get_ct_state()->vf_pc)
#define WRITE_NXPR(nxprnext) (h->get_ct_state()->nxpr = (nxprnext))
#define WRITE_NFPR(nfprnext) (h->get_ct_state()->nfpr = (nfprnext))
#define WRITE_MAXVL(maxvlnext) (h->get_ct_state()->maxvl = (maxvlnext))
#define WRITE_VL(vlnext) (h->get_ct_state()->vl = (vlnext))
+#define WRITE_VF_PC(pcnext) (h->get_ct_state()->vf_pc = (pcnext))
#define INSN_RS1 (insn.rs1())
#define INSN_RS2 (insn.rs2())
@@ -20,14 +25,42 @@
#define INSN_RD (insn.rd())
#define INSN_SEG ((insn.i_imm() >> 9)+1)
-#define UT_READ_XPR(idx, src) (h->get_ut_state(idx)->XPR[src])
-#define UT_WRITE_XPR(idx, dst, value) (h->get_ut_state(idx)->XPR.write(dst, value))
+static inline reg_t read_xpr(hwacha_t* h, insn_t insn, uint32_t idx, size_t src)
+{
+ if (src >= h->get_ct_state()->nxpr)
+ h->take_exception(HWACHA_CAUSE_TVEC_ILLEGAL_REGID, insn.bits());
+ return (h->get_ut_state(idx)->XPR[src]);
+}
+
+static inline void write_xpr(hwacha_t* h, insn_t insn, uint32_t idx, size_t dst, reg_t value)
+{
+ if (dst >= h->get_ct_state()->nxpr)
+ h->take_exception(HWACHA_CAUSE_TVEC_ILLEGAL_REGID, insn.bits());
+ h->get_ut_state(idx)->XPR.write(dst, value);
+}
+
+#define UT_READ_XPR(idx, src) read_xpr(h, insn, idx, src)
+#define UT_WRITE_XPR(idx, dst, value) write_xpr(h, insn, idx, dst, value)
#define UT_RS1(idx) (UT_READ_XPR(idx, INSN_RS1))
#define UT_RS2(idx) (UT_READ_XPR(idx, INSN_RS2))
#define UT_WRITE_RD(idx, value) (UT_WRITE_XPR(idx, INSN_RD, value))
-#define UT_READ_FPR(idx, src) (h->get_ut_state(idx)->FPR[src])
-#define UT_WRITE_FPR(idx, dst, value) (h->get_ut_state(idx)->FPR.write(dst, value))
+static inline reg_t read_fpr(hwacha_t* h, insn_t insn, uint32_t idx, size_t src)
+{
+ if (src >= h->get_ct_state()->nfpr)
+ h->take_exception(HWACHA_CAUSE_TVEC_ILLEGAL_REGID, insn.bits());
+ return (h->get_ut_state(idx)->FPR[src]);
+}
+
+static inline void write_fpr(hwacha_t* h, insn_t insn, uint32_t idx, size_t dst, reg_t value)
+{
+ if (dst >= h->get_ct_state()->nfpr)
+ h->take_exception(HWACHA_CAUSE_TVEC_ILLEGAL_REGID, insn.bits());
+ h->get_ut_state(idx)->FPR.write(dst, value);
+}
+
+#define UT_READ_FPR(idx, src) read_fpr(h, insn, idx, src)
+#define UT_WRITE_FPR(idx, dst, value) write_fpr(h, insn, idx, dst, value)
#define UT_FRS1(idx) (UT_READ_FPR(idx, INSN_RS1))
#define UT_FRS2(idx) (UT_READ_FPR(idx, INSN_RS2))
#define UT_FRS3(idx) (UT_READ_FPR(idx, INSN_RS3))
@@ -61,4 +94,8 @@
} \
}
+#define require_supervisor_hwacha \
+ if (unlikely(!(p->get_state()->sr & SR_S))) \
+ h->take_exception(HWACHA_CAUSE_PRIVILEGED_INSTRUCTION, insn.bits());
+
#endif
diff --git a/hwacha/decode_hwacha_ut.h b/hwacha/decode_hwacha_ut.h
index 675f77c..daad217 100644
--- a/hwacha/decode_hwacha_ut.h
+++ b/hwacha/decode_hwacha_ut.h
@@ -1,7 +1,10 @@
#ifndef _DECODE_HWACHA_UT_H
#define _DECODE_HWACHA_UT_H
+#include "decode.h"
#include "decode_hwacha.h"
+#include "hwacha.h"
+#include "hwacha_xcpt.h"
#define UTIDX (i)
@@ -9,19 +12,68 @@
#undef RS2
#undef WRITE_RD
-#define RS1 UT_RS1(UTIDX)
-#define RS2 UT_RS2(UTIDX)
-#define WRITE_RD(value) UT_WRITE_RD(UTIDX, value)
+static inline reg_t read_rs1(hwacha_t* h, insn_t insn, uint32_t idx)
+{
+ if (INSN_RS1 >= h->get_ct_state()->nxpr)
+ h->take_exception(HWACHA_CAUSE_VF_ILLEGAL_REGID, VF_PC);
+ return UT_RS1(idx);
+}
+
+static inline reg_t read_rs2(hwacha_t* h, insn_t insn, uint32_t idx)
+{
+ if (INSN_RS2 >= h->get_ct_state()->nxpr)
+ h->take_exception(HWACHA_CAUSE_VF_ILLEGAL_REGID, VF_PC);
+ return UT_RS2(idx);
+}
+
+static inline void write_rd(hwacha_t* h, insn_t insn, uint32_t idx, reg_t value)
+{
+ if (INSN_RD >= h->get_ct_state()->nxpr)
+ h->take_exception(HWACHA_CAUSE_VF_ILLEGAL_REGID, VF_PC);
+ UT_WRITE_RD(idx, value);
+}
+
+#define RS1 read_rs1(h, insn, UTIDX)
+#define RS2 read_rs2(h, insn, UTIDX)
+#define WRITE_RD(value) write_rd(h, insn, UTIDX, value)
#undef FRS1
#undef FRS2
#undef FRS3
#undef WRITE_FRD
-#define FRS1 UT_FRS1(UTIDX)
-#define FRS2 UT_FRS2(UTIDX)
-#define FRS3 UT_FRS3(UTIDX)
-#define WRITE_FRD(value) UT_WRITE_FRD(UTIDX, value)
+static inline reg_t read_frs1(hwacha_t* h, insn_t insn, uint32_t idx)
+{
+ if (INSN_RS1 >= h->get_ct_state()->nfpr)
+ h->take_exception(HWACHA_CAUSE_VF_ILLEGAL_REGID, VF_PC);
+ return UT_FRS1(idx);
+}
+
+static inline reg_t read_frs2(hwacha_t* h, insn_t insn, uint32_t idx)
+{
+ if (INSN_RS2 >= h->get_ct_state()->nfpr)
+ h->take_exception(HWACHA_CAUSE_VF_ILLEGAL_REGID, VF_PC);
+ return UT_FRS2(idx);
+}
+
+static inline reg_t read_frs3(hwacha_t* h, insn_t insn, uint32_t idx)
+{
+ if (INSN_RS3 >= h->get_ct_state()->nfpr)
+ h->take_exception(HWACHA_CAUSE_VF_ILLEGAL_REGID, VF_PC);
+ return UT_FRS3(idx);
+}
+
+static inline void write_frd(hwacha_t* h, insn_t insn, uint32_t idx, reg_t value)
+{
+ if (INSN_RD >= h->get_ct_state()->nfpr)
+ h->take_exception(HWACHA_CAUSE_VF_ILLEGAL_REGID, VF_PC);
+ UT_WRITE_FRD(idx, value);
+}
+
+#define FRS1 read_frs1(h, insn, UTIDX)
+#define FRS2 read_frs2(h, insn, UTIDX)
+#define FRS3 read_frs3(h, insn, UTIDX)
+#define WRITE_FRD(value) write_frd(h, insn, UTIDX, value)
// we assume the vector unit has floating-point alus
#undef require_fp
diff --git a/hwacha/hwacha.cc b/hwacha/hwacha.cc
index bd76f6b..b1cf7fc 100644
--- a/hwacha/hwacha.cc
+++ b/hwacha/hwacha.cc
@@ -1,4 +1,6 @@
#include "hwacha.h"
+#include "hwacha_xcpt.h"
+#include "trap.h"
void ct_state_t::reset()
{
@@ -8,6 +10,9 @@ void ct_state_t::reset()
nfpr = 32;
vf_pc = -1;
+
+ cause = 0;
+ aux = 0;
}
void ut_state_t::reset()
@@ -24,14 +29,57 @@ void hwacha_t::reset()
ut_state[i].reset();
}
+static reg_t custom(processor_t* p, insn_t insn, reg_t pc)
+{
+ hwacha_t* h = static_cast<hwacha_t*>(p->get_extension());
+ bool matched = false;
+ reg_t npc = -1;
+
+ try
+ {
+ #define DECLARE_INSN(name, match, mask) \
+ extern reg_t hwacha_##name(processor_t*, insn_t, reg_t); \
+ if ((insn.bits() & mask) == match) { \
+ npc = hwacha_##name(p, insn, pc); \
+ matched = true; \
+ }
+ #include "opcodes_hwacha.h"
+ #undef DECLARE_INSN
+ }
+ catch (trap_instruction_access_fault& t)
+ {
+ h->take_exception(HWACHA_CAUSE_VF_FAULT_FETCH, h->get_ct_state()->vf_pc);
+ }
+ catch (trap_load_address_misaligned& t)
+ {
+ h->take_exception(HWACHA_CAUSE_MISALIGNED_LOAD, t.get_badvaddr());
+ }
+ catch (trap_store_address_misaligned& t)
+ {
+ h->take_exception(HWACHA_CAUSE_MISALIGNED_STORE, t.get_badvaddr());
+ }
+ catch (trap_load_access_fault& t)
+ {
+ h->take_exception(HWACHA_CAUSE_FAULT_LOAD, t.get_badvaddr());
+ }
+ catch (trap_store_access_fault& t)
+ {
+ h->take_exception(HWACHA_CAUSE_FAULT_STORE, t.get_badvaddr());
+ }
+
+ if (!matched)
+ h->take_exception(HWACHA_CAUSE_ILLEGAL_INSTRUCTION, insn.bits());
+
+ return npc;
+}
+
std::vector<insn_desc_t> hwacha_t::get_instructions()
{
std::vector<insn_desc_t> insns;
- #define DECLARE_INSN(name, match, mask) \
- extern reg_t hwacha_##name(processor_t*, insn_t, reg_t); \
- insns.push_back((insn_desc_t){match, mask, &::illegal_instruction, hwacha_##name});
- #include "opcodes_hwacha.h"
- #undef DECLARE_INSN
+ insns.push_back((insn_desc_t){0x0b, 0x7f, &::illegal_instruction, custom});
+ insns.push_back((insn_desc_t){0x2b, 0x7f, &::illegal_instruction, custom});
+ insns.push_back((insn_desc_t){0x5b, 0x7f, &::illegal_instruction, custom});
+ insns.push_back((insn_desc_t){0x7b, 0x7f, &::illegal_instruction, custom});
return insns;
}
@@ -41,6 +89,15 @@ bool hwacha_t::vf_active()
if (get_ut_state(i)->run)
return true;
}
-
return false;
}
+
+void hwacha_t::take_exception(reg_t cause, reg_t aux)
+{
+ get_ct_state()->cause = cause;
+ get_ct_state()->aux = aux;
+ raise_interrupt();
+ if (!(p->get_state()->sr & SR_EI))
+ throw std::logic_error("hwacha exception posted, but SR_EI bit not set!");
+ throw std::logic_error("hwacha exception posted, but IM[COP] bit not set!");
+}
diff --git a/hwacha/hwacha.h b/hwacha/hwacha.h
index 0f4955b..e48bf52 100644
--- a/hwacha/hwacha.h
+++ b/hwacha/hwacha.h
@@ -13,6 +13,9 @@ struct ct_state_t
uint32_t vl;
reg_t vf_pc;
+
+ reg_t cause;
+ reg_t aux;
};
struct ut_state_t
@@ -34,6 +37,8 @@ public:
ct_state_t* get_ct_state() { return &ct_state; }
ut_state_t* get_ut_state(int idx) { return &ut_state[idx]; }
bool vf_active();
+ void take_exception(reg_t, reg_t);
+ void clear_exception() { clear_interrupt(); }
private:
static const int max_uts = 2048;
diff --git a/hwacha/hwacha_xcpt.h b/hwacha/hwacha_xcpt.h
new file mode 100644
index 0000000..5c4dacc
--- /dev/null
+++ b/hwacha/hwacha_xcpt.h
@@ -0,0 +1,17 @@
+#ifndef _HWACHA_XCPT_H
+#define _HWACHA_XCPT_H
+
+#define HWACHA_CAUSE_ILLEGAL_CFG 0 // AUX: 0=illegal nxpr, 1=illegal nfpr
+#define HWACHA_CAUSE_ILLEGAL_INSTRUCTION 1 // AUX: instruction
+#define HWACHA_CAUSE_PRIVILEGED_INSTRUCTION 2 // AUX: instruction
+#define HWACHA_CAUSE_TVEC_ILLEGAL_REGID 3 // AUX: instruction
+#define HWACHA_CAUSE_VF_MISALIGNED_FETCH 4 // AUX: pc
+#define HWACHA_CAUSE_VF_FAULT_FETCH 5 // AUX: pc
+#define HWACHA_CAUSE_VF_ILLEGAL_INSTRUCTION 6 // AUX: pc
+#define HWACHA_CAUSE_VF_ILLEGAL_REGID 7 // AUX: pc
+#define HWACHA_CAUSE_MISALIGNED_LOAD 8 // AUX: badvaddr
+#define HWACHA_CAUSE_MISALIGNED_STORE 9 // AUX: badvaddr
+#define HWACHA_CAUSE_FAULT_LOAD 10 // AUX: badvaddr
+#define HWACHA_CAUSE_FAULT_STORE 11 // AUX: badvaddr
+
+#endif
diff --git a/hwacha/insns/vf.h b/hwacha/insns/vf.h
index 1e5de3c..7bd1973 100644
--- a/hwacha/insns/vf.h
+++ b/hwacha/insns/vf.h
@@ -1,11 +1,14 @@
if (VL) {
if (!h->vf_active()) {
- h->get_ct_state()->vf_pc = XS1 + insn.s_imm();
+ WRITE_VF_PC(XS1 + insn.s_imm());
for (uint32_t i=0; i<VL; i++)
h->get_ut_state(i)->run = true;
}
- mmu_t::insn_fetch_t ut_fetch = p->get_mmu()->load_insn(h->get_ct_state()->vf_pc);
+ if (VF_PC & 3)
+ h->take_exception(HWACHA_CAUSE_VF_MISALIGNED_FETCH, VF_PC);
+
+ mmu_t::insn_fetch_t ut_fetch = p->get_mmu()->load_insn(VF_PC);
insn_t ut_insn = ut_fetch.insn.insn;
bool matched = false;
@@ -13,14 +16,14 @@ if (VL) {
#define DECLARE_INSN(name, match, mask) \
extern reg_t hwacha_##name(processor_t*, insn_t, reg_t); \
if ((ut_insn.bits() & mask) == match) { \
- h->get_ct_state()->vf_pc = hwacha_##name(p, ut_insn, h->get_ct_state()->vf_pc); \
+ WRITE_VF_PC(hwacha_##name(p, ut_insn, VF_PC)); \
matched = true; \
}
#include "opcodes_hwacha_ut.h"
#undef DECLARE_INSN
- // YUNSUP FIXME
- assert(matched);
+ if (!matched)
+ h->take_exception(HWACHA_CAUSE_VF_ILLEGAL_INSTRUCTION, VF_PC);
// if vf is still running, rewind pc so that it will execute again
if (h->vf_active())
diff --git a/hwacha/insns/vsetcfg.h b/hwacha/insns/vsetcfg.h
index a5fd959..c18812d 100644
--- a/hwacha/insns/vsetcfg.h
+++ b/hwacha/insns/vsetcfg.h
@@ -1,7 +1,9 @@
uint32_t nxpr = (XS1 & 0x3f) + (insn.i_imm() & 0x3f);
uint32_t nfpr = ((XS1 >> 6) & 0x3f) + ((insn.i_imm() >> 6) & 0x3f);
-// YUNSUP FIXME
-// raise trap when nxpr/nfpr is larger than possible
+if (nxpr > 32)
+ h->take_exception(HWACHA_CAUSE_ILLEGAL_CFG, 0);
+if (nfpr > 32)
+ h->take_exception(HWACHA_CAUSE_ILLEGAL_CFG, 1);
WRITE_NXPR(nxpr);
WRITE_NFPR(nfpr);
uint32_t maxvl;
diff --git a/hwacha/insns/vxcptaux.h b/hwacha/insns/vxcptaux.h
new file mode 100644
index 0000000..92e2920
--- /dev/null
+++ b/hwacha/insns/vxcptaux.h
@@ -0,0 +1,2 @@
+require_supervisor_hwacha;
+xd = h->get_ct_state()->aux;
diff --git a/hwacha/insns/vxcptcause.h b/hwacha/insns/vxcptcause.h
new file mode 100644
index 0000000..e959247
--- /dev/null
+++ b/hwacha/insns/vxcptcause.h
@@ -0,0 +1,3 @@
+require_supervisor_hwacha;
+h->clear_exception();
+xd = h->get_ct_state()->cause;
diff --git a/hwacha/insns/vxcptkill.h b/hwacha/insns/vxcptkill.h
index e69de29..684a816 100644
--- a/hwacha/insns/vxcptkill.h
+++ b/hwacha/insns/vxcptkill.h
@@ -0,0 +1,3 @@
+require_supervisor_hwacha;
+for (uint32_t i=0; i<VL; i++)
+ h->get_ut_state(i)->run = false;
diff --git a/hwacha/insns/vxcptrestore.h b/hwacha/insns/vxcptrestore.h
index e69de29..cb3d8f0 100644
--- a/hwacha/insns/vxcptrestore.h
+++ b/hwacha/insns/vxcptrestore.h
@@ -0,0 +1 @@
+require_supervisor_hwacha;
diff --git a/hwacha/insns/vxcptsave.h b/hwacha/insns/vxcptsave.h
index e69de29..cb3d8f0 100644
--- a/hwacha/insns/vxcptsave.h
+++ b/hwacha/insns/vxcptsave.h
@@ -0,0 +1 @@
+require_supervisor_hwacha;
diff --git a/hwacha/opcodes_hwacha.h b/hwacha/opcodes_hwacha.h
index 75cbfa6..e384b37 100644
--- a/hwacha/opcodes_hwacha.h
+++ b/hwacha/opcodes_hwacha.h
@@ -35,6 +35,8 @@ DECLARE_INSN(vssegstd, 0x600307b, 0x1e00707f)
DECLARE_INSN(vssegsth, 0x200307b, 0x1e00707f)
DECLARE_INSN(vssegstw, 0x400307b, 0x1e00707f)
DECLARE_INSN(vssegw, 0x400207b, 0x1ff0707f)
+DECLARE_INSN(vxcptaux, 0x200402b, 0xfffff07f)
+DECLARE_INSN(vxcptcause, 0x402b, 0xfffff07f)
DECLARE_INSN(vxcptkill, 0x400302b, 0xffffffff)
DECLARE_INSN(vxcptrestore, 0x200302b, 0xfff07fff)
DECLARE_INSN(vxcptsave, 0x302b, 0xfff07fff)
diff --git a/riscv/pcr.h b/riscv/pcr.h
index 8780cdd..75a349f 100644
--- a/riscv/pcr.h
+++ b/riscv/pcr.h
@@ -59,17 +59,6 @@
#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
// page table entry (PTE) fields
#define PTE_V 0x001 // Entry is a page Table descriptor
diff --git a/riscv/trap.h b/riscv/trap.h
index a7a823b..9a1a2f9 100644
--- a/riscv/trap.h
+++ b/riscv/trap.h
@@ -25,6 +25,7 @@ class mem_trap_t : public trap_t
mem_trap_t(reg_t which, reg_t badvaddr)
: trap_t(which), badvaddr(badvaddr) {}
void side_effects(state_t* state);
+ reg_t get_badvaddr() { return badvaddr; }
private:
reg_t badvaddr;
};
@@ -53,8 +54,5 @@ 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