From 032c38b7e7e50cdeae3714238b5c1809ff26fa30 Mon Sep 17 00:00:00 2001 From: David Harris Date: Tue, 6 Jul 2021 15:29:42 -0400 Subject: [PATCH] MMU produces page fault when upper bits aren't equal. Renamed input to MMU to be 'Address' and moved translation mux into MMU out of TLB --- wally-pipelined/src/ifu/ifu.sv | 2 +- wally-pipelined/src/lsu/lsu.sv | 6 +---- wally-pipelined/src/mmu/mmu.sv | 17 +++++++++----- wally-pipelined/src/mmu/tlb.sv | 18 ++++++--------- wally-pipelined/src/mmu/tlbcontrol.sv | 30 +++++++++++++++++++------ wally-pipelined/src/privileged/csrsr.sv | 3 ++- 6 files changed, 45 insertions(+), 31 deletions(-) diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 8b113f8cd..2412ffa13 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -120,7 +120,7 @@ module ifu ( endgenerate mmu #(.TLB_ENTRIES(`ITLB_ENTRIES), .IMMU(1)) - immu(.VirtualAddress(PCF), + immu(.Address(PCF), .Size(2'b10), .PTE(PageTableEntryF), .PageTypeWriteVal(PageTypeF), diff --git a/wally-pipelined/src/lsu/lsu.sv b/wally-pipelined/src/lsu/lsu.sv index ff47138c4..c7a915ee4 100644 --- a/wally-pipelined/src/lsu/lsu.sv +++ b/wally-pipelined/src/lsu/lsu.sv @@ -115,10 +115,6 @@ module lsu STATE_PTW_DONE} statetype; statetype CurrState, NextState; - - logic PMPInstrAccessFaultF, PMAInstrAccessFaultF; // *** these are just so that the mmu has somewhere to put these outputs since they aren't used in dmem - // *** if you're allowed to parameterize outputs/ inputs existence, these are an easy delete. - logic DTLBMissM; logic [`XLEN-1:0] PageTableEntryM; logic [1:0] PageTypeM; @@ -216,7 +212,7 @@ module lsu mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0)) - dmmu(.VirtualAddress(MemAdrMtoLSU), + dmmu(.Address(MemAdrMtoLSU), .Size(SizeToLSU[1:0]), .PTE(PageTableEntryM), .PageTypeWriteVal(PageTypeM), diff --git a/wally-pipelined/src/mmu/mmu.sv b/wally-pipelined/src/mmu/mmu.sv index 9372f473d..6194d00e1 100644 --- a/wally-pipelined/src/mmu/mmu.sv +++ b/wally-pipelined/src/mmu/mmu.sv @@ -44,8 +44,8 @@ module mmu #(parameter TLB_ENTRIES = 8, // nuber of TLB Entries // 11 - TLB is accessed for both read and write input logic DisableTranslation, - // Virtual address input - input logic [`XLEN-1:0] VirtualAddress, + // address input (could be virtual or physical) + input logic [`XLEN-1:0] Address, 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 @@ -75,6 +75,8 @@ module mmu #(parameter TLB_ENTRIES = 8, // nuber of TLB Entries ); + logic [`PA_BITS-1:0] TLBPhysicalAddress; + logic [`XLEN+1:0] AddressExt; logic PMPSquashBusAccess, PMASquashBusAccess; logic Cacheable, Idempotent, AtomicAllowed; // *** here so that the pmachecker has somewhere to put these outputs. *** I'm leaving them as outputs to pma checker, but I'm stopping them here. // Translation lookaside buffer @@ -82,6 +84,7 @@ module mmu #(parameter TLB_ENTRIES = 8, // nuber of TLB Entries logic PMAInstrAccessFaultF, PMPInstrAccessFaultF; logic PMALoadAccessFaultM, PMPLoadAccessFaultM; logic PMAStoreAccessFaultM, PMPStoreAccessFaultM; + logic Translate; // only instantiate TLB if Virtual Memory is supported @@ -92,14 +95,16 @@ module mmu #(parameter TLB_ENTRIES = 8, // nuber of TLB Entries assign WriteAccess = WriteAccessM; tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU)) tlb(.*); end else begin // just pass address through as physical - logic [`XLEN+1:0] VAExt; - assign VAExt = {2'b00, VirtualAddress}; // extend length of virtual address if necessary for RV32 - assign PhysicalAddress = VAExt[`PA_BITS-1:0]; + assign Translate = 0; assign TLBMiss = 0; - assign TLBHit = 1; + assign TLBHit = 1; // *** is this necessary assign TLBPageFault = 0; end endgenerate + + // If translation is occuring, select translated physical address from TLB + assign AddressExt = {2'b00, Address}; // extend length of virtual address if necessary for RV32 + mux2 #(`PA_BITS) addressmux(AddressExt[`PA_BITS-1:0], TLBPhysicalAddress, Translate, PhysicalAddress); /////////////////////////////////////////// // Check physical memory accesses diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index f2ab94354..4df7ca402 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -68,8 +68,8 @@ module tlb #(parameter TLB_ENTRIES = 8, input logic ReadAccess, WriteAccess, input logic DisableTranslation, - // Virtual address input - input logic [`XLEN-1:0] VirtualAddress, + // address input before translation (could be physical or virtual) + input logic [`XLEN-1:0] Address, // Controls for writing a new entry to the TLB input logic [`XLEN-1:0] PTE, @@ -80,16 +80,15 @@ module tlb #(parameter TLB_ENTRIES = 8, input logic TLBFlush, // Physical address outputs - output logic [`PA_BITS-1:0] PhysicalAddress, + output logic [`PA_BITS-1:0] TLBPhysicalAddress, output logic TLBMiss, output logic TLBHit, + output logic Translate, // Faults output logic TLBPageFault ); - logic Translate; - // Store current virtual memory mode (SV32, SV39, SV48, ect...) //logic [`SVMODE_BITS-1:0] SvMode; logic [1:0] EffectivePrivilegeMode; // privilege mode, possibly modified by MPRV @@ -99,8 +98,7 @@ module tlb #(parameter TLB_ENTRIES = 8, // Sections of the virtual and physical addresses logic [`VPN_BITS-1:0] VirtualPageNumber; logic [`PPN_BITS-1:0] PhysicalPageNumber, PhysicalPageNumberMixed; - logic [`PA_BITS-1:0] PhysicalAddressFull; - logic [`XLEN+1:0] VAExt; + logic [`XLEN+1:0] AddressExt; // Sections of the page table entry logic [7:0] PTEAccessBits; @@ -116,7 +114,7 @@ module tlb #(parameter TLB_ENTRIES = 8, assign ASID = SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE]; // Determine whether to write TLB - assign VirtualPageNumber = VirtualAddress[`VPN_BITS+11:12]; + assign VirtualPageNumber = Address[`VPN_BITS+11:12]; tlbcontrol tlbcontrol(.*); @@ -134,7 +132,5 @@ module tlb #(parameter TLB_ENTRIES = 8, // Output the hit physical address if translation is currently on. // Provide physical address of zero if not TLBHits, to cause segmentation error if miss somehow percolated through signal - assign VAExt = {2'b00, VirtualAddress}; // extend length of virtual address if necessary for RV32 - mux2 #(`PA_BITS) hitmux('0, {PhysicalPageNumberMixed, VirtualAddress[11:0]}, TLBHit, PhysicalAddressFull); // set PA to 0 if TLB misses, to cause segementation error if this miss somehow passes through system - mux2 #(`PA_BITS) addressmux(VAExt[`PA_BITS-1:0], PhysicalAddressFull, Translate, PhysicalAddress); + mux2 #(`PA_BITS) hitmux('0, {PhysicalPageNumberMixed, Address[11:0]}, TLBHit, TLBPhysicalAddress); // set PA to 0 if TLB misses, to cause segementation error if this miss somehow passes through system endmodule diff --git a/wally-pipelined/src/mmu/tlbcontrol.sv b/wally-pipelined/src/mmu/tlbcontrol.sv index 1301b8151..5d2174d4e 100644 --- a/wally-pipelined/src/mmu/tlbcontrol.sv +++ b/wally-pipelined/src/mmu/tlbcontrol.sv @@ -32,6 +32,7 @@ module tlbcontrol #(parameter TLB_ENTRIES = 8, // Current value of satp CSR (from privileged unit) input logic [`XLEN-1:0] SATP_REGW, + input logic [`XLEN-1:0] Address, 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 @@ -58,7 +59,8 @@ module tlbcontrol #(parameter TLB_ENTRIES = 8, logic [`SVMODE_BITS-1:0] SVMode; logic PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R; // Useful PTE Control Bits - logic DAFault; + logic UpperBitsUnequalPageFault; + logic DAPageFault; logic TLBAccess; // Grab the sv mode from SATP and determine whether translation should occur @@ -66,13 +68,27 @@ module tlbcontrol #(parameter TLB_ENTRIES = 8, assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1 assign Translate = (SVMode != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~ DisableTranslation; generate - if (`XLEN==64) assign SV39Mode = (SVMode == `SV39); - else assign SV39Mode = 0; + if (`XLEN==64) begin + assign SV39Mode = (SVMode == `SV39); + // generate page fault if upper bits aren't all the same + logic UpperOnes39, UpperZeros39, UpperOnes48, UpperZeros48; + assign UpperOnes39 = &(Address[63:39]); + assign UpperZeros39 = ~|(Address[63:39]); + assign UpperOnes48 = &(Address[63:48]); + assign UpperZeros48 = ~|(Address[63:48]); + assign UpperBitsUnequalPageFault = SV39Mode ? (Address[38] ? UpperOnes39 : UpperZeros39) : (Address[47] ? UpperOnes48 : UpperZeros48); + end else begin + assign SV39Mode = 0; + assign UpperBitsUnequalPageFault = 0; + end endgenerate // Determine whether TLB is being used assign TLBAccess = ReadAccess || WriteAccess; + // Check whether upper bits of virtual addresss are all equal + + // unswizzle useful PTE bits assign {PTE_D, PTE_A} = PTEAccessBits[7:6]; assign {PTE_U, PTE_X, PTE_W, PTE_R} = PTEAccessBits[4:1]; @@ -87,8 +103,8 @@ module tlbcontrol #(parameter TLB_ENTRIES = 8, assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) || ((EffectivePrivilegeMode == `S_MODE) && PTE_U); // fault for software handling if access bit is off - assign DAFault = ~PTE_A; - assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || ~PTE_X || DAFault); + assign DAPageFault = ~PTE_A; + assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || ~PTE_X || DAPageFault || UpperBitsUnequalPageFault); end else begin logic ImproperPrivilege, InvalidRead, InvalidWrite; @@ -104,8 +120,8 @@ module tlbcontrol #(parameter TLB_ENTRIES = 8, // low. assign InvalidWrite = WriteAccess && ~PTE_W; // Fault for software handling if access bit is off or writing a page with dirty bit off - assign DAFault = ~PTE_A | WriteAccess & ~PTE_D; - assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || InvalidRead || InvalidWrite || DAFault); + assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D; + assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || InvalidRead || InvalidWrite || DAPageFault || UpperBitsUnequalPageFault); end endgenerate diff --git a/wally-pipelined/src/privileged/csrsr.sv b/wally-pipelined/src/privileged/csrsr.sv index 30c41c0c5..dd492b6f1 100644 --- a/wally-pipelined/src/privileged/csrsr.sv +++ b/wally-pipelined/src/privileged/csrsr.sv @@ -125,7 +125,8 @@ module csrsr ( STATUS_SIE <= #1 0; //`S_SUPPORTED; STATUS_UIE <= #1 0; //`U_SUPPORTED; end else if (~StallW) begin - if (FloatRegWriteW) STATUS_FS_INT <= #12'b11; // mark Float State dirty *** this should happen in M stage, be part of if/else + if (FloatRegWriteW) STATUS_FS_INT <= #12'b11; // mark Float State dirty *** this should happen in M stage, be part of if/else; + // *** also, FS_INT needs to be set when any bits of the fcsr are written if (TrapM) begin // Update interrupt enables per Privileged Spec p. 21 // y = PrivilegeModeW