move unused directory out of src, to indicate "ignore completely"
[soc.git] / unused_please_ignore_completely / TLB / ariane / tlb_content.py
1 from nmigen import Signal, Module, Cat, Const, Elaboratable
2
3 from soc.TLB.ariane.ptw import TLBUpdate, PTE
4
5
6 class TLBEntry:
7 def __init__(self, asid_width):
8 self.asid = Signal(asid_width, name="ent_asid")
9 # SV48 defines four levels of page tables
10 self.vpn0 = Signal(9, name="ent_vpn0")
11 self.vpn1 = Signal(9, name="ent_vpn1")
12 self.vpn2 = Signal(9, name="ent_vpn2")
13 self.vpn3 = Signal(9, name="ent_vpn3")
14 self.is_2M = Signal(name="ent_is_2M")
15 self.is_1G = Signal(name="ent_is_1G")
16 self.is_512G = Signal(name="ent_is_512G")
17 self.valid = Signal(name="ent_valid")
18
19 def flatten(self):
20 return Cat(*self.ports())
21
22 def eq(self, x):
23 return self.flatten().eq(x.flatten())
24
25 def ports(self):
26 return [self.asid, self.vpn0, self.vpn1, self.vpn2,
27 self.is_2M, self.is_1G, self.valid]
28
29
30 class TLBContent(Elaboratable):
31 def __init__(self, pte_width, asid_width):
32 self.asid_width = asid_width
33 self.pte_width = pte_width
34 self.flush_i = Signal() # Flush signal
35 # Update TLB
36 self.update_i = TLBUpdate(asid_width)
37 self.vpn3 = Signal(9)
38 self.vpn2 = Signal(9)
39 self.vpn1 = Signal(9)
40 self.vpn0 = Signal(9)
41 self.replace_en_i = Signal() # replace the following entry,
42 # set by replacement strategy
43 # Lookup signals
44 self.lu_asid_i = Signal(asid_width)
45 self.lu_content_o = Signal(pte_width)
46 self.lu_is_512G_o = Signal()
47 self.lu_is_2M_o = Signal()
48 self.lu_is_1G_o = Signal()
49 self.lu_hit_o = Signal()
50
51 def elaborate(self, platform):
52 m = Module()
53
54 tags = TLBEntry(self.asid_width)
55
56 content = Signal(self.pte_width)
57
58 m.d.comb += [self.lu_hit_o.eq(0),
59 self.lu_is_512G_o.eq(0),
60 self.lu_is_2M_o.eq(0),
61 self.lu_is_1G_o.eq(0)]
62
63 # temporaries for lookup
64 asid_ok = Signal(reset_less=True)
65 # tags_ok = Signal(reset_less=True)
66
67 vpn3_ok = Signal(reset_less=True)
68 vpn2_ok = Signal(reset_less=True)
69 vpn1_ok = Signal(reset_less=True)
70 vpn0_ok = Signal(reset_less=True)
71
72 #tags_2M = Signal(reset_less=True)
73 vpn0_or_2M = Signal(reset_less=True)
74
75 m.d.comb += [
76 # compare asid and vpn*
77 asid_ok.eq(tags.asid == self.lu_asid_i),
78 vpn3_ok.eq(tags.vpn3 == self.vpn3),
79 vpn2_ok.eq(tags.vpn2 == self.vpn2),
80 vpn1_ok.eq(tags.vpn1 == self.vpn1),
81 vpn0_ok.eq(tags.vpn0 == self.vpn0),
82 vpn0_or_2M.eq(tags.is_2M | vpn0_ok)
83 ]
84
85 with m.If(asid_ok & tags.valid):
86 # first level, only vpn3 needs to match
87 with m.If(tags.is_512G & vpn3_ok):
88 m.d.comb += [self.lu_content_o.eq(content),
89 self.lu_is_512G_o.eq(1),
90 self.lu_hit_o.eq(1),
91 ]
92 # second level , second level vpn2 and vpn3 need to match
93 with m.Elif(tags.is_1G & vpn2_ok & vpn3_ok):
94 m.d.comb += [self.lu_content_o.eq(content),
95 self.lu_is_1G_o.eq(1),
96 self.lu_hit_o.eq(1),
97 ]
98 # not a giga page hit nor a tera page hit so check further
99 with m.Elif(vpn1_ok):
100 # this could be a 2 mega page hit or a 4 kB hit
101 # output accordingly
102 with m.If(vpn0_or_2M):
103 m.d.comb += [self.lu_content_o.eq(content),
104 self.lu_is_2M_o.eq(tags.is_2M),
105 self.lu_hit_o.eq(1),
106 ]
107 # ------------------
108 # Update or Flush
109 # ------------------
110
111 # temporaries
112 replace_valid = Signal(reset_less=True)
113 m.d.comb += replace_valid.eq(self.update_i.valid & self.replace_en_i)
114
115 # flush
116 with m.If(self.flush_i):
117 # invalidate (flush) conditions: all if zero or just this ASID
118 with m.If(self.lu_asid_i == Const(0, self.asid_width) |
119 (self.lu_asid_i == tags.asid)):
120 m.d.sync += tags.valid.eq(0)
121
122 # normal replacement
123 with m.Elif(replace_valid):
124 m.d.sync += [ # update tag array
125 tags.asid.eq(self.update_i.asid),
126 tags.vpn3.eq(self.update_i.vpn[27:36]),
127 tags.vpn2.eq(self.update_i.vpn[18:27]),
128 tags.vpn1.eq(self.update_i.vpn[9:18]),
129 tags.vpn0.eq(self.update_i.vpn[0:9]),
130 tags.is_512G.eq(self.update_i.is_512G),
131 tags.is_1G.eq(self.update_i.is_1G),
132 tags.is_2M.eq(self.update_i.is_2M),
133 tags.valid.eq(1),
134 # and content as well
135 content.eq(self.update_i.content.flatten())
136 ]
137 return m
138
139 def ports(self):
140 return [self.flush_i,
141 self.lu_asid_i,
142 self.lu_is_2M_o, self.lu_is_1G_o, self.lu_is_512G_o, self.lu_hit_o,
143 ] + self.update_i.content.ports() + self.update_i.ports()