From 694badcc6bc0d33fd6ce596cb88d39dacc59d8f6 Mon Sep 17 00:00:00 2001 From: David Harris Date: Tue, 6 Jul 2021 03:25:11 -0400 Subject: [PATCH] Created tlbcontrol module to hide details --- wally-pipelined/src/ifu/ifu.sv | 5 +- wally-pipelined/src/lsu/lsu.sv | 5 +- wally-pipelined/src/mmu/mmu.sv | 10 ++- wally-pipelined/src/mmu/tlb.sv | 57 +------------- wally-pipelined/src/mmu/tlbcontrol.sv | 109 ++++++++++++++++++++++++++ wally-pipelined/src/mmu/tlbram.sv | 4 +- 6 files changed, 125 insertions(+), 65 deletions(-) create mode 100644 wally-pipelined/src/mmu/tlbcontrol.sv diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 24952edf..fd927ca6 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -117,10 +117,9 @@ module ifu ( endgenerate mmu #(.TLB_ENTRIES(`ITLB_ENTRIES), .IMMU(1)) - itlb(.TLBAccessType(2'b10), - .VirtualAddress(PCF), + itlb(.VirtualAddress(PCF), .Size(2'b10), - .PTEWriteVal(PageTableEntryF), + .PTE(PageTableEntryF), .PageTypeWriteVal(PageTypeF), .TLBWrite(ITLBWriteF), .TLBFlush(ITLBFlushF), diff --git a/wally-pipelined/src/lsu/lsu.sv b/wally-pipelined/src/lsu/lsu.sv index a2bcf52b..ffd96be9 100644 --- a/wally-pipelined/src/lsu/lsu.sv +++ b/wally-pipelined/src/lsu/lsu.sv @@ -218,10 +218,9 @@ module lsu ( mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0)) - dmmu(.TLBAccessType(MemRWMtoLSU), - .VirtualAddress(MemAdrMtoLSU), + dmmu(.VirtualAddress(MemAdrMtoLSU), .Size(SizeToLSU[1:0]), - .PTEWriteVal(PageTableEntryM), + .PTE(PageTableEntryM), .PageTypeWriteVal(PageTypeM), .TLBWrite(DTLBWriteM), .TLBFlush(DTLBFlushM), diff --git a/wally-pipelined/src/mmu/mmu.sv b/wally-pipelined/src/mmu/mmu.sv index 288fb931..d6d8fb15 100644 --- a/wally-pipelined/src/mmu/mmu.sv +++ b/wally-pipelined/src/mmu/mmu.sv @@ -42,7 +42,6 @@ module mmu #(parameter TLB_ENTRIES = 8, // nuber of TLB Entries // 1x - TLB is accessed for a read (or an instruction) // x1 - TLB is accessed for a write // 11 - TLB is accessed for both read and write - input logic [1:0] TLBAccessType, input logic DisableTranslation, // Virtual address input @@ -50,7 +49,7 @@ module mmu #(parameter TLB_ENTRIES = 8, // nuber of TLB Entries 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 - input logic [`XLEN-1:0] PTEWriteVal, + input logic [`XLEN-1:0] PTE, input logic [1:0] PageTypeWriteVal, input logic TLBWrite, @@ -83,9 +82,12 @@ module mmu #(parameter TLB_ENTRIES = 8, // nuber of TLB Entries // only instantiate TLB if Virtual Memory is supported generate - if (`MEM_VIRTMEM) + if (`MEM_VIRTMEM) begin + logic ReadAccess, WriteAccess; + assign ReadAccess = ExecuteAccessF | ReadAccessM; // execute also acts as a TLB read. Execute and Read are never active for the same MMU, so safe to mix pipestages + assign WriteAccess = WriteAccessM; tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU)) tlb(.*); - else begin // just pass address through as physical + 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]; diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index 34400647..d16a97a4 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -65,14 +65,14 @@ module tlb #(parameter TLB_ENTRIES = 8, // 1x - TLB is accessed for a read (or an instruction) // x1 - TLB is accessed for a write // 11 - TLB is accessed for both read and write - input logic [1:0] TLBAccessType, + input logic ReadAccess, WriteAccess, input logic DisableTranslation, // Virtual address input input logic [`XLEN-1:0] VirtualAddress, // Controls for writing a new entry to the TLB - input logic [`XLEN-1:0] PTEWriteVal, + input logic [`XLEN-1:0] PTE, input logic [1:0] PageTypeWriteVal, input logic TLBWrite, @@ -89,7 +89,6 @@ module tlb #(parameter TLB_ENTRIES = 8, ); logic Translate; - logic TLBAccess, ReadAccess, WriteAccess; // Store current virtual memory mode (SV32, SV39, SV48, ect...) logic [`SVMODE_BITS-1:0] SvMode; @@ -111,13 +110,9 @@ module tlb #(parameter TLB_ENTRIES = 8, logic [1:0] HitPageType; logic CAMHit; logic [`ASID_BITS-1:0] ASID; - logic DAFault; // Grab the sv mode from SATP and determine whether translation should occur - assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]; assign ASID = SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE]; - 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; // Determine whether to write TLB assign WriteEnables = WriteLines & {(TLB_ENTRIES){TLBWrite}}; @@ -135,11 +130,7 @@ module tlb #(parameter TLB_ENTRIES = 8, end endgenerate - // Determine how the TLB is currently being used - // Note that we use ReadAccess for both loads and instruction fetches - assign ReadAccess = TLBAccessType[1]; - assign WriteAccess = TLBAccessType[0]; - assign TLBAccess = ReadAccess || WriteAccess; + tlbcontrol tlbcontrol(.*); // TLB entries are evicted according to the LRU algorithm tlblru #(TLB_ENTRIES) lru(.*); @@ -153,50 +144,10 @@ module tlb #(parameter TLB_ENTRIES = 8, // For superpages, some segments are considered offsets into a larger page. tlbphysicalpagemask PageMask(VirtualPageNumber, PhysicalPageNumber, HitPageType, PhysicalPageNumberMixed); - // unswizzle useful PTE bits - assign {PTE_D, PTE_A} = PTEAccessBits[7:6]; - assign {PTE_U, PTE_X, PTE_W, PTE_R} = PTEAccessBits[4:1]; - - // Check whether the access is allowed, page faulting if not. - generate - if (ITLB == 1) begin - logic ImproperPrivilege; - - // User mode may only execute user mode pages, and supervisor mode may - // only execute non-user mode pages. - 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); - end else begin - logic ImproperPrivilege, InvalidRead, InvalidWrite; - - // User mode may only load/store from user mode pages, and supervisor mode - // may only access user mode pages when STATUS_SUM is low. - assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) || - ((EffectivePrivilegeMode == `S_MODE) && PTE_U && ~STATUS_SUM); - // Check for read error. Reads are invalid when the page is not readable - // (and executable pages are not readable) or when the page is neither - // readable nor executable (and executable pages are readable). - assign InvalidRead = ReadAccess && ~PTE_R && (~STATUS_MXR | ~PTE_X); - // 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 DAFault = ~PTE_A | WriteAccess & ~PTE_D; - assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || InvalidRead || InvalidWrite || DAFault); - end - endgenerate - - // 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 assign PageOffset = VirtualAddress[11:0]; - assign PhysicalAddressFull = TLBHit ? {PhysicalPageNumberMixed, PageOffset} : '0; + assign PhysicalAddressFull = TLBHit ? {PhysicalPageNumberMixed, PageOffset} : '0; // *** in block diagram TLB just works on page numbers mux2 #(`PA_BITS) addressmux(VAExt[`PA_BITS-1:0], PhysicalAddressFull, Translate, PhysicalAddress); - - assign TLBHit = CAMHit & TLBAccess; - assign TLBMiss = ~TLBHit & ~TLBFlush & Translate & TLBAccess; endmodule diff --git a/wally-pipelined/src/mmu/tlbcontrol.sv b/wally-pipelined/src/mmu/tlbcontrol.sv new file mode 100644 index 00000000..21f42dae --- /dev/null +++ b/wally-pipelined/src/mmu/tlbcontrol.sv @@ -0,0 +1,109 @@ +/////////////////////////////////////////// +// tlbcontrol.sv +// +// Written: David_Harris@hmc.edu 5 July 2021 +// Modified: +// +// Purpose: Control signals for TLB +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// 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" + +// The TLB will have 2**ENTRY_BITS total entries +module tlbcontrol #(parameter TLB_ENTRIES = 8, + parameter ITLB = 0) ( +// input logic clk, reset, + + // Current value of satp CSR (from privileged unit) + input logic [`XLEN-1:0] SATP_REGW, + 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 + + // 00 - TLB is not being accessed + // 1x - TLB is accessed for a read (or an instruction) + // x1 - TLB is accessed for a write + // 11 - TLB is accessed for both read and write + input logic ReadAccess, WriteAccess, + input logic DisableTranslation, + input logic TLBFlush, // Invalidate all TLB entries + input logic [7:0] PTEAccessBits, + input logic CAMHit, + output logic TLBMiss, + output logic TLBHit, + output logic TLBPageFault, + output logic [1:0] EffectivePrivilegeMode, + output logic [`SVMODE_BITS-1:0] SvMode, + output logic Translate +); + + // Sections of the page table entry + logic [11:0] PageOffset; + + logic PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R; // Useful PTE Control Bits + logic DAFault; + logic TLBAccess; + + // Grab the sv mode from SATP and determine whether translation should occur + assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]; + 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; + + // Determine whether TLB is being used + assign TLBAccess = ReadAccess || WriteAccess; + + // unswizzle useful PTE bits + assign {PTE_D, PTE_A} = PTEAccessBits[7:6]; + assign {PTE_U, PTE_X, PTE_W, PTE_R} = PTEAccessBits[4:1]; + + // Check whether the access is allowed, page faulting if not. + generate + if (ITLB == 1) begin + logic ImproperPrivilege; + + // User mode may only execute user mode pages, and supervisor mode may + // only execute non-user mode pages. + 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); + end else begin + logic ImproperPrivilege, InvalidRead, InvalidWrite; + + // User mode may only load/store from user mode pages, and supervisor mode + // may only access user mode pages when STATUS_SUM is low. + assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) || + ((EffectivePrivilegeMode == `S_MODE) && PTE_U && ~STATUS_SUM); + // Check for read error. Reads are invalid when the page is not readable + // (and executable pages are not readable) or when the page is neither + // readable nor executable (and executable pages are readable). + assign InvalidRead = ReadAccess && ~PTE_R && (~STATUS_MXR | ~PTE_X); + // 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 DAFault = ~PTE_A | WriteAccess & ~PTE_D; + assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || InvalidRead || InvalidWrite || DAFault); + end + endgenerate + + assign TLBHit = CAMHit & TLBAccess; + assign TLBMiss = ~TLBHit & ~TLBFlush & Translate & TLBAccess; +endmodule diff --git a/wally-pipelined/src/mmu/tlbram.sv b/wally-pipelined/src/mmu/tlbram.sv index 98650d0b..3aa5e65e 100644 --- a/wally-pipelined/src/mmu/tlbram.sv +++ b/wally-pipelined/src/mmu/tlbram.sv @@ -29,7 +29,7 @@ module tlbram #(parameter TLB_ENTRIES = 8) ( input logic clk, reset, - input logic [`XLEN-1:0] PTEWriteVal, + input logic [`XLEN-1:0] PTE, input logic [TLB_ENTRIES-1:0] ReadLines, WriteEnables, output logic [`PPN_BITS-1:0] PhysicalPageNumber, output logic [7:0] PTEAccessBits, @@ -40,7 +40,7 @@ module tlbram #(parameter TLB_ENTRIES = 8) ( logic [`XLEN-1:0] PageTableEntry; // Generate a flop for every entry in the RAM - tlbramline #(`XLEN) tlblineram[TLB_ENTRIES-1:0](clk, reset, ReadLines, WriteEnables, PTEWriteVal, RamRead, PTE_G); + tlbramline #(`XLEN) tlblineram[TLB_ENTRIES-1:0](clk, reset, ReadLines, WriteEnables, PTE, RamRead, PTE_G); assign PageTableEntry = RamRead.or; // OR each column of RAM read to read PTE assign PTEAccessBits = PageTableEntry[7:0];