Browse Source

add hwacha exception support

confprec
Yunsup Lee 13 years ago
parent
commit
0f140bcde4
  1. 3
      config.h.in
  2. 45
      hwacha/decode_hwacha.h
  3. 66
      hwacha/decode_hwacha_ut.h
  4. 69
      hwacha/hwacha.cc
  5. 5
      hwacha/hwacha.h
  6. 17
      hwacha/hwacha_xcpt.h
  7. 13
      hwacha/insns/vf.h
  8. 6
      hwacha/insns/vsetcfg.h
  9. 2
      hwacha/insns/vxcptaux.h
  10. 3
      hwacha/insns/vxcptcause.h
  11. 3
      hwacha/insns/vxcptkill.h
  12. 1
      hwacha/insns/vxcptrestore.h
  13. 1
      hwacha/insns/vxcptsave.h
  14. 2
      hwacha/opcodes_hwacha.h
  15. 11
      riscv/pcr.h
  16. 4
      riscv/trap.h

3
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

45
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

66
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

69
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!");
}

5
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;

17
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

13
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())

6
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;

2
hwacha/insns/vxcptaux.h

@ -0,0 +1,2 @@
require_supervisor_hwacha;
xd = h->get_ct_state()->aux;

3
hwacha/insns/vxcptcause.h

@ -0,0 +1,3 @@
require_supervisor_hwacha;
h->clear_exception();
xd = h->get_ct_state()->cause;

3
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;

1
hwacha/insns/vxcptrestore.h

@ -0,0 +1 @@
require_supervisor_hwacha;

1
hwacha/insns/vxcptsave.h

@ -0,0 +1 @@
require_supervisor_hwacha;

2
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)

11
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

4
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

Loading…
Cancel
Save