1 from nmigen
import Memory
, Module
, Signal
2 from nmigen
.cli
import main
4 from PermissionValidator
import PermissionValidator
6 from RegisterFile
import RegisterFile
8 # The expected form of the data is
10 # Tag (N - 79) / ASID (78 - 64) / PTE (63 - 0)
13 def __init__(self
, asid_size
, vma_size
, pte_size
):
15 * asid_size: Address Space IDentifier (ASID) typically 15 bits
16 * vma_size: Virtual Memory Address (VMA) typically 36 bits
17 * pte_size: Page Table Entry (PTE) typically 64 bits
20 These arguments should represent the largest possible size
21 defined by the MODE settings. See
22 Volume II: RISC-V Privileged Architectures V1.10 Page 57
29 bits_for_LRU
= 8 # Just a placeholder for not. Arbitrary 8!
30 self
.cam_L1
= Cam(vma_size
, cam_size
)
31 self
.reg_file
= RegisterFile(pte_size
+ bits_for_LRU
, cam_size
)
33 # Permission Validator
34 self
.perm_validator
= PermissionValidator(asid_size
+ pte_size
)
37 self
.super = Signal(1) # Supervisor Mode
38 self
.super_access
= Signal(1) # Supervisor Access
39 self
.command
= Signal(2) # 00=None, 01=Search, 10=Write PTE, 11=None
40 self
.xwr
= Signal(3) # Execute, Write, Read
41 self
.mode
= Signal(4) # 4 bits for access to Sv48 on Rv64
42 self
.asid
= Signal(asid_size
) # Address Space IDentifier (ASID)
43 self
.vma
= Signal(vma_size
) # Virtual Memory Address (VMA)
44 self
.pte_in
= Signal(pte_size
) # To be saved Page Table Entry (PTE)
47 self
.hit
= Signal(1) # Denotes if the VMA had a mapped PTE
48 self
.perm_valid
= Signal(1) # Denotes if the permissions are correct
49 self
.pte_out
= Signal(pte_size
) # PTE that was mapped to by the VMA
51 def elaborate(self
, platform
):
55 m
.d
.submodules
.perm_valididator
+= self
.perm_validator
56 m
.d
.submodules
.cam_L1
+= self
.cam_L1
57 m
.d
.sumbmodules
.reg_file
+= self
.reg_file
59 # When MODE specifies translation
60 # TODO add in different bit length handling ie prefix 0s
61 with m
.If(self
.mode
!= 0):
63 self
.cam_L1
.enable
.eq(1),
64 self
.reg_file
.enable
.eq(1)
66 with m
.Switch(self
.command
):
70 self
.cam_L1
.write_enable
.eq(0),
71 self
.cam_L1
.data_in
.eq(self
.vma
)
75 # LRU logic should go in here
76 # Or take in address for writing?
77 # Add hardware option/software option
80 self
.cam_L1
.write_enable
.eq(1),
81 self
.cam_L1
.data_in
.eq(self
.vma
)
83 # Match found in L1 CAM
84 with m
.If(self
.cam_L1
.single_match
85 | self
.cam_L1
.multiple_match
):
86 # Register file shortcut variables
87 reg_addrress
= self
.cam_L1
.match_address
88 reg_data
= self
.reg_file
.register_array
[reg_addrress
]
89 # Set all permission validator fields
92 # Set permission validator data to the correct
93 # register file data according to CAM match
95 self
.perm_validator
.data
.eq(reg_data
),
96 # Execute, Read, Write
97 self
.perm_validator
.xwr
.eq(self
.xwr
),
99 self
.perm_validator
.super.eq(self
.super),
101 self
.perm_validator
.super_access
.eq(self
.super_access
),
102 # Address Space IDentifier (ASID)
103 self
.perm_validator
.asid
.eq(self
.asid
),
104 # Output result of permission validation
105 self
.perm_valid
.eq(self
.perm_validator
.valid
)
107 # Do not output PTE if permissions fail
108 with m
.If(self
.perm_validator
.valid
):
110 self
.pte_out
.eq(reg_data
)
119 self
.perm_valid
.eq(0),
125 self
.cam_L1
.enable
.eq(0),
126 self
.reg_file
.enable
.eq(0),