diff --git a/src/hazard/hazard.sv b/src/hazard/hazard.sv index b47ac410d..94c967f32 100644 --- a/src/hazard/hazard.sv +++ b/src/hazard/hazard.sv @@ -50,8 +50,8 @@ module hazard ( // WFI logic flopenrc #(1) wfiWReg(clk, reset, FlushW, ~StallW, wfiM, wfiW); - assign WFIStallM = wfiW & ~IntPendingM; // WFI waiting for an interrupt or timeout - assign WFIInterruptedM = wfiW & IntPendingM; // WFI detects a pending interrupt. Retire WFI; trap if interrupt is enabled. + assign WFIStallM = wfiM & ~IntPendingM; // WFI waiting for an interrupt or timeout + assign WFIInterruptedM = wfiM & IntPendingM; // WFI detects a pending interrupt. Retire WFI; trap if interrupt is enabled. // stalls and flushes // loads: stall for one cycle if the subsequent instruction depends on the load @@ -76,8 +76,8 @@ module hazard ( assign FlushDCause = TrapM | RetM | CSRWriteFenceM | BPWrongE; assign FlushECause = TrapM | RetM | CSRWriteFenceM |(BPWrongE & ~(DivBusyE | FDivBusyE)); assign FlushMCause = TrapM | RetM | CSRWriteFenceM; - //assign FlushWCause = TrapM & ~WFIInterruptedM; - assign FlushWCause = TrapM; + assign FlushWCause = TrapM & ~WFIInterruptedM; + //assign FlushWCause = TrapM; // Stall causes // Most data depenency stalls are identified in the decode stage @@ -90,13 +90,13 @@ module hazard ( assign StallFCause = '0; assign StallDCause = (LoadStallD | StoreStallD | MDUStallD | CSRRdStallD | FCvtIntStallD | FPUStallD) & ~FlushDCause; assign StallECause = (DivBusyE | FDivBusyE) & ~FlushECause; - //assign StallMCause = WFIStallM & ~FlushMCause; - assign StallMCause = '0; + assign StallMCause = WFIStallM & ~FlushMCause; + //assign StallMCause = '0; // Need to gate IFUStallF when the equivalent FlushFCause = FlushDCause = 1. // assign StallWCause = ((IFUStallF & ~FlushDCause) | LSUStallM) & ~FlushWCause; // Because FlushWCause is a strict subset of FlushDCause, FlushWCause is factored out. - //assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause); - assign StallWCause = (IFUStallF & ~FlushDCause) | ((LSUStallM | WFIStallM) & ~FlushWCause); + assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause); + //assign StallWCause = (IFUStallF & ~FlushDCause) | ((LSUStallM | WFIStallM) & ~FlushWCause); // Stall each stage for cause or if the next stage is stalled // coverage off: StallFCause is always 0 diff --git a/src/privileged/csr.sv b/src/privileged/csr.sv index 38e8945d9..ccd06a1ea 100644 --- a/src/privileged/csr.sv +++ b/src/privileged/csr.sv @@ -39,6 +39,7 @@ module csr import cvw::*; #(parameter cvw_t P) ( input logic CSRReadM, CSRWriteM, // read or write CSR input logic TrapM, // trap is occurring input logic mretM, sretM, wfiM, // return or WFI instruction + output logic wfiW, input logic IntPendingM, // at least one interrupt is pending and could occur if enabled input logic InterruptM, // interrupt is occurring input logic ExceptionM, // interrupt is occurring @@ -200,13 +201,10 @@ module csr import cvw::*; #(parameter cvw_t P) ( /////////////////////////////////////////// // CSR Write values /////////////////////////////////////////// - logic [P.XLEN-1:0] PCW; // *** can optimize out it's just PCM for all now. - logic wfiW; - flopenr #(P.XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW); flopenrc #(1) wfiWReg(clk, reset, FlushW, ~StallW, wfiM, wfiW); assign CSRAdrM = InstrM[31:20]; - assign UnalignedNextEPCM = TrapM ? ((wfiW & IntPendingM) ? PCW+4 : PCM) : CSRWriteValM; + assign UnalignedNextEPCM = TrapM ? PCM : CSRWriteValM; assign NextEPCM = P.C_SUPPORTED ? {UnalignedNextEPCM[P.XLEN-1:1], 1'b0} : {UnalignedNextEPCM[P.XLEN-1:2], 2'b00}; // 3.1.15 alignment assign NextCauseM = TrapM ? {InterruptM, CauseM}: {CSRWriteValM[P.XLEN-1], CSRWriteValM[3:0]}; assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM; diff --git a/src/privileged/privdec.sv b/src/privileged/privdec.sv index a0195f366..e6edbb086 100644 --- a/src/privileged/privdec.sv +++ b/src/privileged/privdec.sv @@ -29,7 +29,7 @@ module privdec import cvw::*; #(parameter cvw_t P) ( input logic clk, reset, - input logic StallM, + input logic StallM, StallW, FlushW, input logic [31:15] InstrM, // privileged instruction function field input logic PrivilegedM, // is this a privileged instruction (from IEU controller) input logic IllegalIEUFPUInstrM, // Not a legal IEU instruction @@ -75,6 +75,8 @@ module privdec import cvw::*; #(parameter cvw_t P) ( /////////////////////////////////////////// // WFI timeout Privileged Spec 3.1.6.5 /////////////////////////////////////////// + logic wfiW; // *** need to merge with others + flopenrc #(1) wfiWReg(clk, reset, FlushW, ~StallW, wfiM, wfiW); // *** remove if (P.U_SUPPORTED) begin:wfi logic [P.WFI_TIMEOUT_BIT:0] WFICount, WFICountPlus1; diff --git a/src/privileged/privileged.sv b/src/privileged/privileged.sv index fff4af8b8..c338d2475 100644 --- a/src/privileged/privileged.sv +++ b/src/privileged/privileged.sv @@ -115,12 +115,14 @@ module privileged import cvw::*; #(parameter cvw_t P) ( logic ExceptionM; // Memory stage instruction caused a fault logic HPTWInstrAccessFaultM; // Hardware page table access fault while fetching instruction PTE + logic wfiW; + // track the current privilege level privmode #(P) privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM, .STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW); // decode privileged instructions - privdec #(P) pmd(.clk, .reset, .StallM, .InstrM(InstrM[31:15]), + privdec #(P) pmd(.clk, .reset, .StallM, .StallW, .FlushW, .InstrM(InstrM[31:15]), .PrivilegedM, .IllegalIEUFPUInstrM, .IllegalCSRAccessM, .PrivilegeModeW, .STATUS_TSR, .STATUS_TVM, .STATUS_TW, .IllegalInstrFaultM, .EcallFaultM, .BreakpointFaultM, .sretM, .mretM, .wfiM, .sfencevmaM); @@ -128,7 +130,7 @@ module privileged import cvw::*; #(parameter cvw_t P) ( // Control and Status Registers csr #(P) csr(.clk, .reset, .FlushM, .FlushW, .StallE, .StallM, .StallW, .InstrM, .InstrOrigM, .PCM, .SrcAM, .IEUAdrM, .PC2NextF, - .CSRReadM, .CSRWriteM, .TrapM, .mretM, .sretM, .wfiM, .IntPendingM, .InterruptM, + .CSRReadM, .CSRWriteM, .TrapM, .mretM, .sretM, .wfiM, .wfiW, .IntPendingM, .InterruptM, .MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT, .InstrValidM, .FRegWriteM, .LoadStallD, .StoreStallD, .BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .BPWrongM, @@ -156,5 +158,5 @@ module privileged import cvw::*; #(parameter cvw_t P) ( .mretM, .sretM, .PrivilegeModeW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MEDELEG_REGW, .STATUS_MIE, .STATUS_SIE, .InstrValidM, .CommittedM, .CommittedF, - .TrapM, .RetM, .wfiM, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .CauseM); + .TrapM, .RetM, .wfiM, .wfiW, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .CauseM); endmodule diff --git a/src/privileged/trap.sv b/src/privileged/trap.sv index bcde634de..00ffc6617 100644 --- a/src/privileged/trap.sv +++ b/src/privileged/trap.sv @@ -33,7 +33,7 @@ module trap import cvw::*; #(parameter cvw_t P) ( input logic LoadAccessFaultM, StoreAmoAccessFaultM, EcallFaultM, InstrPageFaultM, input logic LoadPageFaultM, StoreAmoPageFaultM, // various trap sources input logic mretM, sretM, // return instructions - input logic wfiM, // wait for interrupt instruction + input logic wfiM, wfiW, // wait for interrupt instruction input logic [1:0] PrivilegeModeW, // current privilege mode input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, // interrupt pending, enabled, and delegate CSRs input logic [15:0] MEDELEG_REGW, // exception delegation SR @@ -68,7 +68,7 @@ module trap import cvw::*; #(parameter cvw_t P) ( assign Committed = CommittedM | CommittedF; assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW); assign ValidIntsM = {12{~Committed}} & EnabledIntsM; - assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request. + assign InterruptM = (|ValidIntsM) & InstrValidM & (~wfiM | wfiW); // suppress interrupt if the memory system has partially processed a request. assign DelegateM = P.S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) & (PrivilegeModeW == P.U_MODE | PrivilegeModeW == P.S_MODE);