mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Broken state. address translation not working after changes to hptw to support atomic updates to PT.
This commit is contained in:
parent
eafd52e2bc
commit
62f5f1e622
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 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);
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user