cvw/pipelined/src/privileged/trap.sv

112 lines
5.9 KiB
Systemverilog
Raw Normal View History

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
//
2023-01-11 23:15:08 +00:00
// A component of the CORE-V-WALLY configurable RISC-V project.
2021-01-15 04:37:51 +00:00
//
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
2021-01-15 04:37:51 +00:00
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
2021-01-15 04:37:51 +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
//
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////
2021-01-15 04:37:51 +00:00
`include "wally-config.vh"
2021-01-15 04:37:51 +00:00
module trap (
2022-05-12 15:15:30 +00:00
input logic reset,
(* mark_debug = "true" *) input logic InstrMisalignedFaultM, InstrAccessFaultM, HPTWInstrAccessFaultM, IllegalInstrFaultM,
(* mark_debug = "true" *) input logic BreakpointFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM,
(* mark_debug = "true" *) input logic LoadAccessFaultM, StoreAmoAccessFaultM, EcallFaultM, InstrPageFaultM,
(* mark_debug = "true" *) input logic LoadPageFaultM, StoreAmoPageFaultM,
(* mark_debug = "true" *) input logic mretM, sretM,
2022-05-12 22:06:03 +00:00
input logic [1:0] PrivilegeModeW,
(* mark_debug = "true" *) input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
input logic [`XLEN-1:0] MEDELEG_REGW,
input logic STATUS_MIE, STATUS_SIE,
input logic InstrValidM, wfiM, CommittedM, CommittedF,
2022-05-12 22:26:21 +00:00
output logic TrapM, RetM,
output logic InterruptM, IntPendingM, DelegateM, WFIStallM,
2022-05-12 23:47:21 +00:00
output logic [`LOG_XLEN-1:0] CauseM
2021-01-15 04:37:51 +00:00
);
2021-06-10 00:58:20 +00:00
logic MIntGlobalEnM, SIntGlobalEnM;
2022-05-12 15:21:09 +00:00
logic ExceptionM;
logic Committed;
logic BothInstrAccessFaultM;
2022-12-16 16:27:39 +00:00
(* mark_debug = "true" *) logic [11:0] PendingIntsM, ValidIntsM, EnabledIntsM;
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)
// & 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
///////////////////////////////////////////
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
assign PendingIntsM = MIP_REGW & MIE_REGW;
assign IntPendingM = |PendingIntsM;
2022-12-23 07:58:14 +00:00
assign Committed = CommittedM | CommittedF;
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request.
2022-05-31 21:12:17 +00:00
assign DelegateM = `S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM[3:0]] : MEDELEG_REGW[CauseM]) &
(PrivilegeModeW == `U_MODE | PrivilegeModeW == `S_MODE);
assign WFIStallM = wfiM & ~IntPendingM;
2022-01-28 19:19:24 +00:00
2022-05-12 18:37:47 +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-05-12 18:37:47 +00:00
///////////////////////////////////////////
assign BothInstrAccessFaultM = InstrAccessFaultM | HPTWInstrAccessFaultM;
assign ExceptionM = InstrMisalignedFaultM | BothInstrAccessFaultM | IllegalInstrFaultM |
LoadMisalignedFaultM | StoreAmoMisalignedFaultM |
InstrPageFaultM | LoadPageFaultM | StoreAmoPageFaultM |
2021-07-17 19:57:10 +00:00
BreakpointFaultM | EcallFaultM |
LoadAccessFaultM | StoreAmoAccessFaultM;
2022-05-12 21:55:50 +00:00
assign TrapM = ExceptionM | InterruptM;
assign RetM = mretM | sretM;
2021-01-15 04:37:51 +00:00
2022-05-12 18:37:47 +00:00
///////////////////////////////////////////
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)
2022-05-12 18:37:47 +00:00
///////////////////////////////////////////
2021-01-15 04:37:51 +00:00
always_comb
2022-05-12 18:37:47 +00:00
if (reset) CauseM = 0; // hard reset 3.3
2022-05-12 23:39:10 +00:00
else if (ValidIntsM[11]) CauseM = 11; // Machine External Int
else if (ValidIntsM[3]) CauseM = 3; // Machine Sw Int
else if (ValidIntsM[7]) CauseM = 7; // Machine Timer Int
else if (ValidIntsM[9]) CauseM = 9; // Supervisor External Int
else if (ValidIntsM[1]) CauseM = 1; // Supervisor Sw Int
else if (ValidIntsM[5]) CauseM = 5; // Supervisor Timer Int
2022-05-12 18:37:47 +00:00
else if (InstrPageFaultM) CauseM = 12;
else if (BothInstrAccessFaultM) CauseM = 1;
2022-05-12 18:37:47 +00:00
else if (IllegalInstrFaultM) CauseM = 2;
else if (InstrMisalignedFaultM) CauseM = 0;
else if (BreakpointFaultM) CauseM = 3;
2022-05-12 23:47:21 +00:00
else if (EcallFaultM) CauseM = {{(`LOG_XLEN-4){1'b0}}, {2'b10}, PrivilegeModeW};
2022-05-12 18:37:47 +00:00
else if (LoadMisalignedFaultM) CauseM = 4;
else if (StoreAmoMisalignedFaultM) CauseM = 6;
2022-05-12 18:37:47 +00:00
else if (LoadPageFaultM) CauseM = 13;
else if (StoreAmoPageFaultM) CauseM = 15;
else if (LoadAccessFaultM) CauseM = 5;
else if (StoreAmoAccessFaultM) CauseM = 7;
else CauseM = 0;
endmodule