vmem_params.py
1 from typing import Collection 2 3 from coreblocks.arch.isa_consts import SatpMode, SatpLayout, PAGE_SIZE_LOG 4 5 6 class VirtualMemoryParameters: 7 """Parameters for virtual memory support.""" 8 9 @staticmethod 10 def max_physical_address_bits(xlen: int, supported_schemes: Collection[SatpMode]) -> int: 11 if xlen == 32 and supported_schemes == {SatpMode.BARE}: 12 return 32 # without virtual memory only lower 32 bits of physical addresses are reachable 13 14 satp_layout = SatpLayout(xlen) 15 return satp_layout["ppn"].width + PAGE_SIZE_LOG 16 17 def __init__( 18 self, 19 *, 20 xlen: int, 21 supervisor_mode: bool = False, 22 asidlen: int = 0, 23 supported_schemes: Collection[SatpMode] = (SatpMode.BARE,), 24 ): 25 self.supported_schemes = frozenset(supported_schemes) 26 27 if SatpMode.BARE not in self.supported_schemes: 28 raise ValueError("Supported virtual memory schemes must include BARE") 29 30 if not supervisor_mode and self.supported_schemes != {SatpMode.BARE}: 31 raise ValueError("Virtual memory schemes other than BARE require supervisor mode support") 32 33 if asidlen < 0: 34 raise ValueError(f"ASIDLEN must be non-negative, got {asidlen}") 35 36 self.satp_layout = SatpLayout(xlen) 37 38 max_asidlen = self.satp_layout["asid"].width 39 if asidlen > max_asidlen: 40 raise ValueError(f"ASIDLEN={asidlen} exceeds maximum {max_asidlen} for XLEN={xlen}") 41 42 supported_for_xlen = SatpMode.valid_modes(xlen) 43 if not self.supported_schemes <= supported_for_xlen: 44 raise ValueError(f"Schemes {self.supported_schemes - supported_for_xlen} are not valid for XLEN={xlen}") 45 46 for mode in self.supported_schemes: 47 dependencies = SatpMode.mode_dependencies(mode) 48 if not dependencies <= self.supported_schemes: 49 raise ValueError( 50 f"Schemes {dependencies - self.supported_schemes} are required by {mode} but not supported" 51 ) 52 53 self.xlen = xlen 54 self.asidlen = asidlen 55 self.max_asid = (1 << asidlen) - 1