source: trunk/lib/generic_cache_tsar/include/generic_cache.h@ 334

Last change on this file since 334 was 303, checked in by joannou, 14 years ago

Bug fix in generic_cache_tsar component :
In the read_select function,

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