Project

General

Profile

MMU description » History » Version 129

Alexander Kamkin, 02/13/2015 09:39 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 (&ge; 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 129 Alexander Kamkin
252
h2. Simplified Specification of MIPS''s MMU
253
254
<pre>
255
//==================================================================================================
256
// Virtual Address (VA)
257
//==================================================================================================
258
259
address VA(64)
260
261
//--------------------------------------------------------------------------------------------------
262
// User Mode Segments
263
//--------------------------------------------------------------------------------------------------
264
265
segment USEG (va: VA)
266
  range = (0x0000000000000000, 0x000000007fffffff)
267
268
segment XUSEG(va: VA)
269
  range = (0x0000000080000000, 0x000000ffffffffff)
270
271
//--------------------------------------------------------------------------------------------------
272
// Supervisor Mode Segments
273
//--------------------------------------------------------------------------------------------------
274
275
segment SUSEG(va: VA)
276
  range = (0x0000000000000000, 0x000000007fffffff)
277
278
segment XSUSEG(va: VA)
279
  range = (0x0000000080000000, 0x000000ffffffffff)
280
281
segment XSSEG(va: VA)
282
  range = (0x4000000000000000, 0x400000ffffffffff)
283
  
284
segment CSSEG(va: VA)
285
  range = (0xffffffffc0000000, 0xffffffffdfffffff)
286
287
//--------------------------------------------------------------------------------------------------
288
// Kernel Mode Segments
289
//--------------------------------------------------------------------------------------------------
290
291
segment KUSEG (va: VA)
292
  range = (0x0000000000000000, 0x000000007fffffff)
293
294
segment XKUSEG (va: VA)
295
  range = (0x0000000080000000, 0x000000ffffffffff)
296
297
segment XKSSEG (va: VA)
298
  range = (0x4000000000000000, 0x400000ffffffffff)
299
300
segment XKSEG (va: VA)
301
  range = (0xc000000000000000, 0xc00000ff7fffffff)
302
303
segment CKSSEG (va: VA)
304
  range = (0xffffffffc0000000, 0xffffffffdfffffff)
305
306
segment CKSEG3(va: VA)
307
  range = (0xffffffffe0000000, 0xffffffffffffffff)
308
309
//==================================================================================================
310
// Physical Address (PA)
311
//==================================================================================================
312
313
address PA(36)
314
315
//==================================================================================================
316
// Translation Lookaside Buffer (TLB)
317
//==================================================================================================
318
319
buffer DTLB (va: VA)
320
  ways   = 4
321
  sets   = 1
322
  entry  = (ASID: 8, VPN2: 27, R: 2,               // EntryHi
323
            G0: 1, V0: 1, D0: 1, C0: 3, PFN0: 24,  // EntryLo0
324
            G1: 1, V1: 1, D1: 1, C1: 3, PFN1: 24)  // EntryLo1
325
  index  = 0
326
  match  = VPN2 == va<39..13> // ASID, G and non-4FB pages are unsupported
327
  policy = PLRU
328
329
buffer JTLB (va: VA)
330
  ways   = 64
331
  sets   = 1
332
  entry  = (ASID: 8, VPN2: 27, R: 2,               // EntryHi
333
            G0: 1, V0: 1, D0: 1, C0: 3, PFN0: 24,  // EntryLo0
334
            G1: 1, V1: 1, D1: 1, C1: 3, PFN1: 24)  // EntryLo1
335
  index  = 0
336
  match  = VPN2 == va<39..13> // ASID, G and non-4FB pages are unsupported
337
  policy = NONE
338
339
//==================================================================================================
340
// Cache Memory (L1 and L2)
341
//==================================================================================================
342
343
buffer L1 (pa: PA)
344
  ways   = 4
345
  sets   = 128
346
  entry  = (V: 1 = 0, TAG: 24, DATA: 256)
347
  index  = pa<11..5>
348
  match  = V == 1 && TAG == pa<35..12>
349
  policy = PLRU
350
351
buffer L2 (pa: PA)
352
  ways   = 4
353
  sets   = 4096
354
  entry  = (V: 1 = 0, TAG: 19, DATA: 256)
355
  index  = pa<16..5>
356
  match  = V == 1 && TAG == pa<35..17>
357
  policy = PLRU
358
359
//==================================================================================================
360
// MMU Logic (Interaction between TLB, L1 and L2)
361
//==================================================================================================
362
363
mmu pmem(va: VA) = (data: 64) 
364
  var tlbEntry: JTLB.entry;
365
  var l1Entry: L1.entry;
366
  var l2Entry: L2.entry;
367
368
  var evenOddBit: 5;
369
370
  var g: 1;
371
  var v: 1;
372
  var d: 1;
373
  var c: 3;
374
  var pfn: 24;
375
376
  var pa: PA;
377
378
  var cachePA: PA;
379
  var cacheData: 256;
380
381
  read = {
382
    // The address is unaligned.
383
    if va<0..2> != 0 then
384
      exception("AddressError");
385
    endif; // If the address is unaligned.
386
387
    // The default cache policy.
388
    c = 3;
389
390
    // The address is from the USEG segment (only USEG and KSEG segments are supported).
391
    if USEG(va).hit then
392
      // The address hits the DTLB.
393
      if DTLB(va).hit then
394
        tlbEntry = DTLB(va);
395
      // The address hits the JTLB.
396
      elif JTLB(va).hit then
397
        tlbEntry = JTLB(va);
398
      // The address does not hit the TLB.
399
      else
400
        exception("TLBMiss");
401
      endif; // If the address hits the DTLB.
402
403
      // Only 4KB pages are supported.
404
      evenOddBit = 12;
405
406
      // The VPN is even.
407
      if va<evenOddBit> == 0 then
408
        g   = tlbEntry.G0;
409
        v   = tlbEntry.V0;
410
        d   = tlbEntry.D0;
411
        c   = tlbEntry.C0;
412
        pfn = tlbEntry.PFN0;
413
      // The VPN is odd.
414
      else
415
        g   = tlbEntry.G1;
416
        v   = tlbEntry.V1;
417
        d   = tlbEntry.D1;
418
        c   = tlbEntry.C1;
419
        pfn = tlbEntry.PFN1;
420
      endif; // If the VPN is even.
421
422
      // The EntryLo is valid.
423
      if v == 1 then
424
        pa = pfn<24..(evenOddBit - 12)>::va<(evenOddBit - 1)..0>;
425
      // The EntryLo is invalid.
426
      else
427
        exception("TLBInvalid");
428
      endif; // If the EntryLo is valid.
429
    // The address is from the KSEG0 or KSEG1 segment.
430
    else
431
      pa = va<28..0>;
432
    endif; // If the address is from the USEG segment.
433
434
    // The address is cacheable.
435
    if c<1..0> != 2 then
436
      cachePA = pa;
437
      cachePA<4..0> = 0;
438
439
      // The address hits the L1.
440
      if L1(pa).hit then
441
        l1Entry = L1(pa);
442
        cacheData = l1Entry.DATA;
443
        data = cacheData<(8 * pa<4..0> + 63)..(8 * pa<4..0>)>;
444
      // The address does not hit the L1.
445
      else
446
        // The L2 cache is used.
447
        if c<1..0> == 3 then
448
          // The address hits the L2.
449
          if L2(pa).hit then
450
            l2Entry = L2(pa);
451
            cacheData = l2Entry.DATA;
452
            data = cacheData<(8 * pa<4..0> + 63)..(8 * pa<4..0>)>;
453
454
            // Fill the L1.
455
            l1Entry.V = 1;
456
            l1Entry.TAG = pa<35..12>;
457
            l1Entry.DATA = cacheData;
458
            L1(pa) = l1Entry;
459
          // The address does not hit the L2.
460
          else
461
            cacheData = pmem[cachePA + 24]::pmem[cachePA + 16]::pmem[cachePA + 8]::pmem[cachePA];
462
            data = cacheData<(8 * pa<4..0> + 63)..(8 * pa<4..0>)>;
463
464
            // Fill L2.
465
            l2Entry.V = 1;
466
            l2Entry.TAG = pa<35..17>;
467
            l2Entry.DATA = cacheData;
468
            L2(pa) = l2Entry;
469
470
            // Fill L1.
471
            l1Entry.V = 1;
472
            l1Entry.TAG = pa<35..12>;
473
            l1Entry.DATA = cacheData;
474
            L1(pa) = l1Entry;
475
          endif; // If the address hits the L2.
476
        // The L2 cache is bypassed.
477
        else
478
          cacheData = pmem[cachePA + 24]::pmem[cachePA + 16]::pmem[cachePA + 8]::pmem[cachePA];
479
          data = cacheData<(8 * pa<4..0> + 63)..(8 * pa<4..0>)>;
480
481
          l1Entry.V = 1;
482
          l1Entry.TAG = pa<35..12>;
483
          l1Entry.DATA = cacheData;
484
          L1(pa) = l1Entry;
485
        endif; // If the L2 cache is used.
486
      endif; // If the address hits the L1.
487
    // The address is uncacheable.
488
    else
489
      data = pmem[pa];
490
    endif; // If the address is cacheable.
491
  }
492
493
  write = {
494
    // The address is unaligned.
495
    if va<0..2> != 0 then
496
      exception("AddressError");
497
    endif; // If the address is unaligned.
498
499
    // The default cache policy.
500
    c = 3;
501
502
    // The address is from the USEG segment (only USEG and KSEG segments are supported).
503
    if USEG(va).hit then
504
      // The address hits the DTLB.
505
      if DTLB(va).hit then
506
        tlbEntry = DTLB(va);
507
      // The address hits the JTLB.
508
      elif JTLB(va).hit then
509
        tlbEntry = JTLB(va);
510
      // The address does not hit the TLB.
511
      else
512
        exception("TLBMiss");
513
      endif; // If the address hits the DTLB.
514
515
      // Only 4KB pages are supported.
516
      evenOddBit = 12;
517
518
      // The VPN is even.
519
      if va<evenOddBit> == 0 then
520
        g   = tlbEntry.G0;
521
        v   = tlbEntry.V0;
522
        d   = tlbEntry.D0;
523
        c   = tlbEntry.C0;
524
        pfn = tlbEntry.PFN0;
525
      // The VPN is odd.
526
      else
527
        g   = tlbEntry.G1;
528
        v   = tlbEntry.V1;
529
        d   = tlbEntry.D1;
530
        c   = tlbEntry.C1;
531
        pfn = tlbEntry.PFN1;
532
      endif; // If the VPN is even.
533
534
      // The EntryLo is valid.
535
      if v == 1 then
536
        // The EntryLo is clean.
537
        if d == 1 then
538
          pa = pfn<24..(evenOddBit - 12)>::va<(evenOddBit - 1)..0>;
539
        // The EntryLo is dirty.
540
        else
541
          exception("TLBModified");
542
        endif; // If the EntryLo is clean.
543
      // The EntryLo is invalid.
544
      else
545
        exception("TLBInvalid");
546
      endif; // If the EntryLo is valid.
547
    // The address is from the KSEG0 or KSEG1 segment.
548
    else
549
      pa = va<28..0>;
550
    endif; // If the address is from the USEG segment.
551
552
    // The address is cacheable.
553
    if c<1..0> != 2 then
554
      cachePA = pa;
555
      cachePA<4..0> = 0;
556
557
      // The address hits the L1.
558
      if L1(pa).hit then
559
        // Update the L1.
560
        l1Entry = L1(pa);
561
        l1Entry.DATA<(8 * pa<4..0> + 63)..(8 * pa<4..0>)> = data;
562
        L1(pa) = l1Entry;
563
564
        // Only the write-through policy is supported.
565
        pmem[pa] = data;
566
      // The address does not hit the L1.
567
      else
568
        // The L2 cache is used.
569
        if c<1..0> == 3 then
570
          // The address hits the L2.
571
          if L2(pa).hit then
572
            // Update the L2.
573
            l2Entry = L2(pa);
574
            l2Entry.DATA<(8 * pa<4..0> + 63)..(8 * pa<4..0>)> = data;
575
            L2(pa) = l2Entry;
576
577
            // Fill the L1.
578
            l1Entry.V = 1;
579
            l1Entry.TAG = pa<35..12>;
580
            l1Entry.DATA = l2Entry.DATA;
581
            L1(pa) = l1Entry;
582
583
            // Only the write-through policy is supported.
584
            pmem[pa] = data;
585
          // The address does not hit the L2.
586
          else
587
            pmem[pa] = data;
588
            cacheData = pmem[cachePA + 24]::pmem[cachePA + 16]::pmem[cachePA + 8]::pmem[cachePA];
589
590
            // Fill the L2.
591
            l2Entry.V = 1;
592
            l2Entry.TAG = pa<35..17>;
593
            l2Entry.DATA = cacheData;
594
            L2(pa) = l2Entry;
595
596
            // Fill the L1.
597
            l1Entry.V = 1;
598
            l1Entry.TAG = pa<35..12>;
599
            l1Entry.DATA = cacheData;
600
            L1(pa) = l1Entry;
601
          endif; // If the address hits the L2.
602
        // The L2 cache is bypassed.
603
        else
604
          pmem[pa] = data;
605
          cacheData = pmem[cachePA + 24]::pmem[cachePA + 16]::pmem[cachePA + 8]::pmem[cachePA];
606
607
          // Fill the L2
608
          l1Entry.V = 1;
609
          l1Entry.TAG = pa<35..12>;
610
          l1Entry.DATA = cacheData;
611
          L1(pa) = l1Entry;
612
        endif; // If the L2 cache is used.
613
      endif; // If the address hits the L1.
614
    // The address is uncacheable.
615
    else
616
      pmem[pa] = data;
617
    endif; // If the address is cacheable.
618
  }
619
620
//==================================================================================================
621
// The End
622
//==================================================================================================
623 1 Taya Sergeeva
</pre>