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
/ * * * *
TO - DO:
2021-06-07 13:46:52 +00:00
- Implement faults on accessed / dirty behavior
2021-03-31 02:19:27 +00:00
*/
2021-03-18 18:35:46 +00:00
2021-03-31 02:19:27 +00:00
module pagetablewalker (
// Control signals
2021-06-24 18:47:10 +00:00
input logic clk , reset ,
2021-03-18 18:35:46 +00:00
input logic [ `XLEN - 1 : 0 ] SATP_REGW ,
2021-03-31 02:19:27 +00:00
// Signals from TLBs (addresses to translate)
2021-03-18 18:35:46 +00:00
input logic [ `XLEN - 1 : 0 ] PCF , MemAdrM ,
2021-03-31 02:19:27 +00:00
input logic ITLBMissF , DTLBMissM ,
input logic [ 1 : 0 ] MemRWM ,
2021-03-18 18:35:46 +00:00
2021-03-31 02:19:27 +00:00
// Outputs to the TLBs (PTEs to write)
2021-03-18 18:35:46 +00:00
output logic [ `XLEN - 1 : 0 ] PageTableEntryF , PageTableEntryM ,
2021-04-08 06:44:59 +00:00
output logic [ 1 : 0 ] PageTypeF , PageTypeM ,
2021-03-18 18:35:46 +00:00
output logic ITLBWriteF , DTLBWriteM ,
2021-06-23 21:43:22 +00:00
2021-06-23 23:59:06 +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-03-18 18:35:46 +00:00
input logic [ `XLEN - 1 : 0 ] MMUReadPTE ,
input logic MMUReady ,
2021-06-28 22:26:11 +00:00
input logic HPTWStall ,
2021-03-18 18:35:46 +00:00
2021-06-23 21:43:22 +00:00
// *** modify to send to LSU
2021-03-18 18:35:46 +00:00
output logic [ `XLEN - 1 : 0 ] MMUPAdr ,
2021-06-23 21:43:22 +00:00
output logic MMUTranslate , // *** rename to HPTWReq
2021-03-25 06:48:40 +00:00
2021-04-22 05:51:38 +00:00
// Stall signal
output logic MMUStall ,
2021-03-25 06:48:40 +00:00
// Faults
2021-04-21 23:58:36 +00:00
output logic WalkerInstrPageFaultF ,
output logic WalkerLoadPageFaultM ,
output logic WalkerStorePageFaultM
2021-03-18 18:35:46 +00:00
) ;
2021-03-31 02:19:27 +00:00
// Internal signals
2021-06-24 18:47:10 +00:00
// register TLBs translation miss requests
logic [ `XLEN - 1 : 0 ] TranslationVAdrQ ;
logic ITLBMissFQ , DTLBMissMQ ;
2021-03-18 18:35:46 +00:00
logic [ `PPN_BITS - 1 : 0 ] BasePageTablePPN ;
2021-03-31 02:19:27 +00:00
logic [ `XLEN - 1 : 0 ] TranslationVAdr ;
logic [ `XLEN - 1 : 0 ] SavedPTE , CurrentPTE ;
logic [ `PA_BITS - 1 : 0 ] TranslationPAdr ;
logic [ `PPN_BITS - 1 : 0 ] CurrentPPN ;
2021-06-01 21:50:37 +00:00
logic [ `SVMODE_BITS - 1 : 0 ] SvMode ;
2021-03-31 02:19:27 +00:00
logic MemStore ;
2021-03-18 18:35:46 +00:00
2021-03-31 02:19:27 +00:00
// PTE Control Bits
logic Dirty , Accessed , Global , User ,
Executable , Writable , Readable , Valid ;
// PTE descriptions
logic ValidPTE , AccessAlert , MegapageMisaligned , BadMegapage , LeafPTE ;
2021-03-18 18:35:46 +00:00
2021-04-08 06:44:59 +00:00
// Outputs of walker
logic [ `XLEN - 1 : 0 ] PageTableEntry ;
logic [ 1 : 0 ] PageType ;
2021-06-01 21:50:37 +00:00
assign SvMode = SATP_REGW [ `XLEN - 1 : `XLEN - `SVMODE_BITS ] ;
2021-03-18 18:35:46 +00:00
assign BasePageTablePPN = SATP_REGW [ `PPN_BITS - 1 : 0 ] ;
2021-03-31 02:19:27 +00:00
assign MemStore = MemRWM [ 0 ] ;
2021-03-25 06:48:40 +00:00
// Prefer data address translations over instruction address translations
2021-06-24 18:47:10 +00:00
assign TranslationVAdr = ( DTLBMissM ) ? MemAdrM : PCF ; // *** need to register TranslationVAdr
flopenr # ( `XLEN )
TranslationVAdrReg ( . clk ( clk ) ,
. reset ( reset ) ,
. en ( 1 'b1 ) , // *** use enable later to save power
. d ( TranslationVAdr ) ,
. q ( TranslationVAdrQ ) ) ;
flopr # ( 1 )
DTLBMissMReg ( . clk ( clk ) ,
. reset ( reset ) ,
. d ( DTLBMissM ) ,
. q ( DTLBMissMQ ) ) ;
flopr # ( 1 )
ITLBMissMReg ( . clk ( clk ) ,
. reset ( reset ) ,
. d ( ITLBMissF ) ,
. q ( ITLBMissFQ ) ) ;
assign MMUTranslate = DTLBMissMQ | ITLBMissFQ ;
2021-03-18 18:35:46 +00:00
2021-03-31 02:19:27 +00:00
// unswizzle PTE bits
assign { Dirty , Accessed , Global , User ,
Executable , Writable , Readable , Valid } = CurrentPTE [ 7 : 0 ] ;
2021-04-04 01:28:24 +00:00
2021-03-31 02:19:27 +00:00
// Assign PTE descriptors common across all XLEN values
assign LeafPTE = Executable | Writable | Readable ;
assign ValidPTE = Valid & & ~ ( Writable & & ~ Readable ) ;
2021-06-24 18:47:10 +00:00
assign AccessAlert = ~ Accessed | ( MemStore & ~ Dirty ) ;
2021-03-31 02:19:27 +00:00
2021-04-08 06:44:59 +00:00
// Assign specific outputs to general outputs
assign PageTableEntryF = PageTableEntry ;
assign PageTableEntryM = PageTableEntry ;
assign PageTypeF = PageType ;
assign PageTypeM = PageType ;
2021-06-28 22:26:11 +00:00
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 ;
2021-06-01 21:50:37 +00:00
// space left for more levels
2021-06-28 22:26:11 +00:00
localparam LEAF = 4 'h5 ;
localparam IDLE = 4 'h6 ;
localparam FAULT = 4 'h7 ;
2021-04-13 16:27:12 +00:00
2021-06-28 22:26:11 +00:00
logic [ 3 : 0 ] WalkerState , NextWalkerState ;
logic PRegEn ;
2021-04-13 16:27:12 +00:00
2021-03-18 18:35:46 +00:00
generate
if ( `XLEN = = 32 ) begin
2021-03-31 02:19:27 +00:00
logic [ 9 : 0 ] VPN1 , VPN0 ;
2021-03-18 18:35:46 +00:00
2021-06-24 18:47:10 +00:00
flopenl # ( 3 ) mmureg ( clk , reset , 1 'b1 , NextWalkerState , IDLE , WalkerState ) ;
2021-03-18 18:35:46 +00:00
2021-06-28 22:26:11 +00:00
assign PRegEn = ( WalkerState = = LEVEL1 | | WalkerState = = LEVEL0 ) & & ~ HPTWStall ;
2021-03-31 02:19:27 +00:00
// State transition logic
2021-03-18 18:35:46 +00:00
always_comb begin
case ( WalkerState )
2021-06-28 22:26:11 +00:00
IDLE: if ( MMUTranslate ) NextWalkerState = LEVEL1_WDV ;
2021-03-25 06:48:40 +00:00
else NextWalkerState = IDLE ;
2021-06-28 22:26:11 +00:00
LEVEL1_WDV: if ( HPTWStall ) NextWalkerState = LEVEL1_WDV ;
else NextWalkerState = LEVEL1 ;
LEVEL1:
2021-05-14 11:12:32 +00:00
// *** <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.
2021-06-28 22:26:11 +00:00
if ( ValidPTE & & LeafPTE & & ~ BadMegapage ) NextWalkerState = LEAF ;
2021-05-14 12:06:07 +00:00
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
2021-06-28 22:26:11 +00:00
else if ( ValidPTE & & ~ LeafPTE ) NextWalkerState = LEVEL0_WDV ;
2021-03-25 06:48:40 +00:00
else NextWalkerState = FAULT ;
2021-06-28 22:26:11 +00:00
LEVEL0_WDV: if ( HPTWStall ) NextWalkerState = LEVEL0_WDV ;
else NextWalkerState = LEVEL0 ;
LEVEL0: if ( ValidPTE & & LeafPTE & & ~ AccessAlert )
2021-03-25 06:48:40 +00:00
NextWalkerState = LEAF ;
else NextWalkerState = FAULT ;
2021-06-28 22:26:11 +00:00
LEAF: if ( MMUTranslate ) NextWalkerState = LEVEL1_WDV ;
2021-03-25 06:48:40 +00:00
else NextWalkerState = IDLE ;
2021-06-28 22:26:11 +00:00
FAULT: if ( MMUTranslate ) NextWalkerState = LEVEL1_WDV ;
2021-03-25 06:48:40 +00:00
else NextWalkerState = IDLE ;
2021-04-13 23:19:58 +00:00
// Default case should never happen, but is included for linter.
default : NextWalkerState = IDLE ;
2021-03-18 18:35:46 +00:00
endcase
end
2021-03-25 06:48:40 +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-06-24 18:47:10 +00:00
assign VPN1 = TranslationVAdrQ [ 31 : 22 ] ;
assign VPN0 = TranslationVAdrQ [ 21 : 12 ] ;
2021-03-31 02:19:27 +00:00
// Assign combinational outputs
always_comb begin
// default values
2021-04-13 16:27:12 +00:00
TranslationPAdr = '0 ;
PageTableEntry = '0 ;
PageType = '0 ;
DTLBWriteM = '0 ;
ITLBWriteF = '0 ;
2021-04-21 23:58:36 +00:00
WalkerInstrPageFaultF = '0 ;
WalkerLoadPageFaultM = '0 ;
WalkerStorePageFaultM = '0 ;
2021-04-22 05:51:38 +00:00
MMUStall = '1 ;
2021-06-28 22:26:11 +00:00
2021-03-31 02:19:27 +00:00
case ( NextWalkerState )
2021-04-22 05:51:38 +00:00
IDLE: begin
MMUStall = '0 ;
end
2021-03-31 02:19:27 +00:00
LEVEL1: begin
2021-04-13 16:27:12 +00:00
TranslationPAdr = { BasePageTablePPN , VPN1 , 2 'b00 } ;
2021-03-31 02:19:27 +00:00
end
2021-06-28 22:26:11 +00:00
LEVEL1_WDV: begin
TranslationPAdr = { BasePageTablePPN , VPN1 , 2 'b00 } ;
end
2021-03-31 02:19:27 +00:00
LEVEL0: begin
2021-04-13 16:27:12 +00:00
TranslationPAdr = { CurrentPPN , VPN0 , 2 'b00 } ;
2021-03-31 02:19:27 +00:00
end
2021-06-28 22:26:11 +00:00
LEVEL0_WDV: begin
TranslationPAdr = { CurrentPPN , VPN0 , 2 'b00 } ;
end
2021-03-31 02:19:27 +00:00
LEAF: begin
// Keep physical address alive to prevent HADDR dropping to 0
2021-04-13 16:27:12 +00:00
TranslationPAdr = { CurrentPPN , VPN0 , 2 'b00 } ;
PageTableEntry = CurrentPTE ;
PageType = ( WalkerState = = LEVEL1 ) ? 2 'b01 : 2 'b00 ;
2021-06-24 18:47:10 +00:00
DTLBWriteM = DTLBMissMQ ;
ITLBWriteF = ~ DTLBMissMQ ; // Prefer data over instructions
2021-03-31 02:19:27 +00:00
end
FAULT: begin
2021-04-13 16:27:12 +00:00
TranslationPAdr = { CurrentPPN , VPN0 , 2 'b00 } ;
2021-06-24 18:47:10 +00:00
WalkerInstrPageFaultF = ~ DTLBMissMQ ;
WalkerLoadPageFaultM = DTLBMissMQ & & ~ MemStore ;
WalkerStorePageFaultM = DTLBMissMQ & & MemStore ;
2021-04-22 05:51:38 +00:00
MMUStall = '0 ; // Drop the stall early to enter trap handling code
2021-03-31 02:19:27 +00:00
end
2021-04-13 23:19:58 +00:00
default : begin
// nothing
end
2021-03-31 02:19:27 +00:00
endcase
end
2021-06-28 22:26:11 +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 , MMUReadPTE , SavedPTE ) ;
//mux2 #(32) ptemux(SavedPTE, MMUReadPTE, PRegEn, CurrentPTE);
assign CurrentPTE = SavedPTE ;
2021-03-31 02:19:27 +00:00
assign CurrentPPN = CurrentPTE [ `PPN_BITS + 9 : 10 ] ;
2021-03-25 06:48:40 +00:00
// Assign outputs to ahblite
// *** Currently truncate address to 32 bits. This must be changed if
// we support larger physical address spaces
assign MMUPAdr = TranslationPAdr [ 31 : 0 ] ;
2021-03-18 18:35:46 +00:00
end else begin
2021-06-22 17:29:49 +00:00
2021-06-01 21:50:37 +00:00
logic [ 8 : 0 ] VPN3 , VPN2 , VPN1 , VPN0 ;
2021-03-25 06:48:40 +00:00
2021-06-01 21:50:37 +00:00
logic TerapageMisaligned , GigapageMisaligned , BadTerapage , BadGigapage ;
2021-03-25 06:48:40 +00:00
2021-06-28 22:26:11 +00:00
flopenl # ( 4 ) mmureg ( clk , reset , 1 'b1 , NextWalkerState , IDLE , WalkerState ) ;
assign PRegEn = ( WalkerState = = LEVEL1 | | WalkerState = = LEVEL0 | |
WalkerState = = LEVEL2 | | WalkerState = = LEVEL3 ) & & ~ HPTWStall ;
2021-03-25 06:48:40 +00:00
always_comb begin
case ( WalkerState )
2021-06-28 22:26:11 +00:00
IDLE: if ( MMUTranslate & & SvMode = = `SV48 ) NextWalkerState = LEVEL3_WDV ;
else if ( MMUTranslate & & SvMode = = `SV39 ) NextWalkerState = LEVEL2_WDV ;
2021-06-22 15:21:11 +00:00
else NextWalkerState = IDLE ;
2021-06-28 22:26:11 +00:00
LEVEL3_WDV: if ( HPTWStall ) NextWalkerState = LEVEL3_WDV ;
else NextWalkerState = LEVEL3 ;
LEVEL3:
2021-06-22 15:21:11 +00:00
// *** <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.
2021-06-28 22:26:11 +00:00
if ( ValidPTE & & LeafPTE & & ~ BadTerapage ) NextWalkerState = LEAF ;
2021-06-22 15:21:11 +00:00
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
2021-06-28 22:26:11 +00:00
else if ( ValidPTE & & ~ LeafPTE ) NextWalkerState = LEVEL2_WDV ;
2021-06-22 15:21:11 +00:00
else NextWalkerState = FAULT ;
2021-06-28 22:26:11 +00:00
LEVEL2_WDV: if ( HPTWStall ) NextWalkerState = LEVEL2_WDV ;
else NextWalkerState = LEVEL2 ;
LEVEL2:
2021-05-14 11:12:32 +00:00
// *** <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.
2021-06-28 22:26:11 +00:00
if ( ValidPTE & & LeafPTE & & ~ BadGigapage ) NextWalkerState = LEAF ;
2021-05-14 12:06:07 +00:00
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
2021-06-28 22:26:11 +00:00
else if ( ValidPTE & & ~ LeafPTE ) NextWalkerState = LEVEL1_WDV ;
2021-06-22 15:21:11 +00:00
else NextWalkerState = FAULT ;
2021-06-28 22:26:11 +00:00
LEVEL1_WDV: if ( HPTWStall ) NextWalkerState = LEVEL1_WDV ;
else NextWalkerState = LEVEL1 ;
LEVEL1:
2021-05-14 11:12:32 +00:00
// *** <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.
2021-06-28 22:26:11 +00:00
if ( ValidPTE & & LeafPTE & & ~ BadMegapage ) NextWalkerState = LEAF ;
2021-05-14 12:06:07 +00:00
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; // *** Once the above line is properly tested, delete this line.
2021-06-28 22:26:11 +00:00
else if ( ValidPTE & & ~ LeafPTE ) NextWalkerState = LEVEL0_WDV ;
2021-06-22 15:21:11 +00:00
else NextWalkerState = FAULT ;
2021-06-28 22:26:11 +00:00
LEVEL0_WDV: if ( HPTWStall ) NextWalkerState = LEVEL0_WDV ;
else NextWalkerState = LEVEL0 ;
LEVEL0:
if ( ValidPTE & & LeafPTE & & ~ AccessAlert ) NextWalkerState = LEAF ;
2021-06-22 15:21:11 +00:00
else NextWalkerState = FAULT ;
2021-06-28 22:26:11 +00:00
LEAF: if ( MMUTranslate & & SvMode = = `SV48 ) NextWalkerState = LEVEL3_WDV ;
else if ( MMUTranslate & & SvMode = = `SV39 ) NextWalkerState = LEVEL2_WDV ;
2021-06-22 15:21:11 +00:00
else NextWalkerState = IDLE ;
2021-06-28 22:26:11 +00:00
FAULT: if ( MMUTranslate & & SvMode = = `SV48 ) NextWalkerState = LEVEL3_WDV ;
else if ( MMUTranslate & & SvMode = = `SV39 ) NextWalkerState = LEVEL2_WDV ;
2021-06-22 15:21:11 +00:00
else NextWalkerState = IDLE ;
2021-04-13 23:19:58 +00:00
// Default case should never happen, but is included for linter.
2021-06-22 15:21:11 +00:00
default : NextWalkerState = IDLE ;
2021-03-25 06:48:40 +00:00
endcase
end
2021-06-01 21:50:37 +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 ] ) ;
2021-03-31 02:19:27 +00:00
// A gigapage is a Level 2 leaf page. This page must have zero PPN[1] and
// zero PPN[0]
2021-03-25 06:48:40 +00:00
assign GigapageMisaligned = | ( CurrentPPN [ 17 : 0 ] ) ;
2021-03-31 02:19:27 +00:00
// A megapage is a Level 1 leaf page. This page must have zero PPN[0].
2021-03-25 06:48:40 +00:00
assign MegapageMisaligned = | ( CurrentPPN [ 8 : 0 ] ) ;
2021-03-31 02:19:27 +00:00
2021-06-01 21:50:37 +00:00
assign BadTerapage = TerapageMisaligned | | AccessAlert ; // *** Implement better access/dirty scheme
2021-03-25 06:48:40 +00:00
assign BadGigapage = GigapageMisaligned | | AccessAlert ; // *** Implement better access/dirty scheme
assign BadMegapage = MegapageMisaligned | | AccessAlert ; // *** Implement better access/dirty scheme
2021-06-24 18:47:10 +00:00
assign VPN3 = TranslationVAdrQ [ 47 : 39 ] ;
assign VPN2 = TranslationVAdrQ [ 38 : 30 ] ;
assign VPN1 = TranslationVAdrQ [ 29 : 21 ] ;
assign VPN0 = TranslationVAdrQ [ 20 : 12 ] ;
2021-03-31 02:19:27 +00:00
always_comb begin
// default values
2021-04-13 16:27:12 +00:00
TranslationPAdr = '0 ;
PageTableEntry = '0 ;
PageType = '0 ;
DTLBWriteM = '0 ;
ITLBWriteF = '0 ;
2021-04-21 23:58:36 +00:00
WalkerInstrPageFaultF = '0 ;
WalkerLoadPageFaultM = '0 ;
WalkerStorePageFaultM = '0 ;
2021-05-14 11:12:32 +00:00
// The MMU defaults to stalling the processor
2021-04-22 05:51:38 +00:00
MMUStall = '1 ;
2021-03-31 02:19:27 +00:00
case ( NextWalkerState )
2021-04-22 05:51:38 +00:00
IDLE: begin
MMUStall = '0 ;
end
2021-06-01 21:50:37 +00:00
LEVEL3: begin
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
2021-06-28 22:26:11 +00:00
LEVEL3_WDV: begin
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
2021-03-31 02:19:27 +00:00
LEVEL2: begin
2021-06-01 21:50:37 +00:00
TranslationPAdr = { ( SvMode = = `SV48 ) ? CurrentPPN : BasePageTablePPN , VPN2 , 3 'b000 } ;
2021-03-31 02:19:27 +00:00
end
2021-06-28 22:26:11 +00:00
LEVEL2_WDV: begin
TranslationPAdr = { ( SvMode = = `SV48 ) ? CurrentPPN : BasePageTablePPN , VPN2 , 3 'b000 } ;
end
2021-03-31 02:19:27 +00:00
LEVEL1: begin
2021-04-13 16:27:12 +00:00
TranslationPAdr = { CurrentPPN , VPN1 , 3 'b000 } ;
2021-03-31 02:19:27 +00:00
end
2021-06-28 22:26:11 +00:00
LEVEL1_WDV: begin
TranslationPAdr = { CurrentPPN , VPN1 , 3 'b000 } ;
end
2021-03-31 02:19:27 +00:00
LEVEL0: begin
2021-04-13 16:27:12 +00:00
TranslationPAdr = { CurrentPPN , VPN0 , 3 'b000 } ;
2021-03-31 02:19:27 +00:00
end
2021-06-28 22:26:11 +00:00
LEVEL0_WDV: begin
TranslationPAdr = { CurrentPPN , VPN0 , 3 'b000 } ;
end
2021-03-31 02:19:27 +00:00
LEAF: begin
// Keep physical address alive to prevent HADDR dropping to 0
2021-04-13 16:27:12 +00:00
TranslationPAdr = { CurrentPPN , VPN0 , 3 'b000 } ;
PageTableEntry = CurrentPTE ;
2021-06-01 21:50:37 +00:00
PageType = ( WalkerState = = LEVEL3 ) ? 2 'b11 :
( ( WalkerState = = LEVEL2 ) ? 2 'b10 :
( ( WalkerState = = LEVEL1 ) ? 2 'b01 : 2 'b00 ) ) ;
2021-06-24 18:47:10 +00:00
DTLBWriteM = DTLBMissMQ ;
ITLBWriteF = ~ DTLBMissMQ ; // Prefer data over instructions
2021-03-31 02:19:27 +00:00
end
FAULT: begin
2021-05-14 11:12:32 +00:00
// Keep physical address alive to prevent HADDR dropping to 0
2021-04-13 16:27:12 +00:00
TranslationPAdr = { CurrentPPN , VPN0 , 3 'b000 } ;
2021-06-24 18:47:10 +00:00
WalkerInstrPageFaultF = ~ DTLBMissMQ ;
WalkerLoadPageFaultM = DTLBMissMQ & & ~ MemStore ;
WalkerStorePageFaultM = DTLBMissMQ & & MemStore ;
2021-04-22 05:51:38 +00:00
MMUStall = '0 ; // Drop the stall early to enter trap handling code
2021-03-31 02:19:27 +00:00
end
2021-04-13 23:19:58 +00:00
default : begin
// nothing
end
2021-03-31 02:19:27 +00:00
endcase
end
// Capture page table entry from ahblite
2021-06-28 22:26:11 +00:00
flopenr # ( `XLEN ) ptereg ( clk , reset , PRegEn , MMUReadPTE , SavedPTE ) ;
//mux2 #(`XLEN) ptemux(SavedPTE, MMUReadPTE, PRegEn, CurrentPTE);
assign CurrentPTE = SavedPTE ;
2021-03-31 02:19:27 +00:00
assign CurrentPPN = CurrentPTE [ `PPN_BITS + 9 : 10 ] ;
2021-03-25 06:48:40 +00:00
// Assign outputs to ahblite
// *** Currently truncate address to 32 bits. This must be changed if
// we support larger physical address spaces
2021-06-10 00:58:20 +00:00
assign MMUPAdr = { { ( `XLEN - 32 ) { 1 'b0 } } , TranslationPAdr [ 31 : 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