diff --git a/src/cache/cacheway.sv b/src/cache/cacheway.sv index 96762dbde..3445067a0 100644 --- a/src/cache/cacheway.sv +++ b/src/cache/cacheway.sv @@ -77,6 +77,7 @@ module cacheway import cvw::*; #(parameter cvw_t P, logic ClearDirtyWay; logic SelNonHit; logic SelData; + logic InvalidateCacheDelay; if (!READ_ONLY_CACHE) begin:flushlogic logic FlushWayEn; @@ -121,7 +122,9 @@ module cacheway import cvw::*; #(parameter cvw_t P, assign TagWay = SelData ? ReadTag : '0; // AND part of AOMux assign HitDirtyWay = Dirty & ValidWay; assign DirtyWay = SelDirty & HitDirtyWay; - assign HitWay = ValidWay & (ReadTag == PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]); + assign HitWay = ValidWay & (ReadTag == PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]) & ~InvalidateCacheDelay; + + flop #(1) InvalidateCacheReg(clk, InvalidateCache, InvalidateCacheDelay); ///////////////////////////////////////////////////////////////////////////////////////////// // Data Array diff --git a/src/lsu/lsu.sv b/src/lsu/lsu.sv index f86c62aea..220a42eef 100644 --- a/src/lsu/lsu.sv +++ b/src/lsu/lsu.sv @@ -111,7 +111,9 @@ module lsu import cvw::*; #(parameter cvw_t P) ( logic GatedStallW; // Hazard unit StallW gated when SelHPTW = 1 logic BusStall; // Bus interface busy with multicycle operation + logic LSUBusStallM; // Bus interface busy with multicycle operation masked by IgnoreRequestTLB logic HPTWStall; // HPTW busy with multicycle operation + logic DCacheBusStallM; // Cache or bus stall logic CacheBusHPWTStall; // Cache, bus, or hptw is requesting a stall logic SelSpillE; // Align logic detected a spill and needs to stall @@ -194,7 +196,7 @@ module lsu import cvw::*; #(parameter cvw_t P) ( if(P.VIRTMEM_SUPPORTED) begin : hptw hptw #(P) hptw(.clk, .reset, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF, .DTLBMissM, .DTLBWriteM, .InstrUpdateDAF, .DataUpdateDAM, - .FlushW, .DCacheStallM, .SATP_REGW, .PCSpillF, + .FlushW, .DCacheBusStallM, .SATP_REGW, .PCSpillF, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_ADUE, .PrivilegeModeW, .ReadDataM(ReadDataM[P.XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN .WriteDataM(WriteDataZM), .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M, @@ -225,7 +227,8 @@ module lsu import cvw::*; #(parameter cvw_t P) ( // the trap module. assign CommittedM = SelHPTW | DCacheCommittedM | BusCommittedM; assign GatedStallW = StallW & ~SelHPTW; - assign CacheBusHPWTStall = DCacheStallM | HPTWStall | BusStall; + assign DCacheBusStallM = DCacheStallM | LSUBusStallM; + assign CacheBusHPWTStall = DCacheBusStallM | HPTWStall; assign LSUStallM = CacheBusHPWTStall | SpillStallM; ///////////////////////////////////////////////////////////////////////////////////////////// @@ -352,6 +355,7 @@ module lsu import cvw::*; #(parameter cvw_t P) ( .Cacheable(CacheableOrFlushCacheM), .BusRW, .Stall(GatedStallW), .BusStall, .BusCommitted(BusCommittedM)); + // Mux between the 3 sources of read data, 0: cache, 1: Bus, 2: DTIM // Uncache bus access may be smaller width than LLEN. Duplicate LLENPOVERAHBW times. // *** DTIMReadDataWordM should be increased to LLEN. @@ -386,6 +390,8 @@ module lsu import cvw::*; #(parameter cvw_t P) ( assign {DCacheStallM, DCacheCommittedM} = '0; end + assign LSUBusStallM = BusStall & ~IgnoreRequestTLB; + ///////////////////////////////////////////////////////////////////////////////////////////// // Atomic operations ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/mmu/hptw.sv b/src/mmu/hptw.sv index 7ca4a007a..82eeaef87 100644 --- a/src/mmu/hptw.sv +++ b/src/mmu/hptw.sv @@ -42,7 +42,7 @@ module hptw import cvw::*; #(parameter cvw_t P) ( input logic [1:0] PrivilegeModeW, input logic [P.XLEN-1:0] ReadDataM, // page table entry from LSU input logic [P.XLEN-1:0] WriteDataM, - input logic DCacheStallM, // stall from LSU + input logic DCacheBusStallM, // stall from LSU input logic [2:0] Funct3M, input logic [6:0] Funct7M, input logic ITLBMissF, @@ -145,7 +145,7 @@ module hptw import cvw::*; #(parameter cvw_t P) ( // State flops flopenr #(1) TLBMissMReg(clk, reset, StartWalk, DTLBMissOrUpdateDAM, DTLBWalk); // when walk begins, record whether it was for DTLB (or record 0 for ITLB) - assign PRegEn = HPTWRW[1] & ~DCacheStallM | UpdatePTE; + assign PRegEn = HPTWRW[1] & ~DCacheBusStallM | UpdatePTE; flopenr #(P.XLEN) PTEReg(clk, reset, PRegEn, NextPTE, PTE); // Capture page table entry from data cache // Assign PTE descriptors common across all XLEN values @@ -283,30 +283,30 @@ module hptw import cvw::*; #(parameter cvw_t P) ( flopenl #(.TYPE(statetype)) WalkerStateReg(clk, reset | FlushW, 1'b1, NextWalkerState, IDLE, WalkerState); always_comb case (WalkerState) - IDLE: if (TLBMiss & ~DCacheStallM) NextWalkerState = InitialWalkerState; + IDLE: if (TLBMiss & ~DCacheBusStallM) NextWalkerState = InitialWalkerState; else NextWalkerState = IDLE; L3_ADR: NextWalkerState = L3_RD; // first access in SV48 - L3_RD: if (DCacheStallM) NextWalkerState = L3_RD; + L3_RD: if (DCacheBusStallM) NextWalkerState = L3_RD; else if(HPTWFaultM) NextWalkerState = FAULT; else NextWalkerState = L2_ADR; L2_ADR: if (InitialWalkerState == L2_ADR | ValidNonLeafPTE) NextWalkerState = L2_RD; // first access in SV39 else NextWalkerState = LEAF; - L2_RD: if (DCacheStallM) NextWalkerState = L2_RD; + L2_RD: if (DCacheBusStallM) NextWalkerState = L2_RD; else if(HPTWFaultM) NextWalkerState = FAULT; else NextWalkerState = L1_ADR; L1_ADR: if (InitialWalkerState == L1_ADR | ValidNonLeafPTE) NextWalkerState = L1_RD; // first access in SV32 else NextWalkerState = LEAF; - L1_RD: if (DCacheStallM) NextWalkerState = L1_RD; + L1_RD: if (DCacheBusStallM) NextWalkerState = L1_RD; else if(HPTWFaultM) NextWalkerState = FAULT; else NextWalkerState = L0_ADR; L0_ADR: if (ValidNonLeafPTE) NextWalkerState = L0_RD; else NextWalkerState = LEAF; - L0_RD: if (DCacheStallM) NextWalkerState = L0_RD; + L0_RD: if (DCacheBusStallM) NextWalkerState = L0_RD; else if(HPTWFaultM) NextWalkerState = FAULT; else NextWalkerState = LEAF; LEAF: if (P.SVADU_SUPPORTED & HPTWUpdateDA) NextWalkerState = UPDATE_PTE; else NextWalkerState = IDLE; - UPDATE_PTE: if(DCacheStallM) NextWalkerState = UPDATE_PTE; + UPDATE_PTE: if(DCacheBusStallM) NextWalkerState = UPDATE_PTE; else NextWalkerState = LEAF; FAULT: NextWalkerState = IDLE; default: NextWalkerState = IDLE; // should never be reached