diff --git a/wally-pipelined/src/mmu/pagetablewalker.sv b/wally-pipelined/src/mmu/pagetablewalker.sv index 8c524fbd1..85a76482a 100644 --- a/wally-pipelined/src/mmu/pagetablewalker.sv +++ b/wally-pipelined/src/mmu/pagetablewalker.sv @@ -31,38 +31,22 @@ module pagetablewalker ( - // Control signals input logic clk, reset, - input logic [`XLEN-1:0] SATP_REGW, - - // Signals from TLBs (addresses to translate) - input logic [`XLEN-1:0] PCF, MemAdrM, - input logic ITLBMissF, DTLBMissM, - input logic [1:0] MemRWM, - - // Outputs to the TLBs (PTEs to write) - output logic [`XLEN-1:0] PTE, //PageTableEntryM, - output logic [1:0] PageType, - output logic ITLBWriteF, DTLBWriteM, - output logic SelPTW, - - - // *** modify to send to LSU // *** KMG: These are inputs/results from the ahblite whose addresses should have already been checked, so I don't think they need to be sent through the LSU - input logic [`XLEN-1:0] HPTWReadPTE, - input logic HPTWStall, - - // *** modify to send to LSU - output logic [`XLEN-1:0] HPTWPAdrE, // this probalby should be `PA_BITS wide - output logic [`XLEN-1:0] HPTWPAdrM, // this probalby should be `PA_BITS wide - output logic HPTWRead, - - - // Faults - output logic WalkerInstrPageFaultF, - output logic WalkerLoadPageFaultM, - output logic WalkerStorePageFaultM - ); - + input logic [`XLEN-1:0] SATP_REGW, // includes SATP.MODE to determine number of levels in page table + input logic [`XLEN-1:0] PCF, MemAdrM, // addresses to translate + input logic ITLBMissF, DTLBMissM, // TLB Miss + input logic [1:0] MemRWM, // 10 = read, 01 = write + input logic [`XLEN-1:0] HPTWReadPTE, // page table entry from LSU + input logic HPTWStall, // stall from LSU + output logic [`XLEN-1:0] PTE, // page table entry to TLBs + output logic [1:0] PageType, // page type to TLBs + output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry + output logic SelPTW, // LSU Arbiter should select signals from the PTW rather than from the IEU + output logic [`XLEN-1:0] HPTWPAdrE, // *** this really needs to be 34 bits for RV32 and 64 bits for RV64. Impacts lots of stuff in LSU and D$. On Ross's list to investigate. 7/17/21 + output logic [`XLEN-1:0] HPTWPAdrM, // *** same + output logic HPTWRead, // HPTW requesting to read memory + output logic WalkerInstrPageFaultF, WalkerLoadPageFaultM,WalkerStorePageFaultM // faults +); generate if (`MEM_VIRTMEM) begin @@ -96,13 +80,13 @@ module pagetablewalker // Determine which address to translate assign TranslationVAdr = DTLBWalk ? MemAdrM : PCF; - - flop #(`XLEN) HPTWPAdrMReg(clk, HPTWPAdrE, HPTWPAdrM); - flopenrc #(1) TLBMissMReg(clk, reset, EndWalk, StartWalk | EndWalk, DTLBMissM, DTLBWalk); - flopenl #(.TYPE(statetype)) WalkerStateReg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState); - flopenr #(`XLEN) PTEReg(clk, reset, PRegEn, HPTWReadPTE, PTE); // Capture page table entry from data cache - assign CurrentPPN = PTE[`PPN_BITS+9:10]; + assign CurrentPPN = PTE[`PPN_BITS+9:10]; + // State flops + flop #(`XLEN) HPTWPAdrMReg(clk, HPTWPAdrE, HPTWPAdrM); // *** perhaps HPTW should just send PAdrE, and LSU can latch it as necessary + flopenrc #(1) TLBMissMReg(clk, reset, EndWalk, StartWalk | EndWalk, DTLBMissM, DTLBWalk); // track whether walk is for DTLB or ITLB + flopenr #(`XLEN) PTEReg(clk, reset, PRegEn, HPTWReadPTE, PTE); // Capture page table entry from data cache + // Assign PTE descriptors common across all XLEN values // For non-leaf PTEs, D, A, U bits are reserved and ignored. They do not cause faults while walking the page table assign {Executable, Writable, Readable, Valid} = PTE[3:0]; @@ -137,7 +121,7 @@ module pagetablewalker endcase // TranslationPAdr mux - if (`XLEN==32) begin + if (`XLEN==32) begin // RV32 logic [9:0] VPN1, VPN0; assign VPN1 = TranslationVAdr[31:22]; assign VPN0 = TranslationVAdr[21:12]; @@ -145,7 +129,7 @@ module pagetablewalker case (WalkerState) LEVEL1_SET_ADR: TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00}; LEVEL1_READ: TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00}; - LEVEL1: if (NextWalkerState == LEAF) TranslationPAdr = {2'b00, TranslationVAdr[31:0]}; // ***check this and similar in LEVEL0 and LEAF + LEVEL1: if (NextWalkerState == LEAF) TranslationPAdr = {2'b00, TranslationVAdr[31:0]}; // *** 7/17/21 Ross will check this and similar in LEVEL0 and LEAF else TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; LEVEL0_SET_ADR: TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; LEVEL0_READ: TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; @@ -153,7 +137,7 @@ module pagetablewalker LEAF: TranslationPAdr = {2'b00, TranslationVAdr[31:0]}; default: TranslationPAdr = 0; // cause seg fault if this is improperly used endcase - end else begin + end else begin // RV64 logic [8:0] VPN3, VPN2, VPN1, VPN0; assign VPN3 = TranslationVAdr[47:39]; assign VPN2 = TranslationVAdr[38:30]; @@ -196,7 +180,10 @@ module pagetablewalker end // Page Table Walker FSM - // ***Is there a w ay to reduce the number of cycles needed to do the walk? + // If the setup time on the D$ RAM is short, it should be possible to merge the LEVELx_READ and LEVELx states + // to decrease the latency of the HPTW. However, if the D$ is a cycle limiter, it's better to leave the + // HPTW as shown below to keep the D$ setup time out of the critical path. + flopenl #(.TYPE(statetype)) WalkerStateReg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState); always_comb case (WalkerState) IDLE: if (StartWalk) NextWalkerState = InitialWalkerState; @@ -231,14 +218,9 @@ module pagetablewalker NextWalkerState = IDLE; // should never be reached end endcase - end else begin - assign HPTWPAdrE = 0; - assign HPTWRead = 0; - assign WalkerInstrPageFaultF = 0; - assign WalkerLoadPageFaultM = 0; - assign WalkerStorePageFaultM = 0; - assign SelPTW = 0; + end else begin // No Virtual memory supported; tie HPTW outputs to 0 + assign HPTWPAdrE = 0; assign HPTWRead = 0; assign SelPTW = 0; + assign WalkerInstrPageFaultF = 0; assign WalkerLoadPageFaultM = 0; assign WalkerStorePageFaultM = 0; end endgenerate - endmodule