Fixed combo loop in between the page table walker and i/dtlb.

This commit is contained in:
Ross Thompson 2021-06-24 13:47:10 -05:00
parent aeeaf6d919
commit c02141697d

View File

@ -36,7 +36,7 @@
module pagetablewalker ( module pagetablewalker (
// Control signals // Control signals
input logic HCLK, HRESETn, input logic clk, reset,
input logic [`XLEN-1:0] SATP_REGW, input logic [`XLEN-1:0] SATP_REGW,
// Signals from TLBs (addresses to translate) // Signals from TLBs (addresses to translate)
@ -73,6 +73,10 @@ module pagetablewalker (
); );
// Internal signals // Internal signals
// register TLBs translation miss requests
logic [`XLEN-1:0] TranslationVAdrQ;
logic ITLBMissFQ, DTLBMissMQ;
logic [`PPN_BITS-1:0] BasePageTablePPN; logic [`PPN_BITS-1:0] BasePageTablePPN;
logic [`XLEN-1:0] TranslationVAdr; logic [`XLEN-1:0] TranslationVAdr;
logic [`XLEN-1:0] SavedPTE, CurrentPTE; logic [`XLEN-1:0] SavedPTE, CurrentPTE;
@ -98,8 +102,28 @@ module pagetablewalker (
assign MemStore = MemRWM[0]; assign MemStore = MemRWM[0];
// Prefer data address translations over instruction address translations // Prefer data address translations over instruction address translations
assign TranslationVAdr = (DTLBMissM) ? MemAdrM : PCF; assign TranslationVAdr = (DTLBMissM) ? MemAdrM : PCF; // *** need to register TranslationVAdr
assign MMUTranslate = DTLBMissM || ITLBMissF; flopenr #(`XLEN)
TranslationVAdrReg(.clk(clk),
.reset(reset),
.en(1'b1), // *** use enable later to save power
.d(TranslationVAdr),
.q(TranslationVAdrQ));
flopr #(1)
DTLBMissMReg(.clk(clk),
.reset(reset),
.d(DTLBMissM),
.q(DTLBMissMQ));
flopr #(1)
ITLBMissMReg(.clk(clk),
.reset(reset),
.d(ITLBMissF),
.q(ITLBMissFQ));
assign MMUTranslate = DTLBMissMQ | ITLBMissFQ;
// unswizzle PTE bits // unswizzle PTE bits
assign {Dirty, Accessed, Global, User, assign {Dirty, Accessed, Global, User,
@ -108,7 +132,7 @@ module pagetablewalker (
// Assign PTE descriptors common across all XLEN values // Assign PTE descriptors common across all XLEN values
assign LeafPTE = Executable | Writable | Readable; assign LeafPTE = Executable | Writable | Readable;
assign ValidPTE = Valid && ~(Writable && ~Readable); assign ValidPTE = Valid && ~(Writable && ~Readable);
assign AccessAlert = ~Accessed || (MemStore && ~Dirty); assign AccessAlert = ~Accessed | (MemStore & ~Dirty);
// Assign specific outputs to general outputs // Assign specific outputs to general outputs
assign PageTableEntryF = PageTableEntry; assign PageTableEntryF = PageTableEntry;
@ -129,7 +153,7 @@ localparam LEVEL0 = 3'h0;
if (`XLEN == 32) begin if (`XLEN == 32) begin
logic [9:0] VPN1, VPN0; logic [9:0] VPN1, VPN0;
flopenl #(3) mmureg(HCLK, ~HRESETn, 1'b1, NextWalkerState, IDLE, WalkerState); flopenl #(3) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState);
// State transition logic // State transition logic
always_comb begin always_comb begin
@ -162,8 +186,8 @@ localparam LEVEL0 = 3'h0;
assign MegapageMisaligned = |(CurrentPPN[9:0]); assign MegapageMisaligned = |(CurrentPPN[9:0]);
assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
assign VPN1 = TranslationVAdr[31:22]; assign VPN1 = TranslationVAdrQ[31:22];
assign VPN0 = TranslationVAdr[21:12]; assign VPN0 = TranslationVAdrQ[21:12];
// Assign combinational outputs // Assign combinational outputs
always_comb begin always_comb begin
@ -193,14 +217,14 @@ localparam LEVEL0 = 3'h0;
TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
PageTableEntry = CurrentPTE; PageTableEntry = CurrentPTE;
PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00; PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00;
DTLBWriteM = DTLBMissM; DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissM; // Prefer data over instructions ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
end end
FAULT: begin FAULT: begin
TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
WalkerInstrPageFaultF = ~DTLBMissM; WalkerInstrPageFaultF = ~DTLBMissMQ;
WalkerLoadPageFaultM = DTLBMissM && ~MemStore; WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore;
WalkerStorePageFaultM = DTLBMissM && MemStore; WalkerStorePageFaultM = DTLBMissMQ && MemStore;
MMUStall = '0; // Drop the stall early to enter trap handling code MMUStall = '0; // Drop the stall early to enter trap handling code
end end
default: begin default: begin
@ -210,7 +234,7 @@ localparam LEVEL0 = 3'h0;
end end
// Capture page table entry from ahblite // Capture page table entry from ahblite
flopenr #(32) ptereg(HCLK, ~HRESETn, MMUReady, MMUReadPTE, SavedPTE); flopenr #(32) ptereg(clk, reset, MMUReady, MMUReadPTE, SavedPTE);
mux2 #(32) ptemux(SavedPTE, MMUReadPTE, MMUReady, CurrentPTE); mux2 #(32) ptemux(SavedPTE, MMUReadPTE, MMUReady, CurrentPTE);
assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10]; assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10];
@ -227,7 +251,7 @@ localparam LEVEL0 = 3'h0;
logic TerapageMisaligned, GigapageMisaligned, BadTerapage, BadGigapage; logic TerapageMisaligned, GigapageMisaligned, BadTerapage, BadGigapage;
flopenl #(3) mmureg(HCLK, ~HRESETn, 1'b1, NextWalkerState, IDLE, WalkerState); flopenl #(3) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState);
always_comb begin always_comb begin
case (WalkerState) case (WalkerState)
@ -294,10 +318,10 @@ localparam LEVEL0 = 3'h0;
assign BadGigapage = GigapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme assign BadGigapage = GigapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
assign VPN3 = TranslationVAdr[47:39]; assign VPN3 = TranslationVAdrQ[47:39];
assign VPN2 = TranslationVAdr[38:30]; assign VPN2 = TranslationVAdrQ[38:30];
assign VPN1 = TranslationVAdr[29:21]; assign VPN1 = TranslationVAdrQ[29:21];
assign VPN0 = TranslationVAdr[20:12]; assign VPN0 = TranslationVAdrQ[20:12];
always_comb begin always_comb begin
// default values // default values
@ -338,15 +362,15 @@ localparam LEVEL0 = 3'h0;
PageType = (WalkerState == LEVEL3) ? 2'b11 : PageType = (WalkerState == LEVEL3) ? 2'b11 :
((WalkerState == LEVEL2) ? 2'b10 : ((WalkerState == LEVEL2) ? 2'b10 :
((WalkerState == LEVEL1) ? 2'b01 : 2'b00)); ((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
DTLBWriteM = DTLBMissM; DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissM; // Prefer data over instructions ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
end end
FAULT: begin FAULT: begin
// Keep physical address alive to prevent HADDR dropping to 0 // Keep physical address alive to prevent HADDR dropping to 0
TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; TranslationPAdr = {CurrentPPN, VPN0, 3'b000};
WalkerInstrPageFaultF = ~DTLBMissM; WalkerInstrPageFaultF = ~DTLBMissMQ;
WalkerLoadPageFaultM = DTLBMissM && ~MemStore; WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore;
WalkerStorePageFaultM = DTLBMissM && MemStore; WalkerStorePageFaultM = DTLBMissMQ && MemStore;
MMUStall = '0; // Drop the stall early to enter trap handling code MMUStall = '0; // Drop the stall early to enter trap handling code
end end
default: begin default: begin
@ -356,7 +380,7 @@ localparam LEVEL0 = 3'h0;
end end
// Capture page table entry from ahblite // Capture page table entry from ahblite
flopenr #(`XLEN) ptereg(HCLK, ~HRESETn, MMUReady, MMUReadPTE, SavedPTE); flopenr #(`XLEN) ptereg(clk, reset, MMUReady, MMUReadPTE, SavedPTE);
mux2 #(`XLEN) ptemux(SavedPTE, MMUReadPTE, MMUReady, CurrentPTE); mux2 #(`XLEN) ptemux(SavedPTE, MMUReadPTE, MMUReady, CurrentPTE);
assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10]; assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10];