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 REPLAY 0 | ||||
| `define HPTW_WRITES_SUPPORTED 1 | ||||
|  | ||||
| @ -132,3 +132,4 @@ | ||||
| `define TESTSBP 1 | ||||
| 
 | ||||
| `define REPLAY 0 | ||||
| `define HPTW_WRITES_SUPPORTED 1 | ||||
|  | ||||
| @ -130,3 +130,4 @@ | ||||
| `define TESTSBP 0 | ||||
| 
 | ||||
| `define REPLAY 0 | ||||
| `define HPTW_WRITES_SUPPORTED 0 | ||||
|  | ||||
| @ -128,3 +128,4 @@ | ||||
| `define TESTSBP 0 | ||||
| 
 | ||||
| `define REPLAY 0 | ||||
| `define HPTW_WRITES_SUPPORTED 0 | ||||
|  | ||||
| @ -128,3 +128,4 @@ | ||||
| `define TESTSBP 0 | ||||
| 
 | ||||
| `define REPLAY 0 | ||||
| `define HPTW_WRITES_SUPPORTED 0 | ||||
|  | ||||
| @ -131,3 +131,4 @@ | ||||
| `define TESTSBP 1 | ||||
| 
 | ||||
| `define REPLAY 0 | ||||
| `define HPTW_WRITES_SUPPORTED 0 | ||||
|  | ||||
| @ -131,3 +131,4 @@ | ||||
| `define TESTSBP 0 | ||||
| 
 | ||||
| `define REPLAY 0 | ||||
| `define HPTW_WRITES_SUPPORTED 0 | ||||
|  | ||||
| @ -131,3 +131,4 @@ | ||||
| `define TESTSBP 0 | ||||
| 
 | ||||
