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 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;

View File

@ -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

View File

@ -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;

View File

@ -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;