diff --git a/wally-pipelined/src/tlb_toy/tlb_testbench.sv b/wally-pipelined/src/tlb_toy/tlb_testbench.sv index add65d3d..4e2c7199 100644 --- a/wally-pipelined/src/tlb_toy/tlb_testbench.sv +++ b/wally-pipelined/src/tlb_toy/tlb_testbench.sv @@ -2,19 +2,22 @@ module testbench(); logic clk, reset; // DUT inputs - logic [31:0] PCF; - logic [31:0] PageTableEntryF; - logic ITLBWriteF, ITLBFlushF; + logic [`XLEN-1:0] SATP; + logic [`XLEN-1:0] VirtualAddress; + logic [`XLEN-1:0] PageTableEntryWrite; + logic TLBWrite, TLBFlush; // DUT outputs - logic [31:0] PCPF; - logic ITLBMissF, ITLBHitF; + 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(.*); @@ -31,17 +34,17 @@ module testbench(); // apply test vectors on rising edge of clk always @(posedge clk) begin - #1; {PCF, PageTableEntryF, ITLBWriteF, ITLBFlushF, expected} = testvectors[vectornum]; + #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 ({PCPF, ITLBMissF, ITLBHitF} !== expected) begin // check result - $display("Error: PCF = %b, write = %b, data = %b, flush = %b", PCF, - ITLBWriteF, PageTableEntryF, ITLBFlushF); + 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)", - PCPF, ITLBMissF, ITLBHitF, expected); + PhysicalAddress, TLBMiss, TLBHit, expected); errors = errors + 1; end vectornum = vectornum + 1; diff --git a/wally-pipelined/src/tlb_toy/tlb_toy.sv b/wally-pipelined/src/tlb_toy/tlb_toy.sv index 43c94bab..cafc15fa 100644 --- a/wally-pipelined/src/tlb_toy/tlb_toy.sv +++ b/wally-pipelined/src/tlb_toy/tlb_toy.sv @@ -24,7 +24,7 @@ // OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /////////////////////////////////////////// -// `include "wally-config.vh" +`include "wally-config.vh" /** * sv32 specs @@ -49,126 +49,159 @@ /* *** TODO: * - add LRU algorithm (select the write index based on which entry was used * least recently) - * - rename signals to use .* notation in CAM and RAM */ -module tlb_toy ( - input clk, reset, +// 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 [31:0] PCF, + input [`XLEN-1:0] VirtualAddress, // Controls for writing a new entry to the TLB - input [31:0] PageTableEntryF, - input ITLBWriteF, + input [`XLEN-1:0] PageTableEntryWrite, + input TLBWrite, // Invalidate all TLB entries - input ITLBFlushF, + input TLBFlush, // Physical address outputs - output [31:0] PCPF, - output ITLBMissF, - output ITLBHitF + 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 [2:0] WriteIndexF; + logic [ENTRY_BITS-1:0] WriteIndex; // Sections of the virtual and physical addresses - logic [19:0] VirtualPageNumberF; - logic [21:0] PhysicalPageNumberF; - logic [11:0] PageOffsetF; - logic [33:0] PhysicalAddressF; + 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 [2:0] VPNIndexF; + logic [ENTRY_BITS-1:0] VPNIndex; // RAM access location - logic [2:0] ITLBEntryIndex; + logic [ENTRY_BITS-1:0] EntryIndex; // Page table entry matching the virtual address - logic [31:0] PTEMatchF; + logic [`XLEN-1:0] PageTableEntry; - assign VirtualPageNumberF = PCF[31:12]; - assign PageOffsetF = PCF[11:0]; + 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(VPNIndexF, WriteIndexF, ITLBWriteF, ITLBEntryIndex); + mux2 #(3) indexmux(VPNIndex, WriteIndex, TLBWrite, EntryIndex); // Currently use random replacement algorithm - rand3 rdm(clk, reset, WriteIndexF); + tlb_rand rdm(.*); - ram8x32 ram(clk, reset, ITLBEntryIndex, PageTableEntryF, ITLBWriteF, PTEMatchF); - cam8x21 cam(clk, reset, ITLBWriteF, VirtualPageNumberF, WriteIndexF, - ITLBFlushF, VPNIndexF, ITLBHitF); + tlb_ram #(ENTRY_BITS) ram(.*); + tlb_cam #(ENTRY_BITS, ARCH.VPN_BITS) cam(.*); always_comb begin - assign PhysicalPageNumberF = PTEMatchF[31:10]; + assign PhysicalPageNumber = PageTableEntry[ARCH.PPN_BITS+9:10]; - if (ITLBHitF) begin - assign PhysicalAddressF = {PhysicalPageNumberF, PageOffsetF}; + if (TLBHit) begin + assign PhysicalAddressFull = {PhysicalPageNumber, PageOffset}; end else begin - assign PhysicalAddressF = 34'b0; + 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 - assign PCPF = PhysicalAddressF[31:0]; - assign ITLBMissF = ~ITLBHitF & ~(ITLBWriteF | ITLBFlushF); + 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 -// *** Add parameter for number of tlb lines (currently 8) -module ram8x32 ( - input clk, reset, - input [2:0] address, - input [31:0] data, - input we, +module tlb_ram #(parameter ENTRY_BITS = 3) ( + input clk, reset, + input [ENTRY_BITS-1:0] EntryIndex, + input [`XLEN-1:0] PageTableEntryWrite, + input TLBWrite, - output [31:0] out_data + output [`XLEN-1:0] PageTableEntry ); - logic [31:0] ram [0:7]; + localparam NENTRIES = 2**ENTRY_BITS; + + logic [`XLEN-1:0] ram [0:NENTRIES-1]; always @(posedge clk) begin - if (we) ram[address] <= data; + if (TLBWrite) ram[EntryIndex] <= PageTableEntryWrite; end - assign out_data = ram[address]; + assign PageTableEntry = ram[EntryIndex]; initial begin - for (int i = 0; i < 8; i++) - ram[i] = 32'h0; + for (int i = 0; i < NENTRIES; i++) + ram[i] = `XLEN'b0; end endmodule -module cam8x21 ( - input clk, reset, we, - input [19:0] pattern, - input [2:0] write_address, - input ITLBFlushF, - output [2:0] matched_address, - output match_found +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 ); - logic [20:0] ram [0:7]; - logic [7:0] match_line; + localparam NENTRIES = 2**ENTRY_BITS; - logic [2:0] matched_address_comb; - logic match_found_comb; + // 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 (we) ram[write_address] <= {1'b1,pattern}; - if (ITLBFlushF) begin - for (int i = 0; i < 8; i++) - ram[i][20] = 1'b0; + 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 = 3'b0; - for (int i = 0; i < 8; i++) begin - if (ram[i] == {1'b1,pattern} && !match_found_comb) begin + 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 @@ -178,31 +211,23 @@ module cam8x21 ( end end - assign matched_address = matched_address_comb; - assign match_found = match_found_comb & ~(we | ITLBFlushF); + assign VPNIndex = matched_address_comb; + assign TLBHit = match_found_comb & ~(TLBWrite | TLBFlush); initial begin - for (int i = 0; i < 8; i++) - ram[i] <= 0; + for (int i = 0; i < NENTRIES; i++) + ram[i] <= '0; end endmodule -module mux2 #(parameter WIDTH = 8) ( - input logic [WIDTH-1:0] d0, d1, - input logic s, - output logic [WIDTH-1:0] y); - - assign y = s ? d1 : d0; -endmodule - -module rand3 ( +module tlb_rand #(parameter ENTRY_BITS = 3) ( input clk, reset, - output [2:0] WriteIndexF + output [ENTRY_BITS:0] WriteIndex ); logic [31:0] data; assign data = $urandom; - assign WriteIndexF = data[2:0]; + assign WriteIndex = data[ENTRY_BITS:0]; endmodule