diff --git a/wally-pipelined/src/cache/icache.sv b/wally-pipelined/src/cache/icache.sv index 89b2ff9e7..943ab1b8d 100644 --- a/wally-pipelined/src/cache/icache.sv +++ b/wally-pipelined/src/cache/icache.sv @@ -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 diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 6cf6220f1..23d44608c 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -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); diff --git a/wally-pipelined/src/mmu/pagetablewalker.sv b/wally-pipelined/src/mmu/pagetablewalker.sv index 3670069b4..a8f9500f0 100644 --- a/wally-pipelined/src/mmu/pagetablewalker.sv +++ b/wally-pipelined/src/mmu/pagetablewalker.sv @@ -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 // *** 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 diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index edcb7203c..d59ec3133 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -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