| `define REPLAY 0 | ||||
| `define HPTW_WRITES_SUPPORTED 0 | ||||
|  | ||||
| @ -79,8 +79,8 @@ module lsuvirtmem( | ||||
|   logic                       HPTWWrite; | ||||
| 
 | ||||
|   assign AnyCPUReqM = (|MemRWM) | (|AtomicM); | ||||
|   assign ITLBMissOrDAFaultF = ITLBMissF | InstrDAPageFaultF; | ||||
|   assign DTLBMissOrDAFaultM = DTLBMissM | DataDAPageFaultM;   | ||||
|   assign ITLBMissOrDAFaultF = ITLBMissF | (`HPTW_WRITES_SUPPORTED & InstrDAPageFaultF); | ||||
|   assign DTLBMissOrDAFaultM = DTLBMissM | (`HPTW_WRITES_SUPPORTED & DataDAPageFaultM);   | ||||
|   interlockfsm interlockfsm ( | ||||
|     .clk, .reset, .AnyCPUReqM, .ITLBMissOrDAFaultF, .ITLBWriteF, | ||||
|     .DTLBMissOrDAFaultM, .DTLBWriteM, .TrapM, .DCacheStallM, | ||||
| @ -88,7 +88,7 @@ module lsuvirtmem( | ||||
|   hptw hptw( // *** remove logic from (), mention this in style guide CH3
 | ||||
|     .clk, .reset, .SATP_REGW, .PCF, .IEUAdrM, .MemRWM, .AtomicM, | ||||
|     .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), | ||||
|     .DCacheStallM, .HPTWAdr, .HPTWRead, .HPTWWrite, .HPTWSize); | ||||
| 
 | ||||
|  | ||||
| @ -29,7 +29,7 @@ | ||||
| ///////////////////////////////////////////
 | ||||
| 
 | ||||
| `include "wally-config.vh" | ||||
| `define HTPW_DA_WRITES_SUPPORTED 1 | ||||
| 
 | ||||
| module hptw | ||||
|   ( | ||||
|    input logic                 clk, reset, | ||||
| @ -71,21 +71,10 @@ 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; | ||||
|   logic                     SaveHPTWAdr, SelHPTWWriteAdr; | ||||
|   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; | ||||
|    | ||||
|   logic [`PA_BITS-1:0]      HPTWReadAdr; | ||||
|                         | ||||
| 	(* mark_debug = "true" *)      statetype WalkerState, NextWalkerState, InitialWalkerState; | ||||
| 
 | ||||
| @ -101,59 +90,88 @@ 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; | ||||
|     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 #(`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
 | ||||
| 	// 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 {Dirty, Accessed} = PTE[7:6]; | ||||
| 	assign LeafPTE = Executable | Writable | Readable;  | ||||
| 	assign ValidPTE = Valid & ~(Writable & ~Readable); | ||||
| 	assign ValidLeafPTE = 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
 | ||||
|   assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | | ||||
|       ((EffectivePrivilegeMode == `S_MODE) & PTE_U & (~STATUS_SUM & DTLBWalk)); | ||||
|   if(`HPTW_WRITES_SUPPORTED) begin : hptwwrites | ||||
| 
 | ||||
|     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); | ||||
|       // page fault if upper bits aren't all the same
 | ||||
|       logic UpperEqual39, UpperEqual48; | ||||
|       assign UpperEqual39 = &(TranslationVAdr[63:38]) | ~|(TranslationVAdr[63:38]); | ||||
|       assign UpperEqual48 = &(TranslationVAdr[63:47]) | ~|(TranslationVAdr[63:47]);  | ||||
|       assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48; | ||||
|   end else begin | ||||
|     end else begin | ||||
|       assign SV39Mode = 0; | ||||
|       assign UpperBitsUnequalPageFault = 0; | ||||
|   end            | ||||
|     end            | ||||
| 
 | ||||
|     assign InvalidRead = ReadAccess & ~Readable & (~STATUS_MXR | ~Executable); | ||||
|     assign InvalidWrite = WriteAccess & ~Writable; | ||||
|     assign OtherPageFault = DTLBWalk? ImproperPrivilege | InvalidRead | InvalidWrite | 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
 | ||||
| 	assign StartWalk = (WalkerState == IDLE) & TLBMiss; | ||||
| 	assign HPTWRead = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD); | ||||
| 	assign DTLBWriteM = (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
 | ||||
| @ -241,7 +259,7 @@ module hptw | ||||
|           else 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; | ||||
|     UPDATE_PTE: if(`HPTW_WRITES_SUPPORTED & DCacheStallM) NextWalkerState = UPDATE_PTE; | ||||
|                 else NextWalkerState = LEAF; | ||||
| 	default: begin | ||||
| 		// synthesis translate_off
 | ||||
|  | ||||
| @ -97,9 +97,14 @@ module tlbcontrol #(parameter ITLB = 0) ( | ||||
|     // only execute non-user mode pages.
 | ||||
|     assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_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
 | ||||
|     assign DAPageFault = Translate & TLBHit & ~PTE_A & ~TLBPageFault; | ||||
|     assign TLBPageFault = (Translate  & TLBHit & (ImproperPrivilege | ~PTE_X | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); | ||||
|       assign DAPageFault = ~PTE_A; | ||||
|       assign TLBPageFault = (Translate  & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); | ||||
|     end | ||||
|   end else begin:dtlb // Data TLB fault checking
 | ||||
|     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
 | ||||
|     // 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 = Translate & TLBHit & (~PTE_A | WriteAccess & ~PTE_D) & ~TLBPageFault;  | ||||
|     assign TLBPageFault =  (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); | ||||
|     if(`HPTW_WRITES_SUPPORTED) begin : hptwwrites | ||||
|       assign DAPageFault = Translate & TLBHit & (~PTE_A | WriteAccess & ~PTE_D) & ~TLBPageFault;  | ||||
|       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 | ||||
| 
 | ||||
|   assign TLBHit = CAMHit & TLBAccess; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user