From e27bc1cbf74fcc45fe26b3130fe9f4678fb2e71e Mon Sep 17 00:00:00 2001 From: Thomas Fleming Date: Fri, 14 May 2021 07:12:32 -0400 Subject: [PATCH] Clean up MMU code --- wally-pipelined/misc/lzd.sv | 136 ++++++++++ wally-pipelined/misc/tlb_toy/tlb_testbench.sv | 58 ----- wally-pipelined/misc/tlb_toy/tlb_toy.sv.OLD | 233 ------------------ wally-pipelined/misc/tlb_toy/tlb_toy.tv | 11 - wally-pipelined/src/ebu/ahblite.sv | 2 +- .../src/{ebu => mmu}/pagetablewalker.sv | 81 ++---- wally-pipelined/src/mmu/tlb.sv | 2 +- wally-pipelined/src/mmu/tlb_rand.sv | 35 --- wally-pipelined/src/privileged/pmpadrdec.sv | 2 +- wally-pipelined/src/privileged/pmpchecker.sv | 11 - 10 files changed, 162 insertions(+), 409 deletions(-) create mode 100644 wally-pipelined/misc/lzd.sv delete mode 100644 wally-pipelined/misc/tlb_toy/tlb_testbench.sv delete mode 100644 wally-pipelined/misc/tlb_toy/tlb_toy.sv.OLD delete mode 100644 wally-pipelined/misc/tlb_toy/tlb_toy.tv rename wally-pipelined/src/{ebu => mmu}/pagetablewalker.sv (81%) delete mode 100644 wally-pipelined/src/mmu/tlb_rand.sv diff --git a/wally-pipelined/misc/lzd.sv b/wally-pipelined/misc/lzd.sv new file mode 100644 index 00000000..5ca99bae --- /dev/null +++ b/wally-pipelined/misc/lzd.sv @@ -0,0 +1,136 @@ +// V. G. Oklobdzija, "Algorithmic design of a hierarchical and modular +// leading zero detector circuit," in Electronics Letters, vol. 29, +// no. 3, pp. 283-284, 4 Feb. 1993, doi: 10.1049/el:19930193. + +module lz2 (P, V, B0, B1); + + input logic B0; + input logic B1; + + output logic P; + output logic V; + + assign V = B0 | B1; + assign P = B0 & ~B1; + +endmodule // lz2 + +// Note: This module is not made out of two lz2's - why not? (MJS) + +module lz4 (ZP, ZV, B0, B1, V0, V1); + + output logic [1:0] ZP; + output logic ZV; + + input logic B0; + input logic B1; + input logic V0; + input logic V1; + + assign ZP[0] = V0 ? B0 : B1; + assign ZP[1] = ~V0; + assign ZV = V0 | V1; + +endmodule // lz4 + +// Note: This module is not made out of two lz4's - why not? (MJS) + +module lz8 (ZP, ZV, B); + + input logic [7:0] B; + + output logic [2:0] ZP; + output logic ZV; + + logic s1p0; + logic s1v0; + logic s1p1; + logic s1v1; + logic s2p0; + logic s2v0; + logic s2p1; + logic s2v1; + logic [1:0] ZPa; + logic [1:0] ZPb; + logic ZVa; + logic ZVb; + + lz2 l1(s1p0, s1v0, B[2], B[3]); + lz2 l2(s1p1, s1v1, B[0], B[1]); + lz4 l3(ZPa, ZVa, s1p0, s1p1, s1v0, s1v1); + + lz2 l4(s2p0, s2v0, B[6], B[7]); + lz2 l5(s2p1, s2v1, B[4], B[5]); + lz4 l6(ZPb, ZVb, s2p0, s2p1, s2v0, s2v1); + + assign ZP[1:0] = ZVb ? ZPb : ZPa; + assign ZP[2] = ~ZVb; + assign ZV = ZVa | ZVb; + +endmodule // lz8 + +module lz16 (ZP, ZV, B); + + input logic [15:0] B; + + output logic [3:0] ZP; + output logic ZV; + + logic [2:0] ZPa; + logic [2:0] ZPb; + logic ZVa; + logic ZVb; + + lz8 l1(ZPa, ZVa, B[7:0]); + lz8 l2(ZPb, ZVb, B[15:8]); + + assign ZP[2:0] = ZVb ? ZPb : ZPa; + assign ZP[3] = ~ZVb; + assign ZV = ZVa | ZVb; + +endmodule // lz16 + +module lz32 (ZP, ZV, B); + + input logic [31:0] B; + + output logic [4:0] ZP; + output logic ZV; + + logic [3:0] ZPa; + logic [3:0] ZPb; + logic ZVa; + logic ZVb; + + lz16 l1(ZPa, ZVa, B[15:0]); + lz16 l2(ZPb, ZVb, B[31:16]); + + assign ZP[3:0] = ZVb ? ZPb : ZPa; + assign ZP[4] = ~ZVb; + assign ZV = ZVa | ZVb; + +endmodule // lz32 + +// This module returns the number of leading zeros ZP in the 64-bit +// number B. If there are no ones in B, then ZP and ZV are both 0. + +module lz64 (ZP, ZV, B); + + input logic [63:0] B; + + output logic [5:0] ZP; + output logic ZV; + + logic [4:0] ZPa; + logic [4:0] ZPb; + logic ZVa; + logic ZVb; + + lz32 l1(ZPa, ZVa, B[31:0]); + lz32 l2(ZPb, ZVb, B[63:32]); + + assign ZV = ZVa | ZVb; + assign ZP[4:0] = (ZVb ? ZPb : ZPa) & {5{ZV}}; + assign ZP[5] = ~ZVb & ZV; + +endmodule // lz64 diff --git a/wally-pipelined/misc/tlb_toy/tlb_testbench.sv b/wally-pipelined/misc/tlb_toy/tlb_testbench.sv deleted file mode 100644 index 4aa30542..00000000 --- a/wally-pipelined/misc/tlb_toy/tlb_testbench.sv +++ /dev/null @@ -1,58 +0,0 @@ -`include "wally-config.vh" - -module tlb_testbench(); - logic clk, reset; - - // DUT inputs - logic [`XLEN-1:0] SATP; - logic [`XLEN-1:0] VirtualAddress; - logic [`XLEN-1:0] PageTableEntryWrite; - logic TLBWrite, TLBFlush; - - // DUT outputs - logic [`XLEN-1:0] PhysicalAddress; - logic TLBMiss, TLBHit; - - // Testbench signals - logic [33:0] expected; - logic [31:0] vectornum, errors; - logic [99:0] testvectors[10000:0]; - - assign SATP = {1'b1, 31'b0}; - - // instantiate device under test - tlb_toy dut(.*); - - // generate clock - always begin - clk=1; #5; clk=0; #5; - end - - // at start of test, load vectors and pulse reset - initial begin - $readmemb("tlb_toy.tv", testvectors); - vectornum = 0; errors = 0; reset = 1; #22; reset = 0; - end - - // apply test vectors on rising edge of clk - always @(posedge clk) begin - #1; {VirtualAddress, PageTableEntryWrite, TLBWrite, TLBFlush, expected} = testvectors[vectornum]; - end - - // check results on falling edge of clk - always @(negedge clk) - if (~reset) begin // skip during reset - if ({PhysicalAddress, TLBMiss, TLBHit} !== expected) begin // check result - $display("Error: VirtualAddress = %b, write = %b, data = %b, flush = %b", VirtualAddress, - TLBWrite, PageTableEntryWrite, TLBFlush); - $display(" outputs = %b %b %b (%b expected)", - PhysicalAddress, TLBMiss, TLBHit, expected); - errors = errors + 1; - end - vectornum = vectornum + 1; - if (testvectors[vectornum] === 100'bx) begin - $display("%d tests completed with %d errors", vectornum, errors); - $stop; - end - end -endmodule diff --git a/wally-pipelined/misc/tlb_toy/tlb_toy.sv.OLD b/wally-pipelined/misc/tlb_toy/tlb_toy.sv.OLD deleted file mode 100644 index cafc15fa..00000000 --- a/wally-pipelined/misc/tlb_toy/tlb_toy.sv.OLD +++ /dev/null @@ -1,233 +0,0 @@ -/////////////////////////////////////////// -// tlb_toy.sv -// -// Written: jtorrey@hmc.edu 16 February 2021 -// Modified: -// -// Purpose: Example translation lookaside buffer -// Cache of virtural-to-physical address translations -// -// 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" - -/** - * sv32 specs - * ---------- - * Virtual address [31:0] (32 bits) - * [________________________________] - * |--VPN1--||--VPN0--||----OFF---| - * 10 10 12 - * - * Physical address [33:0] (34 bits) - * [__________________________________] - * |---PPN1---||--PPN0--||----OFF---| - * 12 10 12 - * - * Page Table Entry [31:0] (32 bits) - * [________________________________] - * |---PPN1---||--PPN0--|||DAGUXWRV - * 12 10 ^^ - * RSW(2) -- for OS - */ - -/* *** TODO: - * - add LRU algorithm (select the write index based on which entry was used - * least recently) - */ - -// The TLB will have 2**ENTRY_BITS total entries -module tlb_toy #(parameter ENTRY_BITS = 3) ( - input clk, reset, - - // Current value of satp CSR (from privileged unit) - input [`XLEN-1:0] SATP, // *** How do we get this? - - // Virtual address input - input [`XLEN-1:0] VirtualAddress, - - // Controls for writing a new entry to the TLB - input [`XLEN-1:0] PageTableEntryWrite, - input TLBWrite, - - // Invalidate all TLB entries - input TLBFlush, - - // Physical address outputs - output [`XLEN-1:0] PhysicalAddress, - output TLBMiss, - output TLBHit -); - - generate - if (`XLEN == 32) begin: ARCH - localparam VPN_BITS = 20; - localparam PPN_BITS = 22; - localparam PA_BITS = 34; - - logic SvMode; - assign SvMode = SATP[31]; // *** change to an enum somehow? - end else begin: ARCH - localparam VPN_BITS = 27; - localparam PPN_BITS = 44; - localparam PA_BITS = 56; - - logic SvMode; // currently just a boolean whether translation enabled - assign SvMode = SATP[63]; // *** change to an enum somehow? - end - endgenerate - - // Index (currently random) to write the next TLB entry - logic [ENTRY_BITS-1:0] WriteIndex; - - // Sections of the virtual and physical addresses - logic [ARCH.VPN_BITS-1:0] VirtualPageNumber; - logic [ARCH.PPN_BITS-1:0] PhysicalPageNumber; - logic [11:0] PageOffset; - logic [ARCH.PA_BITS-1:0] PhysicalAddressFull; - - // Pattern and pattern location in the CAM - logic [ENTRY_BITS-1:0] VPNIndex; - - // RAM access location - logic [ENTRY_BITS-1:0] EntryIndex; - - // Page table entry matching the virtual address - logic [`XLEN-1:0] PageTableEntry; - - assign VirtualPageNumber = VirtualAddress[ARCH.VPN_BITS+11:12]; - assign PageOffset = VirtualAddress[11:0]; - - // Choose a read or write location to the entry list - mux2 #(3) indexmux(VPNIndex, WriteIndex, TLBWrite, EntryIndex); - - // Currently use random replacement algorithm - tlb_rand rdm(.*); - - tlb_ram #(ENTRY_BITS) ram(.*); - tlb_cam #(ENTRY_BITS, ARCH.VPN_BITS) cam(.*); - - always_comb begin - assign PhysicalPageNumber = PageTableEntry[ARCH.PPN_BITS+9:10]; - - if (TLBHit) begin - assign PhysicalAddressFull = {PhysicalPageNumber, PageOffset}; - end else begin - assign PhysicalAddressFull = 8'b0; // *** Actual behavior; disabled until walker functioning - //assign PhysicalAddressFull = {2'b0, VirtualPageNumber, PageOffset} // *** pass through should be removed as soon as walker ready - end - end - - generate - if (`XLEN == 32) begin - mux2 #(`XLEN) addressmux(VirtualAddress, PhysicalAddressFull[31:0], ARCH.SvMode, PhysicalAddress); - end else begin - mux2 #(`XLEN) addressmux(VirtualAddress, {8'b0, PhysicalAddressFull}, ARCH.SvMode, PhysicalAddress); - end - endgenerate - - assign TLBMiss = ~TLBHit & ~(TLBWrite | TLBFlush) & ARCH.SvMode; -endmodule - -module tlb_ram #(parameter ENTRY_BITS = 3) ( - input clk, reset, - input [ENTRY_BITS-1:0] EntryIndex, - input [`XLEN-1:0] PageTableEntryWrite, - input TLBWrite, - - output [`XLEN-1:0] PageTableEntry -); - - localparam NENTRIES = 2**ENTRY_BITS; - - logic [`XLEN-1:0] ram [0:NENTRIES-1]; - always @(posedge clk) begin - if (TLBWrite) ram[EntryIndex] <= PageTableEntryWrite; - end - - assign PageTableEntry = ram[EntryIndex]; - - initial begin - for (int i = 0; i < NENTRIES; i++) - ram[i] = `XLEN'b0; - end - -endmodule - -module tlb_cam #(parameter ENTRY_BITS = 3, - parameter KEY_BITS = 20) ( - input clk, reset, - input [KEY_BITS-1:0] VirtualPageNumber, - input [ENTRY_BITS-1:0] WriteIndex, - input TLBWrite, - input TLBFlush, - output [ENTRY_BITS-1:0] VPNIndex, - output TLBHit -); - - localparam NENTRIES = 2**ENTRY_BITS; - - // Each entry of this memory has KEY_BITS for the key plus one valid bit. - logic [KEY_BITS:0] ram [0:NENTRIES-1]; - - logic [ENTRY_BITS-1:0] matched_address_comb; - logic match_found_comb; - - always @(posedge clk) begin - if (TLBWrite) ram[WriteIndex] <= {1'b1,VirtualPageNumber}; - if (TLBFlush) begin - for (int i = 0; i < NENTRIES; i++) - ram[i][KEY_BITS] = 1'b0; // Zero out msb (valid bit) of all entries - end - end - - // *** Check whether this for loop synthesizes correctly - always_comb begin - match_found_comb = 1'b0; - matched_address_comb = '0; - for (int i = 0; i < NENTRIES; i++) begin - if (ram[i] == {1'b1,VirtualPageNumber} && !match_found_comb) begin - matched_address_comb = i; - match_found_comb = 1; - end else begin - matched_address_comb = matched_address_comb; - match_found_comb = match_found_comb; - end - end - end - - assign VPNIndex = matched_address_comb; - assign TLBHit = match_found_comb & ~(TLBWrite | TLBFlush); - - initial begin - for (int i = 0; i < NENTRIES; i++) - ram[i] <= '0; - end - -endmodule - -module tlb_rand #(parameter ENTRY_BITS = 3) ( - input clk, reset, - output [ENTRY_BITS:0] WriteIndex -); - - logic [31:0] data; - assign data = $urandom; - assign WriteIndex = data[ENTRY_BITS:0]; - -endmodule diff --git a/wally-pipelined/misc/tlb_toy/tlb_toy.tv b/wally-pipelined/misc/tlb_toy/tlb_toy.tv deleted file mode 100644 index 329f3aac..00000000 --- a/wally-pipelined/misc/tlb_toy/tlb_toy.tv +++ /dev/null @@ -1,11 +0,0 @@ -// tlb_toy.tv -// PCF _ PageTableEntryF _ ITLBWriteF _ ITLBFlushF ___ PCPF _ ITLBMissF _ ITLBHitF -10101010101010101010101010101010_00000000000000000000000000000000_0_0___00000000000000000000000000000000_1_0 -// Write test: Add translation aaaaa -> 044444 to TLB -10101010101010101010101010101010_00010001000100010001001100110010_1_0___00000000000000000000000000000000_0_0 -10101010101010101010101010101010_00000000000000000000000000000000_0_0___01000100010001000100101010101010_0_1 -10101010101010101010101010101010_00000000000000000000000000000000_0_0___01000100010001000100101010101010_0_1 -10101010100010101010101010101010_00000000000000000000000000000000_0_0___00000000000000000000000000000000_1_0 -// Flush test: should invalidate all entries -00000000000000000000000000000000_00000000000000000000000000000000_0_1___00000000000000000000000000000000_0_0 -10101010101010101010101010101010_00000000000000000000000000000000_0_0___00000000000000000000000000000000_1_0 diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index b6103400..a31448ea 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -54,7 +54,7 @@ module ahblite ( // Signals from MMU input logic MMUStall, input logic [`XLEN-1:0] MMUPAdr, - input logic MMUTranslate, MMUTranslationComplete, + input logic MMUTranslate, output logic [`XLEN-1:0] MMUReadPTE, output logic MMUReady, // Signals from PMA checker diff --git a/wally-pipelined/src/ebu/pagetablewalker.sv b/wally-pipelined/src/mmu/pagetablewalker.sv similarity index 81% rename from wally-pipelined/src/ebu/pagetablewalker.sv rename to wally-pipelined/src/mmu/pagetablewalker.sv index e178154b..c548c1f1 100644 --- a/wally-pipelined/src/ebu/pagetablewalker.sv +++ b/wally-pipelined/src/mmu/pagetablewalker.sv @@ -29,11 +29,7 @@ /* *** TO-DO: - - Faults have a timing issue and currently do not work. - - Leaf state brings HADDR down to zeros (maybe fixed?) - - Complete rv64ic case - Implement better accessed/dirty behavior - - Implement read/write/execute checking (either here or in TLB) */ module pagetablewalker ( @@ -58,7 +54,6 @@ module pagetablewalker ( // Signals to ahblite (memory addresses to access) output logic [`XLEN-1:0] MMUPAdr, output logic MMUTranslate, - output logic MMUTranslationComplete, // Stall signal output logic MMUStall, @@ -70,7 +65,6 @@ module pagetablewalker ( ); // Internal signals - logic SvMode, TLBMiss; logic [`PPN_BITS-1:0] BasePageTablePPN; logic [`XLEN-1:0] TranslationVAdr; logic [`XLEN-1:0] SavedPTE, CurrentPTE; @@ -88,37 +82,10 @@ module pagetablewalker ( logic [`XLEN-1:0] PageTableEntry; logic [1:0] PageType; - // Signals for direct, fake translations. Not part of the final Wally version. - logic [`XLEN-1:0] DirectInstrPTE, DirectMemPTE; - localparam DirectPTEFlags = {2'b0, 8'b00001111}; - - logic [`VPN_BITS-1:0] PCPageNumber, MemAdrPageNumber; - assign BasePageTablePPN = SATP_REGW[`PPN_BITS-1:0]; assign MemStore = MemRWM[0]; - assign PCPageNumber = PCF[`VPN_BITS+11:12]; - assign MemAdrPageNumber = MemAdrM[`VPN_BITS+11:12]; - - // Create fake page table entries for direct virtual to physical translation - generate - if (`XLEN == 32) begin - assign DirectInstrPTE = {PCPageNumber, DirectPTEFlags}; - assign DirectMemPTE = {MemAdrPageNumber, DirectPTEFlags}; - end else begin - assign DirectInstrPTE = {10'b0, PCPageNumber, DirectPTEFlags}; - assign DirectMemPTE = {10'b0, MemAdrPageNumber, DirectPTEFlags}; - end - endgenerate - - // Direct translation flops - //flopenr #(`XLEN) instrpte(HCLK, ~HRESETn, ITLBMissF, DirectInstrPTE, PageTableEntryF); - //flopenr #(`XLEN) datapte(HCLK, ~HRESETn, DTLBMissM, DirectMemPTE, PageTableEntryM); - - //flopr #(1) iwritesignal(HCLK, ~HRESETn, ITLBMissF, ITLBWriteF); - //flopr #(1) dwritesignal(HCLK, ~HRESETn, DTLBMissM, DTLBWriteM); - // Prefer data address translations over instruction address translations assign TranslationVAdr = (DTLBMissM) ? MemAdrM : PCF; assign MMUTranslate = DTLBMissM || ITLBMissF; @@ -150,8 +117,6 @@ module pagetablewalker ( if (`XLEN == 32) begin logic [9:0] VPN1, VPN0; - assign SvMode = SATP_REGW[31]; - flopenl #(3) mmureg(HCLK, ~HRESETn, 1'b1, NextWalkerState, IDLE, WalkerState); // State transition logic @@ -160,11 +125,12 @@ module pagetablewalker ( IDLE: if (MMUTranslate) NextWalkerState = LEVEL1; else NextWalkerState = IDLE; LEVEL1: if (~MMUReady) NextWalkerState = LEVEL1; - // else if (~ValidPTE || (LeafPTE && BadMegapage)) - // NextWalkerState = FAULT; - // *** Leave megapage implementation for later - // *** need to check if megapage valid/aligned - else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; + // *** According to the architecture, we should + // fault upon finding a superpage that is misaligned or has 0 + // access bit. The following commented line of code is + // supposed to perform that check. However, it is untested. + else if (ValidPTE && LeafPTE && ~BadMegapage) NextWalkerState = LEAF; + // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** If you test the above line, delete this line else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0; else NextWalkerState = FAULT; LEVEL0: if (~MMUReady) NextWalkerState = LEVEL0; @@ -180,13 +146,12 @@ module pagetablewalker ( endcase end - // A megapage is a Level 1 leaf page. This page must have zero PPN[0]. assign MegapageMisaligned = |(CurrentPPN[9:0]); assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme assign VPN1 = TranslationVAdr[31:22]; - assign VPN0 = TranslationVAdr[21:12]; // *** could optimize by not passing offset? + assign VPN0 = TranslationVAdr[21:12]; // Assign combinational outputs always_comb begin @@ -194,7 +159,6 @@ module pagetablewalker ( TranslationPAdr = '0; PageTableEntry = '0; PageType ='0; - MMUTranslationComplete = '0; DTLBWriteM = '0; ITLBWriteF = '0; WalkerInstrPageFaultF = '0; @@ -217,13 +181,11 @@ module pagetablewalker ( TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; PageTableEntry = CurrentPTE; PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00; - MMUTranslationComplete = '1; DTLBWriteM = DTLBMissM; ITLBWriteF = ~DTLBMissM; // Prefer data over instructions end FAULT: begin TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; - MMUTranslationComplete = '1; WalkerInstrPageFaultF = ~DTLBMissM; WalkerLoadPageFaultM = DTLBMissM && ~MemStore; WalkerStorePageFaultM = DTLBMissM && MemStore; @@ -248,13 +210,10 @@ module pagetablewalker ( end else begin localparam LEVEL2 = 3'h5; - assign SvMode = SATP_REGW[63]; - logic [8:0] VPN2, VPN1, VPN0; logic GigapageMisaligned, BadGigapage; - // *** Do we need a synchronizer here for walker to talk to ahblite? flopenl #(3) mmureg(HCLK, ~HRESETn, 1'b1, NextWalkerState, IDLE, WalkerState); always_comb begin @@ -262,14 +221,21 @@ module pagetablewalker ( IDLE: if (MMUTranslate) NextWalkerState = LEVEL2; else NextWalkerState = IDLE; LEVEL2: if (~MMUReady) NextWalkerState = LEVEL2; - else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; + // *** According to the architecture, we should + // fault upon finding a superpage that is misaligned or has 0 + // access bit. The following commented line of code is + // supposed to perform that check. However, it is untested. + else if (ValidPTE && LeafPTE && ~BadGigapage) NextWalkerState = LEAF; + // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** If you test the above line, delete this line else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL1; else NextWalkerState = FAULT; LEVEL1: if (~MMUReady) NextWalkerState = LEVEL1; - // else if (~ValidPTE || (LeafPTE && BadMegapage)) - // NextWalkerState = FAULT; - // *** Leave megapage implementation for later - else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; + // *** According to the architecture, we should + // fault upon finding a superpage that is misaligned or has 0 + // access bit. The following commented line of code is + // supposed to perform that check. However, it is untested. + else if (ValidPTE && LeafPTE && ~BadMegapage) NextWalkerState = LEAF; + // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** If you test the above line, delete this line else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0; else NextWalkerState = FAULT; LEVEL0: if (~MMUReady) NextWalkerState = LEVEL0; @@ -296,20 +262,20 @@ module pagetablewalker ( assign VPN2 = TranslationVAdr[38:30]; assign VPN1 = TranslationVAdr[29:21]; - assign VPN0 = TranslationVAdr[20:12]; // *** could optimize by not passing offset? + assign VPN0 = TranslationVAdr[20:12]; - // *** Should translate this flop block into our flop module notation always_comb begin // default values TranslationPAdr = '0; PageTableEntry = '0; PageType = '0; - MMUTranslationComplete = '0; DTLBWriteM = '0; ITLBWriteF = '0; WalkerInstrPageFaultF = '0; WalkerLoadPageFaultM = '0; WalkerStorePageFaultM = '0; + + // The MMU defaults to stalling the processor MMUStall = '1; case (NextWalkerState) @@ -331,13 +297,12 @@ module pagetablewalker ( PageTableEntry = CurrentPTE; PageType = (WalkerState == LEVEL2) ? 2'b11 : ((WalkerState == LEVEL1) ? 2'b01 : 2'b00); - MMUTranslationComplete = '1; DTLBWriteM = DTLBMissM; ITLBWriteF = ~DTLBMissM; // Prefer data over instructions end FAULT: begin + // Keep physical address alive to prevent HADDR dropping to 0 TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; - MMUTranslationComplete = '1; WalkerInstrPageFaultF = ~DTLBMissM; WalkerLoadPageFaultM = DTLBMissM && ~MemStore; WalkerStorePageFaultM = DTLBMissM && MemStore; diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index 24a04940..7ed594e4 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -129,6 +129,7 @@ module tlb #(parameter ENTRY_BITS = 3, assign Translate = SvMode & (PrivilegeModeW != `M_MODE); // 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; @@ -179,7 +180,6 @@ module tlb #(parameter ENTRY_BITS = 3, end endgenerate - // *** Not the cleanest solution. // The highest segment of the physical page number has some extra bits // than the highest segment of the virtual page number. localparam EXTRA_PHYSICAL_BITS = `PPN_HIGH_SEGMENT_BITS - `VPN_SEGMENT_BITS; diff --git a/wally-pipelined/src/mmu/tlb_rand.sv b/wally-pipelined/src/mmu/tlb_rand.sv deleted file mode 100644 index afb0bb2c..00000000 --- a/wally-pipelined/src/mmu/tlb_rand.sv +++ /dev/null @@ -1,35 +0,0 @@ -/////////////////////////////////////////// -// tlb_rand.sv -// -// Written: jtorrey@hmc.edu & tfleming@hmc.edu 16 February 2021 -// Modified: -// -// Purpose: Outputs a random index for writing to the 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. -/////////////////////////////////////////// - -module tlb_rand #(parameter ENTRY_BITS = 3) ( - input clk, reset, - output [ENTRY_BITS-1:0] WriteIndex -); - - logic [31:0] data; - assign data = 32'b0; - assign WriteIndex = data[ENTRY_BITS-1:0]; - -endmodule diff --git a/wally-pipelined/src/privileged/pmpadrdec.sv b/wally-pipelined/src/privileged/pmpadrdec.sv index cbcc511b..1e2a14a1 100644 --- a/wally-pipelined/src/privileged/pmpadrdec.sv +++ b/wally-pipelined/src/privileged/pmpadrdec.sv @@ -71,7 +71,7 @@ module pmpadrdec ( generate if (`XLEN == 32 || `XLEN == 64) begin // priority encoder to translate address to range - // *** We'd like to replace this with a + // *** We'd like to replace this with a better priority encoder // *** We should not be truncating 64 bit physical addresses to 32 bits... always_comb casez (CurrentPMPAdr[31:0]) diff --git a/wally-pipelined/src/privileged/pmpchecker.sv b/wally-pipelined/src/privileged/pmpchecker.sv index f1babc71..261475a4 100644 --- a/wally-pipelined/src/privileged/pmpchecker.sv +++ b/wally-pipelined/src/privileged/pmpchecker.sv @@ -150,17 +150,6 @@ module pmpchecker ( Match && L_Bit && InvalidRead : EnforcePMP && InvalidRead; -/* - assign PMPInstrAccessFaultF = 1'b0; - assign PMPStoreAccessFaultM = 1'b0; - assign PMPLoadAccessFaultM = 1'b0; -*/ - - /* - If no PMP entry matches an M-mode access, the access succeeds. If no PMP entry matches an -S-mode or U-mode access, but at least one PMP entry is implemented, the access fails. -*/ - assign PMPSquashBusAccess = PMPInstrAccessFaultF || PMPLoadAccessFaultM || PMPStoreAccessFaultM; endmodule