From 1d8bc2dc1bd170801d4dcf04a66d1c6949baa5c3 Mon Sep 17 00:00:00 2001 From: David Harris Date: Thu, 2 Jun 2022 09:37:59 -0700 Subject: [PATCH] Added stalls for pending SFENCE.VMA and FENCE.I in hazard unit --- pipelined/src/hazard/hazard.sv | 17 +++++++---------- pipelined/src/ieu/controller.sv | 20 ++++++++++++-------- pipelined/src/ieu/ieu.sv | 4 ++-- pipelined/src/wally/wallypipelinedcore.sv | 8 ++++---- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/pipelined/src/hazard/hazard.sv b/pipelined/src/hazard/hazard.sv index 3cee7b037..b9163d6b4 100644 --- a/pipelined/src/hazard/hazard.sv +++ b/pipelined/src/hazard/hazard.sv @@ -32,13 +32,13 @@ module hazard( // Detect hazards -(* mark_debug = "true" *) input logic BPPredWrongE, CSRWritePendingDEM, RetM, TrapM, +(* mark_debug = "true" *) input logic BPPredWrongE, CSRWriteFencePendingDEM, RetM, TrapM, (* mark_debug = "true" *) input logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD, (* mark_debug = "true" *) input logic LSUStallM, IFUStallF, (* 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, sfencevmaM, wfiM, IntPendingM, +(* mark_debug = "true" *) input logic 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 @@ -46,7 +46,6 @@ module hazard( logic StallFCause, StallDCause, StallECause, StallMCause, StallWCause; logic FirstUnstalledD, FirstUnstalledE, FirstUnstalledM, FirstUnstalledW; - logic Fence, PrivilegedFlush; // stalls and flushes // loads: stall for one cycle if the subsequent instruction depends on the load @@ -62,7 +61,7 @@ module hazard( // *** can stalls be pushed into earlier stages (e.g. no stall after Decode?) - assign StallFCause = CSRWritePendingDEM & ~(TrapM | RetM | BPPredWrongE); + assign StallFCause = CSRWriteFencePendingDEM & ~(TrapM | RetM | BPPredWrongE); // 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); // *** can we move to decode stage (KP?) @@ -82,12 +81,10 @@ module hazard( assign FirstUnstalledW = ~StallW & StallM; // Each stage flushes if the previous stage is the last one stalled (for cause) or the system has reason to flush - assign Fence = InvalidateICacheM; // | sfencevmaM; // Fences should flush the pipeline and restart *** sfence not working - assign PrivilegedFlush = TrapM | RetM | Fence; // privileged stage change and fences flush pipeline - assign FlushF = BPPredWrongE | Fence; - assign FlushD = FirstUnstalledD | PrivilegedFlush | BPPredWrongE; - assign FlushE = FirstUnstalledE | PrivilegedFlush | BPPredWrongE; // *** why is BPPredWrongE here, but not needed in simple processor - assign FlushM = FirstUnstalledM | PrivilegedFlush; + assign FlushF = BPPredWrongE; + assign FlushD = FirstUnstalledD | TrapM | RetM | BPPredWrongE; + assign FlushE = FirstUnstalledE | TrapM | RetM | BPPredWrongE; // *** why is BPPredWrongE here, but not needed in simple processor + assign FlushM = FirstUnstalledM | TrapM | RetM; // on Trap the memory stage should be flushed going into the W stage, // except if the instruction causing the Trap is an ecall or ebreak. assign FlushW = FirstUnstalledW | (TrapM & ~(BreakpointFaultM | EcallFaultM)); diff --git a/pipelined/src/ieu/controller.sv b/pipelined/src/ieu/controller.sv index 501c3d59a..2818812e6 100644 --- a/pipelined/src/ieu/controller.sv +++ b/pipelined/src/ieu/controller.sv @@ -67,7 +67,7 @@ module controller( output logic RegWriteW, // for datapath and Hazard Unit output logic [2:0] ResultSrcW, // Stall during CSRs - output logic CSRWritePendingDEM, + output logic CSRWriteFencePendingDEM, output logic StoreStallD ); @@ -107,6 +107,8 @@ module controller( logic IEURegWriteE; logic IllegalERegAdrD; logic [1:0] AtomicE; + logic FencePendingD, FencePendingE, FencePendingM; + // Extract fields assign OpD = InstrD[6:0]; @@ -177,6 +179,7 @@ module controller( assign CSRZeroSrcD = InstrD[14] ? (InstrD[19:15] == 0) : (Rs1D == 0); // Is a CSR instruction using zero as the source? assign CSRWriteD = CSRReadD & !(CSRZeroSrcD & InstrD[13]); // Don't write if setting or clearing zeros + assign FencePendingD = PrivilegedD & (InstrD[31:25] == 7'b0001001) | FenceD; // possible sfence.vma or fence.i // ALU Decoding is lazy, only using func7[5] to distinguish add/sub and srl/sra assign sltD = (Funct3D == 3'b010); @@ -203,9 +206,9 @@ module controller( flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD); // Execute stage pipeline control register and logic - flopenrc #(27) controlregE(clk, reset, FlushE, ~StallE, - {RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, InstrValidD}, - {IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, InstrValidE}); + flopenrc #(28) controlregE(clk, reset, FlushE, ~StallE, + {RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FencePendingD, InstrValidD}, + {IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FencePendingE, InstrValidE}); // Branch Logic assign {eqE, ltE, ltuE} = FlagsE; @@ -219,16 +222,17 @@ module controller( assign RegWriteE = IEURegWriteE | FWriteIntE; // IRF register writes could come from IEU or FPU controllers // Memory stage pipeline control register - flopenrc #(18) controlregM(clk, reset, FlushM, ~StallM, - {RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, InstrValidE}, - {RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, InstrValidM}); + flopenrc #(19) controlregM(clk, reset, FlushM, ~StallM, + {RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, FencePendingE, InstrValidE}, + {RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FencePendingM, InstrValidM}); // Writeback stage pipeline control register flopenrc #(4) controlregW(clk, reset, FlushW, ~StallW, {RegWriteM, ResultSrcM}, {RegWriteW, ResultSrcW}); - assign CSRWritePendingDEM = CSRWriteD | CSRWriteE | CSRWriteM; + // Stall pipeline at Fetch if a CSR Write or Fence is pending in the subsequent stages + assign CSRWriteFencePendingDEM = CSRWriteD | CSRWriteE | CSRWriteM | FencePendingD | FencePendingE | FencePendingM; assign StoreStallD = MemRWE[0] & ((|MemRWD) | (|AtomicD)); endmodule diff --git a/pipelined/src/ieu/ieu.sv b/pipelined/src/ieu/ieu.sv index 8fe310370..cb467a7b9 100644 --- a/pipelined/src/ieu/ieu.sv +++ b/pipelined/src/ieu/ieu.sv @@ -71,7 +71,7 @@ module ieu ( output logic FPUStallD, LoadStallD, MDUStallD, CSRRdStallD, output logic PCSrcE, output logic CSRReadM, CSRWriteM, PrivilegedM, - output logic CSRWritePendingDEM, + output logic CSRWriteFencePendingDEM, output logic StoreStallD ); @@ -99,7 +99,7 @@ module ieu ( .Funct3E, .MDUE, .W64E, .JumpE, .StallM, .FlushM, .MemRWM, .CSRReadM, .CSRWriteM, .PrivilegedM, .SCE, .AtomicM, .Funct3M, .RegWriteM, .InvalidateICacheM, .FlushDCacheM, .InstrValidM, .FWriteIntM, - .StallW, .FlushW, .RegWriteW, .ResultSrcW, .CSRWritePendingDEM, .StoreStallD); + .StallW, .FlushW, .RegWriteW, .ResultSrcW, .CSRWriteFencePendingDEM, .StoreStallD); datapath dp( .clk, .reset, .ImmSrcD, .InstrD, .StallE, .FlushE, .ForwardAE, .ForwardBE, diff --git a/pipelined/src/wally/wallypipelinedcore.sv b/pipelined/src/wally/wallypipelinedcore.sv index 30f0c43ef..0e9cd5660 100644 --- a/pipelined/src/wally/wallypipelinedcore.sv +++ b/pipelined/src/wally/wallypipelinedcore.sv @@ -82,7 +82,7 @@ module wallypipelinedcore ( logic StoreAmoMisalignedFaultM, StoreAmoAccessFaultM; logic InvalidateICacheM, FlushDCacheM; logic PCSrcE; - logic CSRWritePendingDEM; + logic CSRWriteFencePendingDEM; logic DivBusyE; logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD; logic SquashSCW; @@ -231,7 +231,7 @@ module wallypipelinedcore ( .FPUStallD, .LoadStallD, .MDUStallD, .CSRRdStallD, .PCSrcE, .CSRReadM, .CSRWriteM, .PrivilegedM, - .CSRWritePendingDEM, .StoreStallD + .CSRWriteFencePendingDEM, .StoreStallD ); // integer execution unit: integer register file, datapath and controller @@ -294,13 +294,13 @@ module wallypipelinedcore ( hazard hzu( - .BPPredWrongE, .CSRWritePendingDEM, .RetM, .TrapM, + .BPPredWrongE, .CSRWriteFencePendingDEM, .RetM, .TrapM, .LoadStallD, .StoreStallD, .MDUStallD, .CSRRdStallD, .LSUStallM, .IFUStallF, .FPUStallD, .FStallD, .DivBusyE, .FDivBusyE, .EcallFaultM, .BreakpointFaultM, - .InvalidateICacheM, .sfencevmaM, .wfiM, .IntPendingM, + .wfiM, .IntPendingM, // Stall & flush outputs .StallF, .StallD, .StallE, .StallM, .StallW, .FlushF, .FlushD, .FlushE, .FlushM, .FlushW