Broken state. address translation not working after changes to hptw to support atomic updates to PT.

This commit is contained in:
Ross Thompson 2022-02-16 23:37:36 -06:00
parent eafd52e2bc
commit 62f5f1e622
10 changed files with 160 additions and 146 deletions

File diff suppressed because one or more lines are too long

View File

@ -75,7 +75,7 @@ module ifu (
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
input logic [1:0] STATUS_MPP, input logic [1:0] STATUS_MPP,
input logic ITLBWriteF, ITLBFlushF, input logic ITLBWriteF, ITLBFlushF,
output logic ITLBMissF, output logic ITLBMissF, InstrDAPageFaultF,
// pmp/pma (inside mmu) signals. *** temporarily from AHB bus but eventually replace with internal versions pre H // 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 [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 [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0],
@ -156,6 +156,7 @@ module ifu (
.InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(), .InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(),
.InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(), .InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(),
.LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(), .LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(),
.DAPageFault(InstrDAPageFaultF),
.AtomicAccessM(1'b0),.ExecuteAccessF(1'b1), .WriteAccessM(1'b0), .ReadAccessM(1'b0), .AtomicAccessM(1'b0),.ExecuteAccessF(1'b1), .WriteAccessM(1'b0), .ReadAccessM(1'b0),
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);

View File

@ -35,9 +35,9 @@ module interlockfsm
(input logic clk, (input logic clk,
input logic reset, input logic reset,
input logic AnyCPUReqM, input logic AnyCPUReqM,
input logic ITLBMissF, input logic ITLBMissOrDAFaultF,
input logic ITLBWriteF, input logic ITLBWriteF,
input logic DTLBMissM, input logic DTLBMissOrDAFaultM,
input logic DTLBWriteM, input logic DTLBWriteM,
input logic TrapM, input logic TrapM,
input logic DCacheStallM, input logic DCacheStallM,
@ -66,10 +66,10 @@ module interlockfsm
always_comb begin always_comb begin
case(InterlockCurrState) case(InterlockCurrState)
STATE_T0_READY: if (TrapM) InterlockNextState = STATE_T0_READY; STATE_T0_READY: if (TrapM) InterlockNextState = STATE_T0_READY;
else if(~ITLBMissF & DTLBMissM & AnyCPUReqM) InterlockNextState = STATE_T3_DTLB_MISS; else if(~ITLBMissOrDAFaultF & DTLBMissOrDAFaultM & AnyCPUReqM) InterlockNextState = STATE_T3_DTLB_MISS;
else if(ITLBMissF & ~DTLBMissM & ~AnyCPUReqM) InterlockNextState = STATE_T4_ITLB_MISS; else if(ITLBMissOrDAFaultF & ~DTLBMissOrDAFaultM & ~AnyCPUReqM) InterlockNextState = STATE_T4_ITLB_MISS;
else if(ITLBMissF & ~DTLBMissM & AnyCPUReqM) InterlockNextState = STATE_T5_ITLB_MISS; else if(ITLBMissOrDAFaultF & ~DTLBMissOrDAFaultM & AnyCPUReqM) InterlockNextState = STATE_T5_ITLB_MISS;
else if(ITLBMissF & DTLBMissM & AnyCPUReqM) InterlockNextState = STATE_T7_DITLB_MISS; else if(ITLBMissOrDAFaultF & DTLBMissOrDAFaultM & AnyCPUReqM) InterlockNextState = STATE_T7_DITLB_MISS;
else InterlockNextState = STATE_T0_READY; else InterlockNextState = STATE_T0_READY;
STATE_T0_REPLAY: if(DCacheStallM) InterlockNextState = STATE_T0_REPLAY; STATE_T0_REPLAY: if(DCacheStallM) InterlockNextState = STATE_T0_REPLAY;
else InterlockNextState = STATE_T0_READY; else InterlockNextState = STATE_T0_READY;
@ -90,7 +90,7 @@ module interlockfsm
// this code has a problem with imperas64mmu as it reads in an invalid uninitalized instruction. InterlockStall becomes x and it propagates // this code has a problem with imperas64mmu as it reads in an invalid uninitalized instruction. InterlockStall becomes x and it propagates
// everywhere. The case statement below implements the same logic but any x on the inputs will resolve to 0. // everywhere. The case statement below implements the same logic but any x on the inputs will resolve to 0.
// Note this will cause a problem for post synthesis gate simulation. // Note this will cause a problem for post synthesis gate simulation.
assign InterlockStall = (InterlockCurrState == STATE_T0_READY & (DTLBMissM | ITLBMissF)) | assign InterlockStall = (InterlockCurrState == STATE_T0_READY & (DTLBMissOrDAFaultM | ITLBMissOrDAFaultF)) |
(InterlockCurrState == STATE_T3_DTLB_MISS) | (InterlockCurrState == STATE_T4_ITLB_MISS) | (InterlockCurrState == STATE_T3_DTLB_MISS) | (InterlockCurrState == STATE_T4_ITLB_MISS) |
(InterlockCurrState == STATE_T5_ITLB_MISS) | (InterlockCurrState == STATE_T7_DITLB_MISS); (InterlockCurrState == STATE_T5_ITLB_MISS) | (InterlockCurrState == STATE_T7_DITLB_MISS);
@ -99,7 +99,7 @@ module interlockfsm
always_comb begin always_comb begin
InterlockStall = 1'b0; InterlockStall = 1'b0;
case(InterlockCurrState) case(InterlockCurrState)
STATE_T0_READY: if((DTLBMissM | ITLBMissF) & ~TrapM) InterlockStall = 1'b1; STATE_T0_READY: if((DTLBMissOrDAFaultM | ITLBMissOrDAFaultF) & ~TrapM) InterlockStall = 1'b1;
STATE_T3_DTLB_MISS: InterlockStall = 1'b1; STATE_T3_DTLB_MISS: InterlockStall = 1'b1;
STATE_T4_ITLB_MISS: InterlockStall = 1'b1; STATE_T4_ITLB_MISS: InterlockStall = 1'b1;
STATE_T5_ITLB_MISS: InterlockStall = 1'b1; STATE_T5_ITLB_MISS: InterlockStall = 1'b1;
@ -112,7 +112,7 @@ module interlockfsm
assign SelReplayCPURequest = (InterlockNextState == STATE_T0_REPLAY); assign SelReplayCPURequest = (InterlockNextState == STATE_T0_REPLAY);
assign SelHPTW = (InterlockCurrState == STATE_T3_DTLB_MISS) | (InterlockCurrState == STATE_T4_ITLB_MISS) | assign SelHPTW = (InterlockCurrState == STATE_T3_DTLB_MISS) | (InterlockCurrState == STATE_T4_ITLB_MISS) |
(InterlockCurrState == STATE_T5_ITLB_MISS) | (InterlockCurrState == STATE_T7_DITLB_MISS); (InterlockCurrState == STATE_T5_ITLB_MISS) | (InterlockCurrState == STATE_T7_DITLB_MISS);
assign IgnoreRequestTLB = (InterlockCurrState == STATE_T0_READY & (ITLBMissF | DTLBMissM)); assign IgnoreRequestTLB = (InterlockCurrState == STATE_T0_READY & (ITLBMissOrDAFaultF | DTLBMissOrDAFaultM));
assign IgnoreRequestTrapM = (InterlockCurrState == STATE_T0_READY & (TrapM)) | assign IgnoreRequestTrapM = (InterlockCurrState == STATE_T0_READY & (TrapM)) |
((InterlockCurrState == STATE_T0_REPLAY) & (TrapM)); ((InterlockCurrState == STATE_T0_REPLAY) & (TrapM));

View File

@ -74,6 +74,7 @@ module lsu (
input logic [1:0] STATUS_MPP, input logic [1:0] STATUS_MPP,
input logic [`XLEN-1:0] PCF, input logic [`XLEN-1:0] PCF,
input logic ITLBMissF, input logic ITLBMissF,
input logic InstrDAPageFaultF,
output logic [`XLEN-1:0] PTE, output logic [`XLEN-1:0] PTE,
output logic [1:0] PageType, output logic [1:0] PageType,
output logic ITLBWriteF, output logic ITLBWriteF,
@ -101,6 +102,7 @@ module lsu (
logic IgnoreRequestTLB, IgnoreRequestTrapM; logic IgnoreRequestTLB, IgnoreRequestTrapM;
logic BusCommittedM, DCacheCommittedM; logic BusCommittedM, DCacheCommittedM;
logic LSUBusWriteCrit; logic LSUBusWriteCrit;
logic DataDAPageFaultM;
flopenrc #(`XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM); flopenrc #(`XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
assign IEUAdrExtM = {2'b00, IEUAdrM}; assign IEUAdrExtM = {2'b00, IEUAdrM};
@ -113,7 +115,8 @@ module lsu (
if(`VIRTMEM_SUPPORTED) begin : VIRTMEM_SUPPORTED if(`VIRTMEM_SUPPORTED) begin : VIRTMEM_SUPPORTED
lsuvirtmem lsuvirtmem(.clk, .reset, .StallW, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF, lsuvirtmem lsuvirtmem(.clk, .reset, .StallW, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF,
.DTLBMissM, .DTLBWriteM, .TrapM, .DCacheStallM, .SATP_REGW, .PCF, .DTLBMissM, .DTLBWriteM, .InstrDAPageFaultF, .DataDAPageFaultM,
.TrapM, .DCacheStallM, .SATP_REGW, .PCF,
.ReadDataM, .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M, .IEUAdrM, .ReadDataM, .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M, .IEUAdrM,
.IEUAdrExtM, .PTE, .PageType, .PreLSURWM, .LSUAtomicM, .IEUAdrE, .IEUAdrExtM, .PTE, .PageType, .PreLSURWM, .LSUAtomicM, .IEUAdrE,
.LSUAdrE, .PreLSUPAdrM, .CPUBusy, .InterlockStall, .SelHPTW, .LSUAdrE, .PreLSUPAdrM, .CPUBusy, .InterlockStall, .SelHPTW,
@ -153,6 +156,7 @@ module lsu (
.InstrAccessFaultF(), .LoadAccessFaultM, .StoreAmoAccessFaultM, .InstrAccessFaultF(), .LoadAccessFaultM, .StoreAmoAccessFaultM,
.InstrPageFaultF(),.LoadPageFaultM, .StoreAmoPageFaultM, .InstrPageFaultF(),.LoadPageFaultM, .StoreAmoPageFaultM,
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, .LoadMisalignedFaultM, .StoreAmoMisalignedFaultM,
.DAPageFault(DataDAPageFaultM),
.AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0), // **** change this to just use PreLSURWM .AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0), // **** change this to just use PreLSURWM
.WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]), .WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]),
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
@ -168,7 +172,7 @@ module lsu (
// Memory System // Memory System
// Either Data Cache or Data Tightly Integrated Memory or just bus interface // Either Data Cache or Data Tightly Integrated Memory or just bus interface
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
logic [`XLEN-1:0] FinalAMOWriteDataM, FinalWriteDataM; logic [`XLEN-1:0] FinalAMOWriteDataM, FinalWriteDataM, PostSWWWriteDataM;
logic [`XLEN-1:0] ReadDataWordM; logic [`XLEN-1:0] ReadDataWordM;
logic [`XLEN-1:0] ReadDataWordMuxM; logic [`XLEN-1:0] ReadDataWordMuxM;
logic IgnoreRequest; logic IgnoreRequest;
@ -244,9 +248,11 @@ module lsu (
assign ReadDataWordMaskedM = CacheableM ? ReadDataWordM : '0; // AND-gate assign ReadDataWordMaskedM = CacheableM ? ReadDataWordM : '0; // AND-gate
subwordwrite subwordwrite(.HRDATA(ReadDataWordMaskedM), .HADDRD(LSUPAdrM[2:0]), subwordwrite subwordwrite(.HRDATA(ReadDataWordMaskedM), .HADDRD(LSUPAdrM[2:0]),
.HSIZED({LSUFunct3M[2], 1'b0, LSUFunct3M[1:0]}), .HSIZED({LSUFunct3M[2], 1'b0, LSUFunct3M[1:0]}),
.HWDATAIN(FinalAMOWriteDataM), .HWDATA(FinalWriteDataM)); .HWDATAIN(FinalAMOWriteDataM), .HWDATA(PostSWWWriteDataM));
end else end else
assign FinalWriteDataM = FinalAMOWriteDataM; assign PostSWWWriteDataM = FinalAMOWriteDataM;
assign FinalWriteDataM = SelHPTW ? PTE : PostSWWWriteDataM;
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// Atomic operations // Atomic operations

View File

@ -37,6 +37,8 @@ module lsuvirtmem(
output logic ITLBWriteF, output logic ITLBWriteF,
input logic DTLBMissM, input logic DTLBMissM,
output logic DTLBWriteM, output logic DTLBWriteM,
input logic InstrDAPageFaultF,
input logic DataDAPageFaultM,
input logic TrapM, input logic TrapM,
input logic DCacheStallM, input logic DCacheStallM,
input logic [`XLEN-1:0] SATP_REGW, // from csr input logic [`XLEN-1:0] SATP_REGW, // from csr
@ -69,23 +71,25 @@ module lsuvirtmem(
logic [2:0] HPTWSize; logic [2:0] HPTWSize;
logic SelReplayCPURequest; logic SelReplayCPURequest;
logic [11:0] PreLSUAdrE; logic [11:0] PreLSUAdrE;
logic ITLBMissOrDAFaultF;
logic DTLBMissOrDAFaultM;
logic HPTWWrite;
assign AnyCPUReqM = (|MemRWM) | (|AtomicM); assign AnyCPUReqM = (|MemRWM) | (|AtomicM);
assign ITLBMissOrDAFaultF = ITLBWriteF | InstrDAPageFaultF;
assign DTLBMissOrDAFaultM = DTLBWriteM | DataDAPageFaultM;
interlockfsm interlockfsm ( interlockfsm interlockfsm (
.clk, .reset, .AnyCPUReqM, .ITLBMissF, .ITLBWriteF, .clk, .reset, .AnyCPUReqM, .ITLBMissOrDAFaultF, .ITLBWriteF,
.DTLBMissM, .DTLBWriteM, .TrapM, .DCacheStallM, .DTLBMissOrDAFaultM, .DTLBWriteM, .TrapM, .DCacheStallM,
.InterlockStall, .SelReplayCPURequest, .SelHPTW, .IgnoreRequestTLB, .IgnoreRequestTrapM); .InterlockStall, .SelReplayCPURequest, .SelHPTW, .IgnoreRequestTLB, .IgnoreRequestTrapM);
hptw hptw( // *** remove logic from (), mention this in style guide CH3 hptw hptw( // *** remove logic from (), mention this in style guide CH3
.clk, .reset, .SATP_REGW, .PCF, .IEUAdrM, .clk, .reset, .SATP_REGW, .PCF, .IEUAdrM, .MemRWM, .AtomicM,
.ITLBMissF(ITLBMissF & ~TrapM), .DTLBMissM(DTLBMissM & ~TrapM), .ITLBMissF(ITLBMissOrDAFaultF & ~TrapM), .DTLBMissM(DTLBMissOrDAFaultM & ~TrapM), // *** Fix me.
.PTE, .PageType, .ITLBWriteF, .DTLBWriteM, .HPTWReadPTE(ReadDataM), .PTE, .PageType, .ITLBWriteF, .DTLBWriteM, .HPTWReadPTE(ReadDataM),
.DCacheStallM, .HPTWAdr, .HPTWRead, .HPTWSize); .DCacheStallM, .HPTWAdr, .HPTWRead, .HPTWWrite, .HPTWSize);
// multiplex the outputs to LSU // multiplex the outputs to LSU
mux2 #(2) rwmux(MemRWM, {HPTWRead, 1'b0}, SelHPTW, PreLSURWM); mux2 #(2) rwmux(MemRWM, {HPTWRead, HPTWWrite}, SelHPTW, PreLSURWM);
mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M); mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M);
mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M); mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M);
mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LSUAtomicM); mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LSUAtomicM);

View File

@ -29,12 +29,13 @@
/////////////////////////////////////////// ///////////////////////////////////////////
`include "wally-config.vh" `include "wally-config.vh"
`define HTPW_DA_WRITES_SUPPORTED 1
module hptw module hptw
( (
input logic clk, reset, input logic clk, reset,
input logic [`XLEN-1:0] SATP_REGW, // includes SATP.MODE to determine number of levels in page table input logic [`XLEN-1:0] SATP_REGW, // includes SATP.MODE to determine number of levels in page table
input logic [`XLEN-1:0] PCF, IEUAdrM, // addresses to translate input logic [`XLEN-1:0] PCF, IEUAdrM, // addresses to translate
input logic [1:0] MemRWM, AtomicM,
(* mark_debug = "true" *) input logic ITLBMissF, DTLBMissM, // TLB Miss (* mark_debug = "true" *) input logic ITLBMissF, DTLBMissM, // TLB Miss
input logic [`XLEN-1:0] HPTWReadPTE, // page table entry from LSU input logic [`XLEN-1:0] HPTWReadPTE, // page table entry from LSU
input logic DCacheStallM, // stall from LSU input logic DCacheStallM, // stall from LSU
@ -43,6 +44,7 @@ module hptw
(* mark_debug = "true" *) output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry (* mark_debug = "true" *) output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry
output logic [`PA_BITS-1:0] HPTWAdr, output logic [`PA_BITS-1:0] HPTWAdr,
output logic HPTWRead, // HPTW requesting to read memory output logic HPTWRead, // HPTW requesting to read memory
output logic HPTWWrite,
output logic [2:0] HPTWSize // 32 or 64 bit access. output logic [2:0] HPTWSize // 32 or 64 bit access.
); );
@ -50,7 +52,7 @@ module hptw
L1_ADR, L1_RD, L1_ADR, L1_RD,
L2_ADR, L2_RD, L2_ADR, L2_RD,
L3_ADR, L3_RD, L3_ADR, L3_RD,
LEAF, IDLE} statetype; LEAF, IDLE, UPDATE_PTE} statetype;
logic DTLBWalk; // register TLBs translation miss requests logic DTLBWalk; // register TLBs translation miss requests
logic [`PPN_BITS-1:0] BasePageTablePPN; logic [`PPN_BITS-1:0] BasePageTablePPN;
@ -65,6 +67,11 @@ module hptw
logic [1:0] NextPageType; logic [1:0] NextPageType;
logic [`SVMODE_BITS-1:0] SvMode; logic [`SVMODE_BITS-1:0] SvMode;
logic [`XLEN-1:0] TranslationVAdr; logic [`XLEN-1:0] TranslationVAdr;
logic Dirty, Accessed;
logic [`XLEN-1:0] NextPTE;
logic UpdatePTE;
logic SetDirty;
logic DAPageFault;
(* mark_debug = "true" *) statetype WalkerState, NextWalkerState, InitialWalkerState; (* mark_debug = "true" *) statetype WalkerState, NextWalkerState, InitialWalkerState;
@ -80,21 +87,30 @@ module hptw
// State flops // State flops
flopenr #(1) TLBMissMReg(clk, reset, StartWalk, DTLBMissM, DTLBWalk); // when walk begins, record whether it was for DTLB (or record 0 for ITLB) flopenr #(1) TLBMissMReg(clk, reset, StartWalk, DTLBMissM, DTLBWalk); // when walk begins, record whether it was for DTLB (or record 0 for ITLB)
assign PRegEn = HPTWRead & ~DCacheStallM; assign PRegEn = HPTWRead & ~DCacheStallM;
flopenr #(`XLEN) PTEReg(clk, reset, PRegEn, HPTWReadPTE, PTE); // Capture page table entry from data cache assign NextPTE = UpdatePTE ? {PTE[`XLEN-1:8], SetDirty , 1'b1, PTE[5:0]} : HPTWReadPTE;
flopenr #(`XLEN) PTEReg(clk, reset, PRegEn | HPTWWrite, NextPTE, PTE); // Capture page table entry from data cache
// Assign PTE descriptors common across all XLEN values // Assign PTE descriptors common across all XLEN values
// For non-leaf PTEs, D, A, U bits are reserved and ignored. They do not cause faults while walking the page table // For non-leaf PTEs, D, A, U bits are reserved and ignored. They do not cause faults while walking the page table
assign {Executable, Writable, Readable, Valid} = PTE[3:0]; assign {Executable, Writable, Readable, Valid} = PTE[3:0];
assign {Dirty, Accessed} = PTE[7:6];
assign LeafPTE = Executable | Writable | Readable; assign LeafPTE = Executable | Writable | Readable;
assign ValidPTE = Valid & ~(Writable & ~Readable); assign ValidPTE = Valid & ~(Writable & ~Readable);
assign ValidLeafPTE = ValidPTE & LeafPTE; assign ValidLeafPTE = ValidPTE & LeafPTE;
assign ValidNonLeafPTE = ValidPTE & ~LeafPTE; assign ValidNonLeafPTE = ValidPTE & ~LeafPTE;
assign SetDirty = ~Dirty & & DTLBWalk & (MemRWM[0] | |AtomicM);
assign DAPageFault = ValidLeafPTE & (~Accessed) | (SetDirty);
// Enable and select signals based on states // Enable and select signals based on states
assign StartWalk = (WalkerState == IDLE) & TLBMiss; assign StartWalk = (WalkerState == IDLE) & TLBMiss;
assign HPTWRead = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD); assign HPTWRead = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD);
assign DTLBWriteM = (WalkerState == LEAF) & DTLBWalk; assign DTLBWriteM = (WalkerState == LEAF) & DTLBWalk;
assign ITLBWriteF = (WalkerState == LEAF) & ~DTLBWalk; assign ITLBWriteF = (WalkerState == LEAF) & ~DTLBWalk;
assign HPTWWrite = (WalkerState == UPDATE_PTE);
assign UpdatePTE = ((WalkerState == L2_ADR | WalkerState == L1_ADR | WalkerState == L0_ADR)
& ValidLeafPTE & ~Misaligned & DAPageFault);
// FSM to track PageType based on the levels of the page table traversed // FSM to track PageType based on the levels of the page table traversed
flopr #(2) PageTypeReg(clk, reset, NextPageType, PageType); flopr #(2) PageTypeReg(clk, reset, NextPageType, PageType);
@ -160,35 +176,31 @@ module hptw
L3_ADR: NextWalkerState = L3_RD; // first access in SV48 L3_ADR: NextWalkerState = L3_RD; // first access in SV48
L3_RD: if (DCacheStallM) NextWalkerState = L3_RD; L3_RD: if (DCacheStallM) NextWalkerState = L3_RD;
else NextWalkerState = L2_ADR; else NextWalkerState = L2_ADR;
// LEVEL3: if (ValidLeafPTE & ~Misaligned) NextWalkerState = LEAF;
// else if (ValidNonLeafPTE) NextWalkerState = L2_ADR;
// else NextWalkerState = FAULT;
L2_ADR: if (InitialWalkerState == L2_ADR) NextWalkerState = L2_RD; // first access in SV39 L2_ADR: if (InitialWalkerState == L2_ADR) NextWalkerState = L2_RD; // first access in SV39
else if (ValidLeafPTE & ~Misaligned) NextWalkerState = LEAF; // could shortcut this by a cyle for all Lx_ADR superpages else if (ValidLeafPTE & ~Misaligned & ~DAPageFault) NextWalkerState = LEAF; // could shortcut this by a cyle for all Lx_ADR superpages
else if (ValidLeafPTE & ~Misaligned & DAPageFault) NextWalkerState = UPDATE_PTE;
else if (ValidNonLeafPTE) NextWalkerState = L2_RD; else if (ValidNonLeafPTE) NextWalkerState = L2_RD;
else NextWalkerState = LEAF; else NextWalkerState = LEAF;
L2_RD: if (DCacheStallM) NextWalkerState = L2_RD; L2_RD: if (DCacheStallM) NextWalkerState = L2_RD;
else NextWalkerState = L1_ADR; else NextWalkerState = L1_ADR;
// LEVEL2: if (ValidLeafPTE & ~Misaligned) NextWalkerState = LEAF;
// else if (ValidNonLeafPTE) NextWalkerState = L1_ADR;
// else NextWalkerState = FAULT;
L1_ADR: if (InitialWalkerState == L1_ADR) NextWalkerState = L1_RD; // first access in SV32 L1_ADR: if (InitialWalkerState == L1_ADR) NextWalkerState = L1_RD; // first access in SV32
else if (ValidLeafPTE & ~Misaligned) NextWalkerState = LEAF; // could shortcut this by a cyle for all Lx_ADR superpages else if (ValidLeafPTE & ~Misaligned & ~DAPageFault) NextWalkerState = LEAF; // could shortcut this by a cyle for all Lx_ADR superpages
else if (ValidLeafPTE & ~Misaligned & DAPageFault) NextWalkerState = UPDATE_PTE;
else if (ValidNonLeafPTE) NextWalkerState = L1_RD; else if (ValidNonLeafPTE) NextWalkerState = L1_RD;
else NextWalkerState = LEAF; else NextWalkerState = LEAF;
L1_RD: if (DCacheStallM) NextWalkerState = L1_RD; L1_RD: if (DCacheStallM) NextWalkerState = L1_RD;
else NextWalkerState = L0_ADR; else NextWalkerState = L0_ADR;
// LEVEL1: if (ValidLeafPTE & ~Misaligned) NextWalkerState = LEAF; L0_ADR: if (ValidLeafPTE & ~Misaligned & ~DAPageFault) NextWalkerState = LEAF; // could shortcut this by a cyle for all Lx_ADR superpages
// else if (ValidNonLeafPTE) NextWalkerState = L0_ADR; else if (ValidLeafPTE & ~Misaligned & DAPageFault) NextWalkerState = UPDATE_PTE;
// else NextWalkerState = FAULT;
L0_ADR: if (ValidLeafPTE & ~Misaligned) NextWalkerState = LEAF; // could shortcut this by a cyle for all Lx_ADR superpages
else if (ValidNonLeafPTE) NextWalkerState = L0_RD; else if (ValidNonLeafPTE) NextWalkerState = L0_RD;
else NextWalkerState = LEAF; else NextWalkerState = LEAF;
L0_RD: if (DCacheStallM) NextWalkerState = L0_RD; L0_RD: if (DCacheStallM) NextWalkerState = L0_RD;
else NextWalkerState = LEAF; else NextWalkerState = LEAF;
// LEVEL0: if (ValidLeafPTE) NextWalkerState = LEAF; LEAF: NextWalkerState = IDLE;
// else NextWalkerState = FAULT; // *** TODO update PTE with dirty/access. write to TLB and update memory.
LEAF: NextWalkerState = IDLE; // updates TLB // probably want to write the PTE in UPDATE_PTE then go to leaf and update TLB.
UPDATE_PTE: if(DCacheStallM) NextWalkerState = UPDATE_PTE;
else NextWalkerState = LEAF;
default: begin default: begin
// synthesis translate_off // synthesis translate_off
if (WalkerState !== 'x) if (WalkerState !== 'x)

