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
//
2023-01-14 03:44:38 +00:00
// Documentation: RISC-V System on Chip Design Chapter 5 (Figure 5.9)
//
2023-01-11 23:15:08 +00:00
// A component of the CORE-V-WALLY configurable RISC-V project.
2024-01-29 13:38:11 +00:00
// https://github.com/openhwgroup/cvw
2021-01-15 04:37:51 +00:00
//
2023-01-10 19:35:20 +00:00
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
2021-01-15 04:37:51 +00:00
//
2023-01-10 19:35:20 +00:00
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
2021-01-15 04:37:51 +00:00
//
2023-01-10 19:35:20 +00:00
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
// may obtain a copy of the License at
2021-01-15 04:37:51 +00:00
//
2023-01-10 19:35:20 +00:00
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work distributed under the
// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
2022-01-07 12:58:40 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////
2021-01-15 04:37:51 +00:00
2023-05-26 17:03:46 +00:00
module trap import cvw : : * ; # ( parameter cvw_t P ) (
2023-03-24 22:32:25 +00:00
input logic reset ,
2024-01-05 22:23:12 +00:00
input logic InstrMisalignedFaultM , InstrAccessFaultM , HPTWInstrAccessFaultM , HPTWInstrPageFaultM , IllegalInstrFaultM ,
2023-03-24 22:32:25 +00:00
input logic BreakpointFaultM , LoadMisalignedFaultM , StoreAmoMisalignedFaultM ,
input logic LoadAccessFaultM , StoreAmoAccessFaultM , EcallFaultM , InstrPageFaultM ,
input logic LoadPageFaultM , StoreAmoPageFaultM , // various trap sources
2023-10-25 03:58:26 +00:00
input logic wfiM , wfiW , // wait for interrupt instruction
2023-03-24 22:32:25 +00:00
input logic [ 1 : 0 ] PrivilegeModeW , // current privilege mode
input logic [ 11 : 0 ] MIP_REGW , MIE_REGW , MIDELEG_REGW , // interrupt pending, enabled, and delegate CSRs
2023-03-29 14:02:09 +00:00
input logic [ 15 : 0 ] MEDELEG_REGW , // exception delegation SR
2023-03-24 22:32:25 +00:00
input logic STATUS_MIE , STATUS_SIE , // machine/supervisor interrupt enables
input logic InstrValidM , // current instruction is valid, not flushed
input logic CommittedM , CommittedF , // LSU/IFU has committed to a bus operation that can't be interrupted
output logic TrapM , // Trap is occurring
output logic InterruptM , // Interrupt is occurring
output logic ExceptionM , // exception is occurring
output logic IntPendingM , // Interrupt is pending, might occur if enabled
output logic DelegateM , // Delegate trap to supervisor handler
2023-03-29 14:02:09 +00:00
output logic [ 3 : 0 ] CauseM // trap cause
2021-01-15 04:37:51 +00:00
) ;
2023-03-24 22:32:25 +00:00
logic MIntGlobalEnM , SIntGlobalEnM ; // Global interupt enables
logic Committed ; // LSU or IFU has committed to a bus operation that can't be interrupted
2024-01-05 22:23:12 +00:00
logic BothInstrAccessFaultM , BothInstrPageFaultM ; // instruction or HPTW ITLB fill caused an Instruction Access Fault
2023-03-24 22:32:25 +00:00
logic [ 11 : 0 ] PendingIntsM , ValidIntsM , EnabledIntsM ; // interrupts are pending, valid, or enabled
2021-01-15 04:37:51 +00:00
2022-05-12 18:37:47 +00:00
///////////////////////////////////////////
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-05-12 18:37:47 +00:00
///////////////////////////////////////////
2023-01-14 03:44:38 +00:00
2023-05-26 17:03:46 +00:00
assign MIntGlobalEnM = ( PrivilegeModeW ! = P . M_MODE ) | STATUS_MIE ; // if M ints enabled or lower priv 3.1.9
assign SIntGlobalEnM = ( PrivilegeModeW = = P . U_MODE ) | ( ( PrivilegeModeW = = P . S_MODE ) & STATUS_SIE ) ; // if in lower priv mode, or if S ints enabled and not in higher priv mode 3.1.9
2023-06-13 03:31:44 +00:00
assign PendingIntsM = MIP_REGW & MIE_REGW ;
assign IntPendingM = | PendingIntsM ;
assign Committed = CommittedM | CommittedF ;
2024-04-21 15:40:11 +00:00
assign EnabledIntsM = ( MIntGlobalEnM ? PendingIntsM & ~ MIDELEG_REGW : '0 ) | ( SIntGlobalEnM ? PendingIntsM & MIDELEG_REGW : '0 ) ;
assign ValidIntsM = Committed ? '0 : EnabledIntsM ;
2023-10-26 17:24:36 +00:00
assign InterruptM = ( | ValidIntsM ) & InstrValidM & ( ~ wfiM | wfiW ) ; // suppress interrupt if the memory system has partially processed a request. Delay interrupt until wfi is in the W stage.
// wfiW is to support possible but unlikely back to back wfi instructions. wfiM would be high in the M stage, while also in the W stage.
2023-06-13 03:31:44 +00:00
assign DelegateM = P . S_SUPPORTED & ( InterruptM ? MIDELEG_REGW [ CauseM ] : MEDELEG_REGW [ CauseM ] ) &
2023-05-26 17:03:46 +00:00
( PrivilegeModeW = = P . U_MODE | PrivilegeModeW = = P . S_MODE ) ;
2022-01-28 19:19:24 +00:00
2022-05-12 18:37:47 +00:00
///////////////////////////////////////////
2023-12-21 00:18:31 +00:00
// Trigger Traps
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-05-12 18:37:47 +00:00
///////////////////////////////////////////
2023-01-14 03:44:38 +00:00
2022-11-29 22:28:14 +00:00
assign BothInstrAccessFaultM = InstrAccessFaultM | HPTWInstrAccessFaultM ;
2024-01-05 22:23:12 +00:00
assign BothInstrPageFaultM = InstrPageFaultM | HPTWInstrPageFaultM ;
2023-04-16 06:13:39 +00:00
// coverage off -item e 1 -fecexprrow 2
// excludes InstrMisalignedFaultM from coverage of this line, since misaligned instructions cannot occur in rv64gc.
2022-11-29 22:28:14 +00:00
assign ExceptionM = InstrMisalignedFaultM | BothInstrAccessFaultM | IllegalInstrFaultM |
2022-01-27 23:11:27 +00:00
LoadMisalignedFaultM | StoreAmoMisalignedFaultM |
2024-01-05 22:23:12 +00:00
BothInstrPageFaultM | LoadPageFaultM | StoreAmoPageFaultM |
2021-07-17 19:57:10 +00:00
BreakpointFaultM | EcallFaultM |
2022-01-27 23:11:27 +00:00
LoadAccessFaultM | StoreAmoAccessFaultM ;
2023-04-16 06:13:39 +00:00
// coverage on
2023-10-09 21:03:37 +00:00
assign TrapM = ( ExceptionM & ~ CommittedF ) | InterruptM ; // *** RT: review this additional ~CommittedF with DH and update priv chapter.
2021-01-15 04:37:51 +00:00
2022-05-12 18:37:47 +00:00
///////////////////////////////////////////
2023-12-13 19:33:59 +00:00
// Cause priority defined in privileged spec
2022-05-12 18:37:47 +00:00
///////////////////////////////////////////
2023-01-14 03:44:38 +00:00
2021-01-15 04:37:51 +00:00
always_comb
2024-04-21 15:40:11 +00:00
if ( reset ) CauseM = 4 'd0 ; // hard reset 3.3
else if ( ValidIntsM [ 11 ] ) CauseM = 4 'd11 ; // Machine External Int
else if ( ValidIntsM [ 3 ] ) CauseM = 4 'd3 ; // Machine Sw Int
else if ( ValidIntsM [ 7 ] ) CauseM = 4 'd7 ; // Machine Timer Int
else if ( ValidIntsM [ 9 ] ) CauseM = 4 'd9 ; // Supervisor External Int
else if ( ValidIntsM [ 1 ] ) CauseM = 4 'd1 ; // Supervisor Sw Int
else if ( ValidIntsM [ 5 ] ) CauseM = 4 'd5 ; // Supervisor Timer Int
else if ( BothInstrPageFaultM ) CauseM = 4 'd12 ;
else if ( BothInstrAccessFaultM ) CauseM = 4 'd1 ;
else if ( IllegalInstrFaultM ) CauseM = 4 'd2 ;
2023-04-11 06:18:25 +00:00
// coverage off
// Misaligned instructions cannot occur in rv64gc
2024-04-21 15:40:11 +00:00
else if ( InstrMisalignedFaultM ) CauseM = 4 'd0 ;
2023-04-11 06:18:25 +00:00
// coverage on
2024-04-21 15:40:11 +00:00
else if ( BreakpointFaultM ) CauseM = 4 'd3 ;
2023-03-29 14:02:09 +00:00
else if ( EcallFaultM ) CauseM = { 2 'b10 , PrivilegeModeW } ;
2024-04-21 15:40:11 +00:00
else if ( StoreAmoMisalignedFaultM & ~ P . ZICCLSM_SUPPORTED ) CauseM = 4 'd6 ; // misaligned faults are higher priority if they always are taken
else if ( LoadMisalignedFaultM & ~ P . ZICCLSM_SUPPORTED ) CauseM = 4 'd4 ;
else if ( StoreAmoPageFaultM ) CauseM = 4 'd15 ;
else if ( LoadPageFaultM ) CauseM = 4 'd13 ;
else if ( StoreAmoAccessFaultM ) CauseM = 4 'd7 ;
else if ( LoadAccessFaultM ) CauseM = 4 'd5 ;
else if ( StoreAmoMisalignedFaultM & P . ZICCLSM_SUPPORTED ) CauseM = 4 'd6 ; // See priority in Privileged Spec 3.1.15
else if ( LoadMisalignedFaultM & P . ZICCLSM_SUPPORTED ) CauseM = 4 'd4 ;
else CauseM = 4 'd0 ;
2021-07-06 18:43:53 +00:00
endmodule