From fc39535e4e170c008bcf29c15b5a2b7271a1edbb Mon Sep 17 00:00:00 2001 From: Thomas Fleming Date: Thu, 8 Apr 2021 03:24:10 -0400 Subject: [PATCH] Refactor TLB into multiple files --- wally-pipelined/src/mmu/tlb.sv | 113 ++++------------------------ wally-pipelined/src/mmu/tlb_cam.sv | 72 ++++++++++++++++++ wally-pipelined/src/mmu/tlb_ram.sv | 60 +++++++++++++++ wally-pipelined/src/mmu/tlb_rand.sv | 35 +++++++++ 4 files changed, 182 insertions(+), 98 deletions(-) create mode 100644 wally-pipelined/src/mmu/tlb_cam.sv create mode 100644 wally-pipelined/src/mmu/tlb_ram.sv create mode 100644 wally-pipelined/src/mmu/tlb_rand.sv diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index 194b1c22f..066e0c428 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -50,7 +50,6 @@ /* *** TODO: * - add LRU algorithm (select the write index based on which entry was used * least recently) - * - refactor modules into multiple files */ // The TLB will have 2**ENTRY_BITS total entries @@ -96,10 +95,8 @@ module tlb #(parameter ENTRY_BITS = 3) ( assign SvMode = SATP_REGW[63]; // currently just a boolean whether translation enabled end endgenerate - // *** Currently fake virtual memory being on for testing purposes - // *** DO NOT ENABLE UNLESS TESTING - // assign SvMode = 1; + // Whether translation should occur assign Translate = SvMode & (PrivilegeModeW != `M_MODE); // *** If we want to support multiple virtual memory modes (ie sv39 AND sv48), @@ -113,18 +110,18 @@ module tlb #(parameter ENTRY_BITS = 3) ( // 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; + + // Sections of the page table entry logic [7:0] PTEAccessBits; logic [11:0] PageOffset; - logic [`PA_BITS-1:0] PhysicalAddressFull; // Pattern location in the CAM and type of page hit logic [ENTRY_BITS-1:0] VPNIndex; logic [1:0] HitPageType; - // RAM access location - logic [ENTRY_BITS-1:0] EntryIndex; - - logic CAMHit; + // Whether the virtual address has a match in the CAM + logic CAMHit; assign VirtualPageNumber = VirtualAddress[`VPN_BITS+11:12]; assign PageOffset = VirtualAddress[11:0]; @@ -138,17 +135,26 @@ module tlb #(parameter ENTRY_BITS = 3) ( // *** check whether access is allowed, otherwise fault assign TLBPageFault = 0; // *** temporary + // *** 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; + // Replace segments of the virtual page number with segments of the physical + // page number. For 4 KB pages, the entire virtual page number is replaced. + // For superpages, some segments are considered offsets into a larger page. page_number_mixer #(`PPN_BITS, `PPN_HIGH_SEGMENT_BITS) physical_mixer(PhysicalPageNumber, {{EXTRA_PHYSICAL_BITS{1'b0}}, VirtualPageNumber}, HitPageType, PhysicalPageNumberMixed); + // Provide physical address only on TLBHits to cause catastrophic errors if + // garbage address is used. assign PhysicalAddressFull = (TLBHit) ? {PhysicalPageNumberMixed, PageOffset} : '0; + // Output the hit physical address if translation is currently on. generate if (`XLEN == 32) begin mux2 #(`XLEN) addressmux(VirtualAddress, PhysicalAddressFull[31:0], Translate, PhysicalAddress); @@ -160,92 +166,3 @@ module tlb #(parameter ENTRY_BITS = 3) ( assign TLBHit = CAMHit & TLBAccess; assign TLBMiss = ~TLBHit & ~TLBFlush & Translate & TLBAccess; endmodule - -// *** use actual flop notation instead of initialbegin and alwaysff -module tlb_ram #(parameter ENTRY_BITS = 3) ( - input clk, reset, - input [ENTRY_BITS-1:0] VPNIndex, // Index to read from - input [ENTRY_BITS-1:0] WriteIndex, - input [`XLEN-1:0] PageTableEntryWrite, - input TLBWrite, - - output [`PPN_BITS-1:0] PhysicalPageNumber, - output [7:0] PTEAccessBits -); - - localparam NENTRIES = 2**ENTRY_BITS; - - logic [`XLEN-1:0] ram [0:NENTRIES-1]; - logic [`XLEN-1:0] PageTableEntry; - always @(posedge clk) begin - if (TLBWrite) ram[WriteIndex] <= PageTableEntryWrite; - end - - assign PageTableEntry = ram[VPNIndex]; - assign PTEAccessBits = PageTableEntry[7:0]; - assign PhysicalPageNumber = PageTableEntry[`PPN_BITS+9:10]; - - 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, - parameter HIGH_SEGMENT_BITS = 10) ( - input clk, reset, - input [KEY_BITS-1:0] VirtualPageNumber, - input [1:0] PageTypeWrite, - input [ENTRY_BITS-1:0] WriteIndex, - input TLBWrite, - input TLBFlush, - output [ENTRY_BITS-1:0] VPNIndex, - output [1:0] HitPageType, - output CAMHit -); - - localparam NENTRIES = 2**ENTRY_BITS; - - logic [NENTRIES-1:0] CAMLineWrite; - logic [1:0] PageTypeList [0:NENTRIES-1]; - logic [NENTRIES-1:0] Matches; - - // Determine which CAM line should be written, based on a binary index - decoder #(ENTRY_BITS) decoder(WriteIndex, CAMLineWrite); - - // Create NENTRIES CAM lines, each of which will independently consider - // whether the requested virtual address is a match. Each line stores the - // original virtual page number from when the address was written, regardless - // of page type. However, matches are determined based on a subset of the - // page number segments. - generate - genvar i; - for (i = 0; i < NENTRIES; i++) begin - cam_line #(KEY_BITS, HIGH_SEGMENT_BITS) cam_line( - .CAMLineWrite(CAMLineWrite[i] && TLBWrite), - .PageType(PageTypeList[i]), - .Match(Matches[i]), - .*); - end - endgenerate - - // In case there are multiple matches in the CAM, select only one - priority_encoder #(ENTRY_BITS) match_priority(Matches, VPNIndex); - - assign CAMHit = |Matches & ~TLBFlush; - assign HitPageType = PageTypeList[VPNIndex]; - -endmodule - -module tlb_rand #(parameter ENTRY_BITS = 3) ( - input clk, reset, - output [ENTRY_BITS-1:0] WriteIndex -); - - logic [31:0] data; - assign data = $urandom; - assign WriteIndex = data[ENTRY_BITS-1:0]; - -endmodule diff --git a/wally-pipelined/src/mmu/tlb_cam.sv b/wally-pipelined/src/mmu/tlb_cam.sv new file mode 100644 index 000000000..ca25f2b51 --- /dev/null +++ b/wally-pipelined/src/mmu/tlb_cam.sv @@ -0,0 +1,72 @@ +/////////////////////////////////////////// +// tlb_cam.sv +// +// Written: jtorrey@hmc.edu 16 February 2021 +// Modified: +// +// Purpose: Stores virtual page numbers with cached translations. +// Determines whether a given virtual page number is in 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_cam #(parameter ENTRY_BITS = 3, + parameter KEY_BITS = 20, + parameter HIGH_SEGMENT_BITS = 10) ( + input clk, reset, + input [KEY_BITS-1:0] VirtualPageNumber, + input [1:0] PageTypeWrite, + input [ENTRY_BITS-1:0] WriteIndex, + input TLBWrite, + input TLBFlush, + output [ENTRY_BITS-1:0] VPNIndex, + output [1:0] HitPageType, + output CAMHit +); + + localparam NENTRIES = 2**ENTRY_BITS; + + logic [NENTRIES-1:0] CAMLineWrite; + logic [1:0] PageTypeList [0:NENTRIES-1]; + logic [NENTRIES-1:0] Matches; + + // Determine which CAM line should be written, based on a binary index + decoder #(ENTRY_BITS) decoder(WriteIndex, CAMLineWrite); + + // Create NENTRIES CAM lines, each of which will independently consider + // whether the requested virtual address is a match. Each line stores the + // original virtual page number from when the address was written, regardless + // of page type. However, matches are determined based on a subset of the + // page number segments. + generate + genvar i; + for (i = 0; i < NENTRIES; i++) begin + cam_line #(KEY_BITS, HIGH_SEGMENT_BITS) cam_line( + .CAMLineWrite(CAMLineWrite[i] && TLBWrite), + .PageType(PageTypeList[i]), + .Match(Matches[i]), + .*); + end + endgenerate + + // In case there are multiple matches in the CAM, select only one + priority_encoder #(ENTRY_BITS) match_priority(Matches, VPNIndex); + + assign CAMHit = |Matches & ~TLBFlush; + assign HitPageType = PageTypeList[VPNIndex]; + +endmodule diff --git a/wally-pipelined/src/mmu/tlb_ram.sv b/wally-pipelined/src/mmu/tlb_ram.sv new file mode 100644 index 000000000..059a9aa55 --- /dev/null +++ b/wally-pipelined/src/mmu/tlb_ram.sv @@ -0,0 +1,60 @@ +/////////////////////////////////////////// +// tlb_ram.sv +// +// Written: jtorrey@hmc.edu & tfleming@hmc.edu 16 February 2021 +// Modified: +// +// Purpose: Stores page table entries of cached address translations. +// Outputs the physical page number and access bits of the current +// virtual address on a TLB hit. +// +// 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" +`include "wally-constants.vh" + +// *** use actual flop notation instead of initialbegin and alwaysff +module tlb_ram #(parameter ENTRY_BITS = 3) ( + input clk, reset, + input [ENTRY_BITS-1:0] VPNIndex, // Index to read from + input [ENTRY_BITS-1:0] WriteIndex, + input [`XLEN-1:0] PageTableEntryWrite, + input TLBWrite, + + output [`PPN_BITS-1:0] PhysicalPageNumber, + output [7:0] PTEAccessBits +); + + localparam NENTRIES = 2**ENTRY_BITS; + + logic [`XLEN-1:0] ram [0:NENTRIES-1]; + logic [`XLEN-1:0] PageTableEntry; + always @(posedge clk) begin + if (TLBWrite) ram[WriteIndex] <= PageTableEntryWrite; + end + + assign PageTableEntry = ram[VPNIndex]; + assign PTEAccessBits = PageTableEntry[7:0]; + assign PhysicalPageNumber = PageTableEntry[`PPN_BITS+9:10]; + + initial begin + for (int i = 0; i < NENTRIES; i++) + ram[i] = `XLEN'b0; + end + +endmodule \ No newline at end of file diff --git a/wally-pipelined/src/mmu/tlb_rand.sv b/wally-pipelined/src/mmu/tlb_rand.sv new file mode 100644 index 000000000..68a5acad4 --- /dev/null +++ b/wally-pipelined/src/mmu/tlb_rand.sv @@ -0,0 +1,35 @@ +/////////////////////////////////////////// +// 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 = $urandom; + assign WriteIndex = data[ENTRY_BITS-1:0]; + +endmodule