2021-01-15 04:37:51 +00:00
///////////////////////////////////////////
// trap.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
2021-04-15 23:13:42 +00:00
// Modified: dottolia@hmc.edu 14 April 2021: Add support for vectored interrupts
2021-01-15 04:37:51 +00:00
//
2021-10-23 16:41:24 +00:00
// Purpose: Handle Traps: Exceptions and Interrupts
2021-01-15 04:37:51 +00:00
// See RISC-V Privileged Mode Specification 20190608 3.1.10-11
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
2022-01-07 12:58:40 +00:00
// MIT LICENSE
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
2021-01-15 04:37:51 +00:00
//
2022-01-07 12:58:40 +00:00
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
2021-01-15 04:37:51 +00:00
//
2022-01-07 12:58:40 +00:00
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.
////////////////////////////////////////////////////////////////////////////////////////////////
2021-01-15 04:37:51 +00:00
2021-01-23 15:48:12 +00:00
`include " wally-config.vh "
2021-01-15 04:37:51 +00:00
2021-01-23 15:48:12 +00:00
module trap (
2021-11-29 16:06:53 +00:00
input logic clk ,
2021-10-23 16:41:24 +00:00
input logic reset ,
2021-09-27 18:57:46 +00:00
( * mark_debug = " true " * ) input logic InstrMisalignedFaultM , InstrAccessFaultM , IllegalInstrFaultM ,
2022-01-27 23:11:27 +00:00
( * mark_debug = " true " * ) input logic BreakpointFaultM , LoadMisalignedFaultM , StoreAmoMisalignedFaultM ,
( * mark_debug = " true " * ) input logic LoadAccessFaultM , StoreAmoAccessFaultM , EcallFaultM , InstrPageFaultM ,
( * mark_debug = " true " * ) input logic LoadPageFaultM , StoreAmoPageFaultM ,
2022-02-15 19:48:49 +00:00
( * mark_debug = " true " * ) input logic mretM , sretM ,
2021-07-14 20:00:33 +00:00
input logic [ 1 : 0 ] PrivilegeModeW , NextPrivilegeModeM ,
2022-02-15 19:59:29 +00:00
( * mark_debug = " true " * ) input logic [ `XLEN - 1 : 0 ] MEPC_REGW , SEPC_REGW , STVEC_REGW , MTVEC_REGW ,
2022-03-30 20:22:41 +00:00
( * mark_debug = " true " * ) input logic [ 11 : 0 ] MIP_REGW , MIE_REGW , SIP_REGW , SIE_REGW , MIDELEG_REGW ,
2021-07-14 20:00:33 +00:00
input logic STATUS_MIE , STATUS_SIE ,
input logic [ `XLEN - 1 : 0 ] PCM ,
2022-04-22 22:45:23 +00:00
input logic [ `XLEN - 1 : 0 ] IEUAdrM ,
2021-07-14 20:00:33 +00:00
input logic [ 31 : 0 ] InstrM ,
2022-04-17 17:20:35 +00:00
input logic InstrValidM , CommittedM , DivE ,
2021-07-17 19:22:24 +00:00
output logic TrapM , MTrapM , STrapM , UTrapM , RetM ,
2021-07-14 20:00:33 +00:00
output logic InterruptM ,
output logic ExceptionM ,
2021-01-23 15:48:12 +00:00
output logic [ `XLEN - 1 : 0 ] PrivilegedNextPCM , CauseM , NextFaultMtvalM
2021-01-15 04:37:51 +00:00
// output logic [11:0] MIP_REGW, SIP_REGW, UIP_REGW, MIE_REGW, SIE_REGW, UIE_REGW,
// input logic WriteMIPM, WriteSIPM, WriteUIPM, WriteMIEM, WriteSIEM, WriteUIEM
) ;
2021-06-10 00:58:20 +00:00
logic MIntGlobalEnM , SIntGlobalEnM ;
2022-03-30 20:22:41 +00:00
( * mark_debug = " true " * ) logic [ 11 : 0 ] MPendingIntsM , SPendingIntsM ;
2021-04-29 19:21:08 +00:00
//logic InterruptM;
2021-04-15 23:13:42 +00:00
logic [ `XLEN - 1 : 0 ] PrivilegedTrapVector , PrivilegedVectoredTrapVector ;
2021-07-17 19:57:10 +00:00
logic Exception1M ;
2021-01-15 04:37:51 +00:00
// Determine pending enabled interrupts
2021-07-17 20:01:07 +00:00
// interrupt if any sources are pending
// & with a M stage valid bit to avoid interrupts from interrupt a nonexistent flushed instruction (in the M stage)
2021-12-29 04:27:12 +00:00
// & with ~CommittedM to make sure MEPC isn't chosen so as to rerun the same instr twice
2022-03-30 20:22:41 +00:00
// MPendingIntsM[i] = ((priv == M & mstatus.MIE) | (priv < M)) & mip[i] & mie[i] & ~mideleg[i]
// Sinterrupt[i] = ((priv == S & sstatus.SIE) | (priv < S)) & sip[i] & sie[i]
2022-01-02 21:47:21 +00:00
assign MIntGlobalEnM = ( PrivilegeModeW ! = `M_MODE ) | STATUS_MIE ; // if M ints enabled or lower priv 3.1.9
assign SIntGlobalEnM = ( PrivilegeModeW = = `U_MODE ) | ( ( PrivilegeModeW = = `S_MODE ) & STATUS_SIE ) ; // if in lower priv mode, or if S ints enabled and not in higher priv mode 3.1.9
2022-03-30 20:22:41 +00:00
assign MPendingIntsM = { 12 { MIntGlobalEnM } } & MIP_REGW & MIE_REGW & ~ MIDELEG_REGW ;
assign SPendingIntsM = { 12 { SIntGlobalEnM } } & SIP_REGW & SIE_REGW ;
assign InterruptM = ( | MPendingIntsM | | | SPendingIntsM ) & & InstrValidM & & ~ ( CommittedM ) ; // *** RT. CommittedM is a temporary hack to prevent integer division from having an interrupt during divide.
2022-01-28 19:19:24 +00:00
2021-01-15 04:37:51 +00:00
// Trigger Traps and RET
2021-07-17 19:57:10 +00:00
// According to RISC-V Spec Section 1.6, exceptions are caused by instructions. Interrupts are external asynchronous.
// Traps are the union of exceptions and interrupts.
2022-01-28 19:19:24 +00:00
assign ExceptionM = InstrMisalignedFaultM | InstrAccessFaultM | IllegalInstrFaultM |
2022-01-27 23:11:27 +00:00
LoadMisalignedFaultM | StoreAmoMisalignedFaultM |
InstrPageFaultM | LoadPageFaultM | StoreAmoPageFaultM |
2021-07-17 19:57:10 +00:00
BreakpointFaultM | EcallFaultM |
2022-01-27 23:11:27 +00:00
LoadAccessFaultM | StoreAmoAccessFaultM ;
2022-01-28 19:19:24 +00:00
assign TrapM = ExceptionM | InterruptM ; // *** clean this up later DH
2021-01-15 04:37:51 +00:00
assign MTrapM = TrapM & ( NextPrivilegeModeM = = `M_MODE ) ;
assign STrapM = TrapM & ( NextPrivilegeModeM = = `S_MODE ) & `S_SUPPORTED ;
2022-02-15 19:48:49 +00:00
assign RetM = mretM | sretM ;
2021-01-15 04:37:51 +00:00
2021-04-15 23:13:42 +00:00
always_comb
2022-02-15 19:59:29 +00:00
if ( NextPrivilegeModeM = = `S_MODE ) PrivilegedTrapVector = STVEC_REGW ;
else PrivilegedTrapVector = MTVEC_REGW ;
2021-04-15 23:13:42 +00:00
2022-02-15 19:59:29 +00:00
// Handle vectored traps (when mtvec/stvec csr value has bits [1:0] == 01)
2021-04-15 23:13:42 +00:00
// For vectored traps, set program counter to _tvec value + 4 times the cause code
2021-04-30 00:42:14 +00:00
//
// POSSIBLE OPTIMIZATION:
// From 20190608 privielegd spec page 27 (3.1.7)
// > Allowing coarser alignments in Vectored mode enables vectoring to be
// > implemented without a hardware adder circuit.
// For example, we could require m/stvec be aligned on 7 bits to let us replace the adder directly below with
// [untested] PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:7], CauseM[3:0], 4'b0000}
2022-01-05 14:35:25 +00:00
if ( `VECTORED_INTERRUPTS_SUPPORTED ) begin : vec
always_comb
if ( PrivilegedTrapVector [ 1 : 0 ] = = 2 'b01 & CauseM [ `XLEN - 1 ] = = 1 )
2022-03-29 17:11:28 +00:00
PrivilegedVectoredTrapVector = { PrivilegedTrapVector [ `XLEN - 1 : 2 ] + CauseM [ `XLEN - 3 : 0 ] , 2 'b00 } ;
2022-01-05 14:35:25 +00:00
else
PrivilegedVectoredTrapVector = { PrivilegedTrapVector [ `XLEN - 1 : 2 ] , 2 'b00 } ;
end
else begin
assign PrivilegedVectoredTrapVector = { PrivilegedTrapVector [ `XLEN - 1 : 2 ] , 2 'b00 } ;
end
2021-04-15 23:13:42 +00:00
2021-01-15 04:37:51 +00:00
always_comb
2022-04-07 21:32:43 +00:00
if ( TrapM ) PrivilegedNextPCM = PrivilegedVectoredTrapVector ;
else if ( mretM ) PrivilegedNextPCM = MEPC_REGW ;
else PrivilegedNextPCM = SEPC_REGW ;
2021-01-15 04:37:51 +00:00
// Cause priority defined in table 3.7 of 20190608 privileged spec
// Exceptions are of lower priority than all interrupts (3.1.9)
always_comb
if ( reset ) CauseM = 0 ; // hard reset 3.3
2022-03-30 20:22:41 +00:00
else if ( MPendingIntsM [ 11 ] ) CauseM = ( 1 < < ( `XLEN - 1 ) ) + 11 ; // Machine External Int
else if ( MPendingIntsM [ 3 ] ) CauseM = ( 1 < < ( `XLEN - 1 ) ) + 3 ; // Machine Sw Int
else if ( MPendingIntsM [ 7 ] ) CauseM = ( 1 < < ( `XLEN - 1 ) ) + 7 ; // Machine Timer Int
else if ( MPendingIntsM [ 9 ] ) CauseM = ( 1 < < ( `XLEN - 1 ) ) + 9 ; // Supervisor External Int handled by M-mode
else if ( MPendingIntsM [ 1 ] ) CauseM = ( 1 < < ( `XLEN - 1 ) ) + 1 ; // Supervisor Sw Int handled by M-mode
else if ( MPendingIntsM [ 5 ] ) CauseM = ( 1 < < ( `XLEN - 1 ) ) + 5 ; // Supervisor Timer Int handled by M-mode
else if ( SPendingIntsM [ 9 ] ) CauseM = ( 1 < < ( `XLEN - 1 ) ) + 9 ; // Supervisor External Int handled by S-mode
else if ( SPendingIntsM [ 1 ] ) CauseM = ( 1 < < ( `XLEN - 1 ) ) + 1 ; // Supervisor Sw Int handled by S-mode
else if ( SPendingIntsM [ 5 ] ) CauseM = ( 1 < < ( `XLEN - 1 ) ) + 5 ; // Supervisor Timer Int handled by S-mode
2021-01-15 04:37:51 +00:00
else if ( InstrPageFaultM ) CauseM = 12 ;
else if ( InstrAccessFaultM ) CauseM = 1 ;
else if ( InstrMisalignedFaultM ) CauseM = 0 ;
else if ( IllegalInstrFaultM ) CauseM = 2 ;
else if ( BreakpointFaultM ) CauseM = 3 ;
2021-01-23 15:48:12 +00:00
else if ( EcallFaultM ) CauseM = { { ( `XLEN - 2 ) { 1 'b0 } } , PrivilegeModeW } + 8 ;
2021-01-15 04:37:51 +00:00
else if ( LoadMisalignedFaultM ) CauseM = 4 ;
2022-01-27 23:11:27 +00:00
else if ( StoreAmoMisalignedFaultM ) CauseM = 6 ;
2021-01-15 04:37:51 +00:00
else if ( LoadPageFaultM ) CauseM = 13 ;
2022-01-27 23:11:27 +00:00
else if ( StoreAmoPageFaultM ) CauseM = 15 ;
2021-01-15 04:37:51 +00:00
else if ( LoadAccessFaultM ) CauseM = 5 ;
2022-01-27 23:11:27 +00:00
else if ( StoreAmoAccessFaultM ) CauseM = 7 ;
2021-01-15 04:37:51 +00:00
else CauseM = 0 ;
// MTVAL
// 3.1.17: on instruction fetch, load, or store address misaligned access or page fault
// mtval is written with the faulting virtual address.
// On illegal instruction trap, mtval may be written with faulting instruction
// For other traps (including interrupts), mtval is set to 0
// *** hardware breakpoint is supposed to write faulting virtual address per priv p. 38
// *** Page faults not yet implemented
// Technically
always_comb
2022-04-22 22:45:23 +00:00
if ( InstrMisalignedFaultM ) NextFaultMtvalM = IEUAdrM ;
2021-12-19 20:00:30 +00:00
else if ( LoadMisalignedFaultM ) NextFaultMtvalM = IEUAdrM ;
2022-01-27 23:11:27 +00:00
else if ( StoreAmoMisalignedFaultM ) NextFaultMtvalM = IEUAdrM ;
2021-09-13 16:40:40 +00:00
else if ( BreakpointFaultM ) NextFaultMtvalM = PCM ;
2021-04-22 20:17:57 +00:00
else if ( InstrPageFaultM ) NextFaultMtvalM = PCM ;
2021-12-19 20:00:30 +00:00
else if ( LoadPageFaultM ) NextFaultMtvalM = IEUAdrM ;
2022-01-27 23:11:27 +00:00
else if ( StoreAmoPageFaultM ) NextFaultMtvalM = IEUAdrM ;
2021-01-23 15:48:12 +00:00
else if ( IllegalInstrFaultM ) NextFaultMtvalM = { { ( `XLEN - 32 ) { 1 'b0 } } , InstrM } ;
2021-01-15 04:37:51 +00:00
else NextFaultMtvalM = 0 ;
2021-07-06 18:43:53 +00:00
endmodule