WFI terminates when an interrupt is pending even if interrupts are globally disabled

This commit is contained in:
David Harris 2022-05-08 04:30:46 +00:00
parent 412d4656ed
commit a516f89f22
4 changed files with 28 additions and 23 deletions

View File

@ -38,7 +38,7 @@ module hazard(
(* mark_debug = "true" *) input logic FPUStallD, FStallD, (* mark_debug = "true" *) input logic FPUStallD, FStallD,
(* mark_debug = "true" *) input logic DivBusyE,FDivBusyE, (* mark_debug = "true" *) input logic DivBusyE,FDivBusyE,
(* mark_debug = "true" *) input logic EcallFaultM, BreakpointFaultM, (* 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 // Stall & flush outputs
(* mark_debug = "true" *) output logic StallF, StallD, StallE, StallM, StallW, (* mark_debug = "true" *) output logic StallF, StallD, StallE, StallM, StallW,
(* mark_debug = "true" *) output logic FlushF, FlushD, FlushE, FlushM, FlushW (* 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. // If any stages are stalled, the first stage that isn't stalled must flush.
assign StallFCause = CSRWritePendingDEM & ~(TrapM | RetM | BPPredWrongE); 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 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 StallWCause = LSUStallM | IFUStallF;
assign StallF = StallFCause | StallD; assign StallF = StallFCause | StallD;

View File

@ -78,7 +78,7 @@ module privileged (
output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], 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 var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
output logic [2:0] FRM_REGW, output logic [2:0] FRM_REGW,
output logic BreakpointFaultM, EcallFaultM, wfiM output logic BreakpointFaultM, EcallFaultM, wfiM, IntPendingM
); );
logic [1:0] NextPrivilegeModeM; logic [1:0] NextPrivilegeModeM;
@ -226,7 +226,7 @@ module privileged (
.InstrM, .InstrM,
.InstrValidM, .CommittedM, .DivE, .InstrValidM, .CommittedM, .DivE,
.TrapM, .MTrapM, .STrapM, .UTrapM, .RetM, .TrapM, .MTrapM, .STrapM, .UTrapM, .RetM,
.InterruptM, .InterruptM, .IntPendingM,
.ExceptionM, .ExceptionM,
.PrivilegedNextPCM, .CauseM, .NextFaultMtvalM); .PrivilegedNextPCM, .CauseM, .NextFaultMtvalM);
endmodule endmodule

View File

@ -48,7 +48,7 @@ module trap (
input logic [31:0] InstrM, input logic [31:0] InstrM,
input logic InstrValidM, CommittedM, DivE, input logic InstrValidM, CommittedM, DivE,
output logic TrapM, MTrapM, STrapM, UTrapM, RetM, output logic TrapM, MTrapM, STrapM, UTrapM, RetM,
output logic InterruptM, output logic InterruptM, IntPendingM,
output logic ExceptionM, output logic ExceptionM,
output logic [`XLEN-1:0] PrivilegedNextPCM, CauseM, NextFaultMtvalM output logic [`XLEN-1:0] PrivilegedNextPCM, CauseM, NextFaultMtvalM
// output logic [11:0] MIP_REGW, SIP_REGW, UIP_REGW, MIE_REGW, SIE_REGW, UIE_REGW, // 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; logic MIntGlobalEnM, SIntGlobalEnM;
(* mark_debug = "true" *) logic [11:0] MPendingIntsM, SPendingIntsM; (* mark_debug = "true" *) logic [11:0] MPendingIntsM, SPendingIntsM, MValidIntsM, SValidIntsM;
//logic InterruptM; //logic InterruptM;
logic [`XLEN-1:0] PrivilegedTrapVector, PrivilegedVectoredTrapVector; logic [`XLEN-1:0] PrivilegedTrapVector, PrivilegedVectoredTrapVector;
logic Exception1M; logic Exception1M;
@ -65,13 +65,16 @@ module trap (
// interrupt if any sources are pending // 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 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 // & 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] // 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 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 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 MPendingIntsM = MIP_REGW & MIE_REGW;
assign SPendingIntsM = {12{SIntGlobalEnM}} & SIP_REGW & SIE_REGW; assign SPendingIntsM = 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 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 // Trigger Traps and RET
// According to RISC-V Spec Section 1.6, exceptions are caused by instructions. Interrupts are external asynchronous. // 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) // Exceptions are of lower priority than all interrupts (3.1.9)
always_comb always_comb
if (reset) CauseM = 0; // hard reset 3.3 if (reset) CauseM = 0; // hard reset 3.3
else if (MPendingIntsM[11]) CauseM = (1 << (`XLEN-1)) + 11; // Machine External Int else if (MValidIntsM[11]) CauseM = (1 << (`XLEN-1)) + 11; // Machine External Int
else if (MPendingIntsM[3]) CauseM = (1 << (`XLEN-1)) + 3; // Machine Sw Int else if (MValidIntsM[3]) CauseM = (1 << (`XLEN-1)) + 3; // Machine Sw Int
else if (MPendingIntsM[7]) CauseM = (1 << (`XLEN-1)) + 7; // Machine Timer Int else if (MValidIntsM[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 (MValidIntsM[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 (MValidIntsM[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 (MValidIntsM[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 (SValidIntsM[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 (SValidIntsM[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 (SValidIntsM[5]) CauseM = (1 << (`XLEN-1)) + 5; // Supervisor Timer Int handled by S-mode
else if (InstrPageFaultM) CauseM = 12; else if (InstrPageFaultM) CauseM = 12;
else if (InstrAccessFaultM) CauseM = 1; else if (InstrAccessFaultM) CauseM = 1;
else if (IllegalInstrFaultM) CauseM = 2; else if (IllegalInstrFaultM) CauseM = 2;

View File

@ -112,7 +112,7 @@ module wallypipelinedcore (
logic [1:0] PrivilegeModeW; logic [1:0] PrivilegeModeW;
logic [`XLEN-1:0] PTE; logic [`XLEN-1:0] PTE;
logic [1:0] PageType; logic [1:0] PageType;
logic wfiM; logic wfiM, IntPendingM;
// PMA checker signals // PMA checker signals
var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0]; var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0];
@ -306,7 +306,7 @@ module wallypipelinedcore (
.FPUStallD, .FStallD, .FPUStallD, .FStallD,
.DivBusyE, .FDivBusyE, .DivBusyE, .FDivBusyE,
.EcallFaultM, .BreakpointFaultM, .EcallFaultM, .BreakpointFaultM,
.InvalidateICacheM, .wfiM, .InvalidateICacheM, .wfiM, .IntPendingM,
// Stall & flush outputs // Stall & flush outputs
.StallF, .StallD, .StallE, .StallM, .StallW, .StallF, .StallD, .StallE, .StallM, .StallW,
.FlushF, .FlushD, .FlushE, .FlushM, .FlushW .FlushF, .FlushD, .FlushE, .FlushM, .FlushW
@ -341,7 +341,7 @@ module wallypipelinedcore (
.PrivilegeModeW, .SATP_REGW, .PrivilegeModeW, .SATP_REGW,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS,
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.FRM_REGW,.BreakpointFaultM, .EcallFaultM, .wfiM .FRM_REGW,.BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM
); );
end else begin end else begin
assign CSRReadValW = 0; assign CSRReadValW = 0;