MMU description » History » Version 131
Alexander Kamkin, 02/13/2015 10:07 AM
1 | 24 | Alexander Kamkin | h1. MMU Description |
---|---|---|---|
2 | 1 | Taya Sergeeva | |
3 | 128 | Alexander Kamkin | _~By Alexander Kamkin, Taya Sergeeva, and Andrei Tatarnikov~_ |
4 | 62 | Alexander Kamkin | |
5 | 63 | Alexander Kamkin | {{toc}} |
6 | |||
7 | 35 | Alexander Kamkin | A _memory management unit_ (_MMU_) is known to be one of the most complex and error-prone components of a modern microprocessor. MicroTESK has a special subsystem, called _MMU subsystem_, intended for (1) specifying memory devices and (2) deriving testing knowledge from such specifications. The subsystem provides unified facilities for describing memory buffers (like _L1_ and _L2 caches_, _translation look-aside buffers_ (_TLBs_), etc.) as well as a means for connecting several buffers into a memory hierarchy. |
8 | 1 | Taya Sergeeva | |
9 | 72 | Alexander Kamkin | h2. Grammar |
10 | 66 | Alexander Kamkin | |
11 | <pre> |
||
12 | 102 | Andrei Tatarnikov | startRule |
13 | : declaration* EOF! |
||
14 | 66 | Alexander Kamkin | ; |
15 | 1 | Taya Sergeeva | |
16 | 102 | Andrei Tatarnikov | declaration |
17 | 66 | Alexander Kamkin | : address |
18 | 102 | Andrei Tatarnikov | | segment |
19 | 66 | Alexander Kamkin | | buffer |
20 | 102 | Andrei Tatarnikov | | mmu |
21 | 66 | Alexander Kamkin | ; |
22 | </pre> |
||
23 | |||
24 | 103 | Andrei Tatarnikov | The expression syntax is derived from nML/Sim-nML (see [[Sim-nML Language Reference]]). |
25 | 89 | Alexander Kamkin | |
26 | 91 | Alexander Kamkin | h2. Address Description (address) |
27 | 56 | Taya Sergeeva | |
28 | 1 | Taya Sergeeva | A buffer is accessed by an _address_, which is typically a _bit vector_ of a fixed length (width). Different buffers are allowed to have a common address space (e.g., L1 and L2 are usually both addressed by physical addresses). However, in general case, each buffer has its own domain. |
29 | |||
30 | 110 | Andrei Tatarnikov | An address space is described using a keyword @address@. The description includes the address type _identifier_ and the address _width_. The latter is specified in brackets. Its value should be non-negative (zero-length addresses are permitted). |
31 | 1 | Taya Sergeeva | |
32 | 75 | Alexander Kamkin | h3. Grammar |
33 | 69 | Alexander Kamkin | |
34 | <pre> |
||
35 | address |
||
36 | 104 | Andrei Tatarnikov | : ''address'' addressTypeID ''('' expr '')'' |
37 | 69 | Alexander Kamkin | ; |
38 | </pre> |
||
39 | |||
40 | 111 | Andrei Tatarnikov | h3. Examples |
41 | 106 | Andrei Tatarnikov | |
42 | <pre>// A 64-bit virtual address (VA). |
||
43 | address VA(64)</pre> |
||
44 | |||
45 | <pre>// A 36-bit physical address (PA). |
||
46 | address PA(36)</pre> |
||
47 | |||
48 | 112 | Andrei Tatarnikov | h2. Address Space Segment Description (segment) |
49 | 1 | Taya Sergeeva | |
50 | 112 | Andrei Tatarnikov | An address space segment is specified using the @segment@ keyword. A segment is associated with a specific address type. It is possible to specify any number (≥ 0) of segments (with different names) for one address type. Each segment is characterized by its _identifier_ and _address range_. Different segments should have different names, but address ranges are allowed to overlap, and moreover, to be the same. |
51 | 1 | Taya Sergeeva | |
52 | 112 | Andrei Tatarnikov | h3. Grammar |
53 | 69 | Alexander Kamkin | |
54 | <pre> |
||
55 | 112 | Andrei Tatarnikov | segment |
56 | : ''segment'' segmentID ''('' argumentID '':'' addressTypeID '')'' |
||
57 | ''range'' ''='' ''('' expr '','' expr '')'' |
||
58 | 99 | Alexander Kamkin | ; |
59 | 97 | Alexander Kamkin | </pre> |
60 | |||
61 | 112 | Andrei Tatarnikov | h3. Examples |
62 | 97 | Alexander Kamkin | |
63 | 1 | Taya Sergeeva | <pre> |
64 | 112 | Andrei Tatarnikov | segment USEG (va: VA) |
65 | range = (0x0000000000000000, 0x000000007fffffff) |
||
66 | 97 | Alexander Kamkin | </pre> |
67 | |||
68 | 91 | Alexander Kamkin | h2. Buffer Description (buffer) |
69 | 76 | Alexander Kamkin | |
70 | 115 | Andrei Tatarnikov | A buffer is described using a keyword @buffer@. The description specifies a set of parameters, including @ways@, @sets@, @entry@, @index@, @match@ and @policy@. All of the parameters except @index@ (if @sets = 1@) and @policy@ are obligatory. |
71 | 75 | Alexander Kamkin | |
72 | h3. Grammar |
||
73 | 1 | Taya Sergeeva | |
74 | 75 | Alexander Kamkin | <pre> |
75 | 83 | Alexander Kamkin | buffer |
76 | 115 | Andrei Tatarnikov | : ''buffer'' bufferTypeID ''('' addressArgID '':'' addressTypeID '')'' |
77 | 90 | Alexander Kamkin | (bufferParameter)* |
78 | 75 | Alexander Kamkin | ; |
79 | |||
80 | bufferParameter |
||
81 | : ways |
||
82 | | sets |
||
83 | 115 | Andrei Tatarnikov | | entry |
84 | 75 | Alexander Kamkin | | index |
85 | | match |
||
86 | | policy |
||
87 | ; |
||
88 | 1 | Taya Sergeeva | </pre> |
89 | |||
90 | 78 | Alexander Kamkin | h3. Buffer Associativity (ways) |
91 | |||
92 | 84 | Alexander Kamkin | The @ways@ parameter specifies the buffer _associativity_ (the number of lines in a set). The parameter is obligatory; its value should be positive. |
93 | 78 | Alexander Kamkin | |
94 | 1 | Taya Sergeeva | h4. Grammar |
95 | 80 | Alexander Kamkin | |
96 | <pre> |
||
97 | ways |
||
98 | : ''ways'' ''='' expr |
||
99 | 1 | Taya Sergeeva | ; |
100 | </pre> |
||
101 | |||
102 | 80 | Alexander Kamkin | h3. Buffer Length (sets) |
103 | 83 | Alexander Kamkin | |
104 | 84 | Alexander Kamkin | The @sets@ parameter specifies the buffer _length_ (the number of sets a cache). The parameter is obligatory; its value should be positive. |
105 | 78 | Alexander Kamkin | |
106 | 1 | Taya Sergeeva | h4. Grammar |
107 | 80 | Alexander Kamkin | |
108 | <pre> |
||
109 | 1 | Taya Sergeeva | sets |
110 | 80 | Alexander Kamkin | : ''sets'' ''='' expr |
111 | ; |
||
112 | 1 | Taya Sergeeva | </pre> |
113 | |||
114 | 116 | Andrei Tatarnikov | h3. Buffer Line Format (entry) |
115 | 96 | Alexander Kamkin | |
116 | 120 | Andrei Tatarnikov | The @entry@ parameter specifies the buffer _line format_ (a number of named fields). A field has three attributes: a name, a width and, optionally, an initial value. |
117 | 82 | Alexander Kamkin | |
118 | h4. Grammar |
||
119 | 1 | Taya Sergeeva | |
120 | 82 | Alexander Kamkin | <pre> |
121 | 83 | Alexander Kamkin | format |
122 | 119 | Andrei Tatarnikov | : ''entry'' ''='' ''('' field ('','' field)* '')'' |
123 | 82 | Alexander Kamkin | ; |
124 | 1 | Taya Sergeeva | |
125 | field |
||
126 | : fieldID '':'' expr (''='' expr)? |
||
127 | ; |
||
128 | </pre> |
||
129 | |||
130 | h3. Buffer Index Function (index) |
||
131 | 83 | Alexander Kamkin | |
132 | 84 | Alexander Kamkin | The @index@ parameter specifies the _address-to-index function_, which maps an address into the set index. The function may be omitted if the number of sets is @1@. |
133 | 1 | Taya Sergeeva | |
134 | h4. Grammar |
||
135 | |||
136 | 83 | Alexander Kamkin | <pre> |
137 | 1 | Taya Sergeeva | index |
138 | 90 | Alexander Kamkin | : ''index'' ''='' expr |
139 | 83 | Alexander Kamkin | ; |
140 | </pre> |
||
141 | 1 | Taya Sergeeva | |
142 | h3. Buffer Match Predicate (match) |
||
143 | 83 | Alexander Kamkin | |
144 | 84 | Alexander Kamkin | The @match@ parameter specifies the _address-line match predicate_, which checks if an address matches a line. The parameter is obligatory. |
145 | 83 | Alexander Kamkin | |
146 | h4. Grammar |
||
147 | 1 | Taya Sergeeva | |
148 | 83 | Alexander Kamkin | <pre> |
149 | index |
||
150 | 90 | Alexander Kamkin | : ''match'' ''='' expr |
151 | 1 | Taya Sergeeva | ; |
152 | </pre> |
||
153 | 83 | Alexander Kamkin | |
154 | 1 | Taya Sergeeva | h3. Buffer Data Replacement Policy (policy) |
155 | |||
156 | 57 | Taya Sergeeva | The @policy@ parameters specifies the _data replacement_ (_eviction_) _policy_. The parameter is optional. The list of supported policies includes: @RANDOM@, @FIFO@, @PLRU@ and @LRU@. |
157 | 84 | Alexander Kamkin | |
158 | 1 | Taya Sergeeva | h4. Grammar |
159 | |||
160 | <pre> |
||
161 | policy |
||
162 | : ''policy'' ''='' policyID |
||
163 | 54 | Taya Sergeeva | ; |
164 | </pre> |
||
165 | |||
166 | 1 | Taya Sergeeva | h3. Examples |
167 | |||
168 | 84 | Alexander Kamkin | <pre> |
169 | 90 | Alexander Kamkin | // A 4-way set associative cache (L1) addressed by physical addresses (PA). |
170 | 118 | Andrei Tatarnikov | buffer L1(addr: PA) |
171 | 84 | Alexander Kamkin | // The cache associativity. |
172 | 1 | Taya Sergeeva | ways = 4 |
173 | 84 | Alexander Kamkin | // The number of sets. |
174 | 90 | Alexander Kamkin | sets = 128 |
175 | 1 | Taya Sergeeva | // The line format. |
176 | 118 | Andrei Tatarnikov | entry = ( |
177 | 85 | Alexander Kamkin | V : 1 = 0, // The validity flag (by default, the line is invalid). |
178 | TAG : 24, // The tag (the <35..12> address bits). |
||
179 | 1 | Taya Sergeeva | DATA : 256 // The data (4 double words). |
180 | 90 | Alexander Kamkin | ) |
181 | // The address-to-index function (example: using address fields). |
||
182 | index = addr.INDEX |
||
183 | // The address-line predicate (example: using address bits). |
||
184 | 121 | Andrei Tatarnikov | match = addr<35..12> == TAG |
185 | 1 | Taya Sergeeva | // The data replacement policy (example: using predefined policy LRU - Least Recently Used). |
186 | policy = LRU |
||
187 | 91 | Alexander Kamkin | </pre> |
188 | |||
189 | 122 | Andrei Tatarnikov | h2. MMU Description (mmu) |
190 | 91 | Alexander Kamkin | |
191 | 125 | Andrei Tatarnikov | Memory management unit logic is described using the @mmu@ keyword. The description includes two obligatory parameters @read@ and @write@ that describe the semantics of memory read and memory write actions respectively. |
192 | 92 | Alexander Kamkin | |
193 | 91 | Alexander Kamkin | h3. Grammar |
194 | |||
195 | <pre> |
||
196 | 126 | Andrei Tatarnikov | mmu |
197 | : ''mmu'' memoryTypeID ''('' addressArgID '':'' addressTypeID '')'' = dataArgID |
||
198 | 127 | Andrei Tatarnikov | (mmuVariable)* |
199 | (mmuParameter)* |
||
200 | 91 | Alexander Kamkin | ; |
201 | 1 | Taya Sergeeva | |
202 | 127 | Andrei Tatarnikov | mmuVariable |
203 | : ''var'' variableID '':'' variableTypeID (''.'' ''entry'')? '';'' |
||
204 | ; |
||
205 | |||
206 | 126 | Andrei Tatarnikov | mmuParameter |
207 | 127 | Andrei Tatarnikov | : read |
208 | | write |
||
209 | 1 | Taya Sergeeva | ; |
210 | 91 | Alexander Kamkin | </pre> |
211 | 92 | Alexander Kamkin | |
212 | 1 | Taya Sergeeva | h3. Memory Read Action (read) |
213 | 92 | Alexander Kamkin | |
214 | The @read@ parameter specifies the _read action_, which is a sequence of statements describing how the read operation is to be performed (by means of data transfers between buffers). The parameter is obligatory. |
||
215 | 91 | Alexander Kamkin | |
216 | h4. Grammar |
||
217 | |||
218 | <pre> |
||
219 | read |
||
220 | 1 | Taya Sergeeva | : ''read'' ''='' ''{'' sequence ''}'' |
221 | ; |
||
222 | </pre> |
||
223 | 92 | Alexander Kamkin | |
224 | h3. Memory Write Action (write) |
||
225 | |||
226 | 91 | Alexander Kamkin | The @write@ parameter specifies the _read action_, which is a sequence of statements describing how the write operation is to be performed (by means of data transfers between buffers). The parameter is obligatory. |
227 | |||
228 | h4. Grammar |
||
229 | |||
230 | <pre> |
||
231 | write |
||
232 | : ''write'' ''='' ''{'' sequence ''}'' |
||
233 | ; |
||
234 | </pre> |
||
235 | |||
236 | h3. Examples |
||
237 | |||
238 | 93 | Alexander Kamkin | <pre> |
239 | 123 | Andrei Tatarnikov | // A memory unit addressed by virtual addresses (VA). |
240 | 93 | Alexander Kamkin | mmu Memory(addr: VA) = data |
241 | 1 | Taya Sergeeva | // The read action. |
242 | 93 | Alexander Kamkin | read = { |
243 | // Some statements. |
||
244 | 1 | Taya Sergeeva | ... |
245 | 93 | Alexander Kamkin | } |
246 | 1 | Taya Sergeeva | // The write action. |
247 | 93 | Alexander Kamkin | write = { |
248 | // Some statements. |
||
249 | 91 | Alexander Kamkin | ... |
250 | 1 | Taya Sergeeva | } |
251 | 130 | Alexander Kamkin | </pre> |
252 | 129 | Alexander Kamkin | |
253 | h2. Simplified Specification of MIPS''s MMU |
||
254 | |||
255 | <pre> |
||
256 | //================================================================================================== |
||
257 | // Virtual Address (VA) |
||
258 | //================================================================================================== |
||
259 | |||
260 | address VA(64) |
||
261 | |||
262 | //-------------------------------------------------------------------------------------------------- |
||
263 | // User Mode Segments |
||
264 | //-------------------------------------------------------------------------------------------------- |
||
265 | |||
266 | segment USEG (va: VA) |
||
267 | range = (0x0000000000000000, 0x000000007fffffff) |
||
268 | |||
269 | segment XUSEG(va: VA) |
||
270 | range = (0x0000000080000000, 0x000000ffffffffff) |
||
271 | |||
272 | //-------------------------------------------------------------------------------------------------- |
||
273 | // Supervisor Mode Segments |
||
274 | //-------------------------------------------------------------------------------------------------- |
||
275 | |||
276 | segment SUSEG(va: VA) |
||
277 | range = (0x0000000000000000, 0x000000007fffffff) |
||
278 | |||
279 | segment XSUSEG(va: VA) |
||
280 | range = (0x0000000080000000, 0x000000ffffffffff) |
||
281 | |||
282 | segment XSSEG(va: VA) |
||
283 | range = (0x4000000000000000, 0x400000ffffffffff) |
||
284 | |||
285 | segment CSSEG(va: VA) |
||
286 | range = (0xffffffffc0000000, 0xffffffffdfffffff) |
||
287 | |||
288 | //-------------------------------------------------------------------------------------------------- |
||
289 | // Kernel Mode Segments |
||
290 | //-------------------------------------------------------------------------------------------------- |
||
291 | |||
292 | segment KUSEG (va: VA) |
||
293 | range = (0x0000000000000000, 0x000000007fffffff) |
||
294 | |||
295 | segment XKUSEG (va: VA) |
||
296 | range = (0x0000000080000000, 0x000000ffffffffff) |
||
297 | |||
298 | segment XKSSEG (va: VA) |
||
299 | range = (0x4000000000000000, 0x400000ffffffffff) |
||
300 | |||
301 | segment XKSEG (va: VA) |
||
302 | range = (0xc000000000000000, 0xc00000ff7fffffff) |
||
303 | |||
304 | segment CKSSEG (va: VA) |
||
305 | range = (0xffffffffc0000000, 0xffffffffdfffffff) |
||
306 | |||
307 | segment CKSEG3(va: VA) |
||
308 | range = (0xffffffffe0000000, 0xffffffffffffffff) |
||
309 | |||
310 | //================================================================================================== |
||
311 | // Physical Address (PA) |
||
312 | //================================================================================================== |
||
313 | |||
314 | address PA(36) |
||
315 | |||
316 | //================================================================================================== |
||
317 | // Translation Lookaside Buffer (TLB) |
||
318 | //================================================================================================== |
||
319 | |||
320 | buffer DTLB (va: VA) |
||
321 | ways = 4 |
||
322 | sets = 1 |
||
323 | entry = (ASID: 8, VPN2: 27, R: 2, // EntryHi |
||
324 | G0: 1, V0: 1, D0: 1, C0: 3, PFN0: 24, // EntryLo0 |
||
325 | G1: 1, V1: 1, D1: 1, C1: 3, PFN1: 24) // EntryLo1 |
||
326 | index = 0 |
||
327 | 131 | Alexander Kamkin | match = VPN2 == va<39..13> // ASID, G and non-4KB pages are unsupported |
328 | 129 | Alexander Kamkin | policy = PLRU |
329 | |||
330 | buffer JTLB (va: VA) |
||
331 | ways = 64 |
||
332 | sets = 1 |
||
333 | entry = (ASID: 8, VPN2: 27, R: 2, // EntryHi |
||
334 | G0: 1, V0: 1, D0: 1, C0: 3, PFN0: 24, // EntryLo0 |
||
335 | G1: 1, V1: 1, D1: 1, C1: 3, PFN1: 24) // EntryLo1 |
||
336 | index = 0 |
||
337 | 131 | Alexander Kamkin | match = VPN2 == va<39..13> // ASID, G and non-4KB pages are unsupported |
338 | 129 | Alexander Kamkin | policy = NONE |
339 | |||
340 | //================================================================================================== |
||
341 | // Cache Memory (L1 and L2) |
||
342 | //================================================================================================== |
||
343 | |||
344 | buffer L1 (pa: PA) |
||
345 | ways = 4 |
||
346 | sets = 128 |
||
347 | entry = (V: 1 = 0, TAG: 24, DATA: 256) |
||
348 | index = pa<11..5> |
||
349 | match = V == 1 && TAG == pa<35..12> |
||
350 | policy = PLRU |
||
351 | |||
352 | buffer L2 (pa: PA) |
||
353 | ways = 4 |
||
354 | sets = 4096 |
||
355 | entry = (V: 1 = 0, TAG: 19, DATA: 256) |
||
356 | index = pa<16..5> |
||
357 | match = V == 1 && TAG == pa<35..17> |
||
358 | policy = PLRU |
||
359 | |||
360 | //================================================================================================== |
||
361 | // MMU Logic (Interaction between TLB, L1 and L2) |
||
362 | //================================================================================================== |
||
363 | |||
364 | mmu pmem(va: VA) = (data: 64) |
||
365 | var tlbEntry: JTLB.entry; |
||
366 | var l1Entry: L1.entry; |
||
367 | var l2Entry: L2.entry; |
||
368 | |||
369 | var evenOddBit: 5; |
||
370 | |||
371 | var g: 1; |
||
372 | var v: 1; |
||
373 | var d: 1; |
||
374 | var c: 3; |
||
375 | var pfn: 24; |
||
376 | |||
377 | var pa: PA; |
||
378 | |||
379 | var cachePA: PA; |
||
380 | var cacheData: 256; |
||
381 | |||
382 | read = { |
||
383 | // The address is unaligned. |
||
384 | if va<0..2> != 0 then |
||
385 | exception("AddressError"); |
||
386 | endif; // If the address is unaligned. |
||
387 | |||
388 | // The default cache policy. |
||
389 | c = 3; |
||
390 | |||
391 | // The address is from the USEG segment (only USEG and KSEG segments are supported). |
||
392 | if USEG(va).hit then |
||
393 | // The address hits the DTLB. |
||
394 | if DTLB(va).hit then |
||
395 | tlbEntry = DTLB(va); |
||
396 | // The address hits the JTLB. |
||
397 | elif JTLB(va).hit then |
||
398 | tlbEntry = JTLB(va); |
||
399 | // The address does not hit the TLB. |
||
400 | else |
||
401 | exception("TLBMiss"); |
||
402 | endif; // If the address hits the DTLB. |
||
403 | |||
404 | // Only 4KB pages are supported. |
||
405 | evenOddBit = 12; |
||
406 | |||
407 | // The VPN is even. |
||
408 | if va<evenOddBit> == 0 then |
||
409 | g = tlbEntry.G0; |
||
410 | v = tlbEntry.V0; |
||
411 | d = tlbEntry.D0; |
||
412 | c = tlbEntry.C0; |
||
413 | pfn = tlbEntry.PFN0; |
||
414 | // The VPN is odd. |
||
415 | else |
||
416 | g = tlbEntry.G1; |
||
417 | v = tlbEntry.V1; |
||
418 | d = tlbEntry.D1; |
||
419 | c = tlbEntry.C1; |
||
420 | pfn = tlbEntry.PFN1; |
||
421 | endif; // If the VPN is even. |
||
422 | |||
423 | // The EntryLo is valid. |
||
424 | if v == 1 then |
||
425 | pa = pfn<24..(evenOddBit - 12)>::va<(evenOddBit - 1)..0>; |
||
426 | // The EntryLo is invalid. |
||
427 | else |
||
428 | exception("TLBInvalid"); |
||
429 | endif; // If the EntryLo is valid. |
||
430 | // The address is from the KSEG0 or KSEG1 segment. |
||
431 | else |
||
432 | pa = va<28..0>; |
||
433 | endif; // If the address is from the USEG segment. |
||
434 | |||
435 | // The address is cacheable. |
||
436 | if c<1..0> != 2 then |
||
437 | cachePA = pa; |
||
438 | cachePA<4..0> = 0; |
||
439 | |||
440 | // The address hits the L1. |
||
441 | if L1(pa).hit then |
||
442 | l1Entry = L1(pa); |
||
443 | cacheData = l1Entry.DATA; |
||
444 | data = cacheData<(8 * pa<4..0> + 63)..(8 * pa<4..0>)>; |
||
445 | // The address does not hit the L1. |
||
446 | else |
||
447 | // The L2 cache is used. |
||
448 | if c<1..0> == 3 then |
||
449 | // The address hits the L2. |
||
450 | if L2(pa).hit then |
||
451 | l2Entry = L2(pa); |
||
452 | cacheData = l2Entry.DATA; |
||
453 | data = cacheData<(8 * pa<4..0> + 63)..(8 * pa<4..0>)>; |
||
454 | |||
455 | // Fill the L1. |
||
456 | l1Entry.V = 1; |
||
457 | l1Entry.TAG = pa<35..12>; |
||
458 | l1Entry.DATA = cacheData; |
||
459 | L1(pa) = l1Entry; |
||
460 | // The address does not hit the L2. |
||
461 | else |
||
462 | cacheData = pmem[cachePA + 24]::pmem[cachePA + 16]::pmem[cachePA + 8]::pmem[cachePA]; |
||
463 | data = cacheData<(8 * pa<4..0> + 63)..(8 * pa<4..0>)>; |
||
464 | |||
465 | // Fill L2. |
||
466 | l2Entry.V = 1; |
||
467 | l2Entry.TAG = pa<35..17>; |
||
468 | l2Entry.DATA = cacheData; |
||
469 | L2(pa) = l2Entry; |
||
470 | |||
471 | // Fill L1. |
||
472 | l1Entry.V = 1; |
||
473 | l1Entry.TAG = pa<35..12>; |
||
474 | l1Entry.DATA = cacheData; |
||
475 | L1(pa) = l1Entry; |
||
476 | endif; // If the address hits the L2. |
||
477 | // The L2 cache is bypassed. |
||
478 | else |
||
479 | cacheData = pmem[cachePA + 24]::pmem[cachePA + 16]::pmem[cachePA + 8]::pmem[cachePA]; |
||
480 | data = cacheData<(8 * pa<4..0> + 63)..(8 * pa<4..0>)>; |
||
481 | |||
482 | l1Entry.V = 1; |
||
483 | l1Entry.TAG = pa<35..12>; |
||
484 | l1Entry.DATA = cacheData; |
||
485 | L1(pa) = l1Entry; |
||
486 | endif; // If the L2 cache is used. |
||
487 | endif; // If the address hits the L1. |
||
488 | // The address is uncacheable. |
||
489 | else |
||
490 | data = pmem[pa]; |
||
491 | endif; // If the address is cacheable. |
||
492 | } |
||
493 | |||
494 | write = { |
||
495 | // The address is unaligned. |
||
496 | if va<0..2> != 0 then |
||
497 | exception("AddressError"); |
||
498 | endif; // If the address is unaligned. |
||
499 | |||
500 | // The default cache policy. |
||
501 | c = 3; |
||
502 | |||
503 | // The address is from the USEG segment (only USEG and KSEG segments are supported). |
||
504 | if USEG(va).hit then |
||
505 | // The address hits the DTLB. |
||
506 | if DTLB(va).hit then |
||
507 | tlbEntry = DTLB(va); |
||
508 | // The address hits the JTLB. |
||
509 | elif JTLB(va).hit then |
||
510 | tlbEntry = JTLB(va); |
||
511 | // The address does not hit the TLB. |
||
512 | else |
||
513 | exception("TLBMiss"); |
||
514 | endif; // If the address hits the DTLB. |
||
515 | |||
516 | // Only 4KB pages are supported. |
||
517 | evenOddBit = 12; |
||
518 | |||
519 | // The VPN is even. |
||
520 | if va<evenOddBit> == 0 then |
||
521 | g = tlbEntry.G0; |
||
522 | v = tlbEntry.V0; |
||
523 | d = tlbEntry.D0; |
||
524 | c = tlbEntry.C0; |
||
525 | pfn = tlbEntry.PFN0; |
||
526 | // The VPN is odd. |
||
527 | else |
||
528 | g = tlbEntry.G1; |
||
529 | v = tlbEntry.V1; |
||
530 | d = tlbEntry.D1; |
||
531 | c = tlbEntry.C1; |
||
532 | pfn = tlbEntry.PFN1; |
||
533 | endif; // If the VPN is even. |
||
534 | |||
535 | // The EntryLo is valid. |
||
536 | if v == 1 then |
||
537 | // The EntryLo is clean. |
||
538 | if d == 1 then |
||
539 | pa = pfn<24..(evenOddBit - 12)>::va<(evenOddBit - 1)..0>; |
||
540 | // The EntryLo is dirty. |
||
541 | else |
||
542 | exception("TLBModified"); |
||
543 | endif; // If the EntryLo is clean. |
||
544 | // The EntryLo is invalid. |
||
545 | else |
||
546 | exception("TLBInvalid"); |
||
547 | endif; // If the EntryLo is valid. |
||
548 | // The address is from the KSEG0 or KSEG1 segment. |
||
549 | else |
||
550 | pa = va<28..0>; |
||
551 | endif; // If the address is from the USEG segment. |
||
552 | |||
553 | // The address is cacheable. |
||
554 | if c<1..0> != 2 then |
||
555 | cachePA = pa; |
||
556 | cachePA<4..0> = 0; |
||
557 | |||
558 | // The address hits the L1. |
||
559 | if L1(pa).hit then |
||
560 | // Update the L1. |
||
561 | l1Entry = L1(pa); |
||
562 | l1Entry.DATA<(8 * pa<4..0> + 63)..(8 * pa<4..0>)> = data; |
||
563 | L1(pa) = l1Entry; |
||
564 | |||
565 | // Only the write-through policy is supported. |
||
566 | pmem[pa] = data; |
||
567 | // The address does not hit the L1. |
||
568 | else |
||
569 | // The L2 cache is used. |
||
570 | if c<1..0> == 3 then |
||
571 | // The address hits the L2. |
||
572 | if L2(pa).hit then |
||
573 | // Update the L2. |
||
574 | l2Entry = L2(pa); |
||
575 | l2Entry.DATA<(8 * pa<4..0> + 63)..(8 * pa<4..0>)> = data; |
||
576 | L2(pa) = l2Entry; |
||
577 | |||
578 | // Fill the L1. |
||
579 | l1Entry.V = 1; |
||
580 | l1Entry.TAG = pa<35..12>; |
||
581 | l1Entry.DATA = l2Entry.DATA; |
||
582 | L1(pa) = l1Entry; |
||
583 | |||
584 | // Only the write-through policy is supported. |
||
585 | pmem[pa] = data; |
||
586 | // The address does not hit the L2. |
||
587 | else |
||
588 | pmem[pa] = data; |
||
589 | cacheData = pmem[cachePA + 24]::pmem[cachePA + 16]::pmem[cachePA + 8]::pmem[cachePA]; |
||
590 | |||
591 | // Fill the L2. |
||
592 | l2Entry.V = 1; |
||
593 | l2Entry.TAG = pa<35..17>; |
||
594 | l2Entry.DATA = cacheData; |
||
595 | L2(pa) = l2Entry; |
||
596 | |||
597 | // Fill the L1. |
||
598 | l1Entry.V = 1; |
||
599 | l1Entry.TAG = pa<35..12>; |
||
600 | l1Entry.DATA = cacheData; |
||
601 | L1(pa) = l1Entry; |
||
602 | endif; // If the address hits the L2. |
||
603 | // The L2 cache is bypassed. |
||
604 | else |
||
605 | pmem[pa] = data; |
||
606 | cacheData = pmem[cachePA + 24]::pmem[cachePA + 16]::pmem[cachePA + 8]::pmem[cachePA]; |
||
607 | |||
608 | // Fill the L2 |
||
609 | l1Entry.V = 1; |
||
610 | l1Entry.TAG = pa<35..12>; |
||
611 | l1Entry.DATA = cacheData; |
||
612 | L1(pa) = l1Entry; |
||
613 | endif; // If the L2 cache is used. |
||
614 | endif; // If the address hits the L1. |
||
615 | // The address is uncacheable. |
||
616 | else |
||
617 | pmem[pa] = data; |
||
618 | endif; // If the address is cacheable. |
||
619 | } |
||
620 | |||
621 | //================================================================================================== |
||
622 | // The End |
||
623 | //================================================================================================== |
||
624 | 1 | Taya Sergeeva | </pre> |