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

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

RWT commit : Cosmetic (Remove trailing whitespace)

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))
242 && ((cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC) or (cache_state(way, set) == CACHE_SLOT_STATE_VALID_NCC)) )
243 {
244 *dt = cache_data(way, set, word);
245 cache_set_lru(way, set);
246 return true;
247 }
248 }
249 return false;
250 }
251
252 ////////////////////////////////////////////////////////////////////
253 // Read a single 32 bits word.
254 // returns true if (matching tag) and (state == VALID)
255 // Both data & directory are accessed.
256 // The selected way, set and word index are returned in case of hit.
257 /////////////////////////////////////////////////////////////////////
258 inline bool read(addr_t ad,
259 data_t* dt,
260 size_t* selway,
261 size_t* selset,
262 size_t* selword)
263 {
264 const addr_t tag = m_z[ad];
265 const size_t set = m_y[ad];
266 const size_t word = m_x[ad];
267
268 for (size_t way = 0; way < m_ways; way++)
269 {
270 if ((tag == cache_tag(way, set)) and
271 ((cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC)or (cache_state(way, set) == CACHE_SLOT_STATE_VALID_NCC)))
272 {
273 *selway = way;
274 *selset = set;
275 *selword = word;
276 *dt = cache_data(way, set, word);
277 cache_set_lru(way, set);
278 return true;
279 }
280 }
281 return false;
282 }
283
284 ////////////////////////////////////////////////////////////////////
285 // Read a single 32 bits word when the ZOMBI state is used.
286 // Both data and directory are accessed.
287 // returns the access status in the state argument:
288 // - VALID : (matching tag) and (state == VALID)
289 // - ZOMBI : (matching tag) and (state == ZOMBI)
290 // - MISS : no matching tag or EMPTY state
291 // If VALID or ZOMBI, the data, the way, set and word index are
292 // returned in the other arguments.
293 ////////////////////////////////////////////////////////////////////
294 inline void read(addr_t ad,
295 data_t* dt,
296 size_t* selway,
297 size_t* selset,
298 size_t* selword,
299 int* state)
300 {
301 const addr_t tag = m_z[ad];
302 const size_t set = m_y[ad];
303 const size_t word = m_x[ad];
304
305 // default return values
306 *state = CACHE_SLOT_STATE_EMPTY;
307 *selway = 0;
308 *selset = 0;
309 *selword = 0;
310 *dt = 0;
311
312 for (size_t way = 0; way < m_ways; way++)
313 {
314 if (tag == cache_tag(way, set)) // matching tag
315 {
316
317 if (cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC)
318 {
319 *state = CACHE_SLOT_STATE_VALID_CC;
320 *selway = way;
321 *selset = set;
322 *selword = word;
323 *dt = cache_data(way, set, word);
324 cache_set_lru(way, set);
325 }
326 else if (cache_state(way, set) == CACHE_SLOT_STATE_VALID_NCC)
327 {
328 *state = CACHE_SLOT_STATE_VALID_NCC;
329 *selway = way;
330 *selset = set;
331 *selword = word;
332 *dt = cache_data(way, set, word);
333 cache_set_lru(way, set);
334 }
335 else if (cache_state(way, set) == CACHE_SLOT_STATE_ZOMBI)
336 {
337 *state = CACHE_SLOT_STATE_ZOMBI;
338 *selway = way;
339 *selset = set;
340 *selword = word;
341 }
342 }
343 }
344 }
345
346 ////////////////////////////////////////////////////////////////////
347 // Read a single 32 bits word, without LRU update.
348 // returns true if (matching tag) and (state == VALID)
349 // Both data & directory are accessed.
350 // The selected way, set and word index are returned in case of hit.
351 /////////////////////////////////////////////////////////////////////
352 inline bool read_neutral(addr_t ad,
353 data_t* dt,
354 size_t* selway,
355 size_t* selset,
356 size_t* selword)
357 {
358 const addr_t tag = m_z[ad];
359 const size_t set = m_y[ad];
360 const size_t word = m_x[ad];
361
362 for (size_t way = 0; way < m_ways; way++)
363 {
364 if ((tag == cache_tag(way, set))
365 && ((cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC) or (cache_state(way, set) == CACHE_SLOT_STATE_VALID_NCC) ))
366 {
367 *selway = way;
368 *selset = set;
369 *selword = word;
370 *dt = cache_data(way, set, word);
371 return true;
372 }
373 }
374 return false;
375 }
376
377 /////////////////////////////////////////////////////////////////////////////
378 // Read one or two 32 bits word.
379 // Both data & directory are accessed.
380 // Hit if (matching tag) and (valid == true) and (zombi == false)
381 // If the addressed word is not the last in the cache line,
382 // two successive words are returned.
383 // The selected way, set and first word index are returned in case of hit.
384 // This function is used by the cc_vcache to get a 64 bits page table entry.
385 /////////////////////////////////////////////////////////////////////////////
386 inline bool read( addr_t ad,
387 data_t* dt,
388 data_t* dt_next,
389 size_t* selway,
390 size_t* selset,
391 size_t* selword)
392 {
393 const addr_t tag = m_z[ad];
394 const size_t set = m_y[ad];
395 const size_t word = m_x[ad];
396
397 for (size_t way = 0; way < m_ways; way++)
398 {
399 if ((tag == cache_tag(way, set))
400 &&( (cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC)))
401 {
402 *dt = cache_data(way, set, word);
403 if (word + 1 < m_words)
404 {
405 *dt_next = cache_data(way, set, word + 1);
406 }
407 *selway = way;
408 *selset = set;
409 *selword = word;
410 cache_set_lru(way, set);
411 return true;
412 }
413 }
414 return false;
415 }
416
417 ////////////////////////////////////////////////////////////////////
418 // Read one or two 32 bits word.
419 // Both data and directory are accessed.
420 // returns the access status in the state argument:
421 // - VALID : (matching tag) and (state == VALID)
422 // - ZOMBI : (matching tag) and (state == ZOMBI)
423 // - MISS : no matching tag or EMPTY state
424 // If VALID or ZOMBI, the data, the way, set and word index are
425 // returned in the other arguments.
426 ////////////////////////////////////////////////////////////////////
427 inline void read(addr_t ad,
428 data_t* dt,
429 data_t* dt_next,
430 size_t* selway,
431 size_t* selset,
432 size_t* selword,
433 int* state)
434 {
435 const addr_t tag = m_z[ad];
436 const size_t set = m_y[ad];
437 const size_t word = m_x[ad];
438
439 // default return values
440 *state = CACHE_SLOT_STATE_EMPTY;
441 *selway = 0;
442 *selset = 0;
443 *selword = 0;
444 *dt = 0;
445
446 for (size_t way = 0; way < m_ways; way++)
447 {
448 if (tag == cache_tag(way, set)) // matching tag
449 {
450
451 if (cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC)
452 {
453 *state = CACHE_SLOT_STATE_VALID_CC;
454 *selway = way;
455 *selset = set;
456 *selword = word;
457 *dt = cache_data(way, set, word);
458 if (word + 1 < m_words)
459 {
460 *dt_next = cache_data(way, set, word+1);
461 }
462 cache_set_lru(way, set);
463 }
464
465 else if (cache_state(way, set) == CACHE_SLOT_STATE_VALID_NCC)
466 {
467 *state = CACHE_SLOT_STATE_VALID_NCC;
468 *selway = way;
469 *selset = set;
470 *selword = word;
471 *dt = cache_data(way, set, word);
472 if (word + 1 < m_words)
473 {
474 *dt_next = cache_data(way, set, word + 1);
475 }
476 cache_set_lru(way, set);
477 }
478
479 else if (cache_state(way, set) == CACHE_SLOT_STATE_ZOMBI)
480 {
481 *state = CACHE_SLOT_STATE_ZOMBI;
482 *selway = way;
483 *selset = set;
484 *selword = word;
485 }
486 }
487 }
488 }
489
490 ///////////////////////////////////////////////////////////////////////////////
491 // Checks the cache state for a given address.
492 // Only the directory is accessed.
493 // returns true if (matching tag) and (state == VALID)
494 // The selected way, set and first word index are returned in case of hit.
495 // This function can be used when we need to access the directory
496 // while we write in the data part with a different address in the same cycle.
497 ///////////////////////////////////////////////////////////////////////////////
498 inline bool hit(addr_t ad,
499 size_t* selway,
500 size_t* selset,
501 size_t* selword)
502 {
503 const addr_t tag = m_z[ad];
504 const size_t set = m_y[ad];
505 const size_t word = m_x[ad];
506
507 for (size_t way = 0; way < m_ways; way++)
508 {
509 if ((tag == cache_tag(way, set))
510 && ((cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC)or(cache_state(way, set) == CACHE_SLOT_STATE_VALID_NCC)))
511 {
512 *selway = way;
513 *selset = set;
514 *selword = word;
515 cache_set_lru(way, set);
516 return true;
517 }
518 }
519 return false;
520 }
521
522 ///////////////////////////////////////////////////////////////////////////////
523 // Checks the cache state for a given address, when the ZOMBI state is used.
524 // Only the directory is accessed.
525 // Returns the access status in the state argument:
526 // - VALID if (matching tag) and (state == VALID)
527 // - ZOMBI if (matching tag) and (state == ZOMBI)
528 // - EMPTY if no match or (state == EMPTY)
529 // The selected way, set and first word index are returned if not empty.
530 // This function can be used when we need to access the directory
531 // while we write in the data part with a different address in the same cycle.
532 ///////////////////////////////////////////////////////////////////////////////
533 inline void read_dir(addr_t ad,
534 int* state,
535 size_t* way,
536 size_t* set,
537 size_t* word)
538 {
539 const addr_t ad_tag = m_z[ad];
540 const size_t ad_set = m_y[ad];
541 const size_t ad_word = m_x[ad];
542 for (size_t _way = 0; _way < m_ways; _way++)
543 {
544 if ((ad_tag == cache_tag(_way, ad_set)) and
545 (cache_state(_way, ad_set) != CACHE_SLOT_STATE_EMPTY))
546 {
547 *state = cache_state(_way, ad_set);
548 *way = _way;
549 *set = ad_set;
550 *word = ad_word;
551 return;
552 }
553 }
554
555 // return value if not (VALID or ZOMBI)
556 *state = CACHE_SLOT_STATE_EMPTY;
557 }
558
559 ///////////////////////////////////////////////////////////////////////////////
560 // Checks the cache state for a slot (set,way), when the ZOMBI state is used.
561 // Only the directory is accessed.
562 // Returns the access status and the tag value in the state and tag argument.
563 ///////////////////////////////////////////////////////////////////////////////
564 inline void read_dir(size_t way,
565 size_t set,
566 addr_t* tag,
567 int* state)
568 {
569 *state = cache_state(way, set);
570 *tag = cache_tag(way, set);
571 }
572
573 ////////////////////////////////////////////
574 inline addr_t get_tag(size_t way, size_t set)
575 {
576 return cache_tag(way, set);
577 }
578
579 ///////////////////////////////////////////////////////////////////
580 // This function writes a complete 32 bits word
581 // It does not use the directory and cannot miss.
582 //////////////////////////////////////////////////////////////////
583 inline void write(size_t way,
584 size_t set,
585 size_t word,
586 data_t data)
587 {
588 cache_data(way, set, word) = data;
589 cache_set_lru(way, set);
590 }
591
592 ////////////////////////////////////////////////////////////////////////////
593 // this function writes up to 4 bytes, taking into account the byte enable.
594 // It does not use the directory and cannot miss.
595 ////////////////////////////////////////////////////////////////////////////
596 inline void write(size_t way,
597 size_t set,
598 size_t word,
599 data_t data,
600 be_t be)
601 {
602 data_t mask = be2mask(be);
603 data_t prev = cache_data(way, set, word);
604 cache_data(way, set, word) = (mask & data) | (~mask & prev);
605 cache_set_lru(way, set);
606 }
607
608 //////////////////////////////////////////////////////////////////////////
609 // This function invalidates a cache line identified by the set and way.
610 // It returns true if the line was valid, and returns the line index.
611 //////////////////////////////////////////////////////////////////////////
612 inline bool inval(size_t way,
613 size_t set,
614 addr_t* nline)
615 {
616 if ((cache_state(way,set) == CACHE_SLOT_STATE_VALID_CC) or (cache_state(way,set) == CACHE_SLOT_STATE_VALID_NCC))
617 {
618 cache_state(way,set) = CACHE_SLOT_STATE_EMPTY;
619 *nline = (data_t)cache_tag(way,set)* m_sets + set;
620 return true;
621 }
622 return false;
623 }
624
625 //////////////////////////////////////////////////////////////////////////////////
626 // This function selects a victim slot in an associative set.
627 // It cannot fail, as a slot in ZOMBI state is considered EMPTY.
628 // - we search first an EMPTY slot
629 // - if no EMPTY slot, we search an OLD slot, using lru
630 // It returns the line index (Z + Y fields), the selected slot way and set,
631 // and a Boolean indicating that a cleanup is requested.
632 //////////////////////////////////////////////////////////////////////////////////
633 inline bool victim_select(addr_t ad,
634 addr_t* victim,
635 size_t* way,
636 size_t* set)
637 {
638 bool found = false;
639 bool cleanup = false;
640
641 *set = m_y[ad];
642 *way = 0;
643
644 // Search first empty slot
645 for (size_t _way = 0 ; _way < m_ways && !found ; _way++)
646 {
647 if ((cache_state(_way, *set) != CACHE_SLOT_STATE_VALID_CC) and (cache_state(_way, *set) != CACHE_SLOT_STATE_VALID_NCC )) // empty
648 {
649 found = true;
650 cleanup = false;
651 *way = _way;
652 }
653 }
654
655 // If no empty slot, search first old slot (lru == false)
656 if (!found)
657 {
658 for (size_t _way = 0 ; _way < m_ways && !found ; _way++)
659 {
660 if (not cache_lru(_way, *set))
661 {
662 found = true;
663 cleanup = true;
664 *way = _way;
665 }
666 }
667 }
668
669 assert(found && "all ways can't be new at the same time");
670 *victim = (addr_t) ((cache_tag(*way,*set) * m_sets) + *set);
671 return cleanup;
672 }
673
674 //////////////////////////////////////////////////////////////////////////////////
675 // This function selects a victim slot in an associative set.
676 // It can fail if all ways are in ZOMBI state.
677 // - we search first an EMPTY slot
678 // - if no empty slot, we search an OLD slot not in ZOMBI state,
679 // - if not found, we take the first not ZOMBI slot.
680 // It returns the line index (Z + Y fields), the selected slot way and set,
681 // and two Boolean indicating success and a required cleanup.
682 //////////////////////////////////////////////////////////////////////////////////
683 inline void read_select(addr_t ad,
684 addr_t* victim,
685 size_t* way,
686 size_t* set,
687 bool* found,
688 bool* cleanup)
689 {
690 size_t _set = m_y[ad];
691
692 *found = false;
693
694 // Search first empty slot
695 for (size_t _way = 0 ; _way < m_ways && !(*found) ; _way++)
696 {
697 if (cache_state(_way, _set) == CACHE_SLOT_STATE_EMPTY)
698 {
699 *found = true;
700 *cleanup = false;
701 *way = _way;
702 *set = m_y[ad];
703 return;
704 }
705 }
706
707 // Search first not zombi old slot
708 for (size_t _way = 0 ; _way < m_ways && !(*found) ; _way++)
709 {
710 if (not cache_lru(_way, _set) and
711 (cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI))
712 {
713 *found = true;
714 *cleanup = true;
715 *way = _way;
716 *set = m_y[ad];
717 *victim = cache_tag(*way,_set) * m_sets + _set;
718 return;
719 }
720 }
721 // Search first not zombi slot
722 for (size_t _way = 0 ; _way < m_ways && !(*found) ; _way++)
723 {
724 if (cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI)
725 {
726 *found = true;
727 *cleanup = true;
728 *way = _way;
729 *set = m_y[ad];
730 *victim = cache_tag(*way,_set) * m_sets + _set;
731 return;
732 }
733 }
734
735 // no slot found...
736 *found = false;
737 *cleanup = false;
738 }
739
740 //////////////////////////////////////////////////////////////////
741 // This function update the directory part of a slot
742 // identified by the way & set.
743 //////////////////////////////////////////////////////////////////
744 inline void victim_update_tag(addr_t ad,
745 size_t way,
746 size_t set)
747 {
748 addr_t tag = m_z[ad];
749
750 cache_tag(way, set) = tag;
751 cache_state(way, set) = CACHE_SLOT_STATE_VALID_CC;
752 cache_set_lru(way, set);
753 }
754
755 //////////////////////////////////////////////////////////////////
756 // This function write the directory part of a slot
757 // identified by the way & set, when using the ZOMBI state.
758 //////////////////////////////////////////////////////////////////
759 inline void write_dir(addr_t ad,
760 size_t way,
761 size_t set,
762 int state)
763 {
764 addr_t tag = m_z[ad];
765
766 assert( ( (state == CACHE_SLOT_STATE_VALID_CC) or
767 (state == CACHE_SLOT_STATE_VALID_NCC) or
768 (state == CACHE_SLOT_STATE_ZOMBI) or
769 (state == CACHE_SLOT_STATE_EMPTY) ) and
770 "illegal slot state argument in Generic Cache write_dir()");
771
772 assert( (way < m_ways) and
773 "too large way index argument in Generic Cache write_dir()");
774
775 assert( (set < m_sets) and
776 "too large set index argument in Generic Cache write_dir()");
777
778 cache_tag(way, set) = tag;
779 cache_state(way, set) = state;
780
781 if ((state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC)) cache_set_lru(way, set);
782 }
783
784 //////////////////////////////////////////////////////////////////
785 // This function change the state of a slot
786 // identified by the way & set, when using the ZOMBI state.
787 // It does not affect the tag
788 //////////////////////////////////////////////////////////////////
789 inline void write_dir(size_t way,
790 size_t set,
791 int state)
792 {
793 assert( ( (state == CACHE_SLOT_STATE_VALID_CC) or
794 (state == CACHE_SLOT_STATE_VALID_NCC) or
795 (state == CACHE_SLOT_STATE_ZOMBI) or
796 (state == CACHE_SLOT_STATE_EMPTY) ) and
797 "illegal slot state argument in Generic Cache write_dir()");
798
799 assert( (way < m_ways) and
800 "too large way index argument in Generic Cache write_dir()");
801
802 assert( (set < m_sets) and
803 "too large set index argument in Generic Cache write_dir()");
804
805 cache_state(way, set) = state;
806
807 if ( (state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC) ) cache_set_lru(way, set);
808 }
809
810 ///////////////////////////////////////////////////////////////////
811 // This function writes a full cache line in one single cycle.
812 // The target slot is identified by the way & set arguments.
813 // Both DATA and DIRECTORY are written
814 ///////////////////////////////////////////////////////////////////
815 inline void update(addr_t ad,
816 size_t way,
817 size_t set,
818 data_t* buf)
819 {
820 addr_t tag = m_z[ad];
821
822 cache_tag(way, set) = tag;
823 cache_state(way, set) = CACHE_SLOT_STATE_VALID_CC;
824 cache_set_lru(way, set);
825 for (size_t word = 0 ; word < m_words ; word++)
826 {
827 cache_data(way, set, word) = buf[word] ;
828 }
829 }
830
831 ///////////////////////////
832 void fileTrace(FILE* file)
833 {
834 for (size_t nway = 0 ; nway < m_ways ; nway++)
835 {
836 for (size_t nset = 0 ; nset < m_sets ; nset++)
837 {
838 fprintf(file, "%d / ", (int)cache_state(nway, nset));
839 fprintf(file, "way %d / ", (int)nway);
840 fprintf(file, "set %d / ", (int)nset);
841 fprintf(file, "@ = %08zX / ",
842 ((cache_tag(nway, nset) * m_sets + nset) * m_words * 4));
843 for (size_t nword = m_words ; nword > 0 ; nword--)
844 {
845 unsigned int data = cache_data(nway, nset, nword - 1);
846 fprintf(file, "%08X ", data);
847 }
848 fprintf(file, "\n");
849 }
850 }
851 }
852
853 ////////////////////////
854 inline void printTrace()
855 {
856 for (size_t way = 0; way < m_ways ; way++)
857 {
858 for (size_t set = 0 ; set < m_sets ; set++)
859 {
860 addr_t addr = (((addr_t)cache_tag(way,set))*m_words*m_sets+m_words*set)*4;
861 std::cout << std::dec << cache_state(way, set)
862 << " | way " << way
863 << " | set " << set
864 << std::hex << " | @ " << addr;
865
866 for (size_t word = 0 ; word < m_words ; word++)
867 {
868 std::cout << " | " << cache_data(way,set,word) ;
869 }
870 std::cout << std::dec << std::endl ;
871 }
872 }
873 }
874
875};
876
877} // namespace soclib
878
879#endif
880
881// Local Variables:
882// tab-width: 4
883// c-basic-offset: 4
884// c-file-offsets:((innamespace . 0)(inline-open . 0))
885// indent-tabs-mode: nil
886// End:
887
888// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
889
Note: See TracBrowser for help on using the repository browser.