forked from Github_Repos/cvw
Broken state. address translation not working after changes to hptw to support atomic updates to PT.
This commit is contained in:
parent
460b37b21a
commit
565ca4e4a3
File diff suppressed because one or more lines are too long
@ -75,7 +75,7 @@ module ifu (
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
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
|
||||
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],
|
||||
@ -156,6 +156,7 @@ module ifu (
|
||||
.InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(),
|
||||
.InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(),
|
||||
.LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(),
|
||||
.DAPageFault(InstrDAPageFaultF),
|
||||
.AtomicAccessM(1'b0),.ExecuteAccessF(1'b1), .WriteAccessM(1'b0), .ReadAccessM(1'b0),
|
||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
|
||||
|
||||
|
@ -35,9 +35,9 @@ module interlockfsm
|
||||
(input logic clk,
|
||||
input logic reset,
|
||||
input logic AnyCPUReqM,
|
||||
input logic ITLBMissF,
|
||||
input logic ITLBMissOrDAFaultF,
|
||||
input logic ITLBWriteF,
|
||||
input logic DTLBMissM,
|
||||
input logic DTLBMissOrDAFaultM,
|
||||
input logic DTLBWriteM,
|
||||
input logic TrapM,
|
||||
input logic DCacheStallM,
|
||||
@ -66,10 +66,10 @@ module interlockfsm
|
||||
always_comb begin
|
||||
case(InterlockCurrState)
|
||||
STATE_T0_READY: if (TrapM) InterlockNextState = STATE_T0_READY;
|
||||
else if(~ITLBMissF & DTLBMissM & AnyCPUReqM) InterlockNextState = STATE_T3_DTLB_MISS;
|
||||
else if(ITLBMissF & ~DTLBMissM & ~AnyCPUReqM) InterlockNextState = STATE_T4_ITLB_MISS;
|
||||
else if(ITLBMissF & ~DTLBMissM & AnyCPUReqM) InterlockNextState = STATE_T5_ITLB_MISS;
|
||||
else if(ITLBMissF & DTLBMissM & AnyCPUReqM) InterlockNextState = STATE_T7_DITLB_MISS;
|
||||
else if(~ITLBMissOrDAFaultF & DTLBMissOrDAFaultM & AnyCPUReqM) InterlockNextState = STATE_T3_DTLB_MISS;
|
||||
else if(ITLBMissOrDAFaultF & ~DTLBMissOrDAFaultM & ~AnyCPUReqM) InterlockNextState = STATE_T4_ITLB_MISS;
|
||||
else if(ITLBMissOrDAFaultF & ~DTLBMissOrDAFaultM & AnyCPUReqM) InterlockNextState = STATE_T5_ITLB_MISS;
|
||||
else if(ITLBMissOrDAFaultF & DTLBMissOrDAFaultM & AnyCPUReqM) InterlockNextState = STATE_T7_DITLB_MISS;
|
||||
else InterlockNextState = STATE_T0_READY;
|
||||
STATE_T0_REPLAY: if(DCacheStallM) InterlockNextState = STATE_T0_REPLAY;
|
||||
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
|
||||
// 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.
|
||||
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_T5_ITLB_MISS) | (InterlockCurrState == STATE_T7_DITLB_MISS);
|
||||
|
||||
@ -99,7 +99,7 @@ module interlockfsm
|
||||
always_comb begin
|
||||
InterlockStall = 1'b0;
|
||||
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_T4_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 SelHPTW = (InterlockCurrState == STATE_T3_DTLB_MISS) | (InterlockCurrState == STATE_T4_ITLB_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)) |
|
||||
((InterlockCurrState == STATE_T0_REPLAY) & (TrapM));
|
||||
|
||||
|
@ -74,6 +74,7 @@ module lsu (
|
||||
input logic [1:0] STATUS_MPP,
|
||||
input logic [`XLEN-1:0] PCF,
|
||||
input logic ITLBMissF,
|
||||
input logic InstrDAPageFaultF,
|
||||
output logic [`XLEN-1:0] PTE,
|
||||
output logic [1:0] PageType,
|
||||
output logic ITLBWriteF,
|
||||
@ -101,7 +102,8 @@ module lsu (
|
||||
logic IgnoreRequestTLB, IgnoreRequestTrapM;
|
||||
logic BusCommittedM, DCacheCommittedM;
|
||||
logic LSUBusWriteCrit;
|
||||
|
||||
logic DataDAPageFaultM;
|
||||
|
||||
flopenrc #(`XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
|
||||
assign IEUAdrExtM = {2'b00, IEUAdrM};
|
||||
assign LSUStallM = DCacheStallM | InterlockStall | BusStall;
|
||||
@ -113,7 +115,8 @@ module lsu (
|
||||
|
||||
if(`VIRTMEM_SUPPORTED) begin : VIRTMEM_SUPPORTED
|
||||
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,
|
||||
.IEUAdrExtM, .PTE, .PageType, .PreLSURWM, .LSUAtomicM, .IEUAdrE,
|
||||
.LSUAdrE, .PreLSUPAdrM, .CPUBusy, .InterlockStall, .SelHPTW,
|
||||
@ -152,7 +155,8 @@ module lsu (
|
||||
.Cacheable(CacheableM), .Idempotent(), .AtomicAllowed(),
|
||||
.InstrAccessFaultF(), .LoadAccessFaultM, .StoreAmoAccessFaultM,
|
||||
.InstrPageFaultF(),.LoadPageFaultM, .StoreAmoPageFaultM,
|
||||
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM,
|
||||
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM,
|
||||
.DAPageFault(DataDAPageFaultM),
|
||||
.AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0), // **** change this to just use PreLSURWM
|
||||
.WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]),
|
||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
|
||||
@ -168,7 +172,7 @@ module lsu (
|
||||
// Memory System
|
||||
// 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] ReadDataWordMuxM;
|
||||
logic IgnoreRequest;
|
||||
@ -244,9 +248,11 @@ module lsu (
|
||||
assign ReadDataWordMaskedM = CacheableM ? ReadDataWordM : '0; // AND-gate
|
||||
subwordwrite subwordwrite(.HRDATA(ReadDataWordMaskedM), .HADDRD(LSUPAdrM[2:0]),
|
||||
.HSIZED({LSUFunct3M[2], 1'b0, LSUFunct3M[1:0]}),
|
||||
.HWDATAIN(FinalAMOWriteDataM), .HWDATA(FinalWriteDataM));
|
||||
.HWDATAIN(FinalAMOWriteDataM), .HWDATA(PostSWWWriteDataM));
|
||||
end else
|
||||
assign FinalWriteDataM = FinalAMOWriteDataM;
|
||||
assign PostSWWWriteDataM = FinalAMOWriteDataM;
|
||||
|
||||
assign FinalWriteDataM = SelHPTW ? PTE : PostSWWWriteDataM;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Atomic operations
|
||||
|
@ -37,6 +37,8 @@ module lsuvirtmem(
|
||||
output logic ITLBWriteF,
|
||||
input logic DTLBMissM,
|
||||
output logic DTLBWriteM,
|
||||
input logic InstrDAPageFaultF,
|
||||
input logic DataDAPageFaultM,
|
||||
input logic TrapM,
|
||||
input logic DCacheStallM,
|
||||
input logic [`XLEN-1:0] SATP_REGW, // from csr
|
||||
@ -69,23 +71,25 @@ module lsuvirtmem(
|
||||
logic [2:0] HPTWSize;
|
||||
logic SelReplayCPURequest;
|
||||
logic [11:0] PreLSUAdrE;
|
||||
|
||||
|
||||
logic ITLBMissOrDAFaultF;
|
||||
logic DTLBMissOrDAFaultM;
|
||||
logic HPTWWrite;
|
||||
|
||||
assign AnyCPUReqM = (|MemRWM) | (|AtomicM);
|
||||
|
||||
assign ITLBMissOrDAFaultF = ITLBWriteF | InstrDAPageFaultF;
|
||||
assign DTLBMissOrDAFaultM = DTLBWriteM | DataDAPageFaultM;
|
||||
interlockfsm interlockfsm (
|
||||
.clk, .reset, .AnyCPUReqM, .ITLBMissF, .ITLBWriteF,
|
||||
.DTLBMissM, .DTLBWriteM, .TrapM, .DCacheStallM,
|
||||
.clk, .reset, .AnyCPUReqM, .ITLBMissOrDAFaultF, .ITLBWriteF,
|
||||
.DTLBMissOrDAFaultM, .DTLBWriteM, .TrapM, .DCacheStallM,
|
||||
.InterlockStall, .SelReplayCPURequest, .SelHPTW, .IgnoreRequestTLB, .IgnoreRequestTrapM);
|
||||
hptw hptw( // *** remove logic from (), mention this in style guide CH3
|
||||
.clk, .reset, .SATP_REGW, .PCF, .IEUAdrM,
|
||||
.ITLBMissF(ITLBMissF & ~TrapM), .DTLBMissM(DTLBMissM & ~TrapM),
|
||||
.clk, .reset, .SATP_REGW, .PCF, .IEUAdrM, .MemRWM, .AtomicM,
|
||||
.ITLBMissF(ITLBMissOrDAFaultF & ~TrapM), .DTLBMissM(DTLBMissOrDAFaultM & ~TrapM), // *** Fix me.
|
||||
.PTE, .PageType, .ITLBWriteF, .DTLBWriteM, .HPTWReadPTE(ReadDataM),
|
||||
.DCacheStallM, .HPTWAdr, .HPTWRead, .HPTWSize);
|
||||
.DCacheStallM, .HPTWAdr, .HPTWRead, .HPTWWrite, .HPTWSize);
|
||||
|
||||
// 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 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M);
|
||||
mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LSUAtomicM);
|
||||
|
@ -29,12 +29,13 @@
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
`define HTPW_DA_WRITES_SUPPORTED 1
|
||||
module hptw
|
||||
(
|
||||
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] PCF, IEUAdrM, // addresses to translate
|
||||
input logic [1:0] MemRWM, AtomicM,
|
||||
(* mark_debug = "true" *) input logic ITLBMissF, DTLBMissM, // TLB Miss
|
||||
input logic [`XLEN-1:0] HPTWReadPTE, // page table entry 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
|
||||
output logic [`PA_BITS-1:0] HPTWAdr,
|
||||
output logic HPTWRead, // HPTW requesting to read memory
|
||||
output logic HPTWWrite,
|
||||
output logic [2:0] HPTWSize // 32 or 64 bit access.
|
||||
);
|
||||
|
||||
@ -50,7 +52,7 @@ module hptw
|
||||
L1_ADR, L1_RD,
|
||||
L2_ADR, L2_RD,
|
||||
L3_ADR, L3_RD,
|
||||
LEAF, IDLE} statetype;
|
||||
LEAF, IDLE, UPDATE_PTE} statetype;
|
||||
|
||||
logic DTLBWalk; // register TLBs translation miss requests
|
||||
logic [`PPN_BITS-1:0] BasePageTablePPN;
|
||||
@ -65,7 +67,12 @@ module hptw
|
||||
logic [1:0] NextPageType;
|
||||
logic [`SVMODE_BITS-1:0] SvMode;
|
||||
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;
|
||||
|
||||
// Extract bits from CSRs and inputs
|
||||
@ -80,21 +87,30 @@ module hptw
|
||||
// State flops
|
||||
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;
|
||||
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
|
||||
// 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 ValidPTE = Valid & ~(Writable & ~Readable);
|
||||
assign ValidLeafPTE = 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
|
||||
assign StartWalk = (WalkerState == IDLE) & TLBMiss;
|
||||
assign HPTWRead = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD);
|
||||
assign DTLBWriteM = (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
|
||||
flopr #(2) PageTypeReg(clk, reset, NextPageType, PageType);
|
||||
@ -156,39 +172,35 @@ module hptw
|
||||
always_comb
|
||||
case (WalkerState)
|
||||
IDLE: if (TLBMiss) NextWalkerState = InitialWalkerState;
|
||||
else NextWalkerState = IDLE;
|
||||
L3_ADR: NextWalkerState = L3_RD; // first access in SV48
|
||||
L3_RD: if (DCacheStallM) NextWalkerState = L3_RD;
|
||||
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
|
||||
else if (ValidLeafPTE & ~Misaligned) NextWalkerState = LEAF; // could shortcut this by a cyle for all Lx_ADR superpages
|
||||
else if (ValidNonLeafPTE) NextWalkerState = L2_RD;
|
||||
else NextWalkerState = LEAF;
|
||||
L2_RD: if (DCacheStallM) NextWalkerState = L2_RD;
|
||||
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
|
||||
else if (ValidLeafPTE & ~Misaligned) NextWalkerState = LEAF; // could shortcut this by a cyle for all Lx_ADR superpages
|
||||
else if (ValidNonLeafPTE) NextWalkerState = L1_RD;
|
||||
else NextWalkerState = LEAF;
|
||||
L1_RD: if (DCacheStallM) NextWalkerState = L1_RD;
|
||||
else NextWalkerState = L0_ADR;
|
||||
// LEVEL1: if (ValidLeafPTE & ~Misaligned) NextWalkerState = LEAF;
|
||||
// else if (ValidNonLeafPTE) NextWalkerState = L0_ADR;
|
||||
// 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 NextWalkerState = LEAF;
|
||||
L0_RD: if (DCacheStallM) NextWalkerState = L0_RD;
|
||||
else NextWalkerState = LEAF;
|
||||
// LEVEL0: if (ValidLeafPTE) NextWalkerState = LEAF;
|
||||
// else NextWalkerState = FAULT;
|
||||
LEAF: NextWalkerState = IDLE; // updates TLB
|
||||
else NextWalkerState = IDLE;
|
||||
L3_ADR: NextWalkerState = L3_RD; // first access in SV48
|
||||
L3_RD: if (DCacheStallM) NextWalkerState = L3_RD;
|
||||
else NextWalkerState = L2_ADR;
|
||||
L2_ADR: if (InitialWalkerState == L2_ADR) NextWalkerState = L2_RD; // first access in SV39
|
||||
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 NextWalkerState = LEAF;
|
||||
L2_RD: if (DCacheStallM) NextWalkerState = L2_RD;
|
||||
else NextWalkerState = L1_ADR;
|
||||
L1_ADR: if (InitialWalkerState == L1_ADR) NextWalkerState = L1_RD; // first access in SV32
|
||||
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 NextWalkerState = LEAF;
|
||||
L1_RD: if (DCacheStallM) NextWalkerState = L1_RD;
|
||||
else NextWalkerState = L0_ADR;
|
||||
L0_ADR: 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 = L0_RD;
|
||||
else NextWalkerState = LEAF;
|
||||
L0_RD: if (DCacheStallM) NextWalkerState = L0_RD;
|
||||
else NextWalkerState = LEAF;
|
||||
LEAF: NextWalkerState = IDLE;
|
||||
// *** TODO update PTE with dirty/access. write to TLB and update memory.
|
||||
// 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
|
||||
// synthesis translate_off
|
||||
if (WalkerState !== 'x)
|
||||
|
@ -34,20 +34,20 @@
|
||||
module mmu #(parameter TLB_ENTRIES = 8, // number of TLB Entries
|
||||
parameter IMMU = 0) (
|
||||
|
||||
input logic clk, reset,
|
||||
input logic clk, reset,
|
||||
// Current value of satp CSR (from privileged unit)
|
||||
input logic [`XLEN-1:0] SATP_REGW,
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
input logic [`XLEN-1:0] SATP_REGW,
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
|
||||
// Current privilege level of the processeor
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
|
||||
// 00 - TLB is not being accessed
|
||||
// 1x - TLB is accessed for a read (or an instruction)
|
||||
// x1 - TLB is accessed for a write
|
||||
// 11 - TLB is accessed for both read and write
|
||||
input logic DisableTranslation,
|
||||
input logic DisableTranslation,
|
||||
|
||||
// VAdr goes to the TLB only. Virtual if the TLB is active.
|
||||
// PAdr goes to address mux bypassing the TLB. PAdr used when there is no translation.
|
||||
@ -57,32 +57,33 @@ module mmu #(parameter TLB_ENTRIES = 8, // number of TLB Entries
|
||||
// performed.
|
||||
// PhysicalAddress is selected to be PAdr when no translation or the translated VAdr (TLBPAdr)
|
||||
// when there is translation.
|
||||
input logic [`PA_BITS-1:0] PAdr, // *** consider renaming this.
|
||||
input logic [`XLEN-1:0] VAdr,
|
||||
input logic [1:0] Size, // 00 = 8 bits, 01 = 16 bits, 10 = 32 bits , 11 = 64 bits
|
||||
input logic [`PA_BITS-1:0] PAdr, // *** consider renaming this.
|
||||
input logic [`XLEN-1:0] VAdr,
|
||||
input logic [1:0] Size, // 00 = 8 bits, 01 = 16 bits, 10 = 32 bits , 11 = 64 bits
|
||||
|
||||
// Controls for writing a new entry to the TLB
|
||||
input logic [`XLEN-1:0] PTE,
|
||||
input logic [1:0] PageTypeWriteVal,
|
||||
input logic TLBWrite,
|
||||
input logic [`XLEN-1:0] PTE,
|
||||
input logic [1:0] PageTypeWriteVal,
|
||||
input logic TLBWrite,
|
||||
|
||||
// Invalidate all TLB entries
|
||||
input logic TLBFlush,
|
||||
input logic TLBFlush,
|
||||
|
||||
// Physical address outputs
|
||||
output logic [`PA_BITS-1:0] PhysicalAddress,
|
||||
output logic TLBMiss,
|
||||
output logic Cacheable, Idempotent, AtomicAllowed,
|
||||
output logic TLBMiss,
|
||||
output logic Cacheable, Idempotent, AtomicAllowed,
|
||||
|
||||
// Faults
|
||||
output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM,
|
||||
output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM,
|
||||
output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM,
|
||||
output logic InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM,
|
||||
output logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM,
|
||||
output logic DAPageFault,
|
||||
output logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM,
|
||||
|
||||
// PMA checker signals
|
||||
input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM,
|
||||
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 logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM,
|
||||
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]
|
||||
);
|
||||
|
||||
logic [`PA_BITS-1:0] TLBPAdr;
|
||||
@ -109,7 +110,7 @@ module mmu #(parameter TLB_ENTRIES = 8, // number of TLB Entries
|
||||
.PrivilegeModeW, .ReadAccess, .WriteAccess,
|
||||
.DisableTranslation, .PTE, .PageTypeWriteVal,
|
||||
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
|
||||
.Translate, .TLBPageFault);
|
||||
.Translate, .TLBPageFault, .DAPageFault);
|
||||
end else begin:tlb// just pass address through as physical
|
||||
assign Translate = 0;
|
||||
assign TLBMiss = 0;
|
||||
|
@ -56,43 +56,44 @@
|
||||
// The TLB will have 2**ENTRY_BITS total entries
|
||||
module tlb #(parameter TLB_ENTRIES = 8,
|
||||
parameter ITLB = 0) (
|
||||
input logic clk, reset,
|
||||
input logic clk, reset,
|
||||
|
||||
// Current value of satp CSR (from privileged unit)
|
||||
input logic [`SVMODE_BITS-1:0] SATP_MODE,
|
||||
input logic [`ASID_BITS-1:0] SATP_ASID,
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
input logic [`SVMODE_BITS-1:0] SATP_MODE,
|
||||
input logic [`ASID_BITS-1:0] SATP_ASID,
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
|
||||
// Current privilege level of the processeor
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
|
||||
// 00 - TLB is not being accessed
|
||||
// 1x - TLB is accessed for a read (or an instruction)
|
||||
// x1 - TLB is accessed for a write
|
||||
// 11 - TLB is accessed for both read and write
|
||||
input logic ReadAccess, WriteAccess,
|
||||
input logic DisableTranslation,
|
||||
input logic ReadAccess, WriteAccess,
|
||||
input logic DisableTranslation,
|
||||
|
||||
// address input before translation (could be physical or virtual)
|
||||
input logic [`XLEN-1:0] VAdr,
|
||||
input logic [`XLEN-1:0] VAdr,
|
||||
|
||||
// Controls for writing a new entry to the TLB
|
||||
input logic [`XLEN-1:0] PTE,
|
||||
input logic [1:0] PageTypeWriteVal,
|
||||
input logic TLBWrite,
|
||||
input logic [`XLEN-1:0] PTE,
|
||||
input logic [1:0] PageTypeWriteVal,
|
||||
input logic TLBWrite,
|
||||
|
||||
// Invalidate all TLB entries
|
||||
input logic TLBFlush,
|
||||
input logic TLBFlush,
|
||||
|
||||
// Physical address outputs
|
||||
output logic [`PA_BITS-1:0] TLBPAdr,
|
||||
output logic TLBMiss,
|
||||
output logic TLBHit,
|
||||
output logic Translate,
|
||||
output logic [`PA_BITS-1:0] TLBPAdr,
|
||||
output logic TLBMiss,
|
||||
output logic TLBHit,
|
||||
output logic Translate,
|
||||
|
||||
// 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
|
||||
@ -132,7 +133,7 @@ module tlb #(parameter TLB_ENTRIES = 8,
|
||||
tlbcontrol #(ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
|
||||
.PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .TLBFlush,
|
||||
.PTEAccessBits, .CAMHit, .Misaligned, .TLBMiss, .TLBHit, .TLBPageFault,
|
||||
.SV39Mode, .Translate);
|
||||
.DAPageFault, .SV39Mode, .Translate);
|
||||
|
||||
tlblru #(TLB_ENTRIES) lru(.clk, .reset, .TLBWrite, .TLBFlush, .Matches, .CAMHit, .WriteEnables);
|
||||
tlbcam #(TLB_ENTRIES, `VPN_BITS + `ASID_BITS, `VPN_SEGMENT_BITS)
|
||||
|
@ -33,27 +33,28 @@
|
||||
module tlbcontrol #(parameter ITLB = 0) (
|
||||
|
||||
// Current value of satp CSR (from privileged unit)
|
||||
input logic [`SVMODE_BITS-1:0] SATP_MODE,
|
||||
input logic [`XLEN-1:0] VAdr,
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
|
||||
input logic [`SVMODE_BITS-1:0] SATP_MODE,
|
||||
input logic [`XLEN-1:0] VAdr,
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
|
||||
|
||||
// 00 - TLB is not being accessed
|
||||
// 1x - TLB is accessed for a read (or an instruction)
|
||||
// x1 - TLB is accessed for a write
|
||||
// 11 - TLB is accessed for both read and write
|
||||
input logic ReadAccess, WriteAccess,
|
||||
input logic DisableTranslation,
|
||||
input logic TLBFlush, // Invalidate all TLB entries
|
||||
input logic [7:0] PTEAccessBits,
|
||||
input logic CAMHit,
|
||||
input logic Misaligned,
|
||||
output logic TLBMiss,
|
||||
output logic TLBHit,
|
||||
output logic TLBPageFault,
|
||||
output logic SV39Mode,
|
||||
output logic Translate
|
||||
input logic ReadAccess, WriteAccess,
|
||||
input logic DisableTranslation,
|
||||
input logic TLBFlush, // Invalidate all TLB entries
|
||||
input logic [7:0] PTEAccessBits,
|
||||
input logic CAMHit,
|
||||
input logic Misaligned,
|
||||
output logic TLBMiss,
|
||||
output logic TLBHit,
|
||||
output logic TLBPageFault,
|
||||
output logic DAPageFault,
|
||||
output logic SV39Mode,
|
||||
output logic Translate
|
||||
);
|
||||
|
||||
// Sections of the page table entry
|
||||
@ -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 UpperBitsUnequalPageFault;
|
||||
logic DAPageFault;
|
||||
logic TLBAccess;
|
||||
logic ImproperPrivilege;
|
||||
|
||||
@ -98,8 +98,8 @@ module tlbcontrol #(parameter ITLB = 0) (
|
||||
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
|
||||
((EffectivePrivilegeMode == `S_MODE) & PTE_U);
|
||||
// fault for software handling if access bit is off
|
||||
assign DAPageFault = ~PTE_A;
|
||||
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
||||
assign DAPageFault = Translate & TLBHit & ~PTE_A;
|
||||
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
||||
end else begin:dtlb // Data TLB fault checking
|
||||
logic InvalidRead, InvalidWrite;
|
||||
|
||||
@ -115,8 +115,8 @@ module tlbcontrol #(parameter ITLB = 0) (
|
||||
// low.
|
||||
assign InvalidWrite = WriteAccess & ~PTE_W;
|
||||
// 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 TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
||||
assign DAPageFault = Translate & TLBHit & (~PTE_A | WriteAccess & ~PTE_D);
|
||||
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
||||
end
|
||||
|
||||
assign TLBHit = CAMHit & TLBAccess;
|
||||
|
@ -163,7 +163,7 @@ module wallypipelinedcore (
|
||||
logic ICacheMiss;
|
||||
logic ICacheAccess;
|
||||
logic BreakpointFaultM, EcallFaultM;
|
||||
|
||||
logic InstrDAPageFaultF;
|
||||
|
||||
ifu ifu(
|
||||
.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
|
||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
||||
.InstrAccessFaultF
|
||||
|
||||
.InstrAccessFaultF,
|
||||
.InstrDAPageFaultF
|
||||
|
||||
); // instruction fetch unit: PC, branch prediction, instruction cache
|
||||
|
||||
@ -276,6 +276,7 @@ module wallypipelinedcore (
|
||||
.LoadAccessFaultM, // connects to privilege
|
||||
.StoreAmoMisalignedFaultM, // connects to privilege
|
||||
.StoreAmoAccessFaultM, // connects to privilege
|
||||
.InstrDAPageFaultF,
|
||||
|
||||
.PCF, .ITLBMissF, .PTE, .PageType, .ITLBWriteF,
|
||||
.LSUStallM); // change to LSUStallM
|
||||
|
Loading…
Reference in New Issue
Block a user