source: branches/ODCCP/lib/generic_cache_tsar/include/generic_cache.h@ 1064

Last change on this file since 1064 was 460, checked in by devigne, 13 years ago

Introducing merged components between the last trunk TSAR version
and the ODCCP modifications

File size: 38.4 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
188std::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 /**/ //std::cout << "write cache : way = "<<way<<" | set = "<<set<<" | word = "<<word<<" | data = "<<(uint32_t)data << std::endl;
589 cache_data(way, set, word) = data;
590 cache_set_lru(way, set);
591 }
592
593 ////////////////////////////////////////////////////////////////////////////
594 // this function writes up to 4 bytes, taking into account the byte enable.
595 // It does not use the directory and cannot miss.
596 ////////////////////////////////////////////////////////////////////////////
597 inline void write(size_t way,
598 size_t set,
599 size_t word,
600 data_t data,
601 be_t be)
602 {
603 data_t mask = be2mask(be);
604 data_t prev = cache_data(way, set, word);
605 cache_data(way, set, word) = (mask & data) | (~mask & prev);
606 cache_set_lru(way, set);
607 }
608
609 //////////////////////////////////////////////////////////////////////////
610 // This function invalidates a cache line identified by the set and way.
611 // It returns true if the line was valid, and returns the line index.
612 //////////////////////////////////////////////////////////////////////////
613 inline bool inval(size_t way,
614 size_t set,
615 addr_t* nline)
616 {
617 if( (cache_state(way,set) == CACHE_SLOT_STATE_VALID_CC) )
618 {
619 cache_state(way,set) = CACHE_SLOT_STATE_EMPTY;
620 *nline = (data_t)cache_tag(way,set)* m_sets + set;
621 return true;
622 }
623 return false;
624 }
625
626 //////////////////////////////////////////////////////////////////////////////////
627 // This function selects a victim slot in an associative set.
628 // It cannot fail, as a slot in ZOMBI state is considered EMPTY.
629 // - we search first an EMPTY slot
630 // - if no EMPTY slot, we search an OLD slot, using lru
631 // It returns the line index (Z + Y fields), the selected slot way and set,
632 // and a Boolean indicating that a cleanup is requested.
633 //////////////////////////////////////////////////////////////////////////////////
634 inline bool victim_select(addr_t ad,
635 addr_t* victim,
636 size_t* way,
637 size_t* set)
638 {
639 bool found = false;
640 bool cleanup = false;
641
642 *set = m_y[ad];
643 *way = 0;
644
645 // Search first empty slot
646 for ( size_t _way = 0 ; _way < m_ways && !found ; _way++ )
647 {
648 if( ( cache_state(_way, *set) != CACHE_SLOT_STATE_VALID_CC ) ) // empty
649 {
650 found = true;
651 cleanup = false;
652 *way = _way;
653 }
654 }
655
656 // If no empty slot, search first old slot (lru == false)
657 if ( !found )
658 {
659 for ( size_t _way = 0 ; _way < m_ways && !found ; _way++ )
660 {
661 if ( not cache_lru(_way, *set) )
662 {
663 found = true;
664 cleanup = true;
665 *way = _way;
666 }
667 }
668 }
669
670 assert(found && "all ways can't be new at the same time");
671 *victim = (addr_t)((cache_tag(*way,*set) * m_sets) + *set);
672 return cleanup;
673 }
674
675 //////////////////////////////////////////////////////////////////////////////////
676 // This function selects a victim slot in an associative set.
677 // It can fail if all ways are in ZOMBI state.
678 // - we search first an EMPTY slot
679 // - if no empty slot, we search an OLD slot not in ZOMBI state,
680 // - if not found, we take the first not ZOMBI slot.
681 // It returns the line index (Z + Y fields), the selected slot way and set,
682 // and two Boolean indicating success and a required cleanup.
683 //////////////////////////////////////////////////////////////////////////////////
684 inline void read_select(addr_t ad,
685 addr_t* victim,
686 size_t* way,
687 size_t* set,
688 bool* found,
689 bool* cleanup )
690 {
691 size_t _set = m_y[ad];
692
693 *found = false;
694
695 // Search first empty slot
696 for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
697 {
698 if ( cache_state(_way, _set) == CACHE_SLOT_STATE_EMPTY )
699 {
700 *found = true;
701 *cleanup = false;
702 *way = _way;
703 *set = m_y[ad];
704 return;
705 }
706 }
707 //////////////////////////////////////////////////////////////
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) and
712 (cache_state(_way, _set) == CACHE_SLOT_STATE_VALID_NCC) )
713 {
714 *found = true;
715 *cleanup = true;
716 *way = _way;
717 *set = m_y[ad];
718 *victim = (addr_t)((cache_tag(*way,_set) * m_sets) + _set);
719 return;
720 }
721 }*/
722 // Search first not zombi old slot
723 for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
724 {
725 if ( not cache_lru(_way, _set) and
726 (cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI) )
727 {
728 *found = true;
729 *cleanup = true;
730 *way = _way;
731 *set = m_y[ad];
732 *victim = cache_tag(*way,_set) * m_sets + _set;
733 return;
734 }
735 }
736 // Search first not zombi slot
737 for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
738 {
739 if ( cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI)
740 {
741 *found = true;
742 *cleanup = true;
743 *way = _way;
744 *set = m_y[ad];
745 *victim = cache_tag(*way,_set) * m_sets + _set;
746 return;
747 }
748 }
749
750 // no slot found...
751 *found = false;
752 *cleanup = false;
753 }
754
755 //////////////////////////////////////////////////////////////////
756 // This function update the directory part of a slot
757 // identified by the way & set.
758 //////////////////////////////////////////////////////////////////
759 inline void victim_update_tag( addr_t ad,
760 size_t way,
761 size_t set )
762 {
763 addr_t tag = m_z[ad];
764
765 cache_tag(way, set) = tag;
766 cache_state(way, set) = CACHE_SLOT_STATE_VALID_CC;
767 cache_set_lru(way, set);
768 }
769
770 //////////////////////////////////////////////////////////////////
771 // This function write the directory part of a slot
772 // identified by the way & set, when using the ZOMBI state.
773 //////////////////////////////////////////////////////////////////
774 inline void write_dir( addr_t ad,
775 size_t way,
776 size_t set,
777 int state)
778 {
779 addr_t tag = m_z[ad];
780
781 assert( ( (state == CACHE_SLOT_STATE_VALID_CC) or
782 (state == CACHE_SLOT_STATE_VALID_NCC) or
783 (state == CACHE_SLOT_STATE_ZOMBI) or
784 (state == CACHE_SLOT_STATE_EMPTY) ) and
785 "illegal slot state argument in Generic Cache write_dir()");
786
787 assert( (way < m_ways) and
788 "too large way index argument in Generic Cache write_dir()");
789
790 assert( (set < m_sets) and
791 "too large set index argument in Generic Cache write_dir()");
792
793 cache_tag(way, set) = tag;
794 cache_state(way, set) = state;
795
796 if ( (state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC) ) cache_set_lru(way, set);
797 }
798
799 //////////////////////////////////////////////////////////////////
800 // This function change the state of a slot
801 // identified by the way & set, when using the ZOMBI state.
802 // It does not affect the tag
803 //////////////////////////////////////////////////////////////////
804 inline void write_dir( size_t way,
805 size_t set,
806 int state)
807 {
808 assert( ( (state == CACHE_SLOT_STATE_VALID_CC) or
809 (state == CACHE_SLOT_STATE_VALID_NCC) or
810 (state == CACHE_SLOT_STATE_ZOMBI) or
811 (state == CACHE_SLOT_STATE_EMPTY) ) and
812 "illegal slot state argument in Generic Cache write_dir()");
813
814 assert( (way < m_ways) and
815 "too large way index argument in Generic Cache write_dir()");
816
817 assert( (set < m_sets) and
818 "too large set index argument in Generic Cache write_dir()");
819
820 cache_state(way, set) = state;
821
822 if ( (state == CACHE_SLOT_STATE_VALID_CC) or (state == CACHE_SLOT_STATE_VALID_NCC) ) cache_set_lru(way, set);
823 }
824
825 ///////////////////////////////////////////////////////////////////
826 // This function writes a full cache line in one single cycle.
827 // The target slot is identified by the way & set arguments.
828 // Both DATA and DIRECTORY are written
829 ///////////////////////////////////////////////////////////////////
830 inline void update(addr_t ad,
831 size_t way,
832 size_t set,
833 data_t* buf)
834 {
835 addr_t tag = m_z[ad];
836
837 cache_tag(way, set) = tag;
838 cache_state(way, set) = CACHE_SLOT_STATE_VALID_CC;
839 cache_set_lru(way, set);
840 for ( size_t word = 0 ; word < m_words ; word++ )
841 {
842 cache_data(way, set, word) = buf[word] ;
843 }
844 }
845
846 ///////////////////////////
847 void fileTrace(FILE* file)
848 {
849 for( size_t nway = 0 ; nway < m_ways ; nway++)
850 {
851 for( size_t nset = 0 ; nset < m_sets ; nset++)
852 {
853 fprintf(file, "%d / ", (int)cache_state(nway, nset));
854 fprintf(file, "way %d / ", (int)nway);
855 fprintf(file, "set %d / ", (int)nset);
856 fprintf(file, "@ = %08zX / ",
857 ((cache_tag(nway, nset)*m_sets+nset)*m_words*4));
858 for( size_t nword = m_words ; nword > 0 ; nword--)
859 {
860 unsigned int data = cache_data(nway, nset, nword-1);
861 fprintf(file, "%08X ", data );
862 }
863 fprintf(file, "\n");
864 }
865 }
866 }
867
868 ////////////////////////
869 inline void printTrace()
870 {
871 for ( size_t way = 0; way < m_ways ; way++ )
872 {
873 for ( size_t set = 0 ; set < m_sets ; set++ )
874 {
875 addr_t addr = (((addr_t)cache_tag(way,set))*m_words*m_sets+m_words*set)*4;
876 std::cout << std::dec << cache_state(way, set)
877 << " | way " << way
878 << " | set " << set
879 << std::hex << " | @ " << addr;
880
881 for ( size_t word = 0 ; word < m_words ; word++ )
882 {
883 std::cout << " | " << cache_data(way,set,word) ;
884 }
885 std::cout << std::endl ;
886 }
887 }
888 }
889
890 ///////////////////////////////////////////////////////////////////////////
891 // This function is deprecated as it is difficult to implement in 1 cycle.
892 ///////////////////////////////////////////////////////////////////////////
893 __attribute__((deprecated))
894 inline bool inval(addr_t ad)
895 {
896 bool hit = false;
897 const addr_t tag = m_z[ad];
898 const size_t set = m_y[ad];
899
900 for ( size_t way = 0 ; way < m_ways && !hit ; way++ )
901 {
902 if ( (tag == cache_tag(way, set)) and
903 (cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC) )
904 {
905 hit = true;
906 cache_state(way, set) = CACHE_SLOT_STATE_EMPTY;
907 cache_lru(way, set) = false;
908 }
909 }
910 return hit;
911 }
912
913 ////////////////////////////////////////////////////////////////////////////////
914 // This function is deprecated as it is difficult to implement in 1 cycle.
915 ////////////////////////////////////////////////////////////////////////////////
916 __attribute__((deprecated))
917 inline bool inval( addr_t ad,
918 size_t* selway,
919 size_t* selset )
920 {
921 bool hit = false;
922 const addr_t tag = m_z[ad];
923 const size_t set = m_y[ad];
924
925 for ( size_t way = 0 ; way < m_ways && !hit ; way++ )
926 {
927 if ( (tag == cache_tag(way, set)) and
928 (cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC) )
929 {
930 hit = true;
931 cache_state(way, set) = CACHE_SLOT_STATE_EMPTY;
932 cache_lru(way, set) = false;
933 *selway = way;
934 *selset = set;
935 }
936 }
937 return hit;
938 }
939
940 ////////////////////////////////////////////////////////////////////////////////
941 // This function is deprecated as the directory must be a dual port RAM...
942 ////////////////////////////////////////////////////////////////////////////////
943 __attribute__((deprecated))
944 inline bool update( addr_t ad,
945 data_t* buf,
946 addr_t* victim )
947 {
948 size_t set, way;
949 bool cleanup = victim_select(ad, victim, &way, &set);
950 victim_update_tag (ad, way, set);
951
952 for ( size_t word = 0 ; word < m_words ; word++ ) {
953 cache_data(way, set, word) = buf[word] ;
954 }
955
956 return cleanup;
957 }
958
959 ////////////////////////////////////////////////////////////////////////////
960 // this function is deprecated, as it is difficult to implement in 1 cycle.
961 ////////////////////////////////////////////////////////////////////////////
962 __attribute__((deprecated))
963 inline bool write(addr_t ad,
964 data_t dt)
965 {
966 const addr_t tag = m_z[ad];
967 const size_t set = m_y[ad];
968 const size_t word = m_x[ad];
969
970 for ( size_t way = 0; way < m_ways; way++ )
971 {
972 if ( (tag == cache_tag(way, set)) and
973 (cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC) )
974 {
975 cache_data(way, set, word) = dt;
976 cache_set_lru(way, set);
977 return true;
978 }
979 }
980 return false;
981 }
982
983 ////////////////////////////////////////////////////////////////////////////
984 // this function is deprecated, as it is difficult to implement in 1 cycle.
985 ////////////////////////////////////////////////////////////////////////////
986 __attribute__((deprecated))
987 inline bool write(addr_t ad,
988 data_t dt,
989 be_t be)
990 {
991 const addr_t tag = m_z[ad];
992 const size_t set = m_y[ad];
993 const size_t word = m_x[ad];
994
995 for ( size_t way = 0; way < m_ways; way++ )
996 {
997 if ( (tag == cache_tag(way, set)) and
998 (cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC) )
999 {
1000 data_t mask = be2mask(be);
1001 data_t prev = cache_data(way, set, word);
1002 cache_data(way, set, word) = (mask & dt) | (~mask & prev);
1003 cache_set_lru(way, set);
1004 return true;
1005 }
1006 }
1007 return false;
1008 }
1009
1010 /////////////////////////////////////////////////////////////////////////////
1011 // this function is deprecated, as it is difficult to implement in 1 cycle.
1012 /////////////////////////////////////////////////////////////////////////////
1013 __attribute__((deprecated))
1014 inline bool write(addr_t ad,
1015 data_t dt,
1016 size_t* nway)
1017 {
1018 const addr_t tag = m_z[ad];
1019 const size_t set = m_y[ad];
1020 const size_t word = m_x[ad];
1021
1022 for ( size_t way = 0; way < m_ways; way++ )
1023 {
1024 if ( (tag == cache_tag(way, set)) and
1025 (cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC) )
1026 {
1027 cache_data(way, set, word) = dt;
1028 cache_set_lru(way, set);
1029 *nway = way;
1030 return true;
1031 }
1032 }
1033 return false;
1034 }
1035
1036 /////////////////////////////////////////////////////////////////////////////
1037 // this function is deprecated, as it is difficult to implement in 1 cycle.
1038 /////////////////////////////////////////////////////////////////////////////
1039 __attribute__((deprecated))
1040 inline bool write(addr_t ad,
1041 data_t dt,
1042 size_t* nway,
1043 be_t be)
1044 {
1045 const addr_t tag = m_z[ad];
1046 const size_t set = m_y[ad];
1047 const size_t word = m_x[ad];
1048
1049 for ( size_t way = 0; way < m_ways; way++ )
1050 {
1051 if ( (tag == cache_tag(way, set)) and
1052 (cache_state(way, set) == CACHE_SLOT_STATE_VALID_CC) )
1053 {
1054 data_t mask = be2mask(be);
1055 data_t prev = cache_data(way, set, word);
1056 cache_data(way, set, word) = (mask & dt) | (~mask & prev);
1057 cache_set_lru(way, set);
1058 *nway = way;
1059 return true;
1060 }
1061 }
1062 return false;
1063 }
1064
1065};
1066
1067} // namespace soclib
1068
1069#endif
1070
1071// Local Variables:
1072// tab-width: 4
1073// c-basic-offset: 4
1074// c-file-offsets:((innamespace . 0)(inline-open . 0))
1075// indent-tabs-mode: nil
1076// End:
1077
1078// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1079
Note: See TracBrowser for help on using the repository browser.