View File

@ -77,6 +77,7 @@ module mmu #(parameter TLB_ENTRIES = 8, // number of TLB Entries
// Faults // Faults
output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM, output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM,
output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM, output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM,
output logic DAPageFault,
output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM,
// PMA checker signals // PMA checker signals
@ -109,7 +110,7 @@ module mmu #(parameter TLB_ENTRIES = 8, // number of TLB Entries
.PrivilegeModeW, .ReadAccess, .WriteAccess, .PrivilegeModeW, .ReadAccess, .WriteAccess,
.DisableTranslation, .PTE, .PageTypeWriteVal, .DisableTranslation, .PTE, .PageTypeWriteVal,
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit, .TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
.Translate, .TLBPageFault); .Translate, .TLBPageFault, .DAPageFault);
end else begin:tlb// just pass address through as physical end else begin:tlb// just pass address through as physical
assign Translate = 0; assign Translate = 0;
assign TLBMiss = 0; assign TLBMiss = 0;

View File

@ -92,7 +92,8 @@ module tlb #(parameter TLB_ENTRIES = 8,
output logic Translate, output logic Translate,
// Faults // Faults
output logic TLBPageFault output logic TLBPageFault,
output logic DAPageFault
); );
logic [TLB_ENTRIES-1:0] Matches, WriteEnables, PTE_Gs; // used as the one-hot encoding of WriteIndex logic [TLB_ENTRIES-1:0] Matches, WriteEnables, PTE_Gs; // used as the one-hot encoding of WriteIndex
@ -132,7 +133,7 @@ module tlb #(parameter TLB_ENTRIES = 8,
tlbcontrol #(ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, tlbcontrol #(ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
.PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .TLBFlush, .PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .TLBFlush,
.PTEAccessBits, .CAMHit, .Misaligned, .TLBMiss, .TLBHit, .TLBPageFault, .PTEAccessBits, .CAMHit, .Misaligned, .TLBMiss, .TLBHit, .TLBPageFault,
.SV39Mode, .Translate); .DAPageFault, .SV39Mode, .Translate);
tlblru #(TLB_ENTRIES) lru(.clk, .reset, .TLBWrite, .TLBFlush, .Matches, .CAMHit, .WriteEnables); tlblru #(TLB_ENTRIES) lru(.clk, .reset, .TLBWrite, .TLBFlush, .Matches, .CAMHit, .WriteEnables);
tlbcam #(TLB_ENTRIES, `VPN_BITS + `ASID_BITS, `VPN_SEGMENT_BITS) tlbcam #(TLB_ENTRIES, `VPN_BITS + `ASID_BITS, `VPN_SEGMENT_BITS)

