From e57083a0ef112f6cde36022710fbdfb2fefc02eb Mon Sep 17 00:00:00 2001 From: David Harris Date: Fri, 4 Nov 2022 15:21:09 -0700 Subject: [PATCH] HPTW cleanup --- pipelined/src/mmu/hptw.sv | 118 +++++++++++++------------------- pipelined/src/mmu/tlb.sv | 20 +++--- pipelined/src/mmu/tlbcontrol.sv | 14 +--- pipelined/src/mmu/vm64check.sv | 50 ++++++++++++++ 4 files changed, 110 insertions(+), 92 deletions(-) create mode 100644 pipelined/src/mmu/vm64check.sv diff --git a/pipelined/src/mmu/hptw.sv b/pipelined/src/mmu/hptw.sv index 7b303ff4..e2b2573e 100644 --- a/pipelined/src/mmu/hptw.sv +++ b/pipelined/src/mmu/hptw.sv @@ -42,7 +42,7 @@ module hptw input logic [1:0] STATUS_MPP, input logic [1:0] PrivilegeModeW, (* mark_debug = "true" *) input logic ITLBMissOrDAFaultNoTrapF, DTLBMissOrDAFaultNoTrapM, // TLB Miss - input logic [`XLEN-1:0] HPTWReadPTE, // page table entry from LSU + input logic [`XLEN-1:0] HPTWReadPTE, // page table entry from LSU *** change to ReadDataM input logic DCacheStallM, // stall from LSU output logic [`XLEN-1:0] PTE, // page table entry to TLBs output logic [1:0] PageType, // page type to TLBs @@ -106,7 +106,6 @@ module hptw if(`HPTW_WRITES_SUPPORTED) begin : hptwwrites - logic SV39Mode; logic ReadAccess, WriteAccess; logic InvalidRead, InvalidWrite; logic UpperBitsUnequalPageFault; @@ -136,19 +135,9 @@ module hptw assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | ((EffectivePrivilegeMode == `S_MODE) & PTE_U & (~STATUS_SUM & DTLBWalk)); - // *** turn into module common with code in tlbcontrol. - 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 - assign SV39Mode = 0; - assign UpperBitsUnequalPageFault = 0; - end - + // Check for page faults + vm64check vm64check(.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]), .VAdr(TranslationVAdr), + .SV39Mode(), .UpperBitsUnequalPageFault); assign InvalidRead = ReadAccess & ~Readable & (~STATUS_MXR | ~Executable); assign InvalidWrite = WriteAccess & ~Writable; assign OtherPageFault = DTLBWalk? ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequalPageFault | Misaligned | ~Valid : @@ -190,26 +179,26 @@ module hptw // HPTWAdr muxing if (`XLEN==32) begin // RV32 - logic [9:0] VPN; - logic [`PPN_BITS-1:0] PPN; - assign VPN = ((WalkerState == L1_ADR) | (WalkerState == L1_RD)) ? TranslationVAdr[31:22] : TranslationVAdr[21:12]; // select VPN field based on HPTW state - assign PPN = ((WalkerState == L1_ADR) | (WalkerState == L1_RD)) ? BasePageTablePPN : CurrentPPN; - assign HPTWReadAdr = {PPN, VPN, 2'b00}; - assign HPTWSize = 3'b010; + logic [9:0] VPN; + logic [`PPN_BITS-1:0] PPN; + assign VPN = ((WalkerState == L1_ADR) | (WalkerState == L1_RD)) ? TranslationVAdr[31:22] : TranslationVAdr[21:12]; // select VPN field based on HPTW state + assign PPN = ((WalkerState == L1_ADR) | (WalkerState == L1_RD)) ? BasePageTablePPN : CurrentPPN; + assign HPTWReadAdr = {PPN, VPN, 2'b00}; + assign HPTWSize = 3'b010; end else begin // RV64 - logic [8:0] VPN; - logic [`PPN_BITS-1:0] PPN; - always_comb - case (WalkerState) // select VPN field based on HPTW state - L3_ADR, L3_RD: VPN = TranslationVAdr[47:39]; - L2_ADR, L2_RD: VPN = TranslationVAdr[38:30]; - L1_ADR, L1_RD: VPN = TranslationVAdr[29:21]; - default: VPN = TranslationVAdr[20:12]; - endcase - assign PPN = ((WalkerState == L3_ADR) | (WalkerState == L3_RD) | - (SvMode != `SV48 & ((WalkerState == L2_ADR) | (WalkerState == L2_RD)))) ? BasePageTablePPN : CurrentPPN; - assign HPTWReadAdr = {PPN, VPN, 3'b000}; - assign HPTWSize = 3'b011; + logic [8:0] VPN; + logic [`PPN_BITS-1:0] PPN; + always_comb + case (WalkerState) // select VPN field based on HPTW state + L3_ADR, L3_RD: VPN = TranslationVAdr[47:39]; + L2_ADR, L2_RD: VPN = TranslationVAdr[38:30]; + L1_ADR, L1_RD: VPN = TranslationVAdr[29:21]; + default: VPN = TranslationVAdr[20:12]; + endcase + assign PPN = ((WalkerState == L3_ADR) | (WalkerState == L3_RD) | + (SvMode != `SV48 & ((WalkerState == L2_ADR) | (WalkerState == L2_RD)))) ? BasePageTablePPN : CurrentPPN; + assign HPTWReadAdr = {PPN, VPN, 3'b000}; + assign HPTWSize = 3'b011; end // Initial state and misalignment for RV32/64 @@ -228,44 +217,33 @@ module hptw end // Page Table Walker FSM - // If the setup time on the D$ RAM is short, it should be possible to merge the LEVELx_READ and LEVELx states - // to decrease the latency of the HPTW. However, if the D$ is a cycle limiter, it's better to leave the - // HPTW as shown below to keep the D$ setup time out of the critical path. - // *** Is this really true. Talk with Ross. Seems like it's the next state logic on critical path instead. - // *** address TYPE(statetype) flopenl #(.TYPE(statetype)) WalkerStateReg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState); 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; - 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; - 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; - 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; - LEAF: if (DAPageFault) NextWalkerState = UPDATE_PTE; - else NextWalkerState = IDLE; - UPDATE_PTE: if(`HPTW_WRITES_SUPPORTED & DCacheStallM) NextWalkerState = UPDATE_PTE; - else NextWalkerState = LEAF; - default: begin - NextWalkerState = IDLE; // should never be reached - end - endcase // case (WalkerState) + 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; + L2_ADR: if (InitialWalkerState == L2_ADR | ValidNonLeafPTE) NextWalkerState = L2_RD; // first access in SV39 + else NextWalkerState = LEAF; + L2_RD: if (DCacheStallM) NextWalkerState = L2_RD; + else NextWalkerState = L1_ADR; + L1_ADR: if (InitialWalkerState == L1_ADR | ValidNonLeafPTE) NextWalkerState = L1_RD; // first access in SV32 + else if (ValidNonLeafPTE) NextWalkerState = L1_RD; + else NextWalkerState = LEAF; + L1_RD: if (DCacheStallM) NextWalkerState = L1_RD; + else NextWalkerState = L0_ADR; + L0_ADR: if (ValidNonLeafPTE) NextWalkerState = L0_RD; + else NextWalkerState = LEAF; + L0_RD: if (DCacheStallM) NextWalkerState = L0_RD; + else NextWalkerState = LEAF; + LEAF: if (DAPageFault) NextWalkerState = UPDATE_PTE; + else NextWalkerState = IDLE; + UPDATE_PTE: if(`HPTW_WRITES_SUPPORTED & DCacheStallM) NextWalkerState = UPDATE_PTE; + else NextWalkerState = LEAF; + default: NextWalkerState = IDLE; // should never be reached + endcase // case (WalkerState) assign IgnoreRequestTLB = WalkerState == IDLE & TLBMiss; assign SelHPTW = WalkerState != IDLE; diff --git a/pipelined/src/mmu/tlb.sv b/pipelined/src/mmu/tlb.sv index 6954e1d9..2f4fd556 100644 --- a/pipelined/src/mmu/tlb.sv +++ b/pipelined/src/mmu/tlb.sv @@ -116,16 +116,16 @@ module tlb #(parameter TLB_ENTRIES = 8, // we cache Misaligned along with the PTE? This only has to be computed once // in the hptw as it is always the same regardless of the VPN. if(`XLEN == 32) begin - assign MegapageMisaligned = |(PPN[9:0]); // must have zero PPN0 - assign Misaligned = (HitPageType == 2'b01) & MegapageMisaligned; + assign MegapageMisaligned = |(PPN[9:0]); // must have zero PPN0 + assign Misaligned = (HitPageType == 2'b01) & MegapageMisaligned; end else begin - logic GigapageMisaligned, TerapageMisaligned; - assign TerapageMisaligned = |(PPN[26:0]); // must have zero PPN2, PPN1, PPN0 - assign GigapageMisaligned = |(PPN[17:0]); // must have zero PPN1 and PPN0 - assign MegapageMisaligned = |(PPN[8:0]); // must have zero PPN0 - assign Misaligned = ((HitPageType == 2'b11) & TerapageMisaligned) | - ((HitPageType == 2'b10) & GigapageMisaligned) | - ((HitPageType == 2'b01) & MegapageMisaligned); + logic GigapageMisaligned, TerapageMisaligned; + assign TerapageMisaligned = |(PPN[26:0]); // must have zero PPN2, PPN1, PPN0 + assign GigapageMisaligned = |(PPN[17:0]); // must have zero PPN1 and PPN0 + assign MegapageMisaligned = |(PPN[8:0]); // must have zero PPN0 + assign Misaligned = ((HitPageType == 2'b11) & TerapageMisaligned) | + ((HitPageType == 2'b10) & GigapageMisaligned) | + ((HitPageType == 2'b01) & MegapageMisaligned); end assign VPN = VAdr[`VPN_BITS+11:12]; @@ -137,7 +137,7 @@ module tlb #(parameter TLB_ENTRIES = 8, tlblru #(TLB_ENTRIES) lru(.clk, .reset, .TLBWrite, .TLBFlush, .Matches, .CAMHit, .WriteEnables); tlbcam #(TLB_ENTRIES, `VPN_BITS + `ASID_BITS, `VPN_SEGMENT_BITS) - tlbcam(.clk, .reset, .VPN, .PageTypeWriteVal, .SV39Mode, .TLBFlush, .WriteEnables, .PTE_Gs, + tlbcam(.clk, .reset, .VPN, .PageTypeWriteVal, .SV39Mode, .TLBFlush, .WriteEnables, .PTE_Gs, .SATP_ASID, .Matches, .HitPageType, .CAMHit); tlbram #(TLB_ENTRIES) tlbram(.clk, .reset, .PTE, .Matches, .WriteEnables, .PPN, .PTEAccessBits, .PTE_Gs); diff --git a/pipelined/src/mmu/tlbcontrol.sv b/pipelined/src/mmu/tlbcontrol.sv index 5a9e4852..8b3da2f3 100644 --- a/pipelined/src/mmu/tlbcontrol.sv +++ b/pipelined/src/mmu/tlbcontrol.sv @@ -68,22 +68,12 @@ module tlbcontrol #(parameter ITLB = 0) ( // Grab the sv mode from SATP and determine whether translation should occur assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1 assign Translate = (SATP_MODE != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~DisableTranslation; - if (`XLEN==64) begin:rv64 - assign SV39Mode = (SATP_MODE == `SV39); - // page fault if upper bits aren't all the same - logic UpperEqual39, UpperEqual48; - assign UpperEqual39 = &(VAdr[63:38]) | ~|(VAdr[63:38]); - assign UpperEqual48 = &(VAdr[63:47]) | ~|(VAdr[63:47]); - assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48; - end else begin - assign SV39Mode = 0; - assign UpperBitsUnequalPageFault = 0; - end // Determine whether TLB is being used assign TLBAccess = ReadAccess | WriteAccess; // Check whether upper bits of virtual addresss are all equal + vm64check vm64check(.SATP_MODE, .VAdr, .SV39Mode, .UpperBitsUnequalPageFault); // unswizzle useful PTE bits assign {PTE_D, PTE_A} = PTEAccessBits[7:6]; @@ -99,7 +89,7 @@ module tlbcontrol #(parameter ITLB = 0) ( 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 = ~PTE_A; assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); end diff --git a/pipelined/src/mmu/vm64check.sv b/pipelined/src/mmu/vm64check.sv new file mode 100644 index 00000000..cedeb526 --- /dev/null +++ b/pipelined/src/mmu/vm64check.sv @@ -0,0 +1,50 @@ +/////////////////////////////////////////// +// vm64check.sv +// +// Written: David_Harris@hmc.edu 4 November 2022 +// Modified: +// +// Purpose: Check for good upper address bits in RV64 mode +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// MIT LICENSE +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "wally-config.vh" + +module vm64check ( + input logic [`SVMODE_BITS-1:0] SATP_MODE, + input logic [`XLEN-1:0] VAdr, + output logic SV39Mode, UpperBitsUnequalPageFault +); + + if (`XLEN==64) begin:rv64 + assign SV39Mode = (SATP_MODE == `SV39); + // page fault if upper bits aren't all the same + logic UpperEqual39, UpperEqual48; + assign UpperEqual39 = &(VAdr[63:38]) | ~|(VAdr[63:38]); + assign UpperEqual48 = &(VAdr[63:47]) | ~|(VAdr[63:47]); + assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48; + end else begin + assign SV39Mode = 0; + assign UpperBitsUnequalPageFault = 0; + end +endmodule