added page table walker fault exit for icache.

This commit is contained in:
Ross Thompson 2021-07-01 17:59:55 -05:00
parent 61027f650c
commit 118dfa9cec
4 changed files with 144 additions and 117 deletions

View File

@ -45,6 +45,7 @@ module icache
output logic ICacheStallF, output logic ICacheStallF,
input logic ITLBMissF, input logic ITLBMissF,
input logic ITLBWriteF, input logic ITLBWriteF,
input logic WalkerInstrPageFaultF,
// The raw (not decompressed) instruction that was requested // The raw (not decompressed) instruction that was requested
// If this instruction is compressed, upper 16 bits may be the next 16 bits or may be zeros // If this instruction is compressed, upper 16 bits may be the next 16 bits or may be zeros

View File

@ -27,62 +27,64 @@
`include "wally-config.vh" `include "wally-config.vh"
module ifu ( module ifu (
input logic clk, reset, input logic clk, reset,
input logic StallF, StallD, StallE, StallM, StallW, input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushF, FlushD, FlushE, FlushM, FlushW, input logic FlushF, FlushD, FlushE, FlushM, FlushW,
// Fetch // Fetch
input logic [`XLEN-1:0] InstrInF, input logic [`XLEN-1:0] InstrInF,
input logic InstrAckF, input logic InstrAckF,
output logic [`XLEN-1:0] PCF, output logic [`XLEN-1:0] PCF,
output logic [`PA_BITS-1:0] InstrPAdrF, output logic [`PA_BITS-1:0] InstrPAdrF,
output logic InstrReadF, output logic InstrReadF,
output logic ICacheStallF, output logic ICacheStallF,
// Decode // Decode
output logic [`XLEN-1:0] PCD, output logic [`XLEN-1:0] PCD,
// Execute // Execute
output logic [`XLEN-1:0] PCLinkE, output logic [`XLEN-1:0] PCLinkE,
input logic PCSrcE, input logic PCSrcE,
input logic [`XLEN-1:0] PCTargetE, input logic [`XLEN-1:0] PCTargetE,
output logic [`XLEN-1:0] PCE, output logic [`XLEN-1:0] PCE,
output logic BPPredWrongE, output logic BPPredWrongE,
// Mem // Mem
input logic RetM, TrapM, input logic RetM, TrapM,
input logic [`XLEN-1:0] PrivilegedNextPCM, input logic [`XLEN-1:0] PrivilegedNextPCM,
output logic [31:0] InstrD, InstrE, InstrM, InstrW, output logic [31:0] InstrD, InstrE, InstrM, InstrW,
output logic [`XLEN-1:0] PCM, output logic [`XLEN-1:0] PCM,
output logic [4:0] InstrClassM, output logic [4:0] InstrClassM,
output logic BPPredDirWrongM, output logic BPPredDirWrongM,
output logic BTBPredPCWrongM, output logic BTBPredPCWrongM,
output logic RASPredPCWrongM, output logic RASPredPCWrongM,
output logic BPPredClassNonCFIWrongM, output logic BPPredClassNonCFIWrongM,
// Writeback // Writeback
// output logic [`XLEN-1:0] PCLinkW, // output logic [`XLEN-1:0] PCLinkW,
// Faults // Faults
input logic IllegalBaseInstrFaultD, input logic IllegalBaseInstrFaultD,
output logic ITLBInstrPageFaultF, output logic ITLBInstrPageFaultF,
output logic IllegalIEUInstrFaultD, output logic IllegalIEUInstrFaultD,
output logic InstrMisalignedFaultM, output logic InstrMisalignedFaultM,
output logic [`XLEN-1:0] InstrMisalignedAdrM, output logic [`XLEN-1:0] InstrMisalignedAdrM,
// mmu management // mmu management
input logic [1:0] PrivilegeModeW, input logic [1:0] PrivilegeModeW,
input logic [`XLEN-1:0] PageTableEntryF, input logic [`XLEN-1:0] PageTableEntryF,
input logic [1:0] PageTypeF, input logic [1:0] PageTypeF,
input logic [`XLEN-1:0] SATP_REGW, input logic [`XLEN-1:0] SATP_REGW,
input logic STATUS_MXR, STATUS_SUM, input logic STATUS_MXR, STATUS_SUM,
input logic ITLBWriteF, ITLBFlushF, input logic ITLBWriteF, ITLBFlushF,
output logic ITLBMissF, ITLBHitF, input logic WalkerInstrPageFaultF,
output logic ITLBMissF, ITLBHitF,
// pmp/pma (inside mmu) signals. *** temporarily from AHB bus but eventually replace with internal versions pre H // pmp/pma (inside mmu) signals. *** temporarily from AHB bus but eventually replace with internal versions pre H
// input logic [31:0] HADDR, // input logic [31:0] HADDR,
// input logic [2:0] HSIZE, // input logic [2:0] HSIZE,
// input logic HWRITE, // input logic HWRITE,
input logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW, // *** all of these come from the privileged unit, so they're gonna have to come over into ifu and dmem input logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW, // *** all of these come from the privileged unit, so they're gonna have to come over into ifu and dmem
input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
output logic PMPInstrAccessFaultF, PMAInstrAccessFaultF, output logic PMPInstrAccessFaultF, PMAInstrAccessFaultF,
output logic ISquashBusAccessF output logic ISquashBusAccessF
// output logic [5:0] IHSELRegionsF // output logic [5:0] IHSELRegionsF
); );
@ -105,7 +107,6 @@ module ifu (
// if you're allowed to parameterize outputs/ inputs existence, these are an easy delete. // if you're allowed to parameterize outputs/ inputs existence, these are an easy delete.
logic [`PA_BITS-1:0] PCPFmmu, PCNextFPhys; // used to either truncate or expand PCPF and PCNextF into `PA_BITS width. logic [`PA_BITS-1:0] PCPFmmu, PCNextFPhys; // used to either truncate or expand PCPF and PCNextF into `PA_BITS width.
;
generate generate
if (`XLEN==32) begin if (`XLEN==32) begin
@ -152,7 +153,8 @@ module ifu (
icache icache(.*, icache icache(.*,
.PCNextF(PCNextFPhys), .PCNextF(PCNextFPhys),
.PCPF(PCPFmmu)); .PCPF(PCPFmmu),
.WalkerInstrPageFaultF(WalkerInstrPageFaultF));
flopenl #(32) AlignedInstrRawDFlop(clk, reset | reset_q, ~StallD, FlushD ? nop : FinalInstrRawF, nop, InstrRawD); flopenl #(32) AlignedInstrRawDFlop(clk, reset | reset_q, ~StallD, FlushD ? nop : FinalInstrRawF, nop, InstrRawD);

View File

@ -181,31 +181,106 @@ module pagetablewalker
flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState); flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState);
/* -----\/----- EXCLUDED -----\/-----
assign PRegEn = (WalkerState == LEVEL1_WDV || WalkerState == LEVEL0_WDV) && ~HPTWStall; assign PRegEn = (WalkerState == LEVEL1_WDV || WalkerState == LEVEL0_WDV) && ~HPTWStall;
-----/\----- EXCLUDED -----/\----- */
// State transition logic // State transition logic
always_comb begin always_comb begin
PRegEn = 1'b0;
TranslationPAdr = '0;
HPTWRead = 1'b0;
MMUStall = 1'b1;
PageTableEntry = '0;
PageType = '0;
DTLBWriteM = '0;
ITLBWriteF = '0;
WalkerInstrPageFaultF = 1'b0;
WalkerLoadPageFaultM = 1'b0;
WalkerStorePageFaultM = 1'b0;
case (WalkerState) case (WalkerState)
IDLE: if (MMUTranslate) NextWalkerState = LEVEL1_WDV; IDLE: begin
else NextWalkerState = IDLE; if (MMUTranslate && SvMode == `SV32) begin // *** Added SvMode
LEVEL1_WDV: if (HPTWStall) NextWalkerState = LEVEL1_WDV; NextWalkerState = LEVEL1_WDV;
else NextWalkerState = LEVEL1; TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00};
LEVEL1: HPTWRead = 1'b1;
end else begin
NextWalkerState = IDLE;
TranslationPAdr = '0;
MMUStall = 1'b0;
end
end
LEVEL1_WDV: begin
TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00};
if (HPTWStall) begin
NextWalkerState = LEVEL1_WDV;
end else begin
NextWalkerState = LEVEL1;
PRegEn = 1'b1;
end
end
LEVEL1: begin
// *** <FUTURE WORK> According to the architecture, we should // *** <FUTURE WORK> According to the architecture, we should
// fault upon finding a superpage that is misaligned or has 0 // fault upon finding a superpage that is misaligned or has 0
// access bit. The following commented line of code is // access bit. The following commented line of code is
// supposed to perform that check. However, it is untested. // supposed to perform that check. However, it is untested.
if (ValidPTE && LeafPTE && ~BadMegapage) NextWalkerState = LEAF; if (ValidPTE && LeafPTE && ~BadMegapage) begin
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line. NextWalkerState = LEAF;
else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0_WDV; PageTableEntry = CurrentPTE;
else NextWalkerState = FAULT; PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00; // *** not sure about this mux?
LEVEL0_WDV: if (HPTWStall) NextWalkerState = LEVEL0_WDV; DTLBWriteM = DTLBMissMQ;
else NextWalkerState = LEVEL0; ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
LEVEL0: if (ValidPTE & LeafPTE & ~AccessAlert) TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
NextWalkerState = LEAF; end
else NextWalkerState = FAULT; // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
LEAF: NextWalkerState = IDLE; else if (ValidPTE && ~LeafPTE) begin
FAULT: NextWalkerState = IDLE; NextWalkerState = LEVEL0_WDV;
TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
HPTWRead = 1'b1;
end else begin
NextWalkerState = FAULT;
end
end
LEVEL0_WDV: begin
TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
if (HPTWStall) begin
NextWalkerState = LEVEL0_WDV;
end else begin
NextWalkerState = LEVEL0;
PRegEn = 1'b1;
end
end
LEVEL0: begin
if (ValidPTE & LeafPTE & ~AccessAlert) begin
NextWalkerState = LEAF;
PageTableEntry = CurrentPTE;
PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00;
DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
end else begin
NextWalkerState = FAULT;
end
end
LEAF: begin
NextWalkerState = IDLE;
MMUStall = 1'b0;
end
FAULT: begin
NextWalkerState = IDLE;
WalkerInstrPageFaultF = ~DTLBMissMQ;
WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore;
WalkerStorePageFaultM = DTLBMissMQ && MemStore;
MMUStall = 1'b0;
end
// Default case should never happen, but is included for linter. // Default case should never happen, but is included for linter.
default: NextWalkerState = IDLE; default: NextWalkerState = IDLE;
endcase endcase
@ -221,55 +296,6 @@ module pagetablewalker
//assign HPTWRead = (WalkerState == IDLE && MMUTranslate) || //assign HPTWRead = (WalkerState == IDLE && MMUTranslate) ||
// WalkerState == LEVEL2 || WalkerState == LEVEL1; // WalkerState == LEVEL2 || WalkerState == LEVEL1;
// Assign combinational outputs
always_comb begin
// default values
//TranslationPAdr = '0;
PageTableEntry = '0;
PageType ='0;
DTLBWriteM = '0;
ITLBWriteF = '0;
WalkerInstrPageFaultF = '0;
WalkerLoadPageFaultM = '0;
WalkerStorePageFaultM = '0;
//MMUStall = '1;
case (NextWalkerState)
IDLE: begin
//MMUStall = '0;
end
LEVEL1: begin
//TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00};
end
LEVEL1_WDV: begin
//TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00};
end
LEVEL0: begin
//TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
end
LEVEL0_WDV: begin
//TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
end
LEAF: begin
// Keep physical address alive to prevent HADDR dropping to 0
//TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
PageTableEntry = CurrentPTE;
PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00;
DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
end
FAULT: begin
//TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
WalkerInstrPageFaultF = ~DTLBMissMQ;
WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore;
WalkerStorePageFaultM = DTLBMissMQ && MemStore;
// MMUStall = '0; // Drop the stall early to enter trap handling code
end
default: begin
// nothing
end
endcase
end
// Capture page table entry from data cache // Capture page table entry from data cache
// *** may need to delay reading this value until the next clock cycle. // *** may need to delay reading this value until the next clock cycle.
@ -338,7 +364,6 @@ module pagetablewalker
LEVEL3_WDV: begin LEVEL3_WDV: begin
TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000}; TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000};
//HPTWRead = 1'b1;
if (HPTWStall) begin if (HPTWStall) begin
NextWalkerState = LEVEL3_WDV; NextWalkerState = LEVEL3_WDV;
end else begin end else begin
@ -355,12 +380,12 @@ module pagetablewalker
if (ValidPTE && LeafPTE && ~BadTerapage) begin if (ValidPTE && LeafPTE && ~BadTerapage) begin
NextWalkerState = LEAF; NextWalkerState = LEAF;
PageTableEntry = CurrentPTE; PageTableEntry = CurrentPTE;
PageType = (WalkerState == LEVEL3) ? 2'b11 : PageType = (WalkerState == LEVEL3) ? 2'b11 : // *** not sure about this mux?
((WalkerState == LEVEL2) ? 2'b10 : ((WalkerState == LEVEL2) ? 2'b10 :
((WalkerState == LEVEL1) ? 2'b01 : 2'b00)); ((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
DTLBWriteM = DTLBMissMQ; DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
TranslationPAdr = TranslationVAdrQ; TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
end end
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line. // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
else if (ValidPTE && ~LeafPTE) begin else if (ValidPTE && ~LeafPTE) begin
@ -397,7 +422,7 @@ module pagetablewalker
((WalkerState == LEVEL1) ? 2'b01 : 2'b00)); ((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
DTLBWriteM = DTLBMissMQ; DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
TranslationPAdr = TranslationVAdrQ; TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
end end
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line. // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
else if (ValidPTE && ~LeafPTE) begin else if (ValidPTE && ~LeafPTE) begin
@ -434,7 +459,7 @@ module pagetablewalker
((WalkerState == LEVEL1) ? 2'b01 : 2'b00)); ((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
DTLBWriteM = DTLBMissMQ; DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
TranslationPAdr = TranslationVAdrQ; TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
end end
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line. // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
@ -449,7 +474,6 @@ module pagetablewalker
LEVEL0_WDV: begin LEVEL0_WDV: begin
TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; TranslationPAdr = {CurrentPPN, VPN0, 3'b000};
//HPTWRead = 1'b1;
if (HPTWStall) begin if (HPTWStall) begin
NextWalkerState = LEVEL0_WDV; NextWalkerState = LEVEL0_WDV;
end else begin end else begin
@ -467,7 +491,7 @@ module pagetablewalker
((WalkerState == LEVEL1) ? 2'b01 : 2'b00)); ((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
DTLBWriteM = DTLBMissMQ; DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
TranslationPAdr = TranslationVAdrQ; TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
end else begin end else begin
NextWalkerState = FAULT; NextWalkerState = FAULT;
end end

View File

@ -178,9 +178,9 @@ module wallypipelinedhart
logic [2:0] Funct3MfromLSU; logic [2:0] Funct3MfromLSU;
ifu ifu(.InstrInF(InstrRData),
.WalkerInstrPageFaultF(WalkerInstrPageFaultF),
ifu ifu(.InstrInF(InstrRData), .*); // instruction fetch unit: PC, branch prediction, instruction cache .*); // instruction fetch unit: PC, branch prediction, instruction cache
ieu ieu(.*); // integer execution unit: integer register file, datapath and controller ieu ieu(.*); // integer execution unit: integer register file, datapath and controller