source: branches/RWT/lib/generic_cache_tsar/include/generic_cache.h@ 887

Last change on this file since 887 was 823, checked in by devigne, 12 years ago

RWT Commit : Cosmetic

File size: 31.1 KB
Line 
1/* -*- c++ -*-
2 *
3 * SOCLIB_LGPL_HEADER_BEGIN
4 *
5 * This file is part of SoCLib, GNU LGPLv2.1.
6 *
7 * SoCLib is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; version 2.1 of the License.
10 *
11 * SoCLib is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with SoCLib; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 * SOCLIB_LGPL_HEADER_END
22 *
23 * Copyright (c) UPMC, Lip6
24 * Alain Greiner <alain.greiner@lip6.fr> July 2008
25 *
26 * Maintainers: alain
27 */
28
29////////////////////////////////////////////////////////////////////////////////
30// File : generic_cache.h
31// Date : 07/01/2012
32// Authors : Alain Greiner
33/////////////////////////////////////////////////////////////////////////////////
34// This object is a generic, set associative, cache.
35// Each slot can be in three states: VALID, EMPTY or ZOMBI.
36// The ZOMBI state is used by cache coherence protocols to indicate
37// a pending cleanup request.
38// Hit if ( (matching tag) and (state == VALID).
39// The replacement policy is pseudo-LRU. The victim selection process cannot
40// fail if the ZOMBI state is not used.
41// But it can fail if all ways are in ZOMBI state.
42/////////////////////////////////////////////////////////////////////////////////
43// Implementation note
44// The DATA part is implemented as an uint32_t array[nways*nsets*nwords].
45// The DIRECTORY part is implemented as an uint32_t array[nways*nsets].
46// All methods requiring a dual port RAM or cache modification using
47// an associative search have been deprecated.
48/////////////////////////////////////////////////////////////////////////////////
49// Constructor parameters are :
50// - std::string &name
51// - size_t nways : number of associativity levels
52// - size_t nsets : number of sets
53// - size_t nwords : number of words in a cache line
54// The nways, nsets, nwords parameters must be power of 2
55// The nsets parameter cannot be larger than 1024
56// The nways parameter cannot be larger than 16
57// The nwords parameter cannot be larger than 64
58/////////////////////////////////////////////////////////////////////////////////
59// Template parameter is :
60// - addr_t : address format to access the cache
61/////////////////////////////////////////////////////////////////////////////////
62
63#ifndef SOCLIB_GENERIC_CACHE_H
64#define SOCLIB_GENERIC_CACHE_H
65
66#include <systemc>
67#include <cassert>
68#include "arithmetics.h"
69#include "static_assert.h"
70#include "mapping_table.h"
71#include <cstring>
72
73namespace soclib {
74
75enum cache_slot_state_e
76{
77 CACHE_SLOT_STATE_EMPTY,
78 CACHE_SLOT_STATE_VALID_CC,
79 CACHE_SLOT_STATE_ZOMBI,
80 CACHE_SLOT_STATE_VALID_NCC,
81};
82
83//////////////////////////
84template<typename addr_t>
85class GenericCache
86//////////////////////////
87{
88 typedef uint32_t data_t;
89 typedef uint32_t be_t;
90
91 data_t *r_data ;
92 addr_t *r_tag ;
93 int *r_state;
94 bool *r_lru ;
95
96 size_t m_ways;
97 size_t m_sets;
98 size_t m_words;
99
100 const soclib::common::AddressMaskingTable<addr_t> m_x ;
101 const soclib::common::AddressMaskingTable<addr_t> m_y ;
102 const soclib::common::AddressMaskingTable<addr_t> m_z ;
103
104 //////////////////////////////////////////////////////////////
105 inline data_t &cache_data(size_t way, size_t set, size_t word)
106 {
107 return r_data[(way * m_sets * m_words) + (set * m_words) + word];
108 }
109
110 //////////////////////////////////////////////
111 inline addr_t &cache_tag(size_t way, size_t set)
112 {
113 return r_tag[(way * m_sets) + set];
114 }
115
116 //////////////////////////////////////////////
117 inline bool &cache_lru(size_t way, size_t set)
118 {
119 return r_lru[(way * m_sets) + set];
120 }
121
122 //////////////////////////////////////////////
123 inline int &cache_state(size_t way, size_t set)
124 {
125 return r_state[(way * m_sets) + set];
126 }
127
128
129 /////////////////////////////////////////////////
130 inline void cache_set_lru(size_t way, size_t set)
131 {
132 size_t way2;
133
134 cache_lru(way, set) = true;
135
136 for (way2 = 0; way2 < m_ways; way2++)
137 {
138 if (cache_lru(way2, set) == false) return;
139 }
140 // all lines are new -> they all become old
141 for (way2 = 0; way2 < m_ways; way2++)
142 {
143 cache_lru(way2, set) = false;
144 }
145 }
146
147 ////////////////////////////////
148 inline data_t be2mask(be_t be)
149 {
150 data_t mask = 0;
151 if ((be & 0x1) == 0x1) mask = mask | 0x000000FF;
152 if ((be & 0x2) == 0x2) mask = mask | 0x0000FF00;
153 if ((be & 0x4) == 0x4) mask = mask | 0x00FF0000;
154 if ((be & 0x8) == 0x8) mask = mask | 0xFF000000;
155 return mask;
156 }
157
158public:
159
160 //////////////////////////////////////////
161 GenericCache(const std::string &name,
162 size_t nways,
163 size_t nsets,
164 size_t nwords)
165 : m_ways(nways),
166 m_sets(nsets),
167 m_words(nwords),
168
169#define l2 soclib::common::uint32_log2
170
171 m_x(l2(nwords), l2(sizeof(data_t))),
172 m_y(l2(nsets), l2(nwords) + l2(sizeof(data_t))),
173 m_z(8*sizeof(addr_t) - l2(nsets) - l2(nwords) - l2(sizeof(data_t)),
174 l2(nsets) + l2(nwords) + l2(sizeof(data_t)))
175#undef l2
176 {
177 assert(IS_POW_OF_2(nways));
178 assert(IS_POW_OF_2(nsets));
179 assert(IS_POW_OF_2(nwords));
180 assert(nwords);
181 assert(nsets);
182 assert(nways);
183 assert(nwords <= 64);
184 assert(nsets <= 1024);
185 assert(nways <= 16);
186
187#ifdef GENERIC_CACHE_DEBUG
188 std::cout << "constructing " << name << std::endl
189 << "- nways = " << nways << std::endl
190 << "- nsets = " << nsets << std::endl
191 << "- nwords = " << nwords << std::endl
192 << " m_x: " << m_x
193 << " m_y: " << m_y
194 << " m_z: " << m_z
195 << std::endl;
196#endif
197
198 r_data = new data_t[nways * nsets * nwords];
199 r_tag = new addr_t[nways * nsets];
200 r_state = new int[nways * nsets];
201 r_lru = new bool[nways * nsets];
202 }
203
204 ////////////////
205 ~GenericCache()
206 {
207 delete [] r_data;
208 delete [] r_tag;
209 delete [] r_state;
210 delete [] r_lru;
211 }
212
213 ////////////////////
214 inline void reset()
215 {
216 std::memset(r_data, 0, sizeof(*r_data) * m_ways * m_sets * m_words);
217 std::memset(r_tag, 0, sizeof(*r_tag) * m_ways * m_sets);
218 std::memset(r_state, CACHE_SLOT_STATE_EMPTY, sizeof(*r_state) * m_ways * m_sets);
219 std::memset(r_lru, 0, sizeof(*r_lru) * m_ways * m_sets);
220 }
221
222 inline int get_cache_state(int way, int set)
223 {
224 return cache_state(way,set);
225 }
226
227 /////////////////////////////////////////////////////////////////////
228 // Read a single 32 bits word.
229 // returns true if (matching tag) and (state == VALID)
230 // Both data & directory are accessed.
231 /////////////////////////////////////////////////////////////////////
232 inline bool read(addr_t ad,
233 data_t* dt)
234 {
235 const addr_t tag = m_z[ad];
236 const size_t set = m_y[ad];
237 const size_t word = m_x[ad];
238
239 for (size_t way = 0; way < m_ways; way++)
240 {
241 if ((tag == cache_tag(way, set)) and
242 ((cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC) or
243 (cache_state(way, set) == CACHE_SLOT_STATE_VALID_NCC)))
244 {
245 *dt = cache_data(way, set, word);
246 cache_set_lru(way, set);
247 return true;
248 }
249 }
250 return false;
251 }
252
253 ////////////////////////////////////////////////////////////////////
254 // Read a single 32 bits word.
255 // returns true if (matching tag) and (state == VALID)
256 // Both data & directory are accessed.
257 // The selected way, set and word index are returned in case of hit.
258 /////////////////////////////////////////////////////////////////////
259 inline bool read(addr_t ad,
260 data_t* dt,
261 size_t* selway,
262 size_t* selset,
263 size_t* selword)
264 {
265 const addr_t tag = m_z[ad];
266 const size_t set = m_y[ad];
267 const size_t word = m_x[ad];
268
269 for (size_t way = 0; way < m_ways; way++)
270 {
271 if ((tag == cache_tag(way, set)) and
272 ((cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC) or
273 (cache_state(way, set) == CACHE_SLOT_STATE_VALID_NCC)))
274 {
275 *selway = way;
276 *selset = set;
277 *selword = word;
278 *dt = cache_data(way, set, word);
279 cache_set_lru(way, set);
280 return true;
281 }
282 }
283 return false;
284 }
285
286 ////////////////////////////////////////////////////////////////////
287 // Read a single 32 bits word when the ZOMBI state is used.
288 // Both data and directory are accessed.
289 // returns the access status in the state argument:
290 // - VALID : (matching tag) and (state == VALID)
291 // - ZOMBI : (matching tag) and (state == ZOMBI)
292 // - MISS : no matching tag or EMPTY state
293 // If VALID or ZOMBI, the data, the way, set and word index are
294 // returned in the other arguments.
295 ////////////////////////////////////////////////////////////////////
296 inline void read(addr_t ad,
297 data_t* dt,
298 size_t* selway,
299 size_t* selset,
300 size_t* selword,
301 int* state)
302 {
303 const addr_t tag = m_z[ad];
304 const size_t set = m_y[ad];
305 const size_t word = m_x[ad];
306
307 // default return values
308 *state = CACHE_SLOT_STATE_EMPTY;
309 *selway = 0;
310 *selset = 0;
311 *selword = 0;
312 *dt = 0;
313
314 for (size_t way = 0; way < m_ways; way++)
315 {
316 if (tag == cache_tag(way, set)) // matching tag
317 {
318 if (cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC)
319 {
320 *state = CACHE_SLOT_STATE_VALID_CC;
321 *selway = way;
322 *selset = set;
323 *selword = word;
324 *dt = cache_data(way, set, word);
325 cache_set_lru(way, set);
326 }
327 else if (cache_state(way, set) == CACHE_SLOT_STATE_VALID_NCC)
328 {
329 *state = CACHE_SLOT_STATE_VALID_NCC;
330 *selway = way;
331 *selset = set;
332 *selword = word;
333 *dt = cache_data(way, set, word);
334 cache_set_lru(way, set);
335 }
336 else if (cache_state(way, set) == CACHE_SLOT_STATE_ZOMBI)
337 {
338 *state = CACHE_SLOT_STATE_ZOMBI;
339 *selway = way;
340 *selset = set;
341 *selword = word;
342 }
343 }
344 }
345 }
346
347 ////////////////////////////////////////////////////////////////////
348 // Read a single 32 bits word, without LRU update.
349 // returns true if (matching tag) and (state == VALID)
350 // Both data & directory are accessed.
351 // The selected way, set and word index are returned in case of hit.
352 /////////////////////////////////////////////////////////////////////
353 inline bool read_neutral(addr_t ad,
354 data_t* dt,
355 size_t* selway,
356 size_t* selset,
357 size_t* selword)
358 {
359 const addr_t tag = m_z[ad];
360 const size_t set = m_y[ad];
361 const size_t word = m_x[ad];
362
363 for (size_t way = 0; way < m_ways; way++)
364 {
365 if ((tag == cache_tag(way, set)) and
366 ((cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC) or
367 (cache_state(way, set) == CACHE_SLOT_STATE_VALID_NCC)))
368 {
369 *selway = way;
370 *selset = set;
371 *selword = word;
372 *dt = cache_data(way, set, word);
373 return true;
374 }
375 }
376 return false;
377 }
378
379 /////////////////////////////////////////////////////////////////////////////
380 // Read one or two 32 bits word.
381 // Both data & directory are accessed.
382 // Hit if (matching tag) and (valid == true) and (zombi == false)
383 // If the addressed word is not the last in the cache line,
384 // two successive words are returned.
385 // The selected way, set and first word index are returned in case of hit.
386 // This function is used by the cc_vcache to get a 64 bits page table entry.
387 /////////////////////////////////////////////////////////////////////////////
388 inline bool read(addr_t ad,
389 data_t* dt,
390 data_t* dt_next,
391 size_t* selway,
392 size_t* selset,
393 size_t* selword)
394 {
395 const addr_t tag = m_z[ad];
396 const size_t set = m_y[ad];
397 const size_t word = m_x[ad];
398
399 for (size_t way = 0; way < m_ways; way++)
400 {
401 if ((tag == cache_tag(way, set)) and
402 ((cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC)))
403 {
404 *dt = cache_data(way, set, word);
405 if (word + 1 < m_words)
406 {
407 *dt_next = cache_data(way, set, word + 1);
408 }
409 *selway = way;
410 *selset = set;
411 *selword = word;
412 cache_set_lru(way, set);
413 return true;
414 }
415 }
416 return false;
417 }
418
419 ////////////////////////////////////////////////////////////////////
420 // Read one or two 32 bits word.
421 // Both data and directory are accessed.
422 // returns the access status in the state argument:
423 // - VALID : (matching tag) and (state == VALID)
424 // - ZOMBI : (matching tag) and (state == ZOMBI)
425 // - MISS : no matching tag or EMPTY state
426 // If VALID or ZOMBI, the data, the way, set and word index are
427 // returned in the other arguments.
428 ////////////////////////////////////////////////////////////////////
429 inline void read(addr_t ad,
430 data_t* dt,
431 data_t* dt_next,
432 size_t* selway,
433 size_t* selset,
434 size_t* selword,
435 int* state)
436 {
437 const addr_t tag = m_z[ad];
438 const size_t set = m_y[ad];
439 const size_t word = m_x[ad];
440
441 // default return values
442 *state = CACHE_SLOT_STATE_EMPTY;
443 *selway = 0;
444 *selset = 0;
445 *selword = 0;
446 *dt = 0;
447
448 for (size_t way = 0; way < m_ways; way++)
449 {
450 if (tag == cache_tag(way, set)) // matching tag
451 {
452
453 if (cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC)
454 {
455 *state = CACHE_SLOT_STATE_VALID_CC;
456 *selway = way;
457 *selset = set;
458 *selword = word;
459 *dt = cache_data(way, set, word);
460 if (word + 1 < m_words)
461 {
462 *dt_next = cache_data(way, set, word+1);
463 }
464 cache_set_lru(way, set);
465 }
466
467 else if (cache_state(way, set) == CACHE_SLOT_STATE_VALID_NCC)
468 {
469 *state = CACHE_SLOT_STATE_VALID_NCC;
470 *selway = way;
471 *selset = set;
472 *selword = word;
473 *dt = cache_data(way, set, word);
474 if (word + 1 < m_words)
475 {
476 *dt_next = cache_data(way, set, word + 1);
477 }
478 cache_set_lru(way, set);
479 }
480
481 else if (cache_state(way, set) == CACHE_SLOT_STATE_ZOMBI)
482 {
483 *state = CACHE_SLOT_STATE_ZOMBI;
484 *selway = way;
485 *selset = set;
486 *selword = word;
487 }
488 }
489 }
490 }
491
492 ///////////////////////////////////////////////////////////////////////////////
493 // Checks the cache state for a given address.
494 // Only the directory is accessed.
495 // returns true if (matching tag) and (state == VALID)
496 // The selected way, set and first word index are returned in case of hit.
497 // This function can be used when we need to access the directory
498 // while we write in the data part with a different address in the same cycle.
499 ///////////////////////////////////////////////////////////////////////////////
500 inline bool hit(addr_t ad,
501 size_t* selway,
502 size_t* selset,
503 size_t* selword)
504 {
505 const addr_t tag = m_z[ad];
506 const size_t set = m_y[ad];
507 const size_t word = m_x[ad];
508
509 for (size_t way = 0; way < m_ways; way++)
510 {
511 if ((tag == cache_tag(way, set)) and
512 ((cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC) or
513 (cache_state(way, set) == CACHE_SLOT_STATE_VALID_NCC)))
514 {
515 *selway = way;
516 *selset = set;
517 *selword = word;
518 cache_set_lru(way, set);
519 return true;
520 }
521 }
522 return false;
523 }
524
525 ///////////////////////////////////////////////////////////////////////////////
526 // Checks the cache state for a given address, when the ZOMBI state is used.
527 // Only the directory is accessed.
528 // Returns the access status in the state argument:
529 // - VALID if (matching tag) and (state == VALID)
530 // - ZOMBI if (matching tag) and (state == ZOMBI)
531 // - EMPTY if no match or (state == EMPTY)
532 // The selected way, set and first word index are returned if not empty.
533 // This function can be used when we need to access the directory
534 // while we write in the data part with a different address in the same cycle.
535 ///////////////////////////////////////////////////////////////////////////////
536 inline void read_dir(addr_t ad,
537 int* state,
538 size_t* way,
539 size_t* set,
540 size_t* word)
541 {
542 const addr_t ad_tag = m_z[ad];
543 const size_t ad_set = m_y[ad];
544 const size_t ad_word = m_x[ad];
545 for (size_t _way = 0; _way < m_ways; _way++)
546 {
547 if ((ad_tag == cache_tag(_way, ad_set)) and
548 (cache_state(_way, ad_set) != CACHE_SLOT_STATE_EMPTY))
549 {
550 *state = cache_state(_way, ad_set);
551 *way = _way;
552 *set = ad_set;
553 *word = ad_word;
554 return;
555 }
556 }
557
558 // return value if not (VALID or ZOMBI)
559 *state = CACHE_SLOT_STATE_EMPTY;
560 }
561
562 ///////////////////////////////////////////////////////////////////////////////
563 // Checks the cache state for a slot (set,way), when the ZOMBI state is used.
564 // Only the directory is accessed.
565 // Returns the access status and the tag value in the state and tag argument.
566 ///////////////////////////////////////////////////////////////////////////////
567 inline void read_dir(size_t way,
568 size_t set,
569 addr_t* tag,
570 int* state)
571 {
572 *state = cache_state(way, set);
573 *tag = cache_tag(way, set);
574 }
575
576 ////////////////////////////////////////////
577 inline addr_t get_tag(size_t way, size_t set)
578 {
579 return cache_tag(way, set);
580 }
581
582 ///////////////////////////////////////////////////////////////////
583 // This function writes a complete 32 bits word
584 // It does not use the directory and cannot miss.
585 //////////////////////////////////////////////////////////////////
586 inline void write(size_t way,
587 size_t set,
588 size_t word,
589 data_t data)
590 {
591 cache_data(way, set, word) = data;
592 cache_set_lru(way, set);
593 }
594
595 ////////////////////////////////////////////////////////////////////////////
596 // this function writes up to 4 bytes, taking into account the byte enable.
597 // It does not use the directory and cannot miss.
598 ////////////////////////////////////////////////////////////////////////////
599 inline void write(size_t way,
600 size_t set,
601 size_t word,
602 data_t data,
603 be_t be)
604 {
605 data_t mask = be2mask(be);
606 data_t prev = cache_data(way, set, word);
607 cache_data(way, set, word) = (mask & data) | (~mask & prev);
608 cache_set_lru(way, set);
609 }
610
611 //////////////////////////////////////////////////////////////////////////
612 // This function invalidates a cache line identified by the set and way.
613 // It returns true if the line was valid, and returns the line index.
614 //////////////////////////////////////////////////////////////////////////
615 inline bool inval(size_t way,
616 size_t set,
617 addr_t* nline)
618 {
619 if ((cache_state(way,set) == CACHE_SLOT_STATE_VALID_CC) or
620 (cache_state(way,set) == CACHE_SLOT_STATE_VALID_NCC))
621 {
622 cache_state(way,set) = CACHE_SLOT_STATE_EMPTY;
623 *nline = (data_t) cache_tag(way, set) * m_sets + set;
624 return true;
625 }
626 return false;
627 }
628
629 //////////////////////////////////////////////////////////////////////////////////
630 // This function selects a victim slot in an associative set.
631 // It cannot fail, as a slot in ZOMBI state is considered EMPTY.
632 // - we search first an EMPTY slot
633 // - if no EMPTY slot, we search an OLD slot, using lru
634 // It returns the line index (Z + Y fields), the selected slot way and set,
635 // and a Boolean indicating that a cleanup is requested.
636 //////////////////////////////////////////////////////////////////////////////////
637 inline bool victim_select(addr_t ad,
638 addr_t* victim,
639 size_t* way,
640 size_t* set)
641 {
642 bool found = false;
643 bool cleanup = false;
644
645 *set = m_y[ad];
646 *way = 0;
647
648 // Search first empty slot
649 for (size_t _way = 0; _way < m_ways && !found; _way++)
650 {
651 // empty
652 if ((cache_state(_way, *set) != CACHE_SLOT_STATE_VALID_CC) and
653 (cache_state(_way, *set) != CACHE_SLOT_STATE_VALID_NCC))
654 {
655 found = true;
656 cleanup = false;
657 *way = _way;
658 }
659 }
660
661 // If no empty slot, search first old slot (lru == false)
662 if (!found)
663 {
664 for (size_t _way = 0; _way < m_ways && !found; _way++)
665 {
666 if (not cache_lru(_way, *set))
667 {
668 found = true;
669 cleanup = true;
670 *way = _way;
671 }
672 }
673 }
674
675 assert(found && "all ways can't be new at the same time");
676 *victim = (addr_t) ((cache_tag(*way, *set) * m_sets) + *set);
677 return cleanup;
678 }
679
680 //////////////////////////////////////////////////////////////////////////////////
681 // This function selects a victim slot in an associative set.
682 // It can fail if all ways are in ZOMBI state.
683 // - we search first an EMPTY slot
684 // - if no empty slot, we search an OLD slot not in ZOMBI state,
685 // - if not found, we take the first not ZOMBI slot.
686 // It returns the line index (Z + Y fields), the selected slot way and set,
687 // and two Boolean indicating success and a required cleanup.
688 //////////////////////////////////////////////////////////////////////////////////
689 inline void read_select(addr_t ad,
690 addr_t* victim,
691 size_t* way,
692 size_t* set,
693 bool* found,
694 bool* cleanup)
695 {
696 size_t _set = m_y[ad];
697
698 *found = false;
699
700 // Search first empty slot
701 for (size_t _way = 0; _way < m_ways && !(*found); _way++)
702 {
703 if (cache_state(_way, _set) == CACHE_SLOT_STATE_EMPTY)
704 {
705 *found = true;
706 *cleanup = false;
707 *way = _way;
708 *set = m_y[ad];
709 return;
710 }
711 }
712
713 // Search first not zombi old slot
714 for (size_t _way = 0; _way < m_ways && !(*found); _way++)
715 {
716 if (not cache_lru(_way, _set) and
717 (cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI))
718 {
719 *found = true;
720 *cleanup = true;
721 *way = _way;
722 *set = m_y[ad];
723 *victim = cache_tag(*way,_set) * m_sets + _set;
724 return;
725 }
726 }
727 // Search first not zombi slot
728 for (size_t _way = 0; _way < m_ways && !(*found); _way++)
729 {
730 if (cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI)
731 {
732 *found = true;
733 *cleanup = true;
734 *way = _way;
735 *set = m_y[ad];
736 *victim = cache_tag(*way,_set) * m_sets + _set;
737 return;
738 }
739 }
740
741 // no slot found...
742 *found = false;
743 *cleanup = false;
744 }
745
746 //////////////////////////////////////////////////////////////////
747 // This function update the directory part of a slot
748 // identified by the way & set.
749 //////////////////////////////////////////////////////////////////
750 inline void victim_update_tag(addr_t ad,
751 size_t way,
752 size_t set)
753 {
754 addr_t tag = m_z[ad];
755
756 cache_tag(way, set) = tag;
757 cache_state(way, set) = CACHE_SLOT_STATE_VALID_CC;
758 cache_set_lru(way, set);
759 }
760
761 //////////////////////////////////////////////////////////////////
762 // This function write the directory part of a slot
763 // identified by the way & set, when using the ZOMBI state.
764 //////////////////////////////////////////////////////////////////
765 inline void write_dir(addr_t ad,
766 size_t way,
767 size_t set,
768 int state)
769 {
770 addr_t tag = m_z[ad];
771
772 assert(((state == CACHE_SLOT_STATE_VALID_CC) or
773 (state == CACHE_SLOT_STATE_VALID_NCC) or
774 (state == CACHE_SLOT_STATE_ZOMBI) or
775 (state == CACHE_SLOT_STATE_EMPTY)) and
776 "illegal slot state argument in Generic Cache write_dir()");
777
778 assert((way < m_ways) and
779 "too large way index argument in Generic Cache write_dir()");
780
781 assert((set < m_sets) and
782 "too large set index argument in Generic Cache write_dir()");
783
784 cache_tag(way, set) = tag;
785 cache_state(way, set) = state;
786
787 if ((state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC))
788 cache_set_lru(way, set);
789 }
790
791 //////////////////////////////////////////////////////////////////
792 // This function change the state of a slot
793 // identified by the way & set, when using the ZOMBI state.
794 // It does not affect the tag
795 //////////////////////////////////////////////////////////////////
796 inline void write_dir(size_t way,
797 size_t set,
798 int state)
799 {
800 assert(((state == CACHE_SLOT_STATE_VALID_CC) or
801 (state == CACHE_SLOT_STATE_VALID_NCC) or
802 (state == CACHE_SLOT_STATE_ZOMBI) or
803 (state == CACHE_SLOT_STATE_EMPTY) ) and
804 "illegal slot state argument in Generic Cache write_dir()");
805
806 assert((way < m_ways) and
807 "too large way index argument in Generic Cache write_dir()");
808
809 assert((set < m_sets) and
810 "too large set index argument in Generic Cache write_dir()");
811
812 cache_state(way, set) = state;
813
814 if ((state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC))
815 cache_set_lru(way, set);
816 }
817
818 ///////////////////////////////////////////////////////////////////
819 // This function writes a full cache line in one single cycle.
820 // The target slot is identified by the way & set arguments.
821 // Both DATA and DIRECTORY are written
822 ///////////////////////////////////////////////////////////////////
823 inline void update(addr_t ad,
824 size_t way,
825 size_t set,
826 data_t* buf)
827 {
828 addr_t tag = m_z[ad];
829
830 cache_tag(way, set) = tag;
831 cache_state(way, set) = CACHE_SLOT_STATE_VALID_CC;
832 cache_set_lru(way, set);
833 for (size_t word = 0; word < m_words; word++)
834 {
835 cache_data(way, set, word) = buf[word];
836 }
837 }
838
839 ///////////////////////////
840 void fileTrace(FILE* file)
841 {
842 for (size_t nway = 0; nway < m_ways; nway++)
843 {
844 for (size_t nset = 0; nset < m_sets; nset++)
845 {
846 fprintf(file, "%d / ", (int) cache_state(nway, nset));
847 fprintf(file, "way %d / ", (int) nway);
848 fprintf(file, "set %d / ", (int) nset);
849 fprintf(file, "@ = %08zX / ",
850 ((cache_tag(nway, nset) * m_sets + nset) * m_words * 4));
851 for (size_t nword = m_words; nword > 0; nword--)
852 {
853 unsigned int data = cache_data(nway, nset, nword - 1);
854 fprintf(file, "%08X ", data);
855 }
856 fprintf(file, "\n");
857 }
858 }
859 }
860
861 ////////////////////////
862 inline void printTrace()
863 {
864 for (size_t way = 0; way < m_ways; way++)
865 {
866 for (size_t set = 0; set < m_sets; set++)
867 {
868 addr_t addr = (((addr_t) cache_tag(way, set)) * m_words * m_sets + m_words * set) * 4;
869 std::cout << std::dec << cache_state(way, set)
870 << " | way " << way
871 << " | set " << set
872 << std::hex << " | @ " << addr;
873
874 for (size_t word = 0; word < m_words; word++)
875 {
876 std::cout << " | " << cache_data(way, set, word) ;
877 }
878 std::cout << std::dec << std::endl ;
879 }
880 }
881 }
882
883};
884
885} // namespace soclib
886
887#endif
888
889// Local Variables:
890// tab-width: 4
891// c-basic-offset: 4
892// c-file-offsets:((innamespace . 0)(inline-open . 0))
893// indent-tabs-mode: nil
894// End:
895
896// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
897
Note: See TracBrowser for help on using the repository browser.