diff --git a/pipelined/src/hazard/hazard.sv b/pipelined/src/hazard/hazard.sv index b0e13f5f9..159ee10ec 100644 --- a/pipelined/src/hazard/hazard.sv +++ b/pipelined/src/hazard/hazard.sv @@ -60,6 +60,8 @@ module hazard( // A stage must stall if the next stage is stalled // If any stages are stalled, the first stage that isn't stalled must flush. + // *** can stalls be pushed into earlier stages (e.g. no stall after Decode?) + assign StallFCause = CSRWritePendingDEM & ~(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); diff --git a/pipelined/src/privileged/privdec.sv b/pipelined/src/privileged/privdec.sv index da1807103..7bf96d6f4 100644 --- a/pipelined/src/privileged/privdec.sv +++ b/pipelined/src/privileged/privdec.sv @@ -33,16 +33,18 @@ module privdec ( input logic clk, reset, + input logic StallM, input logic [31:20] InstrM, input logic PrivilegedM, IllegalIEUInstrFaultM, IllegalCSRAccessM, IllegalFPUInstrM, input logic [1:0] PrivilegeModeW, input logic STATUS_TSR, STATUS_TVM, STATUS_TW, input logic [1:0] STATUS_FS, - output logic IllegalInstrFaultM, + output logic IllegalInstrFaultM, ITLBFlushF, DTLBFlushM, output logic sretM, mretM, ecallM, ebreakM, wfiM, sfencevmaM); logic IllegalPrivilegedInstrM, IllegalOrDisabledFPUInstrM; logic WFITimeoutM; + logic StallMQ; /////////////////////////////////////////// // Decode privileged instructions @@ -65,7 +67,19 @@ module privdec ( floprc #(`WFI_TIMEOUT_BIT+1) wficountreg(clk, reset, ~wfiM, WFICountPlus1, WFICount); // count while in WFI assign WFITimeoutM = ((STATUS_TW & PrivilegeModeW != `M_MODE) | (`S_SUPPORTED & PrivilegeModeW == `U_MODE)) & WFICount[`WFI_TIMEOUT_BIT]; end else assign WFITimeoutM = 0; - + + /////////////////////////////////////////// + // sfence.vma causes TLB flushes + /////////////////////////////////////////// + // sets ITLBFlush to pulse for one cycle of the sfence.vma instruction + // In this instr we want to flush the tlb and then do a pagetable walk to update the itlb and continue the program. + // But we're still in the stalled sfence instruction, so if itlbflushf == sfencevmaM, tlbflush would never drop and + // the tlbwrite would never take place after the pagetable walk. by adding in ~StallMQ, we are able to drop itlbflush + // after a cycle AND pulse it for another cycle on any further back-to-back sfences. + flopr #(1) StallMReg(.clk, .reset, .d(StallM), .q(StallMQ)); + assign ITLBFlushF = sfencevmaM & ~StallMQ; + assign DTLBFlushM = sfencevmaM; + /////////////////////////////////////////// // Fault on illegal instructions /////////////////////////////////////////// diff --git a/pipelined/src/privileged/privileged.sv b/pipelined/src/privileged/privileged.sv index 74b419944..20803449f 100644 --- a/pipelined/src/privileged/privileged.sv +++ b/pipelined/src/privileged/privileged.sv @@ -100,11 +100,8 @@ module privileged ( logic STATUS_SPP, STATUS_TSR, STATUS_TW, STATUS_TVM; logic STATUS_MIE, STATUS_SIE; logic [11:0] MIP_REGW, MIE_REGW; - logic StallMQ; - logic WFITimeoutM; logic [1:0] NextPrivilegeModeM; - /////////////////////////////////////////// // track the current privilege level /////////////////////////////////////////// @@ -116,9 +113,10 @@ module privileged ( // decode privileged instructions /////////////////////////////////////////// - privdec pmd(.clk, .reset, .InstrM(InstrM[31:20]), + privdec pmd(.clk, .reset, .StallM, .InstrM(InstrM[31:20]), .PrivilegedM, .IllegalIEUInstrFaultM, .IllegalCSRAccessM, .IllegalFPUInstrM, .PrivilegeModeW, .STATUS_TSR, .STATUS_TVM, .STATUS_TW, .STATUS_FS, .IllegalInstrFaultM, + .ITLBFlushF, .DTLBFlushM, .sretM, .mretM, .ecallM, .ebreakM, .wfiM, .sfencevmaM); /////////////////////////////////////////// @@ -158,15 +156,6 @@ module privileged ( assign BreakpointFaultM = ebreakM; // could have other causes too assign EcallFaultM = ecallM; - flopr #(1) StallMReg(.clk, .reset, .d(StallM), .q(StallMQ)); - assign ITLBFlushF = sfencevmaM & ~StallMQ; - assign DTLBFlushM = sfencevmaM; - // sets ITLBFlush to pulse for one cycle of the sfence.vma instruction - // In this instr we want to flush the tlb and then do a pagetable walk to update the itlb and continue the program. - // But we're still in the stalled sfence instruction, so if itlbflushf == sfencevmaM, tlbflush would never drop and - // the tlbwrite would never take place after the pagetable walk. by adding in ~StallMQ, we are able to drop itlbflush - // after a cycle AND pulse it for another cycle on any further back-to-back sfences. - // A page fault might occur because of insufficient privilege during a TLB // lookup or a improperly formatted page table during walking