source: branches/MESI/lib/generic_cache_tsar/include/generic_cache.h@ 750

Last change on this file since 750 was 670, checked in by haoliu, 12 years ago

TSAR branches -- Adding the first version of protocol MESI in TSAR architecture:

File size: 31.0 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_INVALID,
78 CACHE_SLOT_STATE_EXCLUSIVE,
79 CACHE_SLOT_STATE_SHARED,
80 CACHE_SLOT_STATE_MODIFIED,
81 CACHE_SLOT_STATE_ZOMBI
82};
83
84//////////////////////////
85template<typename addr_t>
86class GenericCache
87//////////////////////////
88{
89 typedef uint32_t data_t;
90 typedef uint32_t be_t;
91
92 data_t *r_data ;
93 addr_t *r_tag ;
94 int *r_state;
95 bool *r_lru ;
96
97 size_t m_ways;
98 size_t m_sets;
99 size_t m_words;
100
101 const soclib::common::AddressMaskingTable<addr_t> m_x ;
102 const soclib::common::AddressMaskingTable<addr_t> m_y ;
103 const soclib::common::AddressMaskingTable<addr_t> m_z ;
104
105 //////////////////////////////////////////////////////////////
106 inline data_t &cache_data(size_t way, size_t set, size_t word)
107 {
108 return r_data[(way*m_sets*m_words)+(set*m_words)+word];
109 }
110
111 //////////////////////////////////////////////
112 inline addr_t &cache_tag(size_t way, size_t set)
113 {
114 return r_tag[(way*m_sets)+set];
115 }
116
117 //////////////////////////////////////////////
118 inline bool &cache_lru(size_t way, size_t set)
119 {
120 return r_lru[(way*m_sets)+set];
121 }
122
123 //////////////////////////////////////////////
124 inline int &cache_state(size_t way, size_t set)
125 {
126 return r_state[(way*m_sets)+set];
127 }
128
129
130 /////////////////////////////////////////////////
131 inline void cache_set_lru(size_t way, size_t set)
132 {
133 size_t way2;
134
135 cache_lru(way, set) = true;
136
137 for (way2 = 0; way2 < m_ways; way2++ )
138 {
139 if (cache_lru(way2, set) == false) return;
140 }
141 // all lines are new -> they all become old
142 for (way2 = 0; way2 < m_ways; way2++ )
143 {
144 cache_lru(way2, set) = false;
145 }
146 }
147
148 ////////////////////////////////
149 inline data_t be2mask( be_t be )
150 {
151 data_t mask = 0;
152 if ( (be & 0x1) == 0x1 ) mask = mask | 0x000000FF;
153 if ( (be & 0x2) == 0x2 ) mask = mask | 0x0000FF00;
154 if ( (be & 0x4) == 0x4 ) mask = mask | 0x00FF0000;
155 if ( (be & 0x8) == 0x8 ) mask = mask | 0xFF000000;
156 return mask;
157 }
158
159public:
160
161 //////////////////////////////////////////
162 GenericCache( const std::string &name,
163 size_t nways,
164 size_t nsets,
165 size_t nwords)
166 : m_ways(nways),
167 m_sets(nsets),
168 m_words(nwords),
169
170#define l2 soclib::common::uint32_log2
171
172 m_x( l2(nwords), l2(sizeof(data_t))),
173 m_y( l2(nsets), l2(nwords) + l2(sizeof(data_t))),
174 m_z( 8*sizeof(addr_t) - l2(nsets) - l2(nwords) - l2(sizeof(data_t)),
175 l2(nsets) + l2(nwords) + l2(sizeof(data_t)))
176#undef l2
177 {
178 assert(IS_POW_OF_2(nways));
179 assert(IS_POW_OF_2(nsets));
180 assert(IS_POW_OF_2(nwords));
181 assert(nwords);
182 assert(nsets);
183 assert(nways);
184 assert(nwords <= 64);
185 assert(nsets <= 1024);
186 assert(nways <= 16);
187
188#ifdef GENERIC_CACHE_DEBUG
189std::cout << "constructing " << name << std::endl
190 << "- nways = " << nways << std::endl
191 << "- nsets = " << nsets << std::endl
192 << "- nwords = " << nwords << std::endl
193 << " m_x: " << m_x
194 << " m_y: " << m_y
195 << " m_z: " << m_z
196 << std::endl;
197#endif
198
199 r_data = new data_t[nways*nsets*nwords];
200 r_tag = new addr_t[nways*nsets];
201 r_state = new int[nways*nsets];
202 r_lru = new bool[nways*nsets];
203 }
204
205 ////////////////
206 ~GenericCache()
207 {
208 delete [] r_data;
209 delete [] r_tag;
210 delete [] r_state;
211 delete [] r_lru;
212 }
213
214 ////////////////////
215 inline void reset( )
216 {
217 std::memset(r_data, 0, sizeof(*r_data)*m_ways*m_sets*m_words);
218 std::memset(r_tag, 0, sizeof(*r_tag)*m_ways*m_sets);
219 std::memset(r_state, CACHE_SLOT_STATE_INVALID, sizeof(*r_state)*m_ways*m_sets);
220 std::memset(r_lru, 0, sizeof(*r_lru)*m_ways*m_sets);
221 }
222
223 inline int get_cache_state(int way, int set)
224 {
225 return cache_state(way,set);
226 }
227
228 /////////////////////////////////////////////////////////////////////
229 // Read a single 32 bits word.
230 // returns true if (matching tag) and (state == VALID)
231 // Both data & directory are accessed.
232 /////////////////////////////////////////////////////////////////////
233 inline bool read( addr_t ad,
234 data_t* dt)
235 {
236 const addr_t tag = m_z[ad];
237 const size_t set = m_y[ad];
238 const size_t word = m_x[ad];
239
240 for ( size_t way = 0; way < m_ways; way++ )
241 {
242 if ( (tag == cache_tag(way, set))
243 && ( (cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE) or (cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED) or (cache_state(way, set) == CACHE_SLOT_STATE_SHARED)) )
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_EXCLUSIVE) or (cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED) or (cache_state(way, set) == CACHE_SLOT_STATE_SHARED)) )
273 {
274 *selway = way;
275 *selset = set;
276 *selword = word;
277 *dt = cache_data(way, set, word);
278 cache_set_lru(way, set);
279 return true;
280 }
281 }
282 return false;
283 }
284
285 ////////////////////////////////////////////////////////////////////
286 // Read a single 32 bits word when the ZOMBI state is used.
287 // Both data and directory are accessed.
288 // returns the access status in the state argument:
289 // - VALID : (matching tag) and (state == VALID)
290 // - ZOMBI : (matching tag) and (state == ZOMBI)
291 // - MISS : no matching tag or EMPTY state
292 // If VALID or ZOMBI, the data, the way, set and word index are
293 // returned in the other arguments.
294 ////////////////////////////////////////////////////////////////////
295 inline void read( addr_t ad,
296 data_t* dt,
297 size_t* selway,
298 size_t* selset,
299 size_t* selword,
300 int* state )
301 {
302 const addr_t tag = m_z[ad];
303 const size_t set = m_y[ad];
304 const size_t word = m_x[ad];
305
306 // default return values
307 *state = CACHE_SLOT_STATE_INVALID;
308 *selway = 0;
309 *selset = 0;
310 *selword = 0;
311 *dt = 0;
312
313 for ( size_t way = 0; way < m_ways; way++ )
314 {
315 if ( tag == cache_tag(way, set) ) // matching tag
316 {
317
318 if ( cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE )
319 {
320 *state = CACHE_SLOT_STATE_EXCLUSIVE;
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_SHARED )
328 {
329 *state = CACHE_SLOT_STATE_SHARED;
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_MODIFIED )
337 {
338 *state = CACHE_SLOT_STATE_MODIFIED;
339 *selway = way;
340 *selset = set;
341 *selword = word;
342 *dt = cache_data(way, set, word);
343 cache_set_lru(way, set);
344 }
345 else if ( cache_state(way, set) == CACHE_SLOT_STATE_ZOMBI )
346 {
347 *state = CACHE_SLOT_STATE_ZOMBI;
348 *selway = way;
349 *selset = set;
350 *selword = word;
351 }
352 }
353 }
354 }
355
356 ////////////////////////////////////////////////////////////////////
357 // Read a single 32 bits word, without LRU update.
358 // returns true if (matching tag) and (state == VALID)
359 // Both data & directory are accessed.
360 // The selected way, set and word index are returned in case of hit.
361 /////////////////////////////////////////////////////////////////////
362 inline bool read_neutral( addr_t ad,
363 data_t* dt,
364 size_t* selway,
365 size_t* selset,
366 size_t* selword)
367 {
368 const addr_t tag = m_z[ad];
369 const size_t set = m_y[ad];
370 const size_t word = m_x[ad];
371
372 for ( size_t way = 0; way < m_ways; way++ )
373 {
374 if ( (tag == cache_tag(way, set))
375 && ( (cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE) or (cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED) or (cache_state(way, set) == CACHE_SLOT_STATE_SHARED)) )
376 {
377 *selway = way;
378 *selset = set;
379 *selword = word;
380 *dt = cache_data(way, set, word);
381 return true;
382 }
383 }
384 return false;
385 }
386
387 /////////////////////////////////////////////////////////////////////////////
388 // Read one or two 32 bits word.
389 // Both data & directory are accessed.
390 // Hit if (matching tag) and (valid == true) and (zombi == false)
391 // If the addressed word is not the last in the cache line,
392 // two successive words are returned.
393 // The selected way, set and first word index are returned in case of hit.
394 // This function is used by the cc_vcache to get a 64 bits page table entry.
395 /////////////////////////////////////////////////////////////////////////////
396 inline bool read( addr_t ad,
397 data_t* dt,
398 data_t* dt_next,
399 size_t* selway,
400 size_t* selset,
401 size_t* selword)
402 {
403 const addr_t tag = m_z[ad];
404 const size_t set = m_y[ad];
405 const size_t word = m_x[ad];
406
407 for ( size_t way = 0; way < m_ways; way++ )
408 {
409 if ( (tag == cache_tag(way, set))
410 && ( (cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE) or (cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED) or (cache_state(way, set) == CACHE_SLOT_STATE_SHARED)) )
411 {
412 *dt = cache_data(way, set, word);
413 if ( word+1 < m_words)
414 {
415 *dt_next = cache_data(way, set, word+1);
416 }
417 *selway = way;
418 *selset = set;
419 *selword = word;
420 cache_set_lru(way, set);
421 return true;
422 }
423 }
424 return false;
425 }
426
427 ////////////////////////////////////////////////////////////////////
428 // Read one or two 32 bits word.
429 // Both data and directory are accessed.
430 // returns the access status in the state argument:
431 // - VALID : (matching tag) and (state == VALID)
432 // - ZOMBI : (matching tag) and (state == ZOMBI)
433 // - MISS : no matching tag or EMPTY state
434 // If VALID or ZOMBI, the data, the way, set and word index are
435 // returned in the other arguments.
436 ////////////////////////////////////////////////////////////////////
437 inline void read( addr_t ad,
438 data_t* dt,
439 data_t* dt_next,
440 size_t* selway,
441 size_t* selset,
442 size_t* selword,
443 int* state )
444 {
445 const addr_t tag = m_z[ad];
446 const size_t set = m_y[ad];
447 const size_t word = m_x[ad];
448
449 // default return values
450 *state = CACHE_SLOT_STATE_INVALID;
451 *selway = 0;
452 *selset = 0;
453 *selword = 0;
454 *dt = 0;
455
456 for ( size_t way = 0; way < m_ways; way++ )
457 {
458 if ( tag == cache_tag(way, set) ) // matching tag
459 {
460
461 if ( cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE )
462 {
463 *state = CACHE_SLOT_STATE_EXCLUSIVE;
464 *selway = way;
465 *selset = set;
466 *selword = word;
467 *dt = cache_data(way, set, word);
468 if ( word+1 < m_words)
469 {
470 *dt_next = cache_data(way, set, word+1);
471 }
472 cache_set_lru(way, set);
473 }
474
475 else if ( cache_state(way, set) == CACHE_SLOT_STATE_SHARED )
476 {
477 *state = CACHE_SLOT_STATE_SHARED;
478 *selway = way;
479 *selset = set;
480 *selword = word;
481 *dt = cache_data(way, set, word);
482 if ( word+1 < m_words)
483 {
484 *dt_next = cache_data(way, set, word+1);
485 }
486 cache_set_lru(way, set);
487 }
488
489 else if ( cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED )
490 {
491 *state = CACHE_SLOT_STATE_MODIFIED;
492 *selway = way;
493 *selset = set;
494 *selword = word;
495 *dt = cache_data(way, set, word);
496 if ( word+1 < m_words)
497 {
498 *dt_next = cache_data(way, set, word+1);
499 }
500 cache_set_lru(way, set);
501 }
502
503 else if ( cache_state(way, set) == CACHE_SLOT_STATE_ZOMBI )
504 {
505 *state = CACHE_SLOT_STATE_ZOMBI;
506 *selway = way;
507 *selset = set;
508 *selword = word;
509 }
510 }
511 }
512 }
513
514 ///////////////////////////////////////////////////////////////////////////////
515 // Checks the cache state for a given address.
516 // Only the directory is accessed.
517 // returns true if (matching tag) and (state == VALID)
518 // The selected way, set and first word index are returned in case of hit.
519 // This function can be used when we need to access the directory
520 // while we write in the data part with a different address in the same cycle.
521 ///////////////////////////////////////////////////////////////////////////////
522 inline bool hit( addr_t ad,
523 size_t* selway,
524 size_t* selset,
525 size_t* selword)
526 {
527 const addr_t tag = m_z[ad];
528 const size_t set = m_y[ad];
529 const size_t word = m_x[ad];
530
531 for ( size_t way = 0; way < m_ways; way++ )
532 {
533 if ( (tag == cache_tag(way, set))
534 && ( (cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE) or (cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED) or (cache_state(way, set) == CACHE_SLOT_STATE_SHARED)) )
535 {
536 *selway = way;
537 *selset = set;
538 *selword = word;
539 cache_set_lru(way, set);
540 return true;
541 }
542 }
543 return false;
544 }
545
546 ///////////////////////////////////////////////////////////////////////////////
547 // Checks the cache state for a given address, when the ZOMBI state is used.
548 // Only the directory is accessed.
549 // Returns the access status in the state argument:
550 // - VALID if (matching tag) and (state == VALID)
551 // - ZOMBI if (matching tag) and (state == ZOMBI)
552 // - EMPTY if no match or (state == EMPTY)
553 // The selected way, set and first word index are returned if not empty.
554 // This function can be used when we need to access the directory
555 // while we write in the data part with a different address in the same cycle.
556 ///////////////////////////////////////////////////////////////////////////////
557 inline void read_dir( addr_t ad,
558 int* state,
559 size_t* way,
560 size_t* set,
561 size_t* word)
562 {
563 const addr_t ad_tag = m_z[ad];
564 const size_t ad_set = m_y[ad];
565 const size_t ad_word = m_x[ad];
566 for ( size_t _way = 0; _way < m_ways; _way++ )
567 {
568 if ( (ad_tag == cache_tag(_way, ad_set) ) and
569 (cache_state(_way, ad_set) != CACHE_SLOT_STATE_INVALID) )
570 {
571 *state = cache_state(_way, ad_set);
572 *way = _way;
573 *set = ad_set;
574 *word = ad_word;
575 return;
576 }
577 }
578
579 // return value if not (VALID or ZOMBI)
580 *state = CACHE_SLOT_STATE_INVALID;
581 }
582
583 ///////////////////////////////////////////////////////////////////////////////
584 // Checks the cache state for a slot (set,way), when the ZOMBI state is used.
585 // Only the directory is accessed.
586 // Returns the access status and the tag value in the state and tag argument.
587 ///////////////////////////////////////////////////////////////////////////////
588 inline void read_dir( size_t way,
589 size_t set,
590 addr_t* tag,
591 int* state )
592 {
593 *state = cache_state(way, set);
594 *tag = cache_tag(way, set);
595 }
596
597 ////////////////////////////////////////////
598 inline addr_t get_tag(size_t way, size_t set)
599 {
600 return cache_tag(way, set);
601 }
602
603 ///////////////////////////////////////////////////////////////////
604 // This function writes a complete 32 bits word
605 // It does not use the directory and cannot miss.
606 //////////////////////////////////////////////////////////////////
607 inline void write(size_t way,
608 size_t set,
609 size_t word,
610 data_t data)
611 {
612 /**/ //std::cout << "write cache : way = "<<way<<" | set = "<<set<<" | word = "<<word<<" | data = "<<(uint32_t)data << std::endl;
613 cache_data(way, set, word) = data;
614 cache_set_lru(way, set);
615 }
616
617 ////////////////////////////////////////////////////////////////////////////
618 // this function writes up to 4 bytes, taking into account the byte enable.
619 // It does not use the directory and cannot miss.
620 ////////////////////////////////////////////////////////////////////////////
621 inline void write(size_t way,
622 size_t set,
623 size_t word,
624 data_t data,
625 be_t be)
626 {
627 data_t mask = be2mask(be);
628 data_t prev = cache_data(way, set, word);
629 cache_data(way, set, word) = (mask & data) | (~mask & prev);
630 cache_set_lru(way, set);
631 }
632
633 //////////////////////////////////////////////////////////////////////////
634 // This function invalidates a cache line identified by the set and way.
635 // It returns true if the line was valid, and returns the line index.
636 //////////////////////////////////////////////////////////////////////////
637 inline bool inval(size_t way,
638 size_t set,
639 addr_t* nline)
640 {
641 if( (cache_state(way,set) == CACHE_SLOT_STATE_EXCLUSIVE) or (cache_state(way,set) == CACHE_SLOT_STATE_MODIFIED) or (cache_state(way,set) == CACHE_SLOT_STATE_SHARED))
642 {
643 cache_state(way,set) = CACHE_SLOT_STATE_INVALID;
644 *nline = (data_t)cache_tag(way,set)* m_sets + set;
645 return true;
646 }
647 return false;
648 }
649
650 //////////////////////////////////////////////////////////////////////////////////
651 // This function selects a victim slot in an associative set.
652 // It cannot fail, as a slot in ZOMBI state is considered EMPTY.
653 // - we search first an EMPTY slot
654 // - if no EMPTY slot, we search an OLD slot, using lru
655 // It returns the line index (Z + Y fields), the selected slot way and set,
656 // and a Boolean indicating that a cleanup is requested.
657 //////////////////////////////////////////////////////////////////////////////////
658 inline bool victim_select(addr_t ad,
659 addr_t* victim,
660 size_t* way,
661 size_t* set)
662 {
663 bool found = false;
664 bool cleanup = false;
665
666 *set = m_y[ad];
667 *way = 0;
668
669 // Search first empty slot
670 for ( size_t _way = 0 ; _way < m_ways && !found ; _way++ )
671 {
672 if( ( cache_state(_way, *set) != CACHE_SLOT_STATE_EXCLUSIVE ) and ( cache_state(_way, *set) != CACHE_SLOT_STATE_SHARED ) and ( cache_state(_way, *set) != CACHE_SLOT_STATE_MODIFIED )) // empty
673 {
674 found = true;
675 cleanup = false;
676 *way = _way;
677 }
678 }
679
680 // If no empty slot, search first old slot (lru == false)
681 if ( !found )
682 {
683 for ( size_t _way = 0 ; _way < m_ways && !found ; _way++ )
684 {
685 if ( not cache_lru(_way, *set) )
686 {
687 found = true;
688 cleanup = true;
689 *way = _way;
690 }
691 }
692 }
693
694 assert(found && "all ways can't be new at the same time");
695 *victim = (addr_t)((cache_tag(*way,*set) * m_sets) + *set);
696 return cleanup;
697 }
698
699 //////////////////////////////////////////////////////////////////////////////////
700 // This function selects a victim slot in an associative set.
701 // It can fail if all ways are in ZOMBI state.
702 // - we search first an EMPTY slot
703 // - if no empty slot, we search an OLD slot not in ZOMBI state,
704 // - if not found, we take the first not ZOMBI slot.
705 // It returns the line index (Z + Y fields), the selected slot way and set,
706 // and two Boolean indicating success and a required cleanup.
707 //////////////////////////////////////////////////////////////////////////////////
708 inline void read_select(addr_t ad,
709 addr_t* victim,
710 size_t* way,
711 size_t* set,
712 bool* found,
713 bool* cleanup )
714 {
715 size_t _set = m_y[ad];
716
717 *found = false;
718
719 // Search first empty slot
720 for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
721 {
722 if ( cache_state(_way, _set) == CACHE_SLOT_STATE_INVALID )
723 {
724 *found = true;
725 *cleanup = false;
726 *way = _way;
727 *set = m_y[ad];
728 return;
729 }
730 }
731 //////////////////////////////////////////////////////////////
732 /*for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
733 {
734 if ( not cache_lru(_way, _set) and
735 (cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI) and
736 (cache_state(_way, _set) == CACHE_SLOT_STATE_VALID_NCC) )
737 {
738 *found = true;
739 *cleanup = true;
740 *way = _way;
741 *set = m_y[ad];
742 *victim = (addr_t)((cache_tag(*way,_set) * m_sets) + _set);
743 return;
744 }
745 }*/
746 // Search first not zombi old slot
747 for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
748 {
749 if ( not cache_lru(_way, _set) and
750 (cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI) )
751 {
752 *found = true;
753 *cleanup = true;
754 *way = _way;
755 *set = m_y[ad];
756 *victim = cache_tag(*way,_set) * m_sets + _set;
757 return;
758 }
759 }
760 // Search first not zombi slot
761 for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
762 {
763 if ( cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI)
764 {
765 *found = true;
766 *cleanup = true;
767 *way = _way;
768 *set = m_y[ad];
769 *victim = cache_tag(*way,_set) * m_sets + _set;
770 return;
771 }
772 }
773
774 // no slot found...
775 *found = false;
776 *cleanup = false;
777 }
778
779 //////////////////////////////////////////////////////////////////
780 // This function write the directory part of a slot
781 // identified by the way & set, when using the ZOMBI state.
782 //////////////////////////////////////////////////////////////////
783 inline void write_dir( addr_t ad,
784 size_t way,
785 size_t set,
786 int state)
787 {
788 addr_t tag = m_z[ad];
789
790 assert( ( (state == CACHE_SLOT_STATE_EXCLUSIVE) or
791 (state == CACHE_SLOT_STATE_SHARED) or
792 (state == CACHE_SLOT_STATE_MODIFIED) or
793 (state == CACHE_SLOT_STATE_INVALID) or
794 (state == CACHE_SLOT_STATE_ZOMBI)) and
795 "illegal slot state argument in Generic Cache write_dir()");
796
797 assert( (way < m_ways) and
798 "too large way index argument in Generic Cache write_dir()");
799
800 assert( (set < m_sets) and
801 "too large set index argument in Generic Cache write_dir()");
802
803 cache_tag(way, set) = tag;
804 cache_state(way, set) = state;
805
806 if ( (state == CACHE_SLOT_STATE_EXCLUSIVE) or (state == CACHE_SLOT_STATE_MODIFIED) or (state == CACHE_SLOT_STATE_SHARED) ) cache_set_lru(way, set);
807 }
808
809 //////////////////////////////////////////////////////////////////
810 // This function change the state of a slot
811 // identified by the way & set, when using the ZOMBI state.
812 // It does not affect the tag
813 //////////////////////////////////////////////////////////////////
814 inline void write_dir( size_t way,
815 size_t set,
816 int state)
817 {
818 assert( ( (state == CACHE_SLOT_STATE_EXCLUSIVE) or
819 (state == CACHE_SLOT_STATE_SHARED) or
820 (state == CACHE_SLOT_STATE_MODIFIED) or
821 (state == CACHE_SLOT_STATE_INVALID) or
822 (state == CACHE_SLOT_STATE_ZOMBI)) and
823 "illegal slot state argument in Generic Cache write_dir()");
824
825 assert( (way < m_ways) and
826 "too large way index argument in Generic Cache write_dir()");
827
828 assert( (set < m_sets) and
829 "too large set index argument in Generic Cache write_dir()");
830
831 cache_state(way, set) = state;
832
833 if ( (state == CACHE_SLOT_STATE_EXCLUSIVE) or (state == CACHE_SLOT_STATE_MODIFIED) or (state == CACHE_SLOT_STATE_SHARED) ) cache_set_lru(way, set);
834
835 }
836
837
838};
839
840} // namespace soclib
841
842#endif
843
844// Local Variables:
845// tab-width: 4
846// c-basic-offset: 4
847// c-file-offsets:((innamespace . 0)(inline-open . 0))
848// indent-tabs-mode: nil
849// End:
850
851// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
852
Note: See TracBrowser for help on using the repository browser.