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.
This commit is contained in:
Ross Thompson 2021-11-20 22:35:47 -06:00
parent 0bf1836a3a
commit 705572f0ac
7 changed files with 84 additions and 55 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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,