From 9ec624702d97a61de7a107400dd79838c5040709 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Wed, 30 Jun 2021 16:25:03 -0500 Subject: [PATCH] Major rewrite of ptw to remove combo loop. --- wally-pipelined/regression/wave.do | 42 ++- wally-pipelined/src/lsu/lsu.sv | 41 ++- wally-pipelined/src/lsu/lsuArb.sv | 29 +- wally-pipelined/src/mmu/pagetablewalker.sv | 283 ++++++++++++------ .../testbench/testbench-imperas.sv | 2 +- 5 files changed, 272 insertions(+), 125 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 20a21864..eef15339 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -240,7 +240,7 @@ add wave -noupdate -group AHB /testbench/dut/hart/ebu/HADDRD add wave -noupdate -group AHB /testbench/dut/hart/ebu/HSIZED add wave -noupdate -group AHB /testbench/dut/hart/ebu/HWRITED add wave -noupdate -group AHB /testbench/dut/hart/ebu/StallW -add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/CurrState +add wave -noupdate -expand -group lsu -color Gold /testbench/dut/hart/lsu/CurrState add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/MemRWM add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/DataStall add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/MemAdrM @@ -293,27 +293,36 @@ add wave -noupdate -group CLINT /testbench/dut/uncore/genblk1/clint/MTIME add wave -noupdate -group CLINT /testbench/dut/uncore/genblk1/clint/MTIMECMP add wave -noupdate -group CLINT /testbench/dut/uncore/genblk1/clint/TimerIntM add wave -noupdate -group CLINT /testbench/dut/uncore/genblk1/clint/SwIntM -add wave -noupdate -expand -group ptwalker /testbench/dut/hart/pagetablewalker/PRegEn -add wave -noupdate -expand -group ptwalker -color Gold /testbench/dut/hart/pagetablewalker/WalkerState -add wave -noupdate -expand -group ptwalker /testbench/dut/hart/pagetablewalker/MMUReady -add wave -noupdate -expand -group ptwalker /testbench/dut/hart/pagetablewalker/HPTWStall add wave -noupdate -expand -group ptwalker /testbench/dut/hart/pagetablewalker/MMUTranslate +add wave -noupdate -expand -group ptwalker -color Gold /testbench/dut/hart/pagetablewalker/WalkerState +add wave -noupdate -expand -group ptwalker -color Salmon /testbench/dut/hart/pagetablewalker/HPTWStall add wave -noupdate -expand -group ptwalker /testbench/dut/hart/pagetablewalker/HPTWRead -add wave -noupdate -expand -group ptwalker -divider data add wave -noupdate -expand -group ptwalker /testbench/dut/hart/pagetablewalker/MMUPAdr -add wave -noupdate -expand -group ptwalker /testbench/dut/hart/pagetablewalker/MMUReadPTE -add wave -noupdate -expand -group ptwalker /testbench/dut/hart/pagetablewalker/CurrentPTE +add wave -noupdate -expand -group ptwalker -expand -group pte /testbench/dut/hart/pagetablewalker/MMUReadPTE +add wave -noupdate -expand -group ptwalker -expand -group pte /testbench/dut/hart/pagetablewalker/PRegEn +add wave -noupdate -expand -group ptwalker -expand -group pte /testbench/dut/hart/pagetablewalker/CurrentPTE +add wave -noupdate -expand -group ptwalker -divider data add wave -noupdate -expand -group ptwalker /testbench/dut/hart/pagetablewalker/TranslationPAdr add wave -noupdate -expand -group ptwalker /testbench/dut/hart/pagetablewalker/ValidPTE add wave -noupdate -expand -group ptwalker /testbench/dut/hart/pagetablewalker/LeafPTE add wave -noupdate -expand -group ptwalker /testbench/dut/hart/pagetablewalker/MMUStall +add wave -noupdate -expand -group ptwalker -expand -group {fsm outputs} /testbench/dut/hart/pagetablewalker/TranslationPAdr +add wave -noupdate -expand -group ptwalker -expand -group {fsm outputs} /testbench/dut/hart/pagetablewalker/PageTableEntry +add wave -noupdate -expand -group ptwalker -expand -group {fsm outputs} /testbench/dut/hart/pagetablewalker/PageType +add wave -noupdate -expand -group ptwalker -expand -group {fsm outputs} /testbench/dut/hart/pagetablewalker/ITLBWriteF +add wave -noupdate -expand -group ptwalker -expand -group {fsm outputs} /testbench/dut/hart/pagetablewalker/DTLBWriteM +add wave -noupdate -expand -group ptwalker -expand -group {fsm outputs} /testbench/dut/hart/pagetablewalker/WalkerInstrPageFaultF +add wave -noupdate -expand -group ptwalker -expand -group {fsm outputs} /testbench/dut/hart/pagetablewalker/WalkerLoadPageFaultM +add wave -noupdate -expand -group ptwalker -expand -group {fsm outputs} /testbench/dut/hart/pagetablewalker/WalkerStorePageFaultM +add wave -noupdate -expand -group ptwalker -expand -group {fsm outputs} /testbench/dut/hart/pagetablewalker/MMUStall add wave -noupdate -expand -group {LSU ARB} -color Gold /testbench/dut/hart/arbiter/CurrState -add wave -noupdate -expand -group {LSU ARB} /testbench/dut/hart/arbiter/HPTWTranslate -add wave -noupdate -expand -group {LSU ARB} /testbench/dut/hart/arbiter/HPTWPAdr -add wave -noupdate -expand -group {LSU ARB} /testbench/dut/hart/arbiter/HPTWReadPTE -add wave -noupdate -expand -group {LSU ARB} /testbench/dut/hart/arbiter/HPTWReady -add wave -noupdate -expand -group {LSU ARB} -expand -group toLSU /testbench/dut/hart/arbiter/MemAdrMtoLSU add wave -noupdate -expand -group {LSU ARB} /testbench/dut/hart/arbiter/SelPTW +add wave -noupdate -expand -group {LSU ARB} -expand -group hptw /testbench/dut/hart/arbiter/HPTWTranslate +add wave -noupdate -expand -group {LSU ARB} -expand -group hptw /testbench/dut/hart/arbiter/HPTWRead +add wave -noupdate -expand -group {LSU ARB} -expand -group hptw /testbench/dut/hart/arbiter/HPTWPAdr +add wave -noupdate -expand -group {LSU ARB} -expand -group hptw /testbench/dut/hart/arbiter/HPTWReadPTE +add wave -noupdate -expand -group {LSU ARB} -expand -group hptw /testbench/dut/hart/arbiter/HPTWReady +add wave -noupdate -expand -group {LSU ARB} -expand -group toLSU /testbench/dut/hart/arbiter/MemAdrMtoLSU add wave -noupdate /testbench/dut/hart/lsu/DataStall add wave -noupdate -expand -group csr /testbench/dut/hart/priv/csr/MIP_REGW add wave -noupdate /testbench/dut/uncore/genblk2/plic/ExtIntM @@ -340,9 +349,10 @@ add wave -noupdate -group uart -expand -group outputs /testbench/dut/uncore/genb add wave -noupdate -group uart -expand -group outputs /testbench/dut/uncore/genblk4/uart/TXRDYb add wave -noupdate -group uart -expand -group outputs /testbench/dut/uncore/genblk4/uart/RXRDYb add wave -noupdate -expand -group dtlb /testbench/dut/hart/lsu/dmmu/TLBMiss +add wave -noupdate -expand -group itlb /testbench/dut/hart/ifu/ITLBMissF TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 5} {11172515 ns} 0} {{Cursor 8} {9673965 ns} 0} -quietly wave cursor active 1 +WaveRestoreCursors {{Cursor 5} {11172515 ns} 0} {{Cursor 8} {2967 ns} 0} +quietly wave cursor active 2 configure wave -namecolwidth 250 configure wave -valuecolwidth 189 configure wave -justifyvalue left @@ -357,4 +367,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {11172446 ns} {11172732 ns} +WaveRestoreZoom {2729 ns} {3045 ns} diff --git a/wally-pipelined/src/lsu/lsu.sv b/wally-pipelined/src/lsu/lsu.sv index dc554e52..cd37ce94 100644 --- a/wally-pipelined/src/lsu/lsu.sv +++ b/wally-pipelined/src/lsu/lsu.sv @@ -103,14 +103,17 @@ module lsu ( logic SquashSCM; logic DTLBPageFaultM; logic MemAccessM; - logic [2:0] CurrState, NextState; + logic preCommittedM; - localparam STATE_READY = 0; - localparam STATE_FETCH = 1; - localparam STATE_FETCH_AMO_1 = 2; - localparam STATE_FETCH_AMO_2 = 3; - localparam STATE_STALLED = 4; + typedef enum {STATE_READY, + STATE_FETCH, + STATE_FETCH_AMO_1, + STATE_FETCH_AMO_2, + STATE_STALLED, + STATE_TLB_MISS} statetype; + statetype CurrState, NextState; + logic PMPInstrAccessFaultF, PMAInstrAccessFaultF; // *** these are just so that the mmu has somewhere to put these outputs since they aren't used in dmem // *** if you're allowed to parameterize outputs/ inputs existence, these are an easy delete. @@ -208,15 +211,20 @@ module lsu ( // requests data from memory rather than issuing a single request. - flopr #(3) stateReg(.clk(clk), - .reset(reset), - .d(NextState), - .q(CurrState)); + flopenl #(.TYPE(statetype)) stateReg(.clk(clk), + .load(reset), + .en(1'b1), + .d(NextState), + .val(STATE_READY), + .q(CurrState)); always_comb begin case (CurrState) STATE_READY: - if (AtomicMaskedM[1]) begin + if (DTLBMissM) begin + NextState = STATE_READY; + DataStall = 1'b0; + end else if (AtomicMaskedM[1]) begin NextState = STATE_FETCH_AMO_1; // *** should be some misalign check DataStall = 1'b1; end else if((MemReadM & AtomicM[0]) | (MemWriteM & AtomicM[0])) begin @@ -248,15 +256,13 @@ module lsu ( end end STATE_FETCH: begin + DataStall = 1'b1; if (MemAckW & ~StallW) begin NextState = STATE_READY; - DataStall = 1'b0; end else if (MemAckW & StallW) begin NextState = STATE_STALLED; - DataStall = 1'b1; end else begin NextState = STATE_FETCH; - DataStall = 1'b1; end end STATE_STALLED: begin @@ -267,6 +273,13 @@ module lsu ( NextState = STATE_STALLED; end end + STATE_TLB_MISS: begin + if (DTLBWriteM) begin + NextState = STATE_READY; + end else begin + NextState = STATE_TLB_MISS; + end + end default: begin DataStall = 1'b0; NextState = STATE_READY; diff --git a/wally-pipelined/src/lsu/lsuArb.sv b/wally-pipelined/src/lsu/lsuArb.sv index 9298d79d..dce509f7 100644 --- a/wally-pipelined/src/lsu/lsuArb.sv +++ b/wally-pipelined/src/lsu/lsuArb.sv @@ -81,26 +81,31 @@ module lsuArb // to data memory the d cache is already busy. We can interlock by // leveraging Stall as a d cache busy. We will need an FSM to handle this. - localparam StateReady = 0; - localparam StatePTWPending = 1; - localparam StatePTWActive = 2; + typedef enum{StateReady, + StatePTWPending, + StatePTWActive} statetype; + - logic [1:0] CurrState, NextState; + statetype CurrState, NextState; logic SelPTW; logic HPTWStallD; - flopr #(2) StateReg( - .clk(clk), - .reset(reset), - .d(NextState), - .q(CurrState)); + flopenl #(.TYPE(statetype)) StateReg(.clk(clk), + .load(reset), + .en(1'b1), + .d(NextState), + .val(StateReady), + .q(CurrState)); always_comb begin case(CurrState) StateReady: +/* -----\/----- EXCLUDED -----\/----- if (HPTWTranslate & DataStall) NextState = StatePTWPending; - else if (HPTWTranslate & ~DataStall) NextState = StatePTWActive; + else + -----/\----- EXCLUDED -----/\----- */ + if (HPTWTranslate) NextState = StatePTWActive; else NextState = StateReady; StatePTWPending: if (HPTWTranslate & ~DataStall) NextState = StatePTWActive; @@ -143,11 +148,15 @@ module lsuArb // *** need to rename DcacheStall and Datastall. // not clear at all. I think it should be LSUStall from the LSU, // which is demuxed to HPTWStall and CPUDataStall? (not sure on this last one). + assign HPTWStall = SelPTW ? DataStall : 1'b1; + //assign HPTWStallD = SelPTW ? DataStall : 1'b1; +/* -----\/----- EXCLUDED -----\/----- assign HPTWStallD = SelPTW ? DataStall : 1'b1; flopr #(1) HPTWStallReg (.clk(clk), .reset(reset), .d(HPTWStallD), .q(HPTWStall)); + -----/\----- EXCLUDED -----/\----- */ assign DCacheStall = SelPTW ? 1'b0 : DataStall; // *** this is probably going to change. diff --git a/wally-pipelined/src/mmu/pagetablewalker.sv b/wally-pipelined/src/mmu/pagetablewalker.sv index f5e1d85c..f0f30301 100644 --- a/wally-pipelined/src/mmu/pagetablewalker.sv +++ b/wally-pipelined/src/mmu/pagetablewalker.sv @@ -126,6 +126,7 @@ module pagetablewalker ( assign MMUTranslate = DTLBMissMQ | ITLBMissFQ; + //assign MMUTranslate = DTLBMissM | ITLBMissF; // unswizzle PTE bits assign {Dirty, Accessed, Global, User, @@ -142,20 +143,19 @@ module pagetablewalker ( assign PageTypeF = PageType; assign PageTypeM = PageType; - localparam LEVEL0_WDV = 4'h0; - localparam LEVEL0 = 4'h8; - localparam LEVEL1_WDV = 4'h1; - localparam LEVEL1 = 4'h9; - localparam LEVEL2_WDV = 4'h2; - localparam LEVEL2 = 4'hA; - localparam LEVEL3_WDV = 4'h3; - localparam LEVEL3 = 4'hB; - // space left for more levels - localparam LEAF = 4'h5; - localparam IDLE = 4'h6; - localparam FAULT = 4'h7; + typedef enum {LEVEL0_WDV, + LEVEL0, + LEVEL1_WDV, + LEVEL1, + LEVEL2_WDV, + LEVEL2, + LEVEL3_WDV, + LEVEL3, + LEAF, + IDLE, + FAULT} statetype; - logic [3:0] WalkerState, NextWalkerState; + statetype WalkerState, NextWalkerState; logic PRegEn; @@ -163,7 +163,7 @@ module pagetablewalker ( if (`XLEN == 32) begin logic [9:0] VPN1, VPN0; - flopenl #(3) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState); + flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState); assign PRegEn = (WalkerState == LEVEL1_WDV || WalkerState == LEVEL0_WDV) && ~HPTWStall; @@ -202,13 +202,13 @@ module pagetablewalker ( assign VPN1 = TranslationVAdrQ[31:22]; assign VPN0 = TranslationVAdrQ[21:12]; - assign HPTWRead = (WalkerState == IDLE && MMUTranslate) || - WalkerState == LEVEL2 || WalkerState == LEVEL1; + //assign HPTWRead = (WalkerState == IDLE && MMUTranslate) || +// WalkerState == LEVEL2 || WalkerState == LEVEL1; // Assign combinational outputs always_comb begin // default values - TranslationPAdr = '0; + //TranslationPAdr = '0; PageTableEntry = '0; PageType ='0; DTLBWriteM = '0; @@ -216,38 +216,38 @@ module pagetablewalker ( WalkerInstrPageFaultF = '0; WalkerLoadPageFaultM = '0; WalkerStorePageFaultM = '0; - MMUStall = '1; + //MMUStall = '1; case (NextWalkerState) IDLE: begin - MMUStall = '0; + //MMUStall = '0; end LEVEL1: begin - TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00}; + //TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00}; end LEVEL1_WDV: begin - TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00}; + //TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00}; end LEVEL0: begin - TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; + //TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; end LEVEL0_WDV: begin - TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; + //TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; end LEAF: begin // Keep physical address alive to prevent HADDR dropping to 0 - TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; + //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}; + //TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; WalkerInstrPageFaultF = ~DTLBMissMQ; WalkerLoadPageFaultM = DTLBMissMQ && ~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 default: begin // nothing @@ -278,68 +278,179 @@ module pagetablewalker ( logic TerapageMisaligned, GigapageMisaligned, BadTerapage, BadGigapage; - flopenl #(4) 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 || WalkerState == LEVEL2_WDV || WalkerState == LEVEL3_WDV) && ~HPTWStall; + -----/\----- EXCLUDED -----/\----- */ - assign HPTWRead = (WalkerState == IDLE && MMUTranslate) || WalkerState == LEVEL3 || - WalkerState == LEVEL2 || WalkerState == LEVEL1; + //assign HPTWRead = (WalkerState == IDLE && MMUTranslate) || WalkerState == LEVEL3 || +// WalkerState == LEVEL2 || WalkerState == LEVEL1; always_comb begin + PRegEn = 1'b0; + TranslationPAdr = '0; + HPTWRead = 1'b0; + MMUStall = 1'b1; + + WalkerInstrPageFaultF = 1'b0; + WalkerLoadPageFaultM = 1'b0; + WalkerStorePageFaultM = 1'b0; + case (WalkerState) - IDLE: if (MMUTranslate && SvMode == `SV48) NextWalkerState = LEVEL3_WDV; - else if (MMUTranslate && SvMode == `SV39) NextWalkerState = LEVEL2_WDV; - else NextWalkerState = IDLE; + IDLE: begin + if (MMUTranslate && SvMode == `SV48) begin + NextWalkerState = LEVEL3_WDV; + TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000}; + HPTWRead = 1'b1; + end else if (MMUTranslate && SvMode == `SV39) begin + NextWalkerState = LEVEL2_WDV; + TranslationPAdr = {BasePageTablePPN, VPN2, 3'b000}; + HPTWRead = 1'b1; + end else begin + NextWalkerState = IDLE; + TranslationPAdr = '0; + MMUStall = 1'b0; + end + end - LEVEL3_WDV: if (HPTWStall) NextWalkerState = LEVEL3_WDV; - else NextWalkerState = LEVEL3; - LEVEL3: + LEVEL3_WDV: begin + TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000}; + //HPTWRead = 1'b1; + if (HPTWStall) begin + NextWalkerState = LEVEL3_WDV; + end else begin + NextWalkerState = LEVEL3; + PRegEn = 1'b1; + end + end + + LEVEL3: 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 && ~BadTerapage) begin + NextWalkerState = LEAF; + end + // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line. + else if (ValidPTE && ~LeafPTE) begin + NextWalkerState = LEVEL2_WDV; + TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000}; + HPTWRead = 1'b1; + end else begin + NextWalkerState = FAULT; + WalkerInstrPageFaultF = ~DTLBMissMQ; + WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore; + WalkerStorePageFaultM = DTLBMissMQ && MemStore; + end + + end + + LEVEL2_WDV: begin + TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000}; + //HPTWRead = 1'b1; + if (HPTWStall) begin + NextWalkerState = LEVEL2_WDV; + end else begin + NextWalkerState = LEVEL2; + PRegEn = 1'b1; + end + end + + LEVEL2: 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 && ~BadTerapage) NextWalkerState = LEAF; - // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line. - else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL2_WDV; - else NextWalkerState = FAULT; + if (ValidPTE && LeafPTE && ~BadGigapage) begin + NextWalkerState = LEAF; + end + // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line. + else if (ValidPTE && ~LeafPTE) begin + NextWalkerState = LEVEL1_WDV; + TranslationPAdr = {CurrentPPN, VPN1, 3'b000}; + HPTWRead = 1'b1; + end else begin + NextWalkerState = FAULT; + WalkerInstrPageFaultF = ~DTLBMissMQ; + WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore; + WalkerStorePageFaultM = DTLBMissMQ && MemStore; + end - LEVEL2_WDV: if (HPTWStall) NextWalkerState = LEVEL2_WDV; - else NextWalkerState = LEVEL2; - LEVEL2: - // *** 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 && ~BadGigapage) NextWalkerState = LEAF; - // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line. - else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL1_WDV; - else NextWalkerState = FAULT; + end - LEVEL1_WDV: if (HPTWStall) NextWalkerState = LEVEL1_WDV; - else NextWalkerState = LEVEL1; - LEVEL1: - // *** 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; + LEVEL1_WDV: begin + TranslationPAdr = {CurrentPPN, VPN1, 3'b000}; + //HPTWRead = 1'b1; + if (HPTWStall) begin + NextWalkerState = LEVEL1_WDV; + end else begin + NextWalkerState = LEVEL1; + PRegEn = 1'b1; + end + end - LEVEL0_WDV: if (HPTWStall) NextWalkerState = LEVEL0_WDV; - else NextWalkerState = LEVEL0; - LEVEL0: - if (ValidPTE && LeafPTE && ~AccessAlert) NextWalkerState = LEAF; - else NextWalkerState = FAULT; + 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) begin + NextWalkerState = LEAF; + 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, 3'b000}; + HPTWRead = 1'b1; + end else begin + NextWalkerState = FAULT; + WalkerInstrPageFaultF = ~DTLBMissMQ; + WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore; + WalkerStorePageFaultM = DTLBMissMQ && MemStore; + end + end + + LEVEL0_WDV: begin + TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; + //HPTWRead = 1'b1; + 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; + end else begin + NextWalkerState = FAULT; + WalkerInstrPageFaultF = ~DTLBMissMQ; + WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore; + WalkerStorePageFaultM = DTLBMissMQ && MemStore; + end + end - LEAF: NextWalkerState = IDLE; + LEAF: begin + NextWalkerState = IDLE; + MMUStall = 1'b0; + end + + FAULT: begin + NextWalkerState = IDLE; + MMUStall = 1'b0; + end + + // Default case should never happen + default: begin + NextWalkerState = IDLE; + end - FAULT: NextWalkerState = IDLE; - // Default case should never happen, but is included for linter. - default: NextWalkerState = IDLE; endcase end @@ -363,53 +474,55 @@ module pagetablewalker ( always_comb begin // default values - TranslationPAdr = '0; + //TranslationPAdr = '0; PageTableEntry = '0; PageType = '0; DTLBWriteM = '0; ITLBWriteF = '0; +/* -----\/----- EXCLUDED -----\/----- WalkerInstrPageFaultF = '0; WalkerLoadPageFaultM = '0; WalkerStorePageFaultM = '0; + -----/\----- EXCLUDED -----/\----- */ // The MMU defaults to stalling the processor - MMUStall = '1; + //MMUStall = '1; case (NextWalkerState) IDLE: begin - MMUStall = '0; + //MMUStall = '0; end LEVEL3: begin - TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000}; + //TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000}; // *** this is a huge breaking point. if we're going through level3 every time, even when sv48 is off, // what should translationPAdr be when level3 is just off? end LEVEL3_WDV: begin - TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000}; + //TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000}; // *** this is a huge breaking point. if we're going through level3 every time, even when sv48 is off, // what should translationPAdr be when level3 is just off? end LEVEL2: begin - TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000}; + //TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000}; end LEVEL2_WDV: begin - TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000}; + //TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000}; end LEVEL1: begin - TranslationPAdr = {CurrentPPN, VPN1, 3'b000}; + //TranslationPAdr = {CurrentPPN, VPN1, 3'b000}; end LEVEL1_WDV: begin - TranslationPAdr = {CurrentPPN, VPN1, 3'b000}; + //TranslationPAdr = {CurrentPPN, VPN1, 3'b000}; end LEVEL0: begin - TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; + //TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; end LEVEL0_WDV: begin - TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; + //TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; end LEAF: begin // Keep physical address alive to prevent HADDR dropping to 0 - TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; + //TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; PageTableEntry = CurrentPTE; PageType = (WalkerState == LEVEL3) ? 2'b11 : ((WalkerState == LEVEL2) ? 2'b10 : @@ -419,11 +532,13 @@ module pagetablewalker ( end FAULT: begin // Keep physical address alive to prevent HADDR dropping to 0 - TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; + //TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; +/* -----\/----- EXCLUDED -----\/----- WalkerInstrPageFaultF = ~DTLBMissMQ; WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore; WalkerStorePageFaultM = DTLBMissMQ && MemStore; - MMUStall = '0; // Drop the stall early to enter trap handling code + -----/\----- EXCLUDED -----/\----- */ + //MMUStall = '0; // Drop the stall early to enter trap handling code end default: begin // nothing diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 1bbe6124..95ae9343 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -538,9 +538,9 @@ string tests32f[] = '{ else tests = {tests, tests64iNOc}; if (`M_SUPPORTED) tests = {tests, tests64m}; if (`A_SUPPORTED) tests = {tests, tests64a}; - if (`MEM_VIRTMEM) tests = {tests, tests64mmu}; if (`D_SUPPORTED) tests = {tests64d, tests}; if (`F_SUPPORTED) tests = {tests64f, tests}; + if (`MEM_VIRTMEM) tests = {tests64mmu, tests}; end //tests = {tests64a, tests}; end else begin // RV32