mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
New config option to enable hptw writes to PTE in memory to update Access and Dirty bits.
This commit is contained in:
parent
ad237b3ce5
commit
6cd9d84e7f
@ -126,3 +126,4 @@
|
|||||||
`define TESTSBP 0
|
`define TESTSBP 0
|
||||||
|
|
||||||
`define REPLAY 0
|
`define REPLAY 0
|
||||||
|
`define HPTW_WRITES_SUPPORTED 1
|
||||||
|
@ -132,3 +132,4 @@
|
|||||||
`define TESTSBP 1
|
`define TESTSBP 1
|
||||||
|
|
||||||
`define REPLAY 0
|
`define REPLAY 0
|
||||||
|
`define HPTW_WRITES_SUPPORTED 1
|
||||||
|
@ -130,3 +130,4 @@
|
|||||||
`define TESTSBP 0
|
`define TESTSBP 0
|
||||||
|
|
||||||
`define REPLAY 0
|
`define REPLAY 0
|
||||||
|
`define HPTW_WRITES_SUPPORTED 0
|
||||||
|
@ -128,3 +128,4 @@
|
|||||||
`define TESTSBP 0
|
`define TESTSBP 0
|
||||||
|
|
||||||
`define REPLAY 0
|
`define REPLAY 0
|
||||||
|
`define HPTW_WRITES_SUPPORTED 0
|
||||||
|
@ -128,3 +128,4 @@
|
|||||||
`define TESTSBP 0
|
`define TESTSBP 0
|
||||||
|
|
||||||
`define REPLAY 0
|
`define REPLAY 0
|
||||||
|
`define HPTW_WRITES_SUPPORTED 0
|
||||||
|
@ -131,3 +131,4 @@
|
|||||||
`define TESTSBP 1
|
`define TESTSBP 1
|
||||||
|
|
||||||
`define REPLAY 0
|
`define REPLAY 0
|
||||||
|
`define HPTW_WRITES_SUPPORTED 0
|
||||||
|
@ -131,3 +131,4 @@
|
|||||||
`define TESTSBP 0
|
`define TESTSBP 0
|
||||||
|
|
||||||
`define REPLAY 0
|
`define REPLAY 0
|
||||||
|
`define HPTW_WRITES_SUPPORTED 0
|
||||||
|
@ -131,3 +131,4 @@
|
|||||||
`define TESTSBP 0
|
`define TESTSBP 0
|
||||||
|
|
||||||
`define REPLAY 0
|
`define REPLAY 0
|
||||||
|
`define HPTW_WRITES_SUPPORTED 0
|
||||||
|
@ -79,8 +79,8 @@ module lsuvirtmem(
|
|||||||
logic HPTWWrite;
|
logic HPTWWrite;
|
||||||
|
|
||||||
assign AnyCPUReqM = (|MemRWM) | (|AtomicM);
|
assign AnyCPUReqM = (|MemRWM) | (|AtomicM);
|
||||||
assign ITLBMissOrDAFaultF = ITLBMissF | InstrDAPageFaultF;
|
assign ITLBMissOrDAFaultF = ITLBMissF | (`HPTW_WRITES_SUPPORTED & InstrDAPageFaultF);
|
||||||
assign DTLBMissOrDAFaultM = DTLBMissM | DataDAPageFaultM;
|
assign DTLBMissOrDAFaultM = DTLBMissM | (`HPTW_WRITES_SUPPORTED & DataDAPageFaultM);
|
||||||
interlockfsm interlockfsm (
|
interlockfsm interlockfsm (
|
||||||
.clk, .reset, .AnyCPUReqM, .ITLBMissOrDAFaultF, .ITLBWriteF,
|
.clk, .reset, .AnyCPUReqM, .ITLBMissOrDAFaultF, .ITLBWriteF,
|
||||||
.DTLBMissOrDAFaultM, .DTLBWriteM, .TrapM, .DCacheStallM,
|
.DTLBMissOrDAFaultM, .DTLBWriteM, .TrapM, .DCacheStallM,
|
||||||
@ -88,7 +88,7 @@ module lsuvirtmem(
|
|||||||
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, .MemRWM, .AtomicM,
|
.clk, .reset, .SATP_REGW, .PCF, .IEUAdrM, .MemRWM, .AtomicM,
|
||||||
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW,
|
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW,
|
||||||
.ITLBMissF(ITLBMissOrDAFaultF & ~TrapM), .DTLBMissM(DTLBMissOrDAFaultM & ~TrapM), // *** Fix me.
|
.ITLBMissF(ITLBMissOrDAFaultF & ~TrapM), .DTLBMissM(DTLBMissOrDAFaultM & ~TrapM), // *** Fix me. *** I'm not sure ITLBMiss should be suppressed on TrapM.
|
||||||
.PTE, .PageType, .ITLBWriteF, .DTLBWriteM, .HPTWReadPTE(ReadDataM),
|
.PTE, .PageType, .ITLBWriteF, .DTLBWriteM, .HPTWReadPTE(ReadDataM),
|
||||||
.DCacheStallM, .HPTWAdr, .HPTWRead, .HPTWWrite, .HPTWSize);
|
.DCacheStallM, .HPTWAdr, .HPTWRead, .HPTWWrite, .HPTWSize);
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
`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,
|
||||||
@ -71,21 +71,10 @@ 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 [`XLEN-1:0] NextPTE;
|
||||||
logic UpdatePTE;
|
logic UpdatePTE;
|
||||||
logic SetDirty;
|
|
||||||
logic DAPageFault;
|
logic DAPageFault;
|
||||||
logic SaveHPTWAdr, SelHPTWWriteAdr;
|
logic [`PA_BITS-1:0] HPTWReadAdr;
|
||||||
logic [`PA_BITS-1:0] HPTWWriteAdr, HPTWReadAdr;
|
|
||||||
logic SV39Mode;
|
|
||||||
logic ReadAccess, WriteAccess;
|
|
||||||
logic InvalidRead, InvalidWrite;
|
|
||||||
logic UpperBitsUnequalPageFault;
|
|
||||||
logic ImproperPrivilege;
|
|
||||||
logic [1:0] EffectivePrivilegeMode;
|
|
||||||
logic OtherPageFault;
|
|
||||||
|
|
||||||
|
|
||||||
(* mark_debug = "true" *) statetype WalkerState, NextWalkerState, InitialWalkerState;
|
(* mark_debug = "true" *) statetype WalkerState, NextWalkerState, InitialWalkerState;
|
||||||
|
|
||||||
@ -101,59 +90,88 @@ 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;
|
||||||
assign NextPTE = UpdatePTE ? {PTE[`XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]} : HPTWReadPTE;
|
|
||||||
|
|
||||||
flopenr #(`XLEN) PTEReg(clk, reset, PRegEn | UpdatePTE, NextPTE, PTE); // Capture page table entry from data cache
|
flopenr #(`XLEN) PTEReg(clk, reset, PRegEn | UpdatePTE, NextPTE, PTE); // Capture page table entry from data cache
|
||||||
|
|
||||||
flopenr #(`PA_BITS) HPTWAdrWriteReg(clk, reset, SaveHPTWAdr, HPTWReadAdr, HPTWWriteAdr);
|
|
||||||
assign SaveHPTWAdr = WalkerState == L0_ADR;
|
|
||||||
|
|
||||||
assign SelHPTWWriteAdr = UpdatePTE | HPTWWrite;
|
|
||||||
mux2 #(`PA_BITS) HPTWWriteAdrMux(HPTWReadAdr, HPTWWriteAdr, SelHPTWWriteAdr, HPTWAdr);
|
|
||||||
|
|
||||||
// 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 {PTE_U, Executable, Writable, Readable, Valid} = PTE[4:0];
|
assign {PTE_U, Executable, Writable, Readable, Valid} = PTE[4: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 WriteAccess = (MemRWM[0] | |AtomicM);
|
|
||||||
assign SetDirty = ~Dirty & & DTLBWalk & WriteAccess;
|
|
||||||
assign ReadAccess = MemRWM[1];
|
|
||||||
|
|
||||||
assign EffectivePrivilegeMode = (DTLBWalk == 0) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1
|
if(`HPTW_WRITES_SUPPORTED) begin : hptwwrites
|
||||||
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
|
|
||||||
((EffectivePrivilegeMode == `S_MODE) & PTE_U & (~STATUS_SUM & DTLBWalk));
|
|
||||||
|
|
||||||
|
logic SV39Mode;
|
||||||
|
logic ReadAccess, WriteAccess;
|
||||||
|
logic InvalidRead, InvalidWrite;
|
||||||
|
logic UpperBitsUnequalPageFault;
|
||||||
|
logic OtherPageFault;
|
||||||
|
logic [1:0] EffectivePrivilegeMode;
|
||||||
|
logic ImproperPrivilege;
|
||||||
|
logic SaveHPTWAdr, SelHPTWWriteAdr;
|
||||||
|
logic [`PA_BITS-1:0] HPTWWriteAdr;
|
||||||
|
logic SetDirty;
|
||||||
|
logic Dirty, Accessed;
|
||||||
|
|
||||||
if (`XLEN==64) begin:rv64
|
assign NextPTE = UpdatePTE ? {PTE[`XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]} : HPTWReadPTE; // This will be HPTWReadPTE if not handling DAPageFault.
|
||||||
|
flopenr #(`PA_BITS) HPTWAdrWriteReg(clk, reset, SaveHPTWAdr, HPTWReadAdr, HPTWWriteAdr);
|
||||||
|
assign SaveHPTWAdr = WalkerState == L0_ADR;
|
||||||
|
assign SelHPTWWriteAdr = UpdatePTE | HPTWWrite;
|
||||||
|
mux2 #(`PA_BITS) HPTWWriteAdrMux(HPTWReadAdr, HPTWWriteAdr, SelHPTWWriteAdr, HPTWAdr); // HPTWAdr = HPTWReadAdr if not handling DAPageFault.
|
||||||
|
|
||||||
|
|
||||||
|
assign {Dirty, Accessed} = PTE[7:6];
|
||||||
|
assign WriteAccess = (MemRWM[0] | |AtomicM);
|
||||||
|
assign SetDirty = ~Dirty & & DTLBWalk & WriteAccess;
|
||||||
|
assign ReadAccess = MemRWM[1];
|
||||||
|
|
||||||
|
assign EffectivePrivilegeMode = (DTLBWalk == 0) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1
|
||||||
|
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
|
||||||
|
((EffectivePrivilegeMode == `S_MODE) & PTE_U & (~STATUS_SUM & DTLBWalk));
|
||||||
|
|
||||||
|
// *** turn into module
|
||||||
|
if (`XLEN==64) begin:rv64
|
||||||
assign SV39Mode = (SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS] == `SV39);
|
assign SV39Mode = (SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS] == `SV39);
|
||||||
// page fault if upper bits aren't all the same
|
// page fault if upper bits aren't all the same
|
||||||
logic UpperEqual39, UpperEqual48;
|
logic UpperEqual39, UpperEqual48;
|
||||||
assign UpperEqual39 = &(TranslationVAdr[63:38]) | ~|(TranslationVAdr[63:38]);
|
assign UpperEqual39 = &(TranslationVAdr[63:38]) | ~|(TranslationVAdr[63:38]);
|
||||||
assign UpperEqual48 = &(TranslationVAdr[63:47]) | ~|(TranslationVAdr[63:47]);
|
assign UpperEqual48 = &(TranslationVAdr[63:47]) | ~|(TranslationVAdr[63:47]);
|
||||||
assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48;
|
assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48;
|
||||||
end else begin
|
end else begin
|
||||||
assign SV39Mode = 0;
|
assign SV39Mode = 0;
|
||||||
assign UpperBitsUnequalPageFault = 0;
|
assign UpperBitsUnequalPageFault = 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
assign InvalidRead = ReadAccess & ~Readable & (~STATUS_MXR | ~Executable);
|
assign InvalidRead = ReadAccess & ~Readable & (~STATUS_MXR | ~Executable);
|
||||||
assign InvalidWrite = WriteAccess & ~Writable;
|
assign InvalidWrite = WriteAccess & ~Writable;
|
||||||
assign OtherPageFault = DTLBWalk? ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequalPageFault | Misaligned | ~Valid :
|
assign OtherPageFault = DTLBWalk? ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequalPageFault | Misaligned | ~Valid :
|
||||||
ImproperPrivilege | ~Executable | UpperBitsUnequalPageFault | Misaligned | ~Valid;
|
ImproperPrivilege | ~Executable | UpperBitsUnequalPageFault | Misaligned | ~Valid;
|
||||||
|
|
||||||
assign DAPageFault = ValidLeafPTE & (~Accessed | SetDirty) & ~OtherPageFault;
|
|
||||||
|
// hptw needs to know if there is a Dirty or Access fault occuring on this
|
||||||
|
// memory access. If there is the PTE needs to be updated seting Access
|
||||||
|
// and possibly also Dirty. Dirty is set if the operation is a store/amo.
|
||||||
|
// However any other fault should not cause the update.
|
||||||
|
assign DAPageFault = ValidLeafPTE & (~Accessed | SetDirty) & ~OtherPageFault; // set to 0 if not handling DAPageFault.
|
||||||
|
|
||||||
|
assign HPTWWrite = (WalkerState == UPDATE_PTE);
|
||||||
|
assign UpdatePTE = WalkerState == LEAF & DAPageFault;
|
||||||
|
end else begin // block: hptwwrites
|
||||||
|
assign NextPTE = HPTWReadPTE;
|
||||||
|
assign HPTWAdr = HPTWReadAdr;
|
||||||
|
assign DAPageFault = '0;
|
||||||
|
assign UpdatePTE = '0;
|
||||||
|
assign HPTWWrite = '0;
|
||||||
|
end
|
||||||
|
|
||||||
// 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 & ~DAPageFault) & DTLBWalk;
|
assign DTLBWriteM = (WalkerState == LEAF & ~DAPageFault) & DTLBWalk;
|
||||||
assign ITLBWriteF = (WalkerState == LEAF & ~DAPageFault) & ~DTLBWalk;
|
assign ITLBWriteF = (WalkerState == LEAF & ~DAPageFault) & ~DTLBWalk;
|
||||||
assign HPTWWrite = (WalkerState == UPDATE_PTE);
|
|
||||||
assign UpdatePTE = WalkerState == LEAF & 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
|
||||||
@ -241,7 +259,7 @@ module hptw
|
|||||||
else NextWalkerState = IDLE;
|
else NextWalkerState = IDLE;
|
||||||
// *** TODO update PTE with dirty/access. write to TLB and update memory.
|
// *** 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.
|
// probably want to write the PTE in UPDATE_PTE then go to leaf and update TLB.
|
||||||
UPDATE_PTE: if(DCacheStallM) NextWalkerState = UPDATE_PTE;
|
UPDATE_PTE: if(`HPTW_WRITES_SUPPORTED & DCacheStallM) NextWalkerState = UPDATE_PTE;
|
||||||
else NextWalkerState = LEAF;
|
else NextWalkerState = LEAF;
|
||||||
default: begin
|
default: begin
|
||||||
// synthesis translate_off
|
// synthesis translate_off
|
||||||
|
@ -97,9 +97,14 @@ module tlbcontrol #(parameter ITLB = 0) (
|
|||||||
// only execute non-user mode pages.
|
// only execute non-user mode pages.
|
||||||
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
|
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
|
||||||
((EffectivePrivilegeMode == `S_MODE) & PTE_U);
|
((EffectivePrivilegeMode == `S_MODE) & PTE_U);
|
||||||
|
if(`HPTW_WRITES_SUPPORTED) begin : hptwwrites
|
||||||
|
assign DAPageFault = Translate & TLBHit & ~PTE_A & ~TLBPageFault;
|
||||||
|
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
||||||
|
end else begin
|
||||||
// fault for software handling if access bit is off
|
// fault for software handling if access bit is off
|
||||||
assign DAPageFault = Translate & TLBHit & ~PTE_A & ~TLBPageFault;
|
assign DAPageFault = ~PTE_A;
|
||||||
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
||||||
|
end
|
||||||
end else begin:dtlb // Data TLB fault checking
|
end else begin:dtlb // Data TLB fault checking
|
||||||
logic InvalidRead, InvalidWrite;
|
logic InvalidRead, InvalidWrite;
|
||||||
|
|
||||||
@ -114,9 +119,14 @@ module tlbcontrol #(parameter ITLB = 0) (
|
|||||||
// Check for write error. Writes are invalid when the page's write bit is
|
// Check for write error. Writes are invalid when the page's write bit is
|
||||||
// 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
|
if(`HPTW_WRITES_SUPPORTED) begin : hptwwrites
|
||||||
assign DAPageFault = Translate & TLBHit & (~PTE_A | WriteAccess & ~PTE_D) & ~TLBPageFault;
|
assign DAPageFault = Translate & TLBHit & (~PTE_A | WriteAccess & ~PTE_D) & ~TLBPageFault;
|
||||||
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
|
||||||
|
end else begin
|
||||||
|
// 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));
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
assign TLBHit = CAMHit & TLBAccess;
|
assign TLBHit = CAMHit & TLBAccess;
|
||||||
|
Loading…
Reference in New Issue
Block a user