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

Last change on this file since 577 was 477, checked in by lgarcia, 13 years ago

Reintroducing RWT branch merging the last modifications of the
trunk (CLACK channel)
WARNING: bugs remaining (with 1c16p and small caches (L2:16*16; L1:4*4))

File size: 38.6 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) or (cache_state(way,set) == CACHE_SLOT_STATE_VALID_NCC))
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 ) and ( cache_state(_way, *set) != CACHE_SLOT_STATE_VALID_NCC )) // 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::dec << 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.