diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index 8aaf6570..2741f958 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -88,6 +88,8 @@ module tlb #(parameter ENTRY_BITS = 3, output logic TLBPageFault ); + localparam NENTRIES = 2**ENTRY_BITS; + logic Translate; logic TLBAccess, ReadAccess, WriteAccess; @@ -95,9 +97,8 @@ module tlb #(parameter ENTRY_BITS = 3, logic [`SVMODE_BITS-1:0] SvMode; logic [1:0] EffectivePrivilegeMode; // privilege mode, possibly modified by MPRV - // Index (currently random) to write the next TLB entry - logic [ENTRY_BITS-1:0] WriteIndex; - logic [(2**ENTRY_BITS)-1:0] WriteLines, WriteEnables; // used as the one-hot encoding of WriteIndex + //logic [ENTRY_BITS-1:0] WriteIndex; + logic [NENTRIES-1:0] ReadLines, WriteLines, WriteEnables; // used as the one-hot encoding of WriteIndex // Sections of the virtual and physical addresses logic [`VPN_BITS-1:0] VirtualPageNumber; @@ -113,7 +114,7 @@ module tlb #(parameter ENTRY_BITS = 3, logic PTE_U, PTE_X, PTE_W, PTE_R; // Pattern location in the CAM and type of page hit - logic [ENTRY_BITS-1:0] VPNIndex; + //ogic [ENTRY_BITS-1:0] VPNIndex; logic [1:0] HitPageType; // Whether the virtual address has a match in the CAM @@ -125,7 +126,7 @@ module tlb #(parameter ENTRY_BITS = 3, assign Translate = (SvMode != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~ DisableTranslation; // Decode the integer encoded WriteIndex into the one-hot encoded WriteLines - decoder #(ENTRY_BITS) writedecoder(WriteIndex, WriteLines); + //decoder #(ENTRY_BITS) writedecoder(WriteIndex, WriteLines); assign WriteEnables = WriteLines & {(2**ENTRY_BITS){TLBWrite}}; // The bus width is always the largest it could be for that XLEN. For example, vpn will be 36 bits wide in rv64 diff --git a/wally-pipelined/src/mmu/tlbcam.sv b/wally-pipelined/src/mmu/tlbcam.sv index 07ec38ff..f10442cd 100644 --- a/wally-pipelined/src/mmu/tlbcam.sv +++ b/wally-pipelined/src/mmu/tlbcam.sv @@ -37,7 +37,8 @@ module tlbcam #(parameter ENTRY_BITS = 3, input logic TLBFlush, input logic [2**ENTRY_BITS-1:0] WriteEnables, - output logic [ENTRY_BITS-1:0] VPNIndex, + //output logic [ENTRY_BITS-1:0] VPNIndex, + output logic [2**ENTRY_BITS-1:0] ReadLines, output logic [1:0] HitPageType, output logic CAMHit ); @@ -56,16 +57,16 @@ module tlbcam #(parameter ENTRY_BITS = 3, tlbcamline #(KEY_BITS, SEGMENT_BITS) camlines[NENTRIES-1:0]( .CAMLineWrite(WriteEnables), - .PageType(PageTypeList), - .Match(Matches), + .MatchedPageType(PageTypeList), // *** change name to agree + .Match(ReadLines), // *** change name to agree .*); // In case there are multiple matches in the CAM, select only one // *** it might be guaranteed that the CAM will never have multiple matches. // If so, this is just an encoder - priorityencoder #(ENTRY_BITS) matchencoder(Matches, VPNIndex); + //priorityencoder #(ENTRY_BITS) matchencoder(Matches, VPNIndex); - assign CAMHit = |Matches & ~TLBFlush; - assign HitPageType = PageTypeList[VPNIndex]; + assign CAMHit = |ReadLines & ~TLBFlush; + assign HitPageType = PageTypeList.or; // applies OR to elements of the (NENTRIES x 2) array to get 2-bit result endmodule diff --git a/wally-pipelined/src/mmu/tlbcamline.sv b/wally-pipelined/src/mmu/tlbcamline.sv index 3e882cf1..2eaa3a01 100644 --- a/wally-pipelined/src/mmu/tlbcamline.sv +++ b/wally-pipelined/src/mmu/tlbcamline.sv @@ -50,13 +50,14 @@ module tlbcamline #(parameter KEY_BITS = 20, // PageType == 2'b01 --> megapage // PageType == 2'b10 --> gigapage // PageType == 2'b11 --> terapage - output logic [1:0] PageType, // *** should this be the stored version or the always updated one? + output logic [1:0] MatchedPageType, // *** should this be the stored version or the always updated one? output logic Match ); // This entry has KEY_BITS for the key plus one valid bit. logic Valid; logic [KEY_BITS-1:0] Key; + logic [1:0] PageType; // Split up key and query into sections for each page table level. @@ -98,6 +99,7 @@ module tlbcamline #(parameter KEY_BITS = 20, // On a write, update the type of the page referred to by this line. flopenr #(2) pagetypeflop(clk, reset, CAMLineWrite, PageTypeWriteVal, PageType); + assign MatchedPageType = PageType & {2{Match}}; //mux2 #(2) pagetypemux(StoredPageType, PageTypeWrite, CAMLineWrite, PageType); // On a write, set the valid bit high and update the stored key. diff --git a/wally-pipelined/src/mmu/tlblru.sv b/wally-pipelined/src/mmu/tlblru.sv index e86598f7..f1ac4db2 100644 --- a/wally-pipelined/src/mmu/tlblru.sv +++ b/wally-pipelined/src/mmu/tlblru.sv @@ -28,11 +28,9 @@ module tlblru #(parameter ENTRY_BITS = 3) ( input logic clk, reset, input logic TLBWrite, input logic TLBFlush, - input logic [ENTRY_BITS-1:0] VPNIndex, + input logic [2**ENTRY_BITS-1:0] ReadLines, input logic CAMHit, - input logic [2**ENTRY_BITS-1:0] WriteLines, - - output logic [ENTRY_BITS-1:0] WriteIndex + output logic [2**ENTRY_BITS-1:0] WriteLines ); localparam NENTRIES = 2**ENTRY_BITS; @@ -41,26 +39,27 @@ module tlblru #(parameter ENTRY_BITS = 3) ( logic [NENTRIES-1:0] RUBits, RUBitsNext, RUBitsAccessed; // One-hot encodings of which line is being accessed - logic [NENTRIES-1:0] ReadLineOneHot, AccessLineOneHot; + logic [NENTRIES-1:0] AccessLines; // High if the next access causes all RU bits to be 1 logic AllUsed; // Convert indices to one-hot encodings - decoder #(ENTRY_BITS) readdecoder(VPNIndex, ReadLineOneHot); + //decoder #(ENTRY_BITS) readdecoder(VPNIndex, ReadLineOneHot); // Find the first line not recently used - priorityencoder #(ENTRY_BITS) firstnru(~RUBits, WriteIndex); + tlbpriority #(NENTRIES) nru(~RUBits, WriteLines); + //priorityencoder #(ENTRY_BITS) firstnru(~RUBits, WriteIndex); // Access either the hit line or written line - assign AccessLineOneHot = (TLBWrite) ? WriteLines : ReadLineOneHot; + assign AccessLines = TLBWrite ? WriteLines : ReadLines; // Raise the bit of the recently accessed line - assign RUBitsAccessed = AccessLineOneHot | RUBits; + assign RUBitsAccessed = AccessLines | RUBits; // Determine whether we need to reset the RU bits to all zeroes - assign AllUsed = &(RUBitsAccessed); - assign RUBitsNext = (AllUsed) ? AccessLineOneHot : RUBitsAccessed; + assign AllUsed = &RUBitsAccessed; + assign RUBitsNext = AllUsed ? AccessLines : RUBitsAccessed; // *** seems it should set to 0, not to AccessLines // Update LRU state on any TLB hit or write flopenrc #(NENTRIES) lrustate(clk, reset, TLBFlush, (CAMHit || TLBWrite), diff --git a/wally-pipelined/src/mmu/priorityencoder.sv b/wally-pipelined/src/mmu/tlbpriority.sv similarity index 62% rename from wally-pipelined/src/mmu/priorityencoder.sv rename to wally-pipelined/src/mmu/tlbpriority.sv index 44ce88da..a061f622 100644 --- a/wally-pipelined/src/mmu/priorityencoder.sv +++ b/wally-pipelined/src/mmu/tlbpriority.sv @@ -1,16 +1,15 @@ /////////////////////////////////////////// -// priorityencoder.sv +// tlbpriority.sv // // Written: tfleming@hmc.edu & jtorrey@hmc.edu 7 April 2021 -// Based on implementation from https://www.allaboutcircuits.com/ip-cores/communication-controller/priority-encoder/ -// *** Give proper LGPL attribution for above source // Modified: Teo Ene 15 Apr 2021: // Temporarily removed paramterized priority encoder for non-parameterized one // To get synthesis working quickly // Kmacsaigoren@hmc.edu 28 May 2021: // Added working version of parameterized priority encoder. +// David_Harris@Hmc.edu switched to one-hot output // -// Purpose: One-hot encoding to binary encoder +// Purpose: Priority circuit to choose most significant one-hot output // // A component of the Wally configurable RISC-V project. // @@ -31,35 +30,20 @@ `include "wally-config.vh" -module tlbpriority #(parameter BINARY_BITS = 3) ( - input logic [2**BINARY_BITS - 1:0] onehot, - output logic [BINARY_BITS - 1:0] binary +module tlbpriority #(parameter ENTRIES = 8) ( + input logic [ENTRIES-1:0] a, + output logic [ENTRIES-1:0] y ); + // verilator lint_off UNOPTFLAT + logic [ENTRIES-1:0] nolower; - integer i; - always_comb begin - binary = 0; - for (i = 0; i < 2**BINARY_BITS; i++) begin - // verilator lint_off WIDTH - if (onehot[i]) binary = i; // prioritizes the most significant bit - // verilator lint_on WIDTH - end - end - // *** triple check synthesizability here - - // Ideally this mimics the following: - /* - always_comb begin - casex (one_hot) - 1xx ... x: binary = BINARY_BITS - 1; - 01x ... x: binary = BINARY_BITS - 2; - 001 ... x: binary = BINARY_BITS - 3; - - {...} - - 00 ... 1xx: binary = 2; - 00 ... 01x: binary = 1; - 00 ... 001: binary = 0; - end - */ + // generate thermometer code mask + genvar i; + generate + assign nolower[0] = 1; + for (i=1; i