From 2cdd49c7d2422861b7c6cfc187dd2c627e417705 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 8 May 2022 04:30:46 +0000 Subject: [PATCH] WFI terminates when an interrupt is pending even if interrupts are globally disabled --- pipelined/src/hazard/hazard.sv | 8 +++--- pipelined/src/privileged/privileged.sv | 4 +-- pipelined/src/privileged/trap.sv | 33 ++++++++++++----------- pipelined/src/wally/wallypipelinedcore.sv | 6 ++--- 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/pipelined/src/hazard/hazard.sv b/pipelined/src/hazard/hazard.sv index bb45003f8..b0e13f5f9 100644 --- a/pipelined/src/hazard/hazard.sv +++ b/pipelined/src/hazard/hazard.sv @@ -38,7 +38,7 @@ module hazard( (* mark_debug = "true" *) input logic FPUStallD, FStallD, (* mark_debug = "true" *) input logic DivBusyE,FDivBusyE, (* mark_debug = "true" *) input logic EcallFaultM, BreakpointFaultM, -(* mark_debug = "true" *) input logic InvalidateICacheM, wfiM, +(* mark_debug = "true" *) input logic InvalidateICacheM, wfiM, IntPendingM, // Stall & flush outputs (* mark_debug = "true" *) output logic StallF, StallD, StallE, StallM, StallW, (* mark_debug = "true" *) output logic FlushF, FlushD, FlushE, FlushM, FlushW @@ -61,9 +61,11 @@ module hazard( // If any stages are stalled, the first stage that isn't stalled must flush. assign StallFCause = CSRWritePendingDEM & ~(TrapM | RetM | BPPredWrongE); - assign StallDCause = (LoadStallD | StoreStallD | MDUStallD | CSRRdStallD | FPUStallD | FStallD) & ~(TrapM | RetM | BPPredWrongE); // stall in decode if instruction is a load/mul/csr dependent on previous + // stall in decode if instruction is a load/mul/csr dependent on previous + assign StallDCause = (LoadStallD | StoreStallD | MDUStallD | CSRRdStallD | FPUStallD | FStallD) & ~(TrapM | RetM | BPPredWrongE); assign StallECause = (DivBusyE | FDivBusyE) & ~(TrapM); - assign StallMCause = wfiM & ~TrapM; + // WFI terminates if any enabled interrupt is pending, even if global interrupts are disabled. It could also terminate with TW trap + assign StallMCause = wfiM & (~TrapM & ~IntPendingM); assign StallWCause = LSUStallM | IFUStallF; assign StallF = StallFCause | StallD; diff --git a/pipelined/src/privileged/privileged.sv b/pipelined/src/privileged/privileged.sv index 5ae49a9d0..21c7eab2b 100644 --- a/pipelined/src/privileged/privileged.sv +++ b/pipelined/src/privileged/privileged.sv @@ -78,7 +78,7 @@ module privileged ( output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], output logic [2:0] FRM_REGW, - output logic BreakpointFaultM, EcallFaultM, wfiM + output logic BreakpointFaultM, EcallFaultM, wfiM, IntPendingM ); logic [1:0] NextPrivilegeModeM; @@ -226,7 +226,7 @@ module privileged ( .InstrM, .InstrValidM, .CommittedM, .DivE, .TrapM, .MTrapM, .STrapM, .UTrapM, .RetM, - .InterruptM, + .InterruptM, .IntPendingM, .ExceptionM, .PrivilegedNextPCM, .CauseM, .NextFaultMtvalM); endmodule diff --git a/pipelined/src/privileged/trap.sv b/pipelined/src/privileged/trap.sv index 421015ebb..8a5bb2ebf 100644 --- a/pipelined/src/privileged/trap.sv +++ b/pipelined/src/privileged/trap.sv @@ -48,7 +48,7 @@ module trap ( input logic [31:0] InstrM, input logic InstrValidM, CommittedM, DivE, output logic TrapM, MTrapM, STrapM, UTrapM, RetM, - output logic InterruptM, + output logic InterruptM, IntPendingM, output logic ExceptionM, output logic [`XLEN-1:0] PrivilegedNextPCM, CauseM, NextFaultMtvalM // output logic [11:0] MIP_REGW, SIP_REGW, UIP_REGW, MIE_REGW, SIE_REGW, UIE_REGW, @@ -56,7 +56,7 @@ module trap ( ); logic MIntGlobalEnM, SIntGlobalEnM; - (* mark_debug = "true" *) logic [11:0] MPendingIntsM, SPendingIntsM; + (* mark_debug = "true" *) logic [11:0] MPendingIntsM, SPendingIntsM, MValidIntsM, SValidIntsM; //logic InterruptM; logic [`XLEN-1:0] PrivilegedTrapVector, PrivilegedVectoredTrapVector; logic Exception1M; @@ -65,13 +65,16 @@ module trap ( // 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 - // MPendingIntsM[i] = ((priv == M & mstatus.MIE) | (priv < M)) & mip[i] & mie[i] & ~mideleg[i] + // MValidIntsM[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] 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 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. + assign MPendingIntsM = MIP_REGW & MIE_REGW; + assign SPendingIntsM = SIP_REGW & SIE_REGW; + assign IntPendingM = |MPendingIntsM; + assign MValidIntsM = {12{MIntGlobalEnM}} & MPendingIntsM & ~MIDELEG_REGW; + assign SValidIntsM = {12{SIntGlobalEnM}} & SPendingIntsM; + assign InterruptM = (|MValidIntsM || |SValidIntsM) && InstrValidM && ~(CommittedM); // *** RT. CommittedM is a temporary hack to prevent integer division from having an interrupt during divide. // Trigger Traps and RET // According to RISC-V Spec Section 1.6, exceptions are caused by instructions. Interrupts are external asynchronous. @@ -119,15 +122,15 @@ module trap ( // Exceptions are of lower priority than all interrupts (3.1.9) always_comb if (reset) CauseM = 0; // hard reset 3.3 - 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 + else if (MValidIntsM[11]) CauseM = (1 << (`XLEN-1)) + 11; // Machine External Int + else if (MValidIntsM[3]) CauseM = (1 << (`XLEN-1)) + 3; // Machine Sw Int + else if (MValidIntsM[7]) CauseM = (1 << (`XLEN-1)) + 7; // Machine Timer Int + else if (MValidIntsM[9]) CauseM = (1 << (`XLEN-1)) + 9; // Supervisor External Int handled by M-mode + else if (MValidIntsM[1]) CauseM = (1 << (`XLEN-1)) + 1; // Supervisor Sw Int handled by M-mode + else if (MValidIntsM[5]) CauseM = (1 << (`XLEN-1)) + 5; // Supervisor Timer Int handled by M-mode + else if (SValidIntsM[9]) CauseM = (1 << (`XLEN-1)) + 9; // Supervisor External Int handled by S-mode + else if (SValidIntsM[1]) CauseM = (1 << (`XLEN-1)) + 1; // Supervisor Sw Int handled by S-mode + else if (SValidIntsM[5]) CauseM = (1 << (`XLEN-1)) + 5; // Supervisor Timer Int handled by S-mode else if (InstrPageFaultM) CauseM = 12; else if (InstrAccessFaultM) CauseM = 1; else if (IllegalInstrFaultM) CauseM = 2; diff --git a/pipelined/src/wally/wallypipelinedcore.sv b/pipelined/src/wally/wallypipelinedcore.sv index 2a756eaa2..38ef3f9c4 100644 --- a/pipelined/src/wally/wallypipelinedcore.sv +++ b/pipelined/src/wally/wallypipelinedcore.sv @@ -112,7 +112,7 @@ module wallypipelinedcore ( logic [1:0] PrivilegeModeW; logic [`XLEN-1:0] PTE; logic [1:0] PageType; - logic wfiM; + logic wfiM, IntPendingM; // PMA checker signals var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0]; @@ -306,7 +306,7 @@ module wallypipelinedcore ( .FPUStallD, .FStallD, .DivBusyE, .FDivBusyE, .EcallFaultM, .BreakpointFaultM, - .InvalidateICacheM, .wfiM, + .InvalidateICacheM, .wfiM, .IntPendingM, // Stall & flush outputs .StallF, .StallD, .StallE, .StallM, .StallW, .FlushF, .FlushD, .FlushE, .FlushM, .FlushW @@ -341,7 +341,7 @@ module wallypipelinedcore ( .PrivilegeModeW, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, - .FRM_REGW,.BreakpointFaultM, .EcallFaultM, .wfiM + .FRM_REGW,.BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM ); end else begin assign CSRReadValW = 0;