View File

@ -52,6 +52,7 @@ module tlbcontrol #(parameter ITLB = 0) (
output logic TLBMiss, output logic TLBMiss,
output logic TLBHit, output logic TLBHit,
output logic TLBPageFault, output logic TLBPageFault,
output logic DAPageFault,
output logic SV39Mode, output logic SV39Mode,
output logic Translate output logic Translate
); );
@ -63,7 +64,6 @@ module tlbcontrol #(parameter ITLB = 0) (
logic PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits logic PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits
logic UpperBitsUnequalPageFault; logic UpperBitsUnequalPageFault;
logic DAPageFault;
logic TLBAccess; logic TLBAccess;
logic ImproperPrivilege; logic ImproperPrivilege;
@ -98,8 +98,8 @@ module tlbcontrol #(parameter ITLB = 0) (
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
((EffectivePrivilegeMode == `S_MODE) & PTE_U); ((EffectivePrivilegeMode == `S_MODE) & PTE_U);
// fault for software handling if access bit is off // fault for software handling if access bit is off
assign DAPageFault = ~PTE_A; assign DAPageFault = Translate & TLBHit & ~PTE_A;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
end else begin:dtlb // Data TLB fault checking end else begin:dtlb // Data TLB fault checking
logic InvalidRead, InvalidWrite; logic InvalidRead, InvalidWrite;
@ -115,8 +115,8 @@ module tlbcontrol #(parameter ITLB = 0) (
// low. // low.
assign InvalidWrite = WriteAccess & ~PTE_W; assign InvalidWrite = WriteAccess & ~PTE_W;
// Fault for software handling if access bit is off or writing a page with dirty bit off // Fault for software handling if access bit is off or writing a page with dirty bit off
assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D; assign DAPageFault = Translate & TLBHit & (~PTE_A | WriteAccess & ~PTE_D);
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
end end
assign TLBHit = CAMHit & TLBAccess; assign TLBHit = CAMHit & TLBAccess;

