2021-03-18 18:35:46 +00:00
///////////////////////////////////////////
// pagetablewalker.sv
//
// Written: tfleming@hmc.edu 2 March 2021
2021-06-01 21:50:37 +00:00
// Modified: kmacsaigoren@hmc.edu 1 June 2021
// implemented SV48 on top of SV39. This included, adding a level of the FSM for the extra page number segment
// adding support for terapage encoding, and for setting the TranslationPAdr using the new level,
// adding the internal SvMode signal
2021-03-18 18:35:46 +00:00
//
// 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
// 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
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include " wally-config.vh "
2021-03-31 02:19:27 +00:00
/ * * * *
2021-07-01 22:17:53 +00:00
TO - DO:
- Implement faults on accessed / dirty behavior
*/
2021-03-18 18:35:46 +00:00
2021-07-01 22:17:53 +00:00
module pagetablewalker
(
// Control signals
input logic clk , reset ,
input logic [ `XLEN - 1 : 0 ] SATP_REGW ,
2021-03-18 18:35:46 +00:00
2021-07-01 22:17:53 +00:00
// Signals from TLBs (addresses to translate)
input logic [ `XLEN - 1 : 0 ] PCF , MemAdrM ,
input logic ITLBMissF , DTLBMissM ,
input logic [ 1 : 0 ] MemRWM ,
2021-03-18 18:35:46 +00:00
2021-07-01 22:17:53 +00:00
// Outputs to the TLBs (PTEs to write)
output logic [ `XLEN - 1 : 0 ] PageTableEntryF , PageTableEntryM ,
output logic [ 1 : 0 ] PageTypeF , PageTypeM ,
output logic ITLBWriteF , DTLBWriteM ,
2021-03-18 18:35:46 +00:00
2021-06-23 21:43:22 +00:00
2021-07-01 22:17:53 +00:00
// *** 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
2021-07-08 23:03:52 +00:00
input logic [ `XLEN - 1 : 0 ] HPTWReadPTE ,
2021-07-01 22:17:53 +00:00
input logic MMUReady ,
input logic HPTWStall ,
2021-03-18 18:35:46 +00:00
2021-07-01 22:17:53 +00:00
// *** modify to send to LSU
2021-07-15 03:26:07 +00:00
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
2021-07-08 23:03:52 +00:00
output logic HPTWTranslate , // *** rename to HPTWReq
2021-07-15 03:26:07 +00:00
output logic HPTWReadM ,
2021-06-23 21:43:22 +00:00
2021-07-01 22:17:53 +00:00
// Faults
output logic WalkerInstrPageFaultF ,
output logic WalkerLoadPageFaultM ,
output logic WalkerStorePageFaultM
) ;
2021-03-18 18:35:46 +00:00
2021-07-15 03:26:07 +00:00
logic HPTWReadE ;
2021-03-18 18:35:46 +00:00
generate
2021-07-06 03:35:44 +00:00
if ( `MEM_VIRTMEM ) begin
// Internal signals
// register TLBs translation miss requests
2021-07-15 03:26:07 +00:00
logic ITLBMissFQ , DTLBMissMQ ;
2021-06-30 16:24:26 +00:00
2021-07-15 03:26:07 +00:00
logic [ `PPN_BITS - 1 : 0 ] BasePageTablePPN ;
2021-07-06 03:35:44 +00:00
logic [ `XLEN - 1 : 0 ] TranslationVAdr ;
logic [ `XLEN - 1 : 0 ] SavedPTE , CurrentPTE ;
logic [ `PA_BITS - 1 : 0 ] TranslationPAdr ;
2021-07-15 03:26:07 +00:00
logic [ `PPN_BITS - 1 : 0 ] CurrentPPN ;
logic [ `SVMODE_BITS - 1 : 0 ] SvMode ;
logic MemStore ;
2021-07-15 22:30:29 +00:00
logic DTLBWriteM_d ;
2021-07-06 03:35:44 +00:00
// PTE Control Bits
2021-07-15 03:26:07 +00:00
logic Dirty , Accessed , Global , User ,
Executable , Writable , Readable , Valid ;
2021-07-06 03:35:44 +00:00
// PTE descriptions
2021-07-15 03:26:07 +00:00
logic ValidPTE , AccessAlert , MegapageMisaligned , BadMegapage , LeafPTE ;
2021-07-06 03:35:44 +00:00
// Outputs of walker
logic [ `XLEN - 1 : 0 ] PageTableEntry ;
logic [ 1 : 0 ] PageType ;
2021-07-15 03:26:07 +00:00
logic StartWalk ;
logic EndWalk ;
2021-07-06 03:35:44 +00:00
typedef enum { LEVEL0_WDV ,
2021-07-15 03:26:07 +00:00
LEVEL0 ,
LEVEL1_WDV ,
LEVEL1 ,
LEVEL2_WDV ,
LEVEL2 ,
LEVEL3_WDV ,
LEVEL3 ,
LEAF ,
IDLE ,
START ,
FAULT } statetype ;
2021-07-06 03:35:44 +00:00
statetype WalkerState , NextWalkerState ;
2021-07-15 03:26:07 +00:00
logic PRegEn ;
logic SelDataTranslation ;
2021-07-06 03:35:44 +00:00
2021-07-15 03:26:07 +00:00
flop # ( `XLEN ) HPTWPAdrMReg ( . clk ( clk ) ,
. d ( HPTWPAdrE ) ,
. q ( HPTWPAdrM ) ) ;
2021-07-15 22:30:29 +00:00
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 ) ) ;
2021-07-15 03:26:07 +00:00
flop # ( 1 ) HPTWReadMReg ( . clk ( clk ) ,
. d ( HPTWReadE ) ,
. q ( HPTWReadM ) ) ;
2021-07-06 03:35:44 +00:00
assign SvMode = SATP_REGW [ `XLEN - 1 : `XLEN - `SVMODE_BITS ] ;
assign BasePageTablePPN = SATP_REGW [ `PPN_BITS - 1 : 0 ] ;
assign MemStore = MemRWM [ 0 ] ;
// Prefer data address translations over instruction address translations
assign TranslationVAdr = ( SelDataTranslation ) ? MemAdrM : PCF ; // *** need to register TranslationVAdr
assign SelDataTranslation = DTLBMissMQ | DTLBMissM ;
flopenrc # ( 1 )
DTLBMissMReg ( . clk ( clk ) ,
2021-07-15 03:26:07 +00:00
. reset ( reset ) ,
. en ( StartWalk | EndWalk ) ,
. clear ( EndWalk ) ,
. d ( DTLBMissM ) ,
. q ( DTLBMissMQ ) ) ;
2021-07-06 03:35:44 +00:00
flopenrc # ( 1 )
ITLBMissMReg ( . clk ( clk ) ,
2021-07-15 03:26:07 +00:00
. reset ( reset ) ,
. en ( StartWalk | EndWalk ) ,
. clear ( EndWalk ) ,
. d ( ITLBMissF ) ,
. q ( ITLBMissFQ ) ) ;
2021-06-22 17:29:49 +00:00
2021-03-25 06:48:40 +00:00
2021-07-06 03:35:44 +00:00
assign StartWalk = WalkerState = = IDLE & & ( DTLBMissM | ITLBMissF ) ;
assign EndWalk = WalkerState = = LEAF | |
2021-07-15 03:26:07 +00:00
//(WalkerState == LEVEL0 && ValidPTE && LeafPTE && ~AccessAlert) ||
2021-07-15 22:30:29 +00:00
//(WalkerState == LEVEL1 && ValidPTE && LeafPTE && ~AccessAlert) ||
//(WalkerState == LEVEL2 && ValidPTE && LeafPTE && ~AccessAlert) ||
//(WalkerState == LEVEL3 && ValidPTE && LeafPTE && ~AccessAlert) ||
2021-07-15 03:26:07 +00:00
( WalkerState = = FAULT ) ;
2021-06-30 16:24:26 +00:00
2021-07-15 16:00:42 +00:00
assign HPTWTranslate = ( DTLBMissMQ | ITLBMissFQ ) ;
2021-07-08 23:03:52 +00:00
//assign HPTWTranslate = DTLBMissM | ITLBMissF;
2021-07-06 03:35:44 +00:00
// unswizzle PTE bits
assign { Dirty , Accessed , Global , User ,
Executable , Writable , Readable , Valid } = CurrentPTE [ 7 : 0 ] ;
// Assign PTE descriptors common across all XLEN values
assign LeafPTE = Executable | Writable | Readable ;
assign ValidPTE = Valid & & ~ ( Writable & & ~ Readable ) ;
assign AccessAlert = ~ Accessed | ( MemStore & ~ Dirty ) ;
// Assign specific outputs to general outputs
assign PageTableEntryF = PageTableEntry ;
2021-07-15 22:30:29 +00:00
//assign PageTableEntryM = PageTableEntry;
2021-07-06 03:35:44 +00:00
assign PageTypeF = PageType ;
2021-07-15 22:30:29 +00:00
//assign PageTypeM = PageType;
2021-07-06 03:35:44 +00:00
2021-07-15 03:26:07 +00:00
// generate
if ( `XLEN = = 32 ) begin
logic [ 9 : 0 ] VPN1 , VPN0 ;
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 ;
HPTWReadE = 1 'b0 ;
PageTableEntry = '0 ;
PageType = '0 ;
2021-07-15 22:30:29 +00:00
DTLBWriteM_d = '0 ;
2021-07-15 03:26:07 +00:00
ITLBWriteF = '0 ;
WalkerInstrPageFaultF = 1 'b0 ;
WalkerLoadPageFaultM = 1 'b0 ;
WalkerStorePageFaultM = 1 'b0 ;
case ( WalkerState )
IDLE: begin
if ( HPTWTranslate & & SvMode = = `SV32 ) begin // *** Added SvMode
NextWalkerState = START ;
end else begin
NextWalkerState = IDLE ;
end
end
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 ;
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 ) begin
NextWalkerState = LEAF ;
PageTableEntry = CurrentPTE ;
PageType = ( WalkerState = = LEVEL1 ) ? 2 'b01 : 2 'b00 ; // *** not sure about this mux?
2021-07-15 22:30:29 +00:00
DTLBWriteM_d = DTLBMissMQ ;
2021-07-15 03:26:07 +00:00
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 } ;
HPTWReadE = 1 'b1 ;
end else begin
NextWalkerState = FAULT ;
end
end
LEVEL0_WDV: begin
TranslationPAdr = { CurrentPPN , VPN0 , 2 'b00 } ;
HPTWReadE = 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 ;
PageTableEntry = CurrentPTE ;
PageType = ( WalkerState = = LEVEL1 ) ? 2 'b01 : 2 'b00 ;
2021-07-15 22:30:29 +00:00
DTLBWriteM_d = DTLBMissMQ ;
2021-07-15 03:26:07 +00:00
ITLBWriteF = ~ DTLBMissMQ ; // Prefer data over instructions
TranslationPAdr = { 2 'b00 , TranslationVAdr [ 31 : 0 ] } ;
end else begin
NextWalkerState = FAULT ;
end
end
LEAF: begin
NextWalkerState = IDLE ;
end
2021-07-15 22:30:29 +00:00
2021-07-15 03:26:07 +00:00
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
2021-07-06 03:35:44 +00:00
2021-07-15 03:26:07 +00:00
// 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
2021-07-06 03:35:44 +00:00
2021-07-15 03:26:07 +00:00
assign VPN1 = TranslationVAdr [ 31 : 22 ] ;
assign VPN0 = TranslationVAdr [ 21 : 12 ] ;
2021-07-06 03:35:44 +00:00
2021-07-15 03:26:07 +00:00
// 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
2021-07-06 03:35:44 +00:00
2021-07-15 03:26:07 +00:00
logic [ 8 : 0 ] VPN3 , VPN2 , VPN1 , VPN0 ;
2021-07-06 03:35:44 +00:00
2021-07-15 03:26:07 +00:00
logic TerapageMisaligned , GigapageMisaligned , BadTerapage , BadGigapage ;
2021-07-06 03:35:44 +00:00
2021-07-15 03:26:07 +00:00
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 && HPTWTranslate) || WalkerState == LEVEL3 ||
// WalkerState == LEVEL2 || WalkerState == LEVEL1;
2021-07-06 03:35:44 +00:00
2021-07-15 03:26:07 +00:00
always_comb begin
PRegEn = 1 'b0 ;
TranslationPAdr = '0 ;
HPTWReadE = 1 'b0 ;
PageTableEntry = '0 ;
PageType = '0 ;
2021-07-15 22:30:29 +00:00
DTLBWriteM_d = '0 ;
2021-07-15 03:26:07 +00:00
ITLBWriteF = '0 ;
WalkerInstrPageFaultF = 1 'b0 ;
WalkerLoadPageFaultM = 1 'b0 ;
WalkerStorePageFaultM = 1 'b0 ;
case ( WalkerState )
IDLE: begin
if ( HPTWTranslate & & ( SvMode = = `SV48 | | SvMode = = `SV39 ) ) begin
NextWalkerState = START ;
end else begin
NextWalkerState = IDLE ;
2021-07-06 03:35:44 +00:00
end
2021-07-15 03:26:07 +00:00
end
2021-07-06 03:35:44 +00:00
2021-07-15 03:26:07 +00:00
START: begin
if ( HPTWTranslate & & SvMode = = `SV48 ) 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
NextWalkerState = LEVEL3 ;
PRegEn = 1 'b1 ;
end
end
LEVEL3: 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 & & ~ 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 ) ) ;
2021-07-15 22:30:29 +00:00
DTLBWriteM_d = DTLBMissMQ ;
2021-07-15 03:26:07 +00:00
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 ;
2021-07-06 03:35:44 +00:00
TranslationPAdr = { ( SvMode = = `SV48 ) ? CurrentPPN : BasePageTablePPN , VPN2 , 3 'b000 } ;
2021-07-15 03:26:07 +00:00
HPTWReadE = 1 'b1 ;
end else begin
NextWalkerState = FAULT ;
2021-07-06 03:35:44 +00:00
end
2021-07-15 03:26:07 +00:00
end
2021-07-06 03:35:44 +00:00
2021-07-15 03:26:07 +00:00
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
// *** <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 & & ~ BadGigapage ) begin
NextWalkerState = LEAF ;
PageTableEntry = CurrentPTE ;
PageType = ( WalkerState = = LEVEL3 ) ? 2 'b11 :
( ( WalkerState = = LEVEL2 ) ? 2 'b10 :
( ( WalkerState = = LEVEL1 ) ? 2 'b01 : 2 'b00 ) ) ;
2021-07-15 22:30:29 +00:00
DTLBWriteM_d = DTLBMissMQ ;
2021-07-15 03:26:07 +00:00
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 ;
2021-07-06 03:35:44 +00:00
TranslationPAdr = { CurrentPPN , VPN1 , 3 'b000 } ;
2021-07-15 03:26:07 +00:00
HPTWReadE = 1 'b1 ;
end else begin
NextWalkerState = FAULT ;
2021-07-06 03:35:44 +00:00
end
2021-07-15 03:26:07 +00:00
end
2021-07-06 03:35:44 +00:00
2021-07-15 03:26:07 +00:00
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 ;
2021-07-06 03:35:44 +00:00
end
2021-07-15 03:26:07 +00:00
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 ) begin
NextWalkerState = LEAF ;
PageTableEntry = CurrentPTE ;
PageType = ( WalkerState = = LEVEL3 ) ? 2 'b11 :
( ( WalkerState = = LEVEL2 ) ? 2 'b10 :
( ( WalkerState = = LEVEL1 ) ? 2 'b01 : 2 'b00 ) ) ;
2021-07-15 22:30:29 +00:00
DTLBWriteM_d = DTLBMissMQ ;
2021-07-15 03:26:07 +00:00
ITLBWriteF = ~ DTLBMissMQ ; // Prefer data over instructions
TranslationPAdr = TranslationVAdr [ `PA_BITS - 1 : 0 ] ;
2021-07-06 03:35:44 +00:00
end
2021-07-15 03:26:07 +00:00
// 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 ;
2021-07-06 03:35:44 +00:00
end
2021-07-15 03:26:07 +00:00
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 ;
2021-07-06 03:35:44 +00:00
end
2021-07-15 03:26:07 +00:00
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 ) ) ;
2021-07-15 22:30:29 +00:00
DTLBWriteM_d = DTLBMissMQ ;
2021-07-15 03:26:07 +00:00
ITLBWriteF = ~ DTLBMissMQ ; // Prefer data over instructions
TranslationPAdr = TranslationVAdr [ `PA_BITS - 1 : 0 ] ;
end else begin
NextWalkerState = FAULT ;
2021-07-06 03:35:44 +00:00
end
2021-07-15 03:26:07 +00:00
end
LEAF: begin
NextWalkerState = IDLE ;
end
FAULT: begin
NextWalkerState = IDLE ;
WalkerInstrPageFaultF = ~ DTLBMissMQ ;
WalkerLoadPageFaultM = DTLBMissMQ & & ~ MemStore ;
WalkerStorePageFaultM = DTLBMissMQ & & MemStore ;
end
// Default case should never happen
default : begin
NextWalkerState = IDLE ;
end
endcase
2021-07-06 03:35:44 +00:00
end
2021-07-15 03:26:07 +00:00
// 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 ] ;
// 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 ] } ;
end
2021-07-06 03:35:44 +00:00
//endgenerate
end else begin
2021-07-15 03:26:07 +00:00
assign HPTWPAdrE = 0 ;
2021-07-08 23:03:52 +00:00
assign HPTWTranslate = 0 ;
2021-07-15 03:26:07 +00:00
assign HPTWReadE = 0 ;
2021-07-06 03:35:44 +00:00
assign WalkerInstrPageFaultF = 0 ;
assign WalkerLoadPageFaultM = 0 ;
assign WalkerStorePageFaultM = 0 ;
2021-03-25 06:48:40 +00:00
end
endgenerate
2021-03-18 18:35:46 +00:00
2021-04-13 16:27:12 +00:00
endmodule