From 705572f0ac2d5468ca8f8a561b5071757148f403 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Sat, 20 Nov 2021 22:35:47 -0600 Subject: [PATCH] Fixed a very complex interaction between interrupts, the icache, dcache, and hptw. If an interrupt occurred at the start of an ITLB miss or DTLB miss the page table walk should be aborted before starting. --- .../cache/dcache_ptw_interaction_README.txt | 18 +++- wally-pipelined/src/cache/dcachefsm.sv | 21 +++-- wally-pipelined/src/cache/icache.sv | 7 +- wally-pipelined/src/cache/icachefsm.sv | 4 +- wally-pipelined/src/ifu/ifu.sv | 84 ++++++++++--------- wally-pipelined/src/lsu/lsu.sv | 4 +- .../src/wally/wallypipelinedhart.sv | 1 + 7 files changed, 84 insertions(+), 55 deletions(-) diff --git a/wally-pipelined/src/cache/dcache_ptw_interaction_README.txt b/wally-pipelined/src/cache/dcache_ptw_interaction_README.txt index 59d768fc..cc7a96cc 100644 --- a/wally-pipelined/src/cache/dcache_ptw_interaction_README.txt +++ b/wally-pipelined/src/cache/dcache_ptw_interaction_README.txt @@ -24,7 +24,7 @@ in the memory stage. This is the core reason for the complexity. The above table classifies the operations into 8 categories. 2 of the 8 are not possible because a DTLB miss implies a memory operation. Each (I/D)TLB miss results in either a write to the corresponding TLB or a TLB fault. -To complicate things it is possilbe to have current ITLB and DTLB misses, which +To complicate things it is possilbe to have concurrent ITLB and DTLB misses, which both can result in either a write or a fault. The table belows shows the possible scenarios and the sequence of operations. @@ -72,3 +72,19 @@ to normal mode. Type 5a is a Type 4a with a current memory operation. The Dcache first switches to walker mode +Other traps. +A new problem has emerged. What happens when an interrupt occurs during a page table walk? +The dcache has an output called CommittedM which tells the CPU if the memory operation is +committed into the memory system. It would be wrong to pin the interrupt to a memory operation +when it is already or partially committed to the memory system. Instead the next instruction +has to be pinned to the interrupt. The complexity occurs with the ITLB miss; types 4, 5 and 7. + +Type 4: The ITLB misses and starts using the dcache to fetch the page table. There is no memory +operation. Depending on where in the walk the operations could be aborted. If the tlb is not yet +updated then the walk could be aborted. However if the TLB is updated then the interrupt must be +delayed until the next instruction. + +What is the meaning of CommittedM? +This signal informs the CPU if a memory operation is not started or if it is between started +and done. Once a memory op is started it should not be interrupted. This is used to prevent the +CPU from generating an interrupt after the operation is partially or completely done. diff --git a/wally-pipelined/src/cache/dcachefsm.sv b/wally-pipelined/src/cache/dcachefsm.sv index 59f90462..7137fea0 100644 --- a/wally-pipelined/src/cache/dcachefsm.sv +++ b/wally-pipelined/src/cache/dcachefsm.sv @@ -192,16 +192,9 @@ module dcachefsm LRUWriteEn = 1'b0; CommittedM = 1'b0; - if(FlushDCacheM) begin - NextState = STATE_FLUSH; - DCacheStall = 1'b1; - SelAdrM = 2'b11; - FlushAdrCntRst = 1'b1; - FlushWayCntRst = 1'b1; - end // TLB Miss - else if((AnyCPUReqM & DTLBMissM) | ITLBMissF) begin + if(((AnyCPUReqM & DTLBMissM) | ITLBMissF) & ~(ExceptionM | PendingInterruptM)) begin // the LSU arbiter has not yet selected the PTW. // The CPU needs to be stalled until that happens. // If we set DCacheStall for 1 cycle before going to @@ -212,6 +205,16 @@ module dcachefsm DCacheStall = 1'b1; NextState = STATE_PTW_READY; end + + // Flush dcache to next level of memory + else if(FlushDCacheM & ~(ExceptionM | PendingInterruptM)) begin + NextState = STATE_FLUSH; + DCacheStall = 1'b1; + SelAdrM = 2'b11; + FlushAdrCntRst = 1'b1; + FlushWayCntRst = 1'b1; + end + // amo hit else if(AtomicM[1] & (&MemRWM) & CacheableM & ~(ExceptionM | PendingInterruptM) & CacheHit & ~DTLBMissM) begin SelAdrM = 2'b10; @@ -623,7 +626,7 @@ module dcachefsm CntReset = 1'b0; AHBWrite = 1'b0; AHBRead = 1'b0; - CommittedM = 1'b0; + CommittedM = 1'b1; NextState = STATE_READY; diff --git a/wally-pipelined/src/cache/icache.sv b/wally-pipelined/src/cache/icache.sv index d433f6ed..7df4c4b8 100644 --- a/wally-pipelined/src/cache/icache.sv +++ b/wally-pipelined/src/cache/icache.sv @@ -31,7 +31,10 @@ module icache input logic clk, reset, input logic StallF, input logic [`PA_BITS-1:0] PCNextF, - input logic [`PA_BITS-1:0] PCPF, + input logic [`PA_BITS-1:0] PCPF, + + input logic ExceptionM, PendingInterruptM, + // Data read in from the ebu unit input logic [`XLEN-1:0] InstrInF, input logic InstrAckF, @@ -286,6 +289,8 @@ module icache .ITLBMissF, .ITLBWriteF, .WalkerInstrPageFaultF, + .ExceptionM, + .PendingInterruptM, .InstrAckF, .InstrReadF, .hit, diff --git a/wally-pipelined/src/cache/icachefsm.sv b/wally-pipelined/src/cache/icachefsm.sv index 2461e0dd..fa0268bb 100644 --- a/wally-pipelined/src/cache/icachefsm.sv +++ b/wally-pipelined/src/cache/icachefsm.sv @@ -36,6 +36,8 @@ module icachefsm input logic ITLBWriteF, input logic WalkerInstrPageFaultF, + input logic ExceptionM, PendingInterruptM, + // BUS interface input logic InstrAckF, @@ -135,7 +137,7 @@ module icachefsm STATE_READY: begin SelAdr = 2'b00; ICacheReadEn = 1'b1; - if (ITLBMissF) begin + if (ITLBMissF & ~(ExceptionM | PendingInterruptM)) begin NextState = STATE_TLB_MISS; end else if (hit & ~spill) begin ICacheStallF = 1'b0; diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 9ddb3901..b18d8bc3 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -27,60 +27,62 @@ `include "wally-config.vh" module ifu ( - input logic clk, reset, - input logic StallF, StallD, StallE, StallM, StallW, - input logic FlushF, FlushD, FlushE, FlushM, FlushW, + input logic clk, reset, + input logic StallF, StallD, StallE, StallM, StallW, + input logic FlushF, FlushD, FlushE, FlushM, FlushW, // Fetch - input logic [`XLEN-1:0] InstrInF, - input logic InstrAckF, - output logic [`XLEN-1:0] PCF, - output logic [`PA_BITS-1:0] InstrPAdrF, - output logic InstrReadF, - output logic ICacheStallF, + input logic [`XLEN-1:0] InstrInF, + input logic InstrAckF, + output logic [`XLEN-1:0] PCF, + output logic [`PA_BITS-1:0] InstrPAdrF, + output logic InstrReadF, + output logic ICacheStallF, // Execute - output logic [`XLEN-1:0] PCLinkE, - input logic PCSrcE, - input logic [`XLEN-1:0] PCTargetE, - output logic [`XLEN-1:0] PCE, - output logic BPPredWrongE, + output logic [`XLEN-1:0] PCLinkE, + input logic PCSrcE, + input logic [`XLEN-1:0] PCTargetE, + output logic [`XLEN-1:0] PCE, + output logic BPPredWrongE, // Mem - input logic RetM, TrapM, - input logic [`XLEN-1:0] PrivilegedNextPCM, - input logic InvalidateICacheM, - output logic [31:0] InstrD, InstrM, - output logic [`XLEN-1:0] PCM, - output logic [4:0] InstrClassM, - output logic BPPredDirWrongM, - output logic BTBPredPCWrongM, - output logic RASPredPCWrongM, - output logic BPPredClassNonCFIWrongM, + input logic RetM, TrapM, + input logic [`XLEN-1:0] PrivilegedNextPCM, + input logic InvalidateICacheM, + output logic [31:0] InstrD, InstrM, + output logic [`XLEN-1:0] PCM, + output logic [4:0] InstrClassM, + output logic BPPredDirWrongM, + output logic BTBPredPCWrongM, + output logic RASPredPCWrongM, + output logic BPPredClassNonCFIWrongM, // Writeback // output logic [`XLEN-1:0] PCLinkW, // Faults - input logic IllegalBaseInstrFaultD, - output logic ITLBInstrPageFaultF, - output logic IllegalIEUInstrFaultD, - output logic InstrMisalignedFaultM, - output logic [`XLEN-1:0] InstrMisalignedAdrM, + input logic IllegalBaseInstrFaultD, + output logic ITLBInstrPageFaultF, + output logic IllegalIEUInstrFaultD, + output logic InstrMisalignedFaultM, + output logic [`XLEN-1:0] InstrMisalignedAdrM, + input logic ExceptionM, PendingInterruptM, + // mmu management - input logic [1:0] PrivilegeModeW, - input logic [`XLEN-1:0] PTE, - input logic [1:0] PageType, - input logic [`XLEN-1:0] SATP_REGW, - input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, - input logic [1:0] STATUS_MPP, - input logic ITLBWriteF, ITLBFlushF, - input logic WalkerInstrPageFaultF, + input logic [1:0] PrivilegeModeW, + input logic [`XLEN-1:0] PTE, + input logic [1:0] PageType, + input logic [`XLEN-1:0] SATP_REGW, + input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + input logic [1:0] STATUS_MPP, + input logic ITLBWriteF, ITLBFlushF, + input logic WalkerInstrPageFaultF, - output logic ITLBMissF, + output logic ITLBMissF, // pmp/pma (inside mmu) signals. *** temporarily from AHB bus but eventually replace with internal versions pre H - input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], - input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0], + input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], + input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0], - output logic InstrAccessFaultF + output logic InstrAccessFaultF ); logic [`XLEN-1:0] PCCorrectE, UnalignedPCNextF, PCNextF; diff --git a/wally-pipelined/src/lsu/lsu.sv b/wally-pipelined/src/lsu/lsu.sv index 1a97d6b3..a6250203 100644 --- a/wally-pipelined/src/lsu/lsu.sv +++ b/wally-pipelined/src/lsu/lsu.sv @@ -134,8 +134,8 @@ module lsu .SATP_REGW(SATP_REGW), .PCF(PCF), .MemAdrM(MemAdrM), - .ITLBMissF(ITLBMissF), - .DTLBMissM(DTLBMissM), + .ITLBMissF(ITLBMissF & ~PendingInterruptM), + .DTLBMissM(DTLBMissM & ~PendingInterruptM), .MemRWM(MemRWM), .PTE(PTE), .PageType, diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index 15cc61ba..dd167788 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -159,6 +159,7 @@ module wallypipelinedhart ( .StallF, .StallD, .StallE, .StallM, .StallW, .FlushF, .FlushD, .FlushE, .FlushM, .FlushW, + .ExceptionM, .PendingInterruptM, // Fetch .InstrInF(InstrRData), .InstrAckF, .PCF, .InstrPAdrF, .InstrReadF, .ICacheStallF,