cvw/wally-pipelined/src/privileged/trap.sv

156 lines
8.6 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
//
// Purpose: Handle Traps: Exceptions and Interrupt
// 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
//
// 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:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// 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.
///////////////////////////////////////////
`include "wally-config.vh"
2021-01-15 04:37:51 +00:00
module trap (
input logic clk, reset,
input logic InstrMisalignedFaultM, InstrAccessFaultM, IllegalInstrFaultM,
input logic BreakpointFaultM, LoadMisalignedFaultM, StoreMisalignedFaultM,
input logic LoadAccessFaultM, StoreAccessFaultM, EcallFaultM, InstrPageFaultM,
input logic LoadPageFaultM, StorePageFaultM,
input logic mretM, sretM, uretM,
input logic [1:0] PrivilegeModeW, NextPrivilegeModeM,
input logic [`XLEN-1:0] MEPC_REGW, SEPC_REGW, UEPC_REGW, UTVEC_REGW, STVEC_REGW, MTVEC_REGW,
input logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW,
input logic STATUS_MIE, STATUS_SIE,
2021-04-22 20:17:57 +00:00
input logic [`XLEN-1:0] PCM,
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
input logic [31:0] InstrM,
input logic StallW,
input logic InstrValidM, CommittedM,
output logic NonBusTrapM, TrapM, MTrapM, STrapM, UTrapM, RetM,
2021-04-29 19:21:08 +00:00
output logic InterruptM,
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;
logic [11:0] PendingIntsM;
2021-04-29 19:21:08 +00:00
//logic InterruptM;
2021-04-15 23:13:42 +00:00
logic [`XLEN-1:0] PrivilegedTrapVector, PrivilegedVectoredTrapVector;
logic BusTrapM;
2021-01-15 04:37:51 +00:00
// Determine pending enabled interrupts
2021-06-10 00:58:20 +00:00
assign MIntGlobalEnM = (PrivilegeModeW != `M_MODE) || STATUS_MIE; // if M ints enabled or lower priv 3.1.9
2021-01-15 04:37:51 +00:00
assign SIntGlobalEnM = (PrivilegeModeW == `U_MODE) || STATUS_SIE; // if S ints enabled or lower priv 3.1.9
assign PendingIntsM = ((MIP_REGW & MIE_REGW) & ({12{MIntGlobalEnM}} & 12'h888)) | ((SIP_REGW & SIE_REGW) & ({12{SIntGlobalEnM}} & 12'h222));
assign InterruptM = (|PendingIntsM) & InstrValidM & ~CommittedM;
// 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
2021-01-15 04:37:51 +00:00
// Trigger Traps and RET
// Created groups of trap signals so that bus could take in all traps it doesn't already produce (i.e. using just TrapM to squash access created circular paths)
assign BusTrapM = LoadAccessFaultM | StoreAccessFaultM;
assign NonBusTrapM = InstrMisalignedFaultM | InstrAccessFaultM | IllegalInstrFaultM |
LoadMisalignedFaultM | StoreMisalignedFaultM |
InstrPageFaultM | LoadPageFaultM | StorePageFaultM |
BreakpointFaultM | EcallFaultM |
InterruptM;
assign TrapM = BusTrapM | NonBusTrapM;
2021-01-15 04:37:51 +00:00
assign MTrapM = TrapM & (NextPrivilegeModeM == `M_MODE);
assign STrapM = TrapM & (NextPrivilegeModeM == `S_MODE) & `S_SUPPORTED;
assign UTrapM = TrapM & (NextPrivilegeModeM == `U_MODE) & `N_SUPPORTED;
assign RetM = mretM | sretM | uretM;
2021-04-15 23:13:42 +00:00
always_comb
if (NextPrivilegeModeM == `U_MODE) PrivilegedTrapVector = UTVEC_REGW;
else if (NextPrivilegeModeM == `S_MODE) PrivilegedTrapVector = STVEC_REGW;
else PrivilegedTrapVector = MTVEC_REGW;
// Handle vectored traps (when mtvec/stvec/utvec csr value has bits [1:0] == 01)
// For vectored traps, set program counter to _tvec value + 4 times the cause code
//
// 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}
2021-04-15 23:41:25 +00:00
generate
if(`VECTORED_INTERRUPTS_SUPPORTED) begin
always_comb
if (PrivilegedTrapVector[1:0] == 2'b01 && CauseM[`XLEN-1] == 1)
PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2] + {CauseM[`XLEN-5:0], 2'b00}, 2'b00};
2021-04-15 23:41:25 +00:00
else
PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00};
end
else begin
assign PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00};
end
endgenerate
2021-04-15 23:13:42 +00:00
2021-01-15 04:37:51 +00:00
always_comb
if (mretM) PrivilegedNextPCM = MEPC_REGW;
else if (sretM) PrivilegedNextPCM = SEPC_REGW;
else if (uretM) PrivilegedNextPCM = UEPC_REGW;
else PrivilegedNextPCM = PrivilegedVectoredTrapVector;
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
else if (PendingIntsM[11]) CauseM = (1 << (`XLEN-1)) + 11; // Machine External Int
else if (PendingIntsM[3]) CauseM = (1 << (`XLEN-1)) + 3; // Machine Sw Int
else if (PendingIntsM[7]) CauseM = (1 << (`XLEN-1)) + 7; // Machine Timer Int
else if (PendingIntsM[9]) CauseM = (1 << (`XLEN-1)) + 9; // Supervisor External Int
else if (PendingIntsM[1]) CauseM = (1 << (`XLEN-1)) + 1; // Supervisor Sw Int
else if (PendingIntsM[5]) CauseM = (1 << (`XLEN-1)) + 5; // Supervisor Timer Int
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;
else if (EcallFaultM) CauseM = {{(`XLEN-2){1'b0}}, PrivilegeModeW} + 8;
2021-01-15 04:37:51 +00:00
else if (LoadMisalignedFaultM) CauseM = 4;
else if (StoreMisalignedFaultM) CauseM = 6;
else if (LoadPageFaultM) CauseM = 13;
else if (StorePageFaultM) CauseM = 15;
else if (LoadAccessFaultM) CauseM = 5;
else if (StoreAccessFaultM) CauseM = 7;
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
if (InstrMisalignedFaultM) NextFaultMtvalM = InstrMisalignedAdrM;
else if (LoadMisalignedFaultM) NextFaultMtvalM = MemAdrM;
else if (StoreMisalignedFaultM) NextFaultMtvalM = MemAdrM;
2021-04-22 20:17:57 +00:00
else if (InstrPageFaultM) NextFaultMtvalM = PCM;
else if (LoadPageFaultM) NextFaultMtvalM = MemAdrM;
else if (StorePageFaultM) NextFaultMtvalM = MemAdrM;
else if (IllegalInstrFaultM) NextFaultMtvalM = {{(`XLEN-32){1'b0}}, InstrM};
2021-01-15 04:37:51 +00:00
else NextFaultMtvalM = 0;
endmodule