Replace RegisterFile with Memory.
[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
7 # The expected form of the data is
8 # Item (Bits)
9 # Tag (N - 79) / ASID (78 - 64) / PTE (63 - 0)
10
11 class TLB():
12 def __init__(self, asid_size, vma_size, pte_size):
13 """ Arguments
14 * asid_size: Address Space IDentifier (ASID) typically 15 bits
15 * vma_size: Virtual Memory Address (VMA) typically 36 bits
16 * pte_size: Page Table Entry (PTE) typically 64 bits
17
18 Notes:
19 These arguments should represent the largest possible size
20 defined by the MODE settings. See
21 Volume II: RISC-V Privileged Architectures V1.10 Page 57
22 """
23
24 # Internal
25 self.state = 0
26 # L1 Cache Modules
27 L1_size = 8
28 self.cam_L1 = Cam(vma_size, cam_size)
29 self.mem_L1 = Memory(asid_size + pte_size, cam_size)
30
31 # Permission Validator
32 self.perm_validator = PermissionValidator(asid_size + pte_size)
33
34 # Inputs
35 self.super = Signal(1) # Supervisor Mode
36 self.super_access = Signal(1) # Supervisor Access
37 self.command = Signal(2) # 00=None, 01=Search, 10=Write L1, 11=Write L2
38 self.xwr = Signal(3) # Execute, Write, Read
39 self.mode = Signal(4) # 4 bits for access to Sv48 on Rv64
40 self.address_L1 = Signal(max= am_size)
41 self.asid = Signal(asid_size) # Address Space IDentifier (ASID)
42 self.vma = Signal(vma_size) # Virtual Memory Address (VMA)
43 self.pte_in = Signal(pte_size) # To be saved Page Table Entry (PTE)
44
45 # Outputs
46 self.hit = Signal(1) # Denotes if the VMA had a mapped PTE
47 self.perm_valid = Signal(1) # Denotes if the permissions are correct
48 self.pte_out = Signal(pte_size) # PTE that was mapped to by the VMA
49
50 def elaborate(self, platform):
51 m = Module()
52 # Add submodules
53 # Submodules for L1 Cache
54 m.d.submodules.cam_L1 = self.cam_L1
55 m.d.sumbmodules.read_L1 = read_L1 = self.mem_L1.read_port
56 m.d.sumbmodules.read_L1 = write_L1 = self.mem_L1.read_port
57 # Permission Validator Submodule
58 m.d.submodules.perm_valididator = self.perm_validator
59
60 # When MODE specifies translation
61 # TODO add in different bit length handling ie prefix 0s
62 with m.If(self.mode != 0):
63 m.d.comb += [
64 self.cam_L1.enable.eq(1)
65 ]
66 with m.Switch(self.command):
67 # Search
68 with m.Case("01"):
69 m.d.comb += [
70 write_L1.en.eq(0),
71 self.cam_L1.write_enable.eq(0),
72 self.cam_L1.data_in.eq(self.vma)
73 ]
74 # Write L1
75 # Expected that the miss will be handled in software
76 with m.Case("10"):
77 # Memory_L1 Logic
78 m.d.comb += [
79 write_L1.en.eq(1),
80 write_L1.addr.eq(self.address_L1),
81 # The first argument is the LSB
82 write_L1.data.eq(Cat(self.pte, self.asid))
83 ]
84 # CAM_L1 Logic
85 m.d.comb += [
86 self.cam_L1.write_enable.eq(1),
87 self.cam_L1.data_in.eq(self.vma),
88 ]
89 # TODO
90 #with m.Case("11"):
91
92 # Match found in L1 CAM
93 with m.If(self.cam_L1.single_match
94 | self.cam_L1.multiple_match):
95 # Memory shortcut variables
96 mem_addrress = self.cam_L1.match_address
97 # Memory Logic
98 m.d.comb += read_L1.addr(mem_address)
99 # Permission vVlidator Logic
100 m.d.comb += [
101 self.hit.eq(1),
102 # Set permission validator data to the correct
103 # register file data according to CAM match
104 # address
105 self.perm_validator.data.eq(read_L1.data),
106 # Execute, Read, Write
107 self.perm_validator.xwr.eq(self.xwr),
108 # Supervisor Mode
109 self.perm_validator.super.eq(self.super),
110 # Supverisor Access
111 self.perm_validator.super_access.eq(self.super_access),
112 # Address Space IDentifier (ASID)
113 self.perm_validator.asid.eq(self.asid),
114 # Output result of permission validation
115 self.perm_valid.eq(self.perm_validator.valid)
116 ]
117 # Do not output PTE if permissions fail
118 with m.If(self.perm_validator.valid):
119 m.d.comb += [
120 self.pte_out.eq(reg_data)
121 ]
122 with m.Else():
123 m.d.comb += [
124 self.pte_out.eq(0)
125 ]
126 # Miss Logic
127 with m.Else():
128 m.d.comb += [
129 self.hit.eq(0),
130 self.perm_valid.eq(0),
131 self.pte_out.eq(0)
132 ]
133 # When disabled
134 with m.Else():
135 m.d.comb += [
136 self.cam_L1.enable.eq(0),
137 self.reg_file.enable.eq(0),
138 self.hit.eq(0),
139 self.valid.eq(0),
140 self.pte_out.eq(0)
141 ]
142 return m
143