Add logic to TLB to correctly utilize Cam, RegisterFile, and PermissionValidator...
[soc.git] / TLB / src / TLB.py
1 from nmigen import Memory, Module, Signal
2 from nmigen.cli import main
3
4 from PermissionValidator import PermissionValidator
5 from Cam import Cam
6 from RegisterFile import RegisterFile
7
8 # The expected form of the data is
9 # Item (Bits)
10 # Tag (N - 79) / ASID (78 - 64) / PTE (63 - 0)
11
12 class TLB():
13 def __init__(self, asid_size, vma_size, pte_size):
14 """ Arguments
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
18
19 Notes:
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
23 """
24
25 # Internal
26 self.state = 0
27 # L1 Cache Modules
28 L1_size = 8
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)
32
33 # Permission Validator
34 self.perm_validator = PermissionValidator(asid_size + pte_size)
35
36 # Inputs
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)
45
46 # Outputs
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
50
51 def elaborate(self, platform):
52 m = Module()
53
54 # Add submodules
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
58
59 # When MODE specifies translation
60 # TODO add in different bit length handling ie prefix 0s
61 with m.If(self.mode != 0):
62 m.d.comb += [
63 self.cam_L1.enable.eq(1),
64 self.reg_file.enable.eq(1)
65 ]
66 with m.Switch(self.command):
67 # Search
68 with m.Case("01"):
69 m.d.comb += [
70 self.cam_L1.write_enable.eq(0),
71 self.cam_L1.data_in.eq(self.vma)
72 ]
73 # Write
74 with m.Case("10"):
75 # LRU logic should go in here
76 # Or take in address for writing?
77 # Add hardware option/software option
78 # SO MANY CHOICES
79 m.d.comb += [
80 self.cam_L1.write_enable.eq(1),
81 self.cam_L1.data_in.eq(self.vma)
82 ]
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
90 m.d.comb += [
91 self.hit.eq(1),
92 # Set permission validator data to the correct
93 # register file data according to CAM match
94 # address
95 self.perm_validator.data.eq(reg_data),
96 # Execute, Read, Write
97 self.perm_validator.xwr.eq(self.xwr),
98 # Supervisor Mode
99 self.perm_validator.super.eq(self.super),
100 # Supverisor Access
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)
106 ]
107 # Do not output PTE if permissions fail
108 with m.If(self.perm_validator.valid):
109 m.d.comb += [
110 self.pte_out.eq(reg_data)
111 ]
112 with m.Else():
113 m.d.comb += [
114 self.pte_out.eq(0)
115 ]
116 with m.Else():
117 m.d.comb += [
118 self.hit.eq(0),
119 self.perm_valid.eq(0),
120 self.pte_out.eq(0)
121 ]
122 # When disabled
123 with m.Else():
124 m.d.comb += [
125 self.cam_L1.enable.eq(0),
126 self.reg_file.enable.eq(0),
127 self.hit.eq(0),
128 self.valid.eq(0),
129 self.pte_out.eq(0)
130 ]
131 return m
132
133 thing = TLB()
134 print("Gottem")
135