From e0f719d51326a1db45bf8582f1aef28c7a217249 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Fri, 16 Jul 2021 11:12:57 -0500 Subject: [PATCH] Updated the ptw, lsuarb and dcache to hopefully solve the interlock issues. --- wally-pipelined/src/cache/dcache.sv | 67 +- wally-pipelined/src/lsu/lsu.sv | 13 +- wally-pipelined/src/lsu/lsuArb.sv | 65 +- wally-pipelined/src/mmu/pagetablewalker.sv | 778 ++++++++++----------- 4 files changed, 399 insertions(+), 524 deletions(-) diff --git a/wally-pipelined/src/cache/dcache.sv b/wally-pipelined/src/cache/dcache.sv index dc66043c..e5ef5f35 100644 --- a/wally-pipelined/src/cache/dcache.sv +++ b/wally-pipelined/src/cache/dcache.sv @@ -43,7 +43,7 @@ module dcache input logic [`XLEN-1:0] WriteDataM, output logic [`XLEN-1:0] ReadDataW, - output logic [`XLEN-1:0] ReadDataM, + output logic [`XLEN-1:0] ReadDataM, output logic DCacheStall, output logic CommittedM, @@ -53,6 +53,7 @@ module dcache input logic DTLBMissM, input logic CacheableM, input logic DTLBWriteM, + input logic SelPTW, // ahb side output logic [`PA_BITS-1:0] AHBPAdr, // to ahb output logic AHBRead, @@ -443,7 +444,13 @@ module dcache // The page table walker asserts it's control 1 cycle // after the TLBs miss. DCacheStall = 1'b1; + NextState = STATE_READY; + end + else if(SelPTW) begin + // Now we have activated the ptw. + // Do not assert Stall as we are now directing the stall the ptw. NextState = STATE_PTW_READY; + CommittedM = 1'b1; end // amo hit else if(|AtomicM & CacheableM & ~(ExceptionM | PendingInterruptM) & CacheHit & ~DTLBMissM) begin @@ -592,7 +599,7 @@ module dcache // now all output connect to PTW instead of CPU. CommittedM = 1'b1; // return to ready if page table walk completed. - if (DTLBWriteM) begin + if (~SelPTW) begin NextState = STATE_PTW_ACCESS_AFTER_WALK; // read hit valid cached @@ -650,61 +657,15 @@ module dcache STATE_PTW_READ_MISS_READ_WORD_DELAY: begin SelAdrM = 1'b1; - NextState = STATE_PTW_READY; + NextState = STATE_PTW_READY; CommittedM = 1'b1; end STATE_PTW_ACCESS_AFTER_WALK: begin - SelAdrM = 1'b1; - // amo hit - if(|AtomicM & CacheableM & ~(ExceptionM | PendingInterruptM) & CacheHit & ~DTLBMissM) begin - NextState = STATE_AMO_UPDATE; - DCacheStall = 1'b1; - - if(StallW) NextState = STATE_CPU_BUSY; - else NextState = STATE_AMO_UPDATE; - end - // read hit valid cached - else if(MemRWM[1] & CacheableM & ~(ExceptionM | PendingInterruptM) & CacheHit & ~DTLBMissM) begin - DCacheStall = 1'b0; - - if(StallW) NextState = STATE_CPU_BUSY; - else NextState = STATE_READY; - end - // write hit valid cached - else if (MemRWM[0] & CacheableM & ~(ExceptionM | PendingInterruptM) & CacheHit & ~DTLBMissM) begin - DCacheStall = 1'b0; - SRAMWordWriteEnableM = 1'b1; - SetDirtyM = 1'b1; - - if(StallW) NextState = STATE_CPU_BUSY; - else NextState = STATE_READY; - end - // read or write miss valid cached - else if((|MemRWM) & CacheableM & ~(ExceptionM | PendingInterruptM) & ~CacheHit & ~DTLBMissM) begin - NextState = STATE_MISS_FETCH_WDV; - CntReset = 1'b1; - DCacheStall = 1'b1; - end - // uncached write - else if(MemRWM[0] & ~CacheableM & ~ExceptionM & ~DTLBMissM) begin - NextState = STATE_UNCACHED_WRITE; - CntReset = 1'b1; - DCacheStall = 1'b1; - AHBWrite = 1'b1; - end - // uncached read - else if(MemRWM[1] & ~CacheableM & ~ExceptionM & ~DTLBMissM) begin - NextState = STATE_UNCACHED_READ; - CntReset = 1'b1; - DCacheStall = 1'b1; - AHBRead = 1'b1; - end - // fault - else if(AnyCPUReqM & (ExceptionM | PendingInterruptM) & ~DTLBMissM) begin - NextState = STATE_READY; - end - else NextState = STATE_READY; + DCacheStall = 1'b1; + SelAdrM = 1'b1; + CommittedM = 1'b1; + NextState = STATE_READY; end STATE_CPU_BUSY : begin diff --git a/wally-pipelined/src/lsu/lsu.sv b/wally-pipelined/src/lsu/lsu.sv index 0f38b829..56d0cb9c 100644 --- a/wally-pipelined/src/lsu/lsu.sv +++ b/wally-pipelined/src/lsu/lsu.sv @@ -126,7 +126,6 @@ module lsu logic HPTWStall; logic [`XLEN-1:0] HPTWPAdrE; logic [`XLEN-1:0] HPTWPAdrM; - logic HPTWTranslate; logic HPTWReadM; logic [1:0] MemRWMtoDCache; logic [2:0] Funct3MtoDCache; @@ -170,8 +169,8 @@ module lsu .HPTWStall(HPTWStall), .HPTWPAdrE(HPTWPAdrE), .HPTWPAdrM(HPTWPAdrM), - .HPTWTranslate(HPTWTranslate), .HPTWReadM(HPTWReadM), + .SelPTW(SelPTW), .WalkerInstrPageFaultF(WalkerInstrPageFaultF), .WalkerLoadPageFaultM(WalkerLoadPageFaultM), .WalkerStorePageFaultM(WalkerStorePageFaultM)); @@ -182,7 +181,7 @@ module lsu lsuArb arbiter(.clk(clk), .reset(reset), // HPTW connection - .HPTWTranslate(HPTWTranslate), + .SelPTW(SelPTW), .HPTWReadM(HPTWReadM), .HPTWPAdrE(HPTWPAdrE), .HPTWPAdrM(HPTWPAdrM), @@ -214,8 +213,9 @@ module lsu .ReadDataWfromDCache(ReadDataWfromDCache), .CommittedMfromDCache(CommittedMfromDCache), .PendingInterruptMtoDCache(PendingInterruptMtoDCache), - .DCacheStall(DCacheStall), - .SelPTW(SelPTW)); + .DCacheStall(DCacheStall)); + + mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0)) @@ -243,7 +243,9 @@ module lsu // .SelRegions(DHSELRegionsM), .*); // *** the pma/pmp instruction acess faults don't really matter here. is it possible to parameterize which outputs exist? + // *** BUG, this is most likely wrong assign CacheableMtoDCache = SelPTW ? 1'b1 : CacheableM; + generate if (`XLEN == 32) assign DCtoAHBSizeM = CacheableMtoDCache ? 3'b010 : Funct3MtoDCache; else assign DCtoAHBSizeM = CacheableMtoDCache ? 3'b011 : Funct3MtoDCache; @@ -335,6 +337,7 @@ module lsu .DTLBMissM(DTLBMissM), .CacheableM(CacheableMtoDCache), .DTLBWriteM(DTLBWriteM), + .SelPTW(SelPTW), // AHB connection .AHBPAdr(DCtoAHBPAdrM), diff --git a/wally-pipelined/src/lsu/lsuArb.sv b/wally-pipelined/src/lsu/lsuArb.sv index 3b3ad94f..4feec655 100644 --- a/wally-pipelined/src/lsu/lsuArb.sv +++ b/wally-pipelined/src/lsu/lsuArb.sv @@ -30,7 +30,7 @@ module lsuArb (input logic clk, reset, // from page table walker - input logic HPTWTranslate, + input logic SelPTW, input logic HPTWReadM, input logic [`XLEN-1:0] HPTWPAdrE, input logic [`XLEN-1:0] HPTWPAdrM, @@ -62,7 +62,6 @@ module lsuArb output logic [`XLEN-1:0] MemAdrEtoDCache, output logic StallWtoDCache, output logic PendingInterruptMtoDCache, - output logic SelPTW, // from D Cache @@ -73,73 +72,11 @@ module lsuArb input logic DCacheStall ); - - // HPTWTranslate is the request for memory by the page table walker. When - // this is high the page table walker gains priority over the CPU's data - // input. Note the ptw only makes a request after an instruction or data - // tlb miss. It is entirely possible the dcache is currently processing - // a data cache miss when an instruction tlb miss occurs. If an instruction - // in the E stage causes a d cache miss, the d cache will immediately start - // processing the request. Simultaneously the ITLB misses. By the time - // the TLB miss causes the page table walker to issue the first request - // 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. - typedef enum{StateReady, - StatePTWPending, - StatePTWActive} statetype; - - - statetype CurrState, NextState; logic [2:0] PTWSize; - - flopenl #(.TYPE(statetype)) StateReg(.clk(clk), - .load(reset), - .en(1'b1), - .d(NextState), - .val(StateReady), - .q(CurrState)); - - always_comb begin - case(CurrState) - StateReady: - if (HPTWTranslate) NextState = StatePTWActive; - else NextState = StateReady; - StatePTWActive: - if (HPTWTranslate) NextState = StatePTWActive; - else NextState = StateReady; - default: NextState = StateReady; - endcase - end - -/* -----\/----- EXCLUDED -----\/----- - - always_comb begin - case(CurrState) - StateReady: - /-* -----\/----- EXCLUDED -----\/----- - if (HPTWTranslate & DataStall) NextState = StatePTWPending; - else - -----/\----- EXCLUDED -----/\----- *-/ - if (HPTWTranslate) NextState = StatePTWActive; - else NextState = StateReady; - StatePTWPending: - if (HPTWTranslate & ~DataStall) NextState = StatePTWActive; - else if (HPTWTranslate & DataStall) NextState = StatePTWPending; - else NextState = StateReady; - StatePTWActive: - if (HPTWTranslate) NextState = StatePTWActive; - else NextState = StateReady; - default: NextState = StateReady; - endcase - end - - -----/\----- EXCLUDED -----/\----- */ - // multiplex the outputs to LSU assign DisableTranslation = SelPTW; // change names between SelPTW would be confusing in DTLB. - assign SelPTW = (CurrState == StatePTWActive && HPTWTranslate) || (CurrState == StateReady && HPTWTranslate); assign MemRWMtoDCache = SelPTW ? {HPTWReadM, 1'b0} : MemRWM; generate diff --git a/wally-pipelined/src/mmu/pagetablewalker.sv b/wally-pipelined/src/mmu/pagetablewalker.sv index 282d5bf2..8948badf 100644 --- a/wally-pipelined/src/mmu/pagetablewalker.sv +++ b/wally-pipelined/src/mmu/pagetablewalker.sv @@ -9,21 +9,21 @@ // // Purpose: Page Table Walker // Part of the Memory Management Unit (MMU) -// +// // A component of the Wally configurable RISC-V project. -// +// // Copyright (C) 2021 Harvey Mudd College & Oklahoma State University // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, -// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software // is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT // OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /////////////////////////////////////////// @@ -37,107 +37,94 @@ module pagetablewalker ( // Control signals - input logic clk, reset, + input logic clk, reset, input logic [`XLEN-1:0] SATP_REGW, // Signals from TLBs (addresses to translate) input logic [`XLEN-1:0] PCF, MemAdrM, - input logic ITLBMissF, DTLBMissM, - input logic [1:0] MemRWM, + input logic ITLBMissF, DTLBMissM, + input logic [1:0] MemRWM, // Outputs to the TLBs (PTEs to write) output logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM, - output logic [1:0] PageTypeF, PageTypeM, - output logic ITLBWriteF, DTLBWriteM, - - + output logic [1:0] PageTypeF, PageTypeM, + output logic ITLBWriteF, DTLBWriteM, + output logic SelPTW, // *** modify to send to LSU // *** KMG: These are inputs/results from the ahblite whose addresses should have already been checked, so I don't think they need to be sent through the LSU input logic [`XLEN-1:0] HPTWReadPTE, - input logic MMUReady, - input logic HPTWStall, + input logic MMUReady, + input logic HPTWStall, // *** modify to send to LSU output logic [`XLEN-1:0] HPTWPAdrE, // this probalby should be `PA_BITS wide - output logic [`XLEN-1:0] HPTWPAdrM, // this probalby should be `PA_BITS wide - output logic HPTWTranslate, // *** rename to HPTWReq - output logic HPTWReadM, + output logic [`XLEN-1:0] HPTWPAdrM, // this probalby should be `PA_BITS wide + output logic HPTWReadM, // Faults - output logic WalkerInstrPageFaultF, - output logic WalkerLoadPageFaultM, - output logic WalkerStorePageFaultM + output logic WalkerInstrPageFaultF, + output logic WalkerLoadPageFaultM, + output logic WalkerStorePageFaultM ); - logic HPTWReadE; + logic HPTWReadE; generate if (`MEM_VIRTMEM) begin // Internal signals // register TLBs translation miss requests - logic ITLBMissFQ, DTLBMissMQ; - - logic [`PPN_BITS-1:0] BasePageTablePPN; - logic [`XLEN-1:0] TranslationVAdr; - logic [`XLEN-1:0] SavedPTE, CurrentPTE; - logic [`PA_BITS-1:0] TranslationPAdr; - logic [`PPN_BITS-1:0] CurrentPPN; - logic [`SVMODE_BITS-1:0] SvMode; - logic MemStore; - logic DTLBWriteM_d; + logic ITLBMissFQ, DTLBMissMQ; + + logic [`PPN_BITS-1:0] BasePageTablePPN; + logic [`XLEN-1:0] TranslationVAdr; + logic [`XLEN-1:0] SavedPTE, CurrentPTE; + logic [`PA_BITS-1:0] TranslationPAdr; + logic [`PPN_BITS-1:0] CurrentPPN; + logic [`SVMODE_BITS-1:0] SvMode; + logic MemStore; // PTE Control Bits - logic Dirty, Accessed, Global, User, + logic Dirty, Accessed, Global, User, Executable, Writable, Readable, Valid; // PTE descriptions - logic ValidPTE, AccessAlert, MegapageMisaligned, BadMegapage, LeafPTE; + logic ValidPTE, AccessAlert, MegapageMisaligned, BadMegapage, LeafPTE; // Outputs of walker - logic [`XLEN-1:0] PageTableEntry; - logic [1:0] PageType; - logic StartWalk; - logic EndWalk; - - typedef enum {LEVEL0_WDV, + logic [`XLEN-1:0] PageTableEntry; + logic [1:0] PageType; + logic StartWalk; + logic EndWalk; + + typedef enum {LEVEL0_SET_ADRE, + LEVEL0_WDV, LEVEL0, + LEVEL1_SET_ADRE, LEVEL1_WDV, LEVEL1, + LEVEL2_SET_ADRE, LEVEL2_WDV, LEVEL2, + LEVEL3_SET_ADRE, LEVEL3_WDV, LEVEL3, LEAF, IDLE, - START, FAULT} statetype; - statetype WalkerState, NextWalkerState; + statetype WalkerState, NextWalkerState, PreviousWalkerState; - logic PRegEn; - logic SelDataTranslation; - - - flop #(`XLEN) HPTWPAdrMReg(.clk(clk), - .d(HPTWPAdrE), - .q(HPTWPAdrM)); + logic PRegEn; + logic SelDataTranslation; + logic AnyTLBMissM; - flop #(2) PageTypeReg(.clk(clk), - .d(PageType), - .q(PageTypeM)); - flop #(`XLEN) PageTableEntryReg(.clk(clk), - .d(PageTableEntry), - .q(PageTableEntryM)); - - flop #(1) DTLBWriteReg(.clk(clk), - .d(DTLBWriteM_d), - .q(DTLBWriteM)); - flop #(1) HPTWReadMReg(.clk(clk), - .d(HPTWReadE), - .q(HPTWReadM)); + flop #(`XLEN) HPTWPAdrMReg(.clk(clk), + .d(HPTWPAdrE), + .q(HPTWPAdrM)); + assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]; @@ -147,7 +134,7 @@ module pagetablewalker assign MemStore = MemRWM[0]; // Prefer data address translations over instruction address translations - assign TranslationVAdr = (SelDataTranslation) ? MemAdrM : PCF; // *** need to register TranslationVAdr + assign TranslationVAdr = (SelDataTranslation) ? MemAdrM : PCF; assign SelDataTranslation = DTLBMissMQ | DTLBMissM; flopenrc #(1) @@ -157,7 +144,7 @@ module pagetablewalker .clear(EndWalk), .d(DTLBMissM), .q(DTLBMissMQ)); - + flopenrc #(1) ITLBMissMReg(.clk(clk), .reset(reset), @@ -165,22 +152,16 @@ module pagetablewalker .clear(EndWalk), .d(ITLBMissF), .q(ITLBMissFQ)); - - assign StartWalk = WalkerState == IDLE && (DTLBMissM | ITLBMissF); - assign EndWalk = WalkerState == LEAF || - //(WalkerState == LEVEL0 && ValidPTE && LeafPTE && ~AccessAlert) || - //(WalkerState == LEVEL1 && ValidPTE && LeafPTE && ~AccessAlert) || - //(WalkerState == LEVEL2 && ValidPTE && LeafPTE && ~AccessAlert) || - //(WalkerState == LEVEL3 && ValidPTE && LeafPTE && ~AccessAlert) || - (WalkerState == FAULT); - - assign HPTWTranslate = (DTLBMissMQ | ITLBMissFQ); - //assign HPTWTranslate = DTLBMissM | ITLBMissF; + + assign AnyTLBMissM = DTLBMissM | ITLBMissF; + + assign StartWalk = WalkerState == IDLE & AnyTLBMissM; + assign EndWalk = WalkerState == LEAF || WalkerState == FAULT; // unswizzle PTE bits assign {Dirty, Accessed, Global, User, - Executable, Writable, Readable, Valid} = CurrentPTE[7:0]; + Executable, Writable, Readable, Valid} = CurrentPTE[7:0]; // Assign PTE descriptors common across all XLEN values assign LeafPTE = Executable | Writable | Readable; @@ -189,398 +170,391 @@ module pagetablewalker // Assign specific outputs to general outputs assign PageTableEntryF = PageTableEntry; - //assign PageTableEntryM = PageTableEntry; + assign PageTableEntryM = PageTableEntry; assign PageTypeF = PageType; - //assign PageTypeM = PageType; + assign PageTypeM = PageType; // generate if (`XLEN == 32) begin - logic [9:0] VPN1, VPN0; + logic [9:0] VPN1, VPN0; - 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 - always_comb begin + // State transition logic + always_comb begin PRegEn = 1'b0; TranslationPAdr = '0; HPTWReadE = 1'b0; - PageTableEntry = '0; - PageType = '0; - DTLBWriteM_d = '0; - ITLBWriteF = '0; - - WalkerInstrPageFaultF = 1'b0; - WalkerLoadPageFaultM = 1'b0; - WalkerStorePageFaultM = 1'b0; + PageTableEntry = '0; + PageType = '0; + DTLBWriteM = '0; + ITLBWriteF = '0; - case (WalkerState) - IDLE: begin - if (HPTWTranslate && SvMode == `SV32) begin // *** Added SvMode - NextWalkerState = START; - end else begin - NextWalkerState = IDLE; - end - end + WalkerInstrPageFaultF = 1'b0; + WalkerLoadPageFaultM = 1'b0; + WalkerStorePageFaultM = 1'b0; - START: begin - NextWalkerState = LEVEL1_WDV; - TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00}; - HPTWReadE = 1'b1; - end - - LEVEL1_WDV: begin - TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00}; - HPTWReadE = 1'b1; - if (HPTWStall) begin - NextWalkerState = LEVEL1_WDV; - end else begin - NextWalkerState = LEVEL1; + SelPTW = 1'b1; + + case (WalkerState) + IDLE: begin + SelPTW = 1'b0; + if (AnyTLBMissM & SvMode == `SV32) begin + NextWalkerState = LEVEL1_SET_ADRE; + end else begin + NextWalkerState = IDLE; + end + end + + LEVEL1_SET_ADRE: begin + NextWalkerState = LEVEL1_WDV; + TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00}; + end + + LEVEL1_WDV: begin + TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00}; + HPTWReadE = 1'b1; + 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) begin + 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) begin NextWalkerState = LEAF; - PageTableEntry = CurrentPTE; - PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00; // *** not sure about this mux? - DTLBWriteM_d = DTLBMissMQ; - ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions - TranslationPAdr = {2'b00, TranslationVAdr[31: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}; + TranslationPAdr = {2'b00, TranslationVAdr[31: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_SET_ADRE; + TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; HPTWReadE = 1'b1; - end else begin - NextWalkerState = FAULT; - end - end - - LEVEL0_WDV: begin - TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; - HPTWReadE = 1'b1; - if (HPTWStall) begin + end else begin + NextWalkerState = FAULT; + end + end + + LEVEL0_SET_ADRE: begin + NextWalkerState = LEVEL0_WDV; + TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; + end + + LEVEL0_WDV: begin + TranslationPAdr = {CurrentPPN, VPN0, 2'b00}; + HPTWReadE = 1'b1; + if (HPTWStall) begin NextWalkerState = LEVEL0_WDV; - end else begin + end else begin NextWalkerState = LEVEL0; PRegEn = 1'b1; - end - end + end + end - LEVEL0: begin - if (ValidPTE & LeafPTE & ~AccessAlert) begin - NextWalkerState = LEAF; - PageTableEntry = CurrentPTE; - PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00; - DTLBWriteM_d = DTLBMissMQ; - ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions - TranslationPAdr = {2'b00, TranslationVAdr[31:0]}; - end else begin - NextWalkerState = FAULT; - end - end - - LEAF: begin - NextWalkerState = IDLE; - end + LEVEL0: begin + if (ValidPTE & LeafPTE & ~AccessAlert) begin + NextWalkerState = LEAF; + TranslationPAdr = {2'b00, TranslationVAdr[31:0]}; + end else begin + NextWalkerState = FAULT; + end + end - FAULT: begin - NextWalkerState = IDLE; - WalkerInstrPageFaultF = ~DTLBMissMQ; - WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore; - WalkerStorePageFaultM = DTLBMissMQ && MemStore; - end - - // Default case should never happen, but is included for linter. - default: NextWalkerState = IDLE; - endcase - end + LEAF: begin + NextWalkerState = IDLE; + PageTableEntry = CurrentPTE; + PageType = (PreviousWalkerState == LEVEL1) ? 2'b01 : 2'b00; // *** not sure about this mux? + DTLBWriteM = DTLBMissMQ; + ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions + TranslationPAdr = {2'b00, TranslationVAdr[31:0]}; + end - // A megapage is a Level 1 leaf page. This page must have zero PPN[0]. - assign MegapageMisaligned = |(CurrentPPN[9:0]); - assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme + FAULT: begin + NextWalkerState = IDLE; + WalkerInstrPageFaultF = ~DTLBMissMQ; + WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore; + WalkerStorePageFaultM = DTLBMissMQ && MemStore; + end - assign VPN1 = TranslationVAdr[31:22]; - assign VPN0 = TranslationVAdr[21:12]; + // Default case should never happen, but is included for linter. + default: NextWalkerState = IDLE; + endcase + end - + // A megapage is a Level 1 leaf page. This page must have zero PPN[0]. + assign MegapageMisaligned = |(CurrentPPN[9:0]); + assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme - // Capture page table entry from data cache - // *** may need to delay reading this value until the next clock cycle. - // The clk to q latency of the SRAM in the data cache will be long. - // I cannot see directly using this value. This is no different than - // a load delay hazard. This will require rewriting the walker fsm. - // also need a new signal to save. Should be a mealy output of the fsm - // request followed by ~stall. - flopenr #(32) ptereg(clk, reset, PRegEn, HPTWReadPTE, SavedPTE); - //mux2 #(32) ptemux(SavedPTE, HPTWReadPTE, PRegEn, CurrentPTE); - assign CurrentPTE = SavedPTE; - assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10]; + assign VPN1 = TranslationVAdr[31:22]; + assign VPN0 = TranslationVAdr[21:12]; - // Assign outputs to ahblite - // *** Currently truncate address to 32 bits. This must be changed if - // we support larger physical address spaces - assign HPTWPAdrE = TranslationPAdr[31:0]; + + + // Capture page table entry from data cache + // *** may need to delay reading this value until the next clock cycle. + // The clk to q latency of the SRAM in the data cache will be long. + // I cannot see directly using this value. This is no different than + // a load delay hazard. This will require rewriting the walker fsm. + // also need a new signal to save. Should be a mealy output of the fsm + // request followed by ~stall. + flopenr #(32) ptereg(clk, reset, PRegEn, HPTWReadPTE, SavedPTE); + //mux2 #(32) ptemux(SavedPTE, HPTWReadPTE, PRegEn, CurrentPTE); + assign CurrentPTE = SavedPTE; + assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10]; + + // Assign outputs to ahblite + // *** Currently truncate address to 32 bits. This must be changed if + // we support larger physical address spaces + assign HPTWPAdrE = TranslationPAdr[31:0]; end else begin - - logic [8:0] VPN3, VPN2, VPN1, VPN0; - logic TerapageMisaligned, GigapageMisaligned, BadTerapage, BadGigapage; + logic [8:0] VPN3, VPN2, VPN1, VPN0; - flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState); + logic TerapageMisaligned, GigapageMisaligned, BadTerapage, BadGigapage; - /* -----\/----- EXCLUDED -----\/----- - assign PRegEn = (WalkerState == LEVEL1_WDV || WalkerState == LEVEL0_WDV || - WalkerState == LEVEL2_WDV || WalkerState == LEVEL3_WDV) && ~HPTWStall; - -----/\----- EXCLUDED -----/\----- */ + flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState); - //assign HPTWRead = (WalkerState == IDLE && HPTWTranslate) || WalkerState == LEVEL3 || - // WalkerState == LEVEL2 || WalkerState == LEVEL1; - + /* -----\/----- EXCLUDED -----\/----- + assign PRegEn = (WalkerState == LEVEL1_WDV || WalkerState == LEVEL0_WDV || + WalkerState == LEVEL2_WDV || WalkerState == LEVEL3_WDV) && ~HPTWStall; + -----/\----- EXCLUDED -----/\----- */ - always_comb begin + //assign HPTWRead = (WalkerState == IDLE && HPTWTranslate) || WalkerState == LEVEL3 || + // WalkerState == LEVEL2 || WalkerState == LEVEL1; + + + always_comb begin PRegEn = 1'b0; TranslationPAdr = '0; HPTWReadE = 1'b0; - PageTableEntry = '0; - PageType = '0; - DTLBWriteM_d = '0; - ITLBWriteF = '0; - - WalkerInstrPageFaultF = 1'b0; - WalkerLoadPageFaultM = 1'b0; - WalkerStorePageFaultM = 1'b0; + PageTableEntry = '0; + PageType = '0; + DTLBWriteM = '0; + ITLBWriteF = '0; - case (WalkerState) - IDLE: begin - if (HPTWTranslate && (SvMode == `SV48 || SvMode == `SV39)) begin - NextWalkerState = START; - end else begin - NextWalkerState = IDLE; - end - end + WalkerInstrPageFaultF = 1'b0; + WalkerLoadPageFaultM = 1'b0; + WalkerStorePageFaultM = 1'b0; - START: begin - if (HPTWTranslate && SvMode == `SV48) begin + SelPTW = 1'b1; + + case (WalkerState) + IDLE: begin + SelPTW = 1'b0; + if (AnyTLBMissM & SvMode == `SV48) begin + NextWalkerState = LEVEL3_SET_ADRE; + end else if (AnyTLBMissM & SvMode == `SV39) begin + NextWalkerState = LEVEL2_SET_ADRE; + end else begin + NextWalkerState = IDLE; + end + end + + LEVEL3_SET_ADRE: begin + NextWalkerState = LEVEL3_WDV; + TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000}; + end + + LEVEL3_WDV: begin + TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000}; + HPTWReadE = 1'b1; + if (HPTWStall) begin NextWalkerState = LEVEL3_WDV; - TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000}; - HPTWReadE = 1'b1; - end else if (HPTWTranslate && SvMode == `SV39) begin - NextWalkerState = LEVEL2_WDV; - TranslationPAdr = {BasePageTablePPN, VPN2, 3'b000}; - HPTWReadE = 1'b1; - end else begin // *** should not get here - NextWalkerState = IDLE; - TranslationPAdr = '0; - end - end - - LEVEL3_WDV: begin - TranslationPAdr = {BasePageTablePPN, VPN3, 3'b000}; - HPTWReadE = 1'b1; - if (HPTWStall) begin - NextWalkerState = LEVEL3_WDV; - end else begin + 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; - PageTableEntry = CurrentPTE; - PageType = (WalkerState == LEVEL3) ? 2'b11 : // *** not sure about this mux? - ((WalkerState == LEVEL2) ? 2'b10 : - ((WalkerState == LEVEL1) ? 2'b01 : 2'b00)); - DTLBWriteM_d = DTLBMissMQ; - ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions - TranslationPAdr = TranslationVAdr[`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 = LEVEL2_WDV; - TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000}; - HPTWReadE = 1'b1; - end else begin - NextWalkerState = FAULT; - end + end + 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; + TranslationPAdr = TranslationVAdr[`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 = LEVEL2_SET_ADRE; + TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000}; + end else begin + NextWalkerState = FAULT; + end + end - LEVEL2_WDV: begin - TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000}; - HPTWReadE = 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 && ~BadGigapage) begin - NextWalkerState = LEAF; - PageTableEntry = CurrentPTE; - PageType = (WalkerState == LEVEL3) ? 2'b11 : - ((WalkerState == LEVEL2) ? 2'b10 : - ((WalkerState == LEVEL1) ? 2'b01 : 2'b00)); - DTLBWriteM_d = DTLBMissMQ; - ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions - TranslationPAdr = TranslationVAdr[`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 = LEVEL1_WDV; - TranslationPAdr = {CurrentPPN, VPN1, 3'b000}; - HPTWReadE = 1'b1; - end else begin - NextWalkerState = FAULT; - end + LEVEL2_SET_ADRE: begin + NextWalkerState = LEVEL2_WDV; + TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000}; + end - end + LEVEL2_WDV: begin + TranslationPAdr = {(SvMode == `SV48) ? CurrentPPN : BasePageTablePPN, VPN2, 3'b000}; + HPTWReadE = 1'b1; + if (HPTWStall) begin + NextWalkerState = LEVEL2_WDV; + end else begin + NextWalkerState = LEVEL2; + PRegEn = 1'b1; + end + end - LEVEL1_WDV: begin - TranslationPAdr = {CurrentPPN, VPN1, 3'b000}; - HPTWReadE = 1'b1; - if (HPTWStall) begin - NextWalkerState = LEVEL1_WDV; - end else begin - NextWalkerState = LEVEL1; - 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 && ~BadGigapage) begin + NextWalkerState = LEAF; + TranslationPAdr = TranslationVAdr[`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 = LEVEL1_SET_ADRE; + TranslationPAdr = {CurrentPPN, VPN1, 3'b000}; + end else begin + NextWalkerState = FAULT; + 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) begin - NextWalkerState = LEAF; - PageTableEntry = CurrentPTE; - PageType = (WalkerState == LEVEL3) ? 2'b11 : - ((WalkerState == LEVEL2) ? 2'b10 : - ((WalkerState == LEVEL1) ? 2'b01 : 2'b00)); - DTLBWriteM_d = DTLBMissMQ; - ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions - TranslationPAdr = TranslationVAdr[`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, 3'b000}; - HPTWReadE = 1'b1; - end else begin - NextWalkerState = FAULT; - end - end + LEVEL1_SET_ADRE: begin + NextWalkerState = LEVEL1_WDV; + TranslationPAdr = {CurrentPPN, VPN1, 3'b000}; + end - LEVEL0_WDV: begin - TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; - HPTWReadE = 1'b1; - if (HPTWStall) begin - NextWalkerState = LEVEL0_WDV; - end else begin - NextWalkerState = LEVEL0; - PRegEn = 1'b1; - end - end + LEVEL1_WDV: begin + TranslationPAdr = {CurrentPPN, VPN1, 3'b000}; + HPTWReadE = 1'b1; + if (HPTWStall) begin + NextWalkerState = LEVEL1_WDV; + end else begin + NextWalkerState = LEVEL1; + PRegEn = 1'b1; + end + end - LEVEL0: begin - if (ValidPTE && LeafPTE && ~AccessAlert) begin - NextWalkerState = LEAF; - PageTableEntry = CurrentPTE; - PageType = (WalkerState == LEVEL3) ? 2'b11 : - ((WalkerState == LEVEL2) ? 2'b10 : - ((WalkerState == LEVEL1) ? 2'b01 : 2'b00)); - DTLBWriteM_d = DTLBMissMQ; - ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions - TranslationPAdr = TranslationVAdr[`PA_BITS-1:0]; - end else begin - NextWalkerState = FAULT; - end - end - - LEAF: begin - NextWalkerState = IDLE; - 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) begin + NextWalkerState = LEAF; + TranslationPAdr = TranslationVAdr[`PA_BITS-1:0]; - FAULT: begin - NextWalkerState = IDLE; - WalkerInstrPageFaultF = ~DTLBMissMQ; - WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore; - WalkerStorePageFaultM = DTLBMissMQ && MemStore; - end + end + // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line. + else if (ValidPTE && ~LeafPTE) begin + NextWalkerState = LEVEL0_SET_ADRE; + TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; + end else begin + NextWalkerState = FAULT; + end + end - // Default case should never happen - default: begin - NextWalkerState = IDLE; - end + LEVEL0_SET_ADRE: begin + NextWalkerState = LEVEL0_WDV; + TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; + end - endcase - end + LEVEL0_WDV: begin + TranslationPAdr = {CurrentPPN, VPN0, 3'b000}; + HPTWReadE = 1'b1; + if (HPTWStall) begin + NextWalkerState = LEVEL0_WDV; + end else begin + NextWalkerState = LEVEL0; + PRegEn = 1'b1; + end + end - // A terapage is a level 3 leaf page. This page must have zero PPN[2], - // zero PPN[1], and zero PPN[0] - assign TerapageMisaligned = |(CurrentPPN[26:0]); - // A gigapage is a Level 2 leaf page. This page must have zero PPN[1] and - // zero PPN[0] - assign GigapageMisaligned = |(CurrentPPN[17:0]); - // A megapage is a Level 1 leaf page. This page must have zero PPN[0]. - assign MegapageMisaligned = |(CurrentPPN[8:0]); + LEVEL0: begin + if (ValidPTE && LeafPTE && ~AccessAlert) begin + NextWalkerState = LEAF; + TranslationPAdr = TranslationVAdr[`PA_BITS-1:0]; + end else begin + NextWalkerState = FAULT; + end + end - assign BadTerapage = TerapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme - assign BadGigapage = GigapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme - assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme + LEAF: begin + PageTableEntry = CurrentPTE; + PageType = (PreviousWalkerState == LEVEL3) ? 2'b11 : // *** not sure about this mux? + ((PreviousWalkerState == LEVEL2) ? 2'b10 : + ((PreviousWalkerState == LEVEL1) ? 2'b01 : 2'b00)); + DTLBWriteM = DTLBMissMQ; + ITLBWriteF = ~DTLBMissMQ; // Prefer data over instructions + TranslationPAdr = TranslationVAdr[`PA_BITS-1:0]; + NextWalkerState = IDLE; + end - assign VPN3 = TranslationVAdr[47:39]; - assign VPN2 = TranslationVAdr[38:30]; - assign VPN1 = TranslationVAdr[29:21]; - assign VPN0 = TranslationVAdr[20:12]; + FAULT: begin + NextWalkerState = IDLE; + WalkerInstrPageFaultF = ~DTLBMissMQ; + WalkerLoadPageFaultM = DTLBMissMQ && ~MemStore; + WalkerStorePageFaultM = DTLBMissMQ && MemStore; + end + + // Default case should never happen + default: begin + NextWalkerState = IDLE; + end + + endcase + end + + // A terapage is a level 3 leaf page. This page must have zero PPN[2], + // zero PPN[1], and zero PPN[0] + assign TerapageMisaligned = |(CurrentPPN[26:0]); + // A gigapage is a Level 2 leaf page. This page must have zero PPN[1] and + // zero PPN[0] + assign GigapageMisaligned = |(CurrentPPN[17:0]); + // A megapage is a Level 1 leaf page. This page must have zero PPN[0]. + assign MegapageMisaligned = |(CurrentPPN[8:0]); + + assign BadTerapage = TerapageMisaligned || 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 VPN3 = TranslationVAdr[47:39]; + assign VPN2 = TranslationVAdr[38:30]; + assign VPN1 = TranslationVAdr[29:21]; + assign VPN0 = TranslationVAdr[20:12]; - // Capture page table entry from ahblite - flopenr #(`XLEN) ptereg(clk, reset, PRegEn, HPTWReadPTE, SavedPTE); - //mux2 #(`XLEN) ptemux(SavedPTE, HPTWReadPTE, PRegEn, CurrentPTE); - assign CurrentPTE = SavedPTE; - assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10]; + // Capture page table entry from ahblite + flopenr #(`XLEN) ptereg(clk, reset, PRegEn, HPTWReadPTE, SavedPTE); + //mux2 #(`XLEN) ptemux(SavedPTE, HPTWReadPTE, PRegEn, CurrentPTE); + assign CurrentPTE = SavedPTE; + assign CurrentPPN = CurrentPTE[`PPN_BITS+9:10]; - // Assign outputs to ahblite - // *** Currently truncate address to 32 bits. This must be changed if - // we support larger physical address spaces - assign HPTWPAdrE = {{(`XLEN-`PA_BITS){1'b0}}, TranslationPAdr[`PA_BITS-1:0]}; + // *** Major issue. We need the full virtual address here. + // When the TLB's are update it use use the orignal address + // *** Currently truncate address to 32 bits. This must be changed if + // we support larger physical address spaces + assign HPTWPAdrE = {{(`XLEN-`PA_BITS){1'b0}}, TranslationPAdr[`PA_BITS-1:0]}; end //endgenerate end else begin assign HPTWPAdrE = 0; - assign HPTWTranslate = 0; assign HPTWReadE = 0; assign WalkerInstrPageFaultF = 0; assign WalkerLoadPageFaultM = 0; assign WalkerStorePageFaultM = 0; + assign SelPTW = 0; end endgenerate