forked from Github_Repos/cvw
		
	Reorganized TLB to use one-hot read/write select signals to eliminate decoders and encoders
This commit is contained in:
		
							parent
							
								
									c281539f36
								
							
						
					
					
						commit
						8337d6df68
					
				@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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.
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
 | 
			
		||||
@ -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<ENTRIES; i++) 
 | 
			
		||||
      assign nolower[i] = nolower[i-1] & ~a[i-1];
 | 
			
		||||
  endgenerate
 | 
			
		||||
  // verilator lint_on UNOPTFLAT
 | 
			
		||||
  assign y = a & nolower;
 | 
			
		||||
endmodule
 | 
			
		||||
@ -29,11 +29,11 @@
 | 
			
		||||
 | 
			
		||||
module tlbram #(parameter ENTRY_BITS = 3) (
 | 
			
		||||
  input logic                       clk, reset,
 | 
			
		||||
  input logic [ENTRY_BITS-1:0]      VPNIndex,  // Index to read from
 | 
			
		||||
  //input logic [ENTRY_BITS-1:0]      VPNIndex,  // Index to read from
 | 
			
		||||
//  input logic [ENTRY_BITS-1:0]      WriteIndex, // *** unused?
 | 
			
		||||
  input logic [`XLEN-1:0]           PTEWriteVal,
 | 
			
		||||
//  input logic                       TLBWrite,
 | 
			
		||||
  input logic [2**ENTRY_BITS-1:0]   WriteEnables,
 | 
			
		||||
  input logic [2**ENTRY_BITS-1:0]   ReadLines, WriteEnables,
 | 
			
		||||
 | 
			
		||||
  output logic [`PPN_BITS-1:0]      PhysicalPageNumber,
 | 
			
		||||
  output logic [7:0]                PTEAccessBits
 | 
			
		||||
@ -41,14 +41,42 @@ module tlbram #(parameter ENTRY_BITS = 3) (
 | 
			
		||||
 | 
			
		||||
  localparam NENTRIES = 2**ENTRY_BITS;
 | 
			
		||||
 | 
			
		||||
  logic [`XLEN-1:0] ram [NENTRIES-1:0];
 | 
			
		||||
  //logic [`XLEN-1:0] ram[NENTRIES-1:0];
 | 
			
		||||
  logic [`XLEN-1:0] RamRead[NENTRIES-1:0];
 | 
			
		||||
  logic [`XLEN-1:0] PageTableEntry;
 | 
			
		||||
 | 
			
		||||
//  logic [ENTRY_BITS-1:0] VPNIndex;
 | 
			
		||||
 | 
			
		||||
  // Generate a flop for every entry in the RAM
 | 
			
		||||
  flopenr #(`XLEN) pteflops[NENTRIES-1:0](clk, reset, WriteEnables, PTEWriteVal, ram);
 | 
			
		||||
  
 | 
			
		||||
  assign PageTableEntry = ram[VPNIndex];
 | 
			
		||||
  //flopenr #(`XLEN) pteflops[NENTRIES-1:0](clk, reset, WriteEnables, PTEWriteVal, ram);
 | 
			
		||||
  tlbramline #(`XLEN) tlblineram[NENTRIES-1:0](clk, reset, ReadLines, WriteEnables, PTEWriteVal, RamRead);
 | 
			
		||||
/*
 | 
			
		||||
  // temporary code for read
 | 
			
		||||
  // verilator lint_off WIDTH
 | 
			
		||||
  integer i;
 | 
			
		||||
  generate
 | 
			
		||||
    always_comb begin
 | 
			
		||||
      VPNIndex = 0;
 | 
			
		||||
      for (i=0; i<NENTRIES; i++)
 | 
			
		||||
        if (ReadLines[i]) VPNIndex = i;
 | 
			
		||||
    end
 | 
			
		||||
  endgenerate
 | 
			
		||||
  // verilator lint_on WIDTH
 | 
			
		||||
*/
 | 
			
		||||
  //assign PageTableEntry = ram[VPNIndex]; // *** need to fix
 | 
			
		||||
  assign PageTableEntry = RamRead.or; // OR each column of RAM read to read PTE
 | 
			
		||||
  assign PTEAccessBits = PageTableEntry[7:0];
 | 
			
		||||
  assign PhysicalPageNumber = PageTableEntry[`PPN_BITS+9:10];
 | 
			
		||||
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module tlbramline #(parameter WIDTH)
 | 
			
		||||
  (input  logic             clk, reset,
 | 
			
		||||
   input  logic             re, we,
 | 
			
		||||
   input  logic [WIDTH-1:0] d,
 | 
			
		||||
   output logic [WIDTH-1:0] q);
 | 
			
		||||
 | 
			
		||||
   logic [WIDTH-1:0] line;
 | 
			
		||||
   flopenr #(`XLEN) pteflop(clk, reset, we, d, line);
 | 
			
		||||
   assign q = re ? line : 0;
 | 
			
		||||
endmodule
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user