added page table walker fault exit for icache.

This commit is contained in:
Ross Thompson 2021-07-01 17:59:55 -05:00
parent 3dae02818c
commit 386193de00
4 changed files with 144 additions and 117 deletions

View File

@ -45,6 +45,7 @@ module icache
output logic ICacheStallF,
input logic ITLBMissF,
input logic ITLBWriteF,
input logic WalkerInstrPageFaultF,
// 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

View File

@ -27,62 +27,64 @@
`include "wally-config.vh"
module ifu (
input logic clk, reset,
input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushF, FlushD, FlushE, FlushM, FlushW,
input logic clk, reset,
input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushF, FlushD, FlushE, FlushM, FlushW,
// Fetch
input logic [`XLEN-1:0] InstrInF,
input logic InstrAckF,
output logic [`XLEN-1:0] PCF,
input logic [`XLEN-1:0] InstrInF,
input logic InstrAckF,
output logic [`XLEN-1:0] PCF,
output logic [`PA_BITS-1:0] InstrPAdrF,
output logic InstrReadF,
output logic ICacheStallF,
output logic InstrReadF,
output logic ICacheStallF,
// Decode
output logic [`XLEN-1:0] PCD,
output logic [`XLEN-1:0] PCD,
// Execute
output logic [`XLEN-1:0] PCLinkE,
input logic PCSrcE,
input logic [`XLEN-1:0] PCTargetE,
output logic [`XLEN-1:0] PCE,
output logic BPPredWrongE,
output logic [`XLEN-1:0] PCLinkE,
input logic PCSrcE,
input logic [`XLEN-1:0] PCTargetE,
output logic [`XLEN-1:0] PCE,
output logic BPPredWrongE,
// Mem
input logic RetM, TrapM,
input logic [`XLEN-1:0] PrivilegedNextPCM,
output logic [31:0] InstrD, InstrE, InstrM, InstrW,
output logic [`XLEN-1:0] PCM,
output logic [4:0] InstrClassM,
output logic BPPredDirWrongM,
output logic BTBPredPCWrongM,
output logic RASPredPCWrongM,
output logic BPPredClassNonCFIWrongM,
input logic RetM, TrapM,
input logic [`XLEN-1:0] PrivilegedNextPCM,
output logic [31:0] InstrD, InstrE, InstrM, InstrW,
output logic [`XLEN-1:0] PCM,
output logic [4:0] InstrClassM,
output logic BPPredDirWrongM,
output logic BTBPredPCWrongM,
output logic RASPredPCWrongM,
output logic BPPredClassNonCFIWrongM,
// Writeback
// output logic [`XLEN-1:0] PCLinkW,
// Faults
input logic IllegalBaseInstrFaultD,
output logic ITLBInstrPageFaultF,
output logic IllegalIEUInstrFaultD,
output logic InstrMisalignedFaultM,
output logic [`XLEN-1:0] InstrMisalignedAdrM,
input logic IllegalBaseInstrFaultD,
output logic ITLBInstrPageFaultF,
output logic IllegalIEUInstrFaultD,
output logic InstrMisalignedFaultM,
output logic [`XLEN-1:0] InstrMisalignedAdrM,
// mmu management
input logic [1:0] PrivilegeModeW,
input logic [`XLEN-1:0] PageTableEntryF,
input logic [1:0] PageTypeF,
input logic [`XLEN-1:0] SATP_REGW,
input logic STATUS_MXR, STATUS_SUM,
input logic ITLBWriteF, ITLBFlushF,
output logic ITLBMissF, ITLBHitF,
input logic [1:0] PrivilegeModeW,
input logic [`XLEN-1:0] PageTableEntryF,
input logic [1:0] PageTypeF,
input logic [`XLEN-1:0] SATP_REGW,
input logic STATUS_MXR, STATUS_SUM,
input logic ITLBWriteF, ITLBFlushF,
input logic WalkerInstrPageFaultF,
output logic ITLBMissF, ITLBHitF,
// pmp/pma (inside mmu) signals. *** temporarily from AHB bus but eventually replace with internal versions pre H
// input logic [31:0] HADDR,
// input logic [2:0] HSIZE,
// 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 var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
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],
output logic PMPInstrAccessFaultF, PMAInstrAccessFaultF,
output logic ISquashBusAccessF
output logic PMPInstrAccessFaultF, PMAInstrAccessFaultF,
output logic ISquashBusAccessF
// 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.
logic [`PA_BITS-1:0] PCPFmmu, PCNextFPhys; // used to either truncate or expand PCPF and PCNextF into `PA_BITS width.
;
generate
if (`XLEN==32) begin
@ -152,7 +153,8 @@ module ifu (
icache icache(.*,
.PCNextF(PCNextFPhys),
.PCPF(PCPFmmu));
.PCPF(PCPFmmu),
.WalkerInstrPageFaultF(WalkerInstrPageFaultF));
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);
/* -----\/----- EXCLUDED -----\/-----
assign PRegEn = (WalkerState == LEVEL1_WDV || WalkerState == LEVEL0_WDV) && ~HPTWStall;
-----/\----- EXCLUDED -----/\----- */
// State transition logic
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)
IDLE: if (MMUTranslate) NextWalkerState = LEVEL1_WDV;
else NextWalkerState = IDLE;
LEVEL1_WDV: if (HPTWStall) NextWalkerState = LEVEL1_WDV;
else NextWalkerState = LEVEL1;
LEVEL1:
IDLE: begin
if (MMUTranslate && SvMode == `SV32) begin // *** Added SvMode
NextWalkerState = LEVEL1_WDV;
TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00};
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
// fault upon finding a superpage that is misaligned or has 0
// access bit. The following commented line of code is
// supposed to perform that check. However, it is untested.
if (ValidPTE && LeafPTE && ~BadMegapage) NextWalkerState = LEAF;
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0_WDV;
else NextWalkerState = FAULT;
LEVEL0_WDV: if (HPTWStall) NextWalkerState = LEVEL0_WDV;
else NextWalkerState = LEVEL0;
LEVEL0: if (ValidPTE & LeafPTE & ~AccessAlert)
NextWalkerState = LEAF;
else NextWalkerState = FAULT;
LEAF: NextWalkerState = IDLE;
FAULT: NextWalkerState = IDLE;
if (ValidPTE && LeafPTE && ~BadMegapage) begin
NextWalkerState = LEAF;
PageTableEntry = CurrentPTE;
PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00; // *** not sure about this mux?
DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
end
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
else if (ValidPTE && ~LeafPTE) begin
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: NextWalkerState = IDLE;
endcase
@ -221,55 +296,6 @@ module pagetablewalker
//assign HPTWRead = (WalkerState == IDLE && MMUTranslate) ||
// 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
// *** may need to delay reading this value until the next clock cycle.
@ -338,7 +364,6 @@ module pagetablewalker
LEVEL3_WDV: begin
TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000};
//HPTWRead = 1'b1;
if (HPTWStall) begin
NextWalkerState = LEVEL3_WDV;
end else begin
@ -355,12 +380,12 @@ module pagetablewalker
if (ValidPTE && LeafPTE && ~BadTerapage) begin
NextWalkerState = LEAF;
PageTableEntry = CurrentPTE;
PageType = (WalkerState == LEVEL3) ? 2'b11 :
PageType = (WalkerState == LEVEL3) ? 2'b11 : // *** not sure about this mux?
((WalkerState == LEVEL2) ? 2'b10 :
((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
TranslationPAdr = TranslationVAdrQ;
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
end
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
else if (ValidPTE && ~LeafPTE) begin
@ -397,7 +422,7 @@ module pagetablewalker
((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
TranslationPAdr = TranslationVAdrQ;
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
end
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
else if (ValidPTE && ~LeafPTE) begin
@ -434,7 +459,7 @@ module pagetablewalker
((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
TranslationPAdr = TranslationVAdrQ;
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
end
// 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
TranslationPAdr = {CurrentPPN, VPN0, 3'b000};
//HPTWRead = 1'b1;
if (HPTWStall) begin
NextWalkerState = LEVEL0_WDV;
end else begin
@ -467,7 +491,7 @@ module pagetablewalker
((WalkerState == LEVEL1) ? 2'b01 : 2'b00));
DTLBWriteM = DTLBMissMQ;
ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions
TranslationPAdr = TranslationVAdrQ;
TranslationPAdr = TranslationVAdrQ[`PA_BITS-1:0];
end else begin
NextWalkerState = FAULT;
end

View File

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