diff options
author | Yunsup Lee <yunsup@cs.berkeley.edu> | 2013-10-17 19:34:26 -0700 |
---|---|---|
committer | Yunsup Lee <yunsup@cs.berkeley.edu> | 2013-10-17 19:34:26 -0700 |
commit | 0f140bcde46a940f76d3e06857d3f572ab6966c4 (patch) | |
tree | b6f8bb4215691c4a730d323d62ec82282f90e4ff /hwacha | |
parent | 289e2118cb35c023c04085e731952edb70fc18a9 (diff) | |
download | spike-0f140bcde46a940f76d3e06857d3f572ab6966c4.zip spike-0f140bcde46a940f76d3e06857d3f572ab6966c4.tar.gz spike-0f140bcde46a940f76d3e06857d3f572ab6966c4.tar.bz2 |
add hwacha exception support
Diffstat (limited to 'hwacha')
-rw-r--r-- | hwacha/decode_hwacha.h | 45 | ||||
-rw-r--r-- | hwacha/decode_hwacha_ut.h | 66 | ||||
-rw-r--r-- | hwacha/hwacha.cc | 69 | ||||
-rw-r--r-- | hwacha/hwacha.h | 5 | ||||
-rw-r--r-- | hwacha/hwacha_xcpt.h | 17 | ||||
-rw-r--r-- | hwacha/insns/vf.h | 13 | ||||
-rw-r--r-- | hwacha/insns/vsetcfg.h | 6 | ||||
-rw-r--r-- | hwacha/insns/vxcptaux.h | 2 | ||||
-rw-r--r-- | hwacha/insns/vxcptcause.h | 3 | ||||
-rw-r--r-- | hwacha/insns/vxcptkill.h | 3 | ||||
-rw-r--r-- | hwacha/insns/vxcptrestore.h | 1 | ||||
-rw-r--r-- | hwacha/insns/vxcptsave.h | 1 | ||||
-rw-r--r-- | hwacha/opcodes_hwacha.h | 2 |
13 files changed, 209 insertions, 24 deletions
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) |