View File

@ -163,7 +163,7 @@ module wallypipelinedcore (
logic ICacheMiss; logic ICacheMiss;
logic ICacheAccess; logic ICacheAccess;
logic BreakpointFaultM, EcallFaultM; logic BreakpointFaultM, EcallFaultM;
logic InstrDAPageFaultF;
ifu ifu( ifu ifu(
.clk, .reset, .clk, .reset,
@ -201,8 +201,8 @@ module wallypipelinedcore (
// pmp/pma (inside mmu) signals. *** temporarily from AHB bus but eventually replace with internal versions pre H // pmp/pma (inside mmu) signals. *** temporarily from AHB bus but eventually replace with internal versions pre H
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.InstrAccessFaultF .InstrAccessFaultF,
.InstrDAPageFaultF
); // instruction fetch unit: PC, branch prediction, instruction cache ); // instruction fetch unit: PC, branch prediction, instruction cache
@ -276,6 +276,7 @@ module wallypipelinedcore (
.LoadAccessFaultM, // connects to privilege .LoadAccessFaultM, // connects to privilege
.StoreAmoMisalignedFaultM, // connects to privilege .StoreAmoMisalignedFaultM, // connects to privilege
.StoreAmoAccessFaultM, // connects to privilege .StoreAmoAccessFaultM, // connects to privilege
.InstrDAPageFaultF,
.PCF, .ITLBMissF, .PTE, .PageType, .ITLBWriteF, .PCF, .ITLBMissF, .PTE, .PageType, .ITLBWriteF,
.LSUStallM); // change to LSUStallM .LSUStallM); // change to LSUStallM