add hwacha exception support
authorYunsup Lee <yunsup@cs.berkeley.edu>
Fri, 18 Oct 2013 02:34:26 +0000 (19:34 -0700)
committerYunsup Lee <yunsup@cs.berkeley.edu>
Fri, 18 Oct 2013 02:34:26 +0000 (19:34 -0700)
16 files changed:
config.h.in
hwacha/decode_hwacha.h
hwacha/decode_hwacha_ut.h
hwacha/hwacha.cc
hwacha/hwacha.h
hwacha/hwacha_xcpt.h [new file with mode: 0644]
hwacha/insns/vf.h
hwacha/insns/vsetcfg.h
hwacha/insns/vxcptaux.h [new file with mode: 0644]
hwacha/insns/vxcptcause.h [new file with mode: 0644]
hwacha/insns/vxcptkill.h
hwacha/insns/vxcptrestore.h
hwacha/insns/vxcptsave.h
hwacha/opcodes_hwacha.h
riscv/pcr.h
riscv/trap.h

index cac46554b85fb0afb69a80c11728278ed5665183..43d6cec8c54162fddc4ed12ced7766791c9abfe0 100644 (file)
@@ -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
 
index a99736e2ead260946254b6ca878fd9bb50282fc3..9353cb9dae509e8f9e2622d30ed3c07fbb63e2a8 100644 (file)
@@ -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)
 #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())
 #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
index 675f77cc7e8a1a6ea47efae5e2dc0d03358c37c0..daad217a32e164468dd9e7ef02b8d0b2bfde4959 100644 (file)
@@ -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)
 
 #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
index bd76f6b9d9ef21e8ef34889b15bf4c98c0a8de63..b1cf7fc81ce159d67a85f633a335c43af8966939 100644 (file)
@@ -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!");
+}
index 0f4955be5bd54e183cc2ad277c4622cc8b972462..e48bf529cd2488c5fe8173800e637d4cfe9f3e7a 100644 (file)
@@ -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 (file)
index 0000000..5c4dacc
--- /dev/null
@@ -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
index 1e5de3c0ad364a7258bf878dcce88e8fd58a65f7..7bd1973edac9af95b1b52e42444adddd46b13d1a 100644 (file)
@@ -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())
index a5fd9594dea82c96499efc4c71b6bd1ceefd08f5..c18812db50aeeee1f8f6cdb03d945250c6695eb4 100644 (file)
@@ -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 (file)
index 0000000..92e2920
--- /dev/null
@@ -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 (file)
index 0000000..e959247
--- /dev/null
@@ -0,0 +1,3 @@
+require_supervisor_hwacha;
+h->clear_exception();
+xd = h->get_ct_state()->cause;
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..684a816cea109fa18241c222dac007043e5482b8 100644 (file)
@@ -0,0 +1,3 @@
+require_supervisor_hwacha;
+for (uint32_t i=0; i<VL; i++)
+  h->get_ut_state(i)->run = false;
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cb3d8f0a8aad00ff4af976ff87a94125405dd343 100644 (file)
@@ -0,0 +1 @@
+require_supervisor_hwacha;
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cb3d8f0a8aad00ff4af976ff87a94125405dd343 100644 (file)
@@ -0,0 +1 @@
+require_supervisor_hwacha;
index 75cbfa62a7060c6a79744f070e0f690598cf400b..e384b375e79ea9c3a8866467ad9a07e5f1348878 100644 (file)
@@ -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)
index 8780cdd99a6bf3b0df9b2c6987c935f10003a0cc..75a349ffe29d8cb95818586d061ffa657d44face 100644 (file)
 #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
index a7a823bcd3fc6479bfd9023dfb3ec99befaf56d0..9a1a2f91e9e9afd5b27aa9c61cb23e839bbf5158 100644 (file)
@@ -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