diff options
| author | Prashanth Mundkur | 2018-01-29 06:02:48 -0800 |
|---|---|---|
| committer | Prashanth Mundkur | 2018-01-29 06:39:38 -0800 |
| commit | f206ae0ab7ff4e1870a002db2c9e2f030244ce31 (patch) | |
| tree | 46b5b9f478c6968265bed23ae7510d461b96c7f0 | |
| parent | 5a33eab7bc05f45cde76253f84e139b2428fbbe7 (diff) | |
Added ecall/mret and exception support.
| -rw-r--r-- | riscv/Makefile | 2 | ||||
| -rw-r--r-- | riscv/prelude.sail | 10 | ||||
| -rw-r--r-- | riscv/riscv.sail | 17 | ||||
| -rw-r--r-- | riscv/riscv_sys.sail | 289 |
4 files changed, 316 insertions, 2 deletions
diff --git a/riscv/Makefile b/riscv/Makefile index fabaaafc..00451f6f 100644 --- a/riscv/Makefile +++ b/riscv/Makefile @@ -1,4 +1,4 @@ -SAIL_SRCS = prelude.sail riscv_types.sail riscv.sail +SAIL_SRCS = prelude.sail riscv_types.sail riscv_sys.sail riscv.sail SAIL_DIR ?= $(realpath ..) export SAIL_DIR diff --git a/riscv/prelude.sail b/riscv/prelude.sail index 427da759..69fc1017 100644 --- a/riscv/prelude.sail +++ b/riscv/prelude.sail @@ -331,6 +331,7 @@ union exception = { Error_not_implemented : string, Error_misaligned_access, Error_EBREAK, + Error_internal_error } val "sign_extend" : forall 'n 'm, 'm >= 'n. (bits('n), atom('m)) -> bits('m) @@ -373,3 +374,12 @@ val operator << = "shift_bits_left" : forall 'n 'm. (bits('n), bits('m)) -> bits val vector64 : int -> bits(64) function vector64 n = __raw_GetSlice_int(64, n, 0) + +val vector_update_subrange_dec = "update_subrange" : forall 'n 'm 'o. + (bits('n), atom('m), atom('o), bits('m - ('o - 1))) -> bits('n) + +val vector_update_subrange_inc = "update_subrange" : forall 'n 'm 'o. + (vector('n, inc, bit), atom('m), atom('o), vector('o - ('m - 1), inc, bit)) -> vector('n, inc, bit) + +overload vector_update_subrange = {vector_update_subrange_dec, vector_update_subrange_inc} + diff --git a/riscv/riscv.sail b/riscv/riscv.sail index beb29327..76d98dcf 100644 --- a/riscv/riscv.sail +++ b/riscv/riscv.sail @@ -275,7 +275,22 @@ union clause ast = ECALL function clause decode 0b000000000000 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(ECALL) -function clause execute ECALL = not_implemented("ECALL is not implemented") +function clause execute ECALL = + let t : sync_exception = + struct { trap = match (cur_privilege) { + USER => User_ECall, + MACHINE => Machine_ECall + }, + badaddr = (None : option(regval)) } in + nextPC = handle_exception_ctl(cur_privilege, CTL_TRAP(t), PC) + +/* ****************************************************************** */ +union clause ast = MRET + +function clause decode 0b0011000 @ 0b00010 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(MRET) + +function clause execute MRET = + nextPC = handle_exception_ctl(cur_privilege, CTL_MRET, PC) /* ****************************************************************** */ union clause ast = EBREAK diff --git a/riscv/riscv_sys.sail b/riscv/riscv_sys.sail new file mode 100644 index 00000000..84002ed7 --- /dev/null +++ b/riscv/riscv_sys.sail @@ -0,0 +1,289 @@ +/* exception codes */ + +enum Interrupts = { + UserSWIntr, + SupervisorSWIntr, + ReservedIntr0, + MachineSWIntr, + + UserTimerIntr, + SupervisorTimerIntr, + ReservedIntr1, + MachineTimerIntr, + + UserExternalIntr, + SupervisorExternalIntr, + ReservedIntr2, + MachineExternalIntr +} + +enum ExceptionCode = { + Misaligned_Fetch, + Fetch_Access, + Illegal_Instr, + Breakpoint, + Misaligned_Load, + + Load_Access, + Misaligned_Store, + Store_Access, + + User_ECall, + Supervisor_ECall, + ReservedExc0, + Machine_ECall, + + Fetch_PageFault, + Load_PageFault, + ReservedExc1, + Store_PageFault +} + +/* machine mode registers */ + +/* FIXME: currently we have only those used by riscv-tests. */ + +bitfield Mstatus : bits(64) = { + SD : 63, + + SXL : 35 .. 34, + UXL : 33 .. 32, + + TSR : 22, + TW : 21, + TVM : 20, + MXR : 19, + SUM : 18, + MPRV : 17, + + XS : 16 .. 15, + FS : 14 .. 13, + + MPP : 12 .. 11, + SPP : 8, + + MPIE : 7, + SPIE : 5, + UPIE : 4, + + MIE : 3, + SIE : 1, + UIE : 0 +} +register mstatus : Mstatus + +bitfield Mip : bits(64) = { + MEIP : 11, + SEIP : 9, + UEIP : 8, + + MTIP : 7, + STIP : 5, + UTIP : 4, + + MSIP : 3, + SSIP : 1, + USIP : 0, + +} +register mip : Mip + +bitfield Mie : bits(64) = { + MEIE : 11, + SEIE : 9, + UEIE : 8, + + MTIE : 7, + STIE : 5, + UTIE : 4, + + MSIE : 3, + SSIE : 1, + USIE : 0, + +} +register mie : Mie + +bitfield Mideleg : bits(64) = { + MEID : 6, + SEID : 5, + UEID : 4, + + MTID : 6, + STID : 5, + UTID : 4, + + MSID : 3, + SSID : 1, + USID : 0 +} +register mideleg : Mideleg + +bitfield Medeleg : bits(64) = { + STORE_PAGE_FAULT : 15, + LOAD_PAGE_FAULT : 13, + FETCH_PAGE_FAULT : 12, + MACHINE_ECALL : 10, + SUPERVISOR_ECALL : 9, + USER_ECALL : 8, + STORE_ACCESS : 7, + MISALIGNED_STORE : 6, + LOAD_ACCESS : 5, + MISALIGNED_LOAD : 4, + BREAKPOINT : 3, + ILLEGAL_INSTR : 2, + FETCH_ACCESS : 1, + MISALIGNED_FETCH : 0 +} +register medeleg : Medeleg + +/* exception registers */ +register mepc : regval +register mtval : regval +register mtvec : regval +register mscratch : regval + +/* other registers */ + +register pmpaddr0 : regval +register pmpcfg0 : regval +/* TODO: this should be readonly, and always 0 for now */ +register mhartid : regval + +/* instruction control flow */ + +struct sync_exception = { + trap : ExceptionCode, + badaddr : option(regval) +} + +union ctl_result = { + CTL_TRAP : sync_exception, +/* TODO: + CTL_URET, + CTL_SRET, +*/ + CTL_MRET +} + +/* privilege level */ + +union privilege = { + MACHINE, + USER +} +register cur_privilege : privilege + +function priv_to_bits(p : privilege) -> bits(2) = + match (p) { + USER => 0b00, + MACHINE => 0b11 + } +function bits_to_priv(b : bits(2)) -> privilege = + match (b) { + 0b00 => USER, + 0b11 => MACHINE + } + +/* handle exceptional ctl flow by updating nextPC */ + +function handle_exception_ctl(cur_priv : privilege, ctl : ctl_result, + pc: regval) -> regval = + /* TODO: check delegation */ + match (cur_priv, ctl) { + (_, CTL_TRAP(e)) => { + mepc = pc; + mcause = e.trap; + + mstatus->MPIE() = mstatus.MIE(); + mstatus->MIE() = false; + mstatus->MPP() = priv_to_bits(cur_priv); + cur_privilege = MACHINE; + + match (e.trap) { + Misaligned_Fetch => { + match (e.badaddr) { + Some(a) => mtval = a, + None => throw(Error_internal_error) + } + }, + Fetch_Access => { + match (e.badaddr) { + Some(a) => mtval = a, + None => throw(Error_internal_error) + } + }, + Illegal_Instr => { + match (e.badaddr) { + Some(a) => mtval = a, + None => throw(Error_internal_error) + } + }, + + Breakpoint => not_implemented("breakpoint"), + + Misaligned_Load => { + match (e.badaddr) { + Some(a) => mtval = a, + None => throw(Error_internal_error) + } + }, + Load_Access => { + match (e.badaddr) { + Some(a) => mtval = a, + None => throw(Error_internal_error) + } + }, + Misaligned_Store => { + match (e.badaddr) { + Some(a) => mtval = a, + None => throw(Error_internal_error) + } + }, + Store_Access => { + match (e.badaddr) { + Some(a) => mtval = a, + None => throw(Error_internal_error) + } + }, + + User_ECall => { + mtval = EXTZ(0b0) + }, + Supervisor_ECall => { + mtval = EXTZ(0b0) + }, + Machine_ECall => { + mtval = EXTZ(0b0) + }, + + Fetch_PageFault => { + match (e.badaddr) { + Some(a) => mtval = a, + None => throw(Error_internal_error) + } + }, + Load_PageFault => { + match (e.badaddr) { + Some(a) => mtval = a, + None => throw(Error_internal_error) + } + }, + Store_PageFault => { + match (e.badaddr) { + Some(a) => mtval = a, + None => throw(Error_internal_error) + } + } + }; + /* TODO: make register read explicit */ + mtvec + }, + (_, CTL_MRET) => { + mstatus->MIE() = mstatus.MPIE(); + mstatus->MPIE() = true; + cur_privilege = bits_to_priv(mstatus.MPP()); + mstatus->MPP() = priv_to_bits(USER); + mepc + } + } |
