2021-01-15 04:37:51 +00:00
///////////////////////////////////////////
2021-02-15 15:10:50 +00:00
// privileged.sv
2021-01-15 04:37:51 +00:00
//
// Written: David_Harris@hmc.edu 5 January 2021
// Modified:
//
// Purpose: Implements the CSRs, Exceptions, and Privileged operations
// See RISC-V Privileged Mode Specification 20190608
//
// 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.
///////////////////////////////////////////
2021-01-23 15:48:12 +00:00
`include " wally-config.vh "
2021-01-15 04:37:51 +00:00
2021-06-04 15:59:14 +00:00
// *** remove signals not needed by PMA/PMP now that it is moved
2021-01-23 15:48:12 +00:00
module privileged (
2021-02-02 04:44:41 +00:00
input logic clk , reset ,
2021-06-08 16:41:25 +00:00
input logic FlushD , FlushE , FlushM , FlushW , StallD , StallE , StallM , StallW ,
2021-02-26 22:00:07 +00:00
input logic CSRReadM , CSRWriteM ,
2021-01-23 15:48:12 +00:00
input logic [ `XLEN - 1 : 0 ] SrcAM ,
2021-05-29 03:11:37 +00:00
input logic [ `XLEN - 1 : 0 ] PCF , PCD , PCE , PCM ,
input logic [ 31 : 0 ] InstrD , InstrE , InstrM , InstrW ,
2021-02-02 18:02:31 +00:00
output logic [ `XLEN - 1 : 0 ] CSRReadValW ,
2021-01-23 15:48:12 +00:00
output logic [ `XLEN - 1 : 0 ] PrivilegedNextPCM ,
2021-06-02 14:03:19 +00:00
output logic RetM , TrapM , NonBusTrapM ,
2021-04-01 19:55:05 +00:00
output logic ITLBFlushF , DTLBFlushM ,
2021-06-08 16:32:46 +00:00
input logic InstrValidM , InstrValidW , CommittedM ,
input logic FloatRegWriteW , LoadStallD ,
2021-03-31 16:54:02 +00:00
input logic BPPredDirWrongM ,
input logic BTBPredPCWrongM ,
input logic RASPredPCWrongM ,
input logic BPPredClassNonCFIWrongM ,
input logic [ 4 : 0 ] InstrClassM ,
2021-02-02 04:44:41 +00:00
input logic PrivilegedM ,
2021-04-21 23:58:36 +00:00
input logic ITLBInstrPageFaultF , DTLBLoadPageFaultM , DTLBStorePageFaultM ,
input logic WalkerInstrPageFaultF , WalkerLoadPageFaultM , WalkerStorePageFaultM ,
2021-05-01 02:18:01 +00:00
input logic InstrMisalignedFaultM , IllegalIEUInstrFaultD , IllegalFPUInstrD ,
2021-04-22 19:34:02 +00:00
input logic LoadMisalignedFaultM ,
input logic StoreMisalignedFaultM ,
2021-02-02 04:44:41 +00:00
input logic TimerIntM , ExtIntM , SwIntM ,
2021-02-02 20:09:24 +00:00
input logic [ `XLEN - 1 : 0 ] InstrMisalignedAdrM , MemAdrM ,
2021-02-02 04:44:41 +00:00
input logic [ 4 : 0 ] SetFflagsM ,
2021-06-04 21:05:07 +00:00
// Trap signals from pmp/pma in mmu
// *** do these need to be split up into one for dmem and one for ifu?
// instead, could we only care about the instr and F pins that come from ifu and only care about the load/store and m pins that come from dmem?
input logic PMAInstrAccessFaultF , PMPInstrAccessFaultF ,
input logic PMALoadAccessFaultM , PMPLoadAccessFaultM ,
input logic PMAStoreAccessFaultM , PMPStoreAccessFaultM ,
2021-05-18 14:42:51 +00:00
output logic IllegalFPUInstrE ,
2021-03-18 18:35:46 +00:00
output logic [ 1 : 0 ] PrivilegeModeW ,
2021-03-05 06:22:53 +00:00
output logic [ `XLEN - 1 : 0 ] SATP_REGW ,
2021-04-21 23:58:36 +00:00
output logic STATUS_MXR , STATUS_SUM ,
2021-06-04 21:05:07 +00:00
output logic [ 63 : 0 ] PMPCFG01_REGW , PMPCFG23_REGW ,
2021-06-08 19:29:22 +00:00
output var logic [ `XLEN - 1 : 0 ] PMPADDR_ARRAY_REGW [ 0 : `PMP_ENTRIES - 1 ] ,
2021-06-08 16:41:25 +00:00
output logic [ 2 : 0 ] FRM_REGW
2021-01-15 04:37:51 +00:00
) ;
2021-03-18 18:35:46 +00:00
logic [ 1 : 0 ] NextPrivilegeModeM ;
2021-01-15 04:37:51 +00:00
2021-01-23 15:48:12 +00:00
logic [ `XLEN - 1 : 0 ] CauseM , NextFaultMtvalM ;
logic [ `XLEN - 1 : 0 ] MEPC_REGW , SEPC_REGW , UEPC_REGW , UTVEC_REGW , STVEC_REGW , MTVEC_REGW ;
logic [ `XLEN - 1 : 0 ] MEDELEG_REGW , MIDELEG_REGW , SEDELEG_REGW , SIDELEG_REGW ;
2021-01-15 04:37:51 +00:00
// logic [11:0] MIP_REGW, SIP_REGW, UIP_REGW, MIE_REGW, SIE_REGW, UIE_REGW;
logic uretM , sretM , mretM , ecallM , ebreakM , wfiM , sfencevmaM ;
2021-01-27 12:46:52 +00:00
logic IllegalCSRAccessM ;
2021-04-13 17:39:22 +00:00
logic IllegalIEUInstrFaultE , IllegalIEUInstrFaultM ;
2021-05-18 14:42:51 +00:00
logic IllegalFPUInstrM ;
2021-04-21 23:58:36 +00:00
logic LoadPageFaultM , StorePageFaultM ;
logic InstrPageFaultF , InstrPageFaultD , InstrPageFaultE , InstrPageFaultM ;
2021-04-22 19:34:02 +00:00
logic InstrAccessFaultF , InstrAccessFaultD , InstrAccessFaultE , InstrAccessFaultM ;
logic LoadAccessFaultM , StoreAccessFaultM ;
2021-01-27 12:46:52 +00:00
logic IllegalInstrFaultM ;
2021-01-15 04:37:51 +00:00
logic BreakpointFaultM , EcallFaultM ;
2021-04-29 19:21:08 +00:00
logic MTrapM , STrapM , UTrapM ;
logic InterruptM ;
2021-01-15 04:37:51 +00:00
logic [ 1 : 0 ] STATUS_MPP ;
2021-06-05 01:04:19 +00:00
logic STATUS_SPP , STATUS_TSR , STATUS_MPRV ; // **** status mprv is unused outside of the csr module as of 4 June 2021. should it be deleted alltogether from the module, or should I leav the pin here in case someone needs it?
2021-01-15 04:37:51 +00:00
logic STATUS_MIE , STATUS_SIE ;
logic [ 11 : 0 ] MIP_REGW , MIE_REGW ;
2021-01-29 04:21:12 +00:00
logic md , sd ;
2021-01-15 04:37:51 +00:00
2021-04-29 06:20:39 +00:00
2021-01-29 04:21:12 +00:00
///////////////////////////////////////////
2021-01-15 04:37:51 +00:00
// track the current privilege level
2021-01-29 04:21:12 +00:00
///////////////////////////////////////////
2021-01-15 04:37:51 +00:00
2021-01-29 04:21:12 +00:00
// get bits of DELEG registers based on CAUSE
assign md = CauseM [ `XLEN - 1 ] ? MIDELEG_REGW [ CauseM [ 4 : 0 ] ] : MEDELEG_REGW [ CauseM [ 4 : 0 ] ] ;
assign sd = CauseM [ `XLEN - 1 ] ? SIDELEG_REGW [ CauseM [ 4 : 0 ] ] : SEDELEG_REGW [ CauseM [ 4 : 0 ] ] ; // depricated
2021-01-15 04:37:51 +00:00
2021-01-29 04:21:12 +00:00
// PrivilegeMode FSM
always_comb
2021-02-15 15:10:50 +00:00
/ * if ( reset ) NextPrivilegeModeM = `M_MODE ; // Privilege resets to 11 (Machine Mode) // moved reset to flop
else */ if ( mretM ) NextPrivilegeModeM = STATUS_MPP ;
2021-01-29 04:21:12 +00:00
else if ( sretM ) NextPrivilegeModeM = { 1 'b0 , STATUS_SPP } ;
else if ( uretM ) NextPrivilegeModeM = `U_MODE ;
else if ( TrapM ) begin // Change privilege based on DELEG registers (see 3.1.8)
if ( PrivilegeModeW = = `U_MODE )
if ( `N_SUPPORTED & `U_SUPPORTED & md & sd ) NextPrivilegeModeM = `U_MODE ;
else if ( `S_SUPPORTED & md ) NextPrivilegeModeM = `S_MODE ;
else NextPrivilegeModeM = `M_MODE ;
else if ( PrivilegeModeW = = `S_MODE )
if ( `S_SUPPORTED & md ) NextPrivilegeModeM = `S_MODE ;
else NextPrivilegeModeM = `M_MODE ;
else NextPrivilegeModeM = `M_MODE ;
end else NextPrivilegeModeM = PrivilegeModeW ;
2021-02-15 15:10:50 +00:00
flopenl # ( 2 ) privmodereg ( clk , reset , ~ StallW , NextPrivilegeModeM , `M_MODE , PrivilegeModeW ) ;
2021-01-29 04:21:12 +00:00
///////////////////////////////////////////
// decode privileged instructions
///////////////////////////////////////////
privdec pmd ( . InstrM ( InstrM [ 31 : 20 ] ) , . * ) ;
///////////////////////////////////////////
// Control and Status Registers
///////////////////////////////////////////
csr csr ( . * ) ;
///////////////////////////////////////////
2021-01-15 04:37:51 +00:00
// Extract exceptions by name and handle them
2021-01-29 04:21:12 +00:00
///////////////////////////////////////////
2021-01-15 04:37:51 +00:00
assign BreakpointFaultM = ebreakM ; // could have other causes too
assign EcallFaultM = ecallM ;
2021-04-01 19:55:05 +00:00
assign ITLBFlushF = sfencevmaM ;
assign DTLBFlushM = sfencevmaM ;
2021-04-21 23:58:36 +00:00
// A page fault might occur because of insufficient privilege during a TLB
// lookup or a improperly formatted page table during walking
assign InstrPageFaultF = ITLBInstrPageFaultF | | WalkerInstrPageFaultF ;
assign LoadPageFaultM = DTLBLoadPageFaultM | | WalkerLoadPageFaultM ;
assign StorePageFaultM = DTLBStorePageFaultM | | WalkerStorePageFaultM ;
2021-01-27 12:46:52 +00:00
2021-04-29 06:20:39 +00:00
assign InstrAccessFaultF = PMAInstrAccessFaultF | | PMPInstrAccessFaultF ;
assign LoadAccessFaultM = PMALoadAccessFaultM | | PMPLoadAccessFaultM ;
assign StoreAccessFaultM = PMAStoreAccessFaultM | | PMPStoreAccessFaultM ;
2021-01-27 12:46:52 +00:00
// pipeline fault signals
2021-04-13 17:39:22 +00:00
flopenrc # ( 2 ) faultregD ( clk , reset , FlushD , ~ StallD ,
{ InstrPageFaultF , InstrAccessFaultF } ,
{ InstrPageFaultD , InstrAccessFaultD } ) ;
2021-05-01 02:18:01 +00:00
flopenrc # ( 4 ) faultregE ( clk , reset , FlushE , ~ StallE ,
{ IllegalIEUInstrFaultD , InstrPageFaultD , InstrAccessFaultD , IllegalFPUInstrD } , // ** vs IllegalInstrFaultInD
{ IllegalIEUInstrFaultE , InstrPageFaultE , InstrAccessFaultE , IllegalFPUInstrE } ) ;
flopenrc # ( 4 ) faultregM ( clk , reset , FlushM , ~ StallM ,
{ IllegalIEUInstrFaultE , InstrPageFaultE , InstrAccessFaultE , IllegalFPUInstrE } ,
{ IllegalIEUInstrFaultM , InstrPageFaultM , InstrAccessFaultM , IllegalFPUInstrM } ) ;
2021-01-27 12:46:52 +00:00
2021-01-29 04:21:12 +00:00
trap trap ( . * ) ;
2021-01-27 12:46:52 +00:00
2021-01-15 04:37:51 +00:00
endmodule