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

Last change on this file since 298 was 297, checked in by alain, 14 years ago

Introducing the 3 states (EMPTY,VALID,ZOMBI) states in cache directory

File size: 33.2 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 // Search first empty slot
603 for ( size_t _way = 0 ; _way < m_ways && !found ; _way++ )
604 {
605 if ( cache_state(_way, *set) == CACHE_SLOT_STATE_EMPTY )
606 {
607 *found = true;
608 *cleanup = false;
609 *way = _way;
610 *set = m_y[ad];
611 return;
612 }
613 }
614 // Search first not zombi old slot
615 if ( !found )
616 {
617 for ( size_t _way = 0 ; _way < m_ways && !found ; _way++ )
618 {
619 if ( not cache_lru(_way, *set) and
620 (cache_state(_way, *set) != CACHE_SLOT_STATE_ZOMBI) )
621 {
622 *found = true;
623 *cleanup = true;
624 *way = _way;
625 *set = m_y[ad];
626 *victim = (addr_t)((cache_tag(*way,*set) * m_sets) + *set);
627 return;
628 }
629 }
630 }
631 // Search first not zombi slot
632 if ( !found )
633 {
634 for ( size_t _way = 0 ; _way < m_ways && !found ; _way++ )
635 {
636 if ( cache_state(_way, *set) != CACHE_SLOT_STATE_ZOMBI)
637 {
638 *found = true;
639 *cleanup = true;
640 *way = _way;
641 *set = m_y[ad];
642 *victim = (addr_t)((cache_tag(*way,*set) * m_sets) + *set);
643 return;
644 }
645 }
646 }
647
648 // no slot found...
649 *found = false;
650 *cleanup = false;
651 }
652
653 //////////////////////////////////////////////////////////////////
654 // This function update the directory part of a slot
655 // identified by the way & set.
656 //////////////////////////////////////////////////////////////////
657 inline void victim_update_tag( addr_t ad,
658 size_t way,
659 size_t set )
660 {
661 tag_t tag = m_z[ad];
662
663 cache_tag(way, set) = tag;
664 cache_state(way, set) = CACHE_SLOT_STATE_VALID;
665 cache_set_lru(way, set);
666 }
667
668 //////////////////////////////////////////////////////////////////
669 // This function write the directory part of a slot
670 // identified by the way & set, when using the ZOMBI state.
671 //////////////////////////////////////////////////////////////////
672 inline void write_dir( addr_t ad,
673 size_t way,
674 size_t set,
675 int state)
676 {
677 tag_t tag = m_z[ad];
678
679 assert( ( (state == CACHE_SLOT_STATE_VALID) or
680 (state == CACHE_SLOT_STATE_ZOMBI) or
681 (state == CACHE_SLOT_STATE_EMPTY) ) and
682 "illegal slot state argument in Generic Cache write_dir()");
683
684 assert( (way < m_ways) and
685 "too large way index argument in Generic Cache write_dir()");
686
687 assert( (set < m_sets) and
688 "too large set index argument in Generic Cache write_dir()");
689
690 cache_tag(way, set) = tag;
691 cache_state(way, set) = state;
692
693 if ( state == CACHE_SLOT_STATE_VALID ) cache_set_lru(way, set);
694 }
695
696 ///////////////////////////////////////////////////////////////////
697 // This function writes a full cache line in one single cycle.
698 // The target slot is identified by the way & set arguments.
699 // Both DATA and DIRECTORY are written
700 ///////////////////////////////////////////////////////////////////
701 inline void update(addr_t ad,
702 size_t way,
703 size_t set,
704 data_t* buf)
705 {
706 tag_t tag = m_z[ad];
707
708 cache_tag(way, set) = tag;
709 cache_state(way, set) = CACHE_SLOT_STATE_VALID;
710 cache_set_lru(way, set);
711 for ( size_t word = 0 ; word < m_words ; word++ )
712 {
713 cache_data(way, set, word) = buf[word] ;
714 }
715 }
716
717 ///////////////////////////
718 void fileTrace(FILE* file)
719 {
720 for( size_t nway = 0 ; nway < m_ways ; nway++)
721 {
722 for( size_t nset = 0 ; nset < m_sets ; nset++)
723 {
724 fprintf(file, "%d / ", (int)cache_state(nway, nset));
725 fprintf(file, "way %d / ", (int)nway);
726 fprintf(file, "set %d / ", (int)nset);
727 fprintf(file, "@ = %08zX / ",
728 ((cache_tag(nway, nset)*m_sets+nset)*m_words*4));
729 for( size_t nword = m_words ; nword > 0 ; nword--)
730 {
731 unsigned int data = cache_data(nway, nset, nword-1);
732 fprintf(file, "%08X ", data );
733 }
734 fprintf(file, "\n");
735 }
736 }
737 }
738
739 ////////////////////////
740 inline void printTrace()
741 {
742 for ( size_t way = 0; way < m_ways ; way++ )
743 {
744 for ( size_t set = 0 ; set < m_sets ; set++ )
745 {
746 std::cout << std::dec << cache_state(way, set) << " | " ;
747 std::cout << "way " << way << " | " ;
748 std::cout << "set " << set << std::hex << " | " ;
749 std::cout << "@ " << (cache_tag(way,set)*m_words*m_sets+m_words*set)*4 ;
750 for ( size_t word = 0 ; word < m_words ; word++ )
751 {
752 std::cout << " | " << cache_data(way,set,word) ;
753 }
754 std::cout << std::endl ;
755 }
756 }
757 }
758
759 ///////////////////////////////////////////////////////////////////////////
760 // This function is deprecated as it is difficult to implement in 1 cycle.
761 ///////////////////////////////////////////////////////////////////////////
762 __attribute__((deprecated))
763 inline bool inval(addr_t ad)
764 {
765 bool hit = false;
766 const tag_t tag = m_z[ad];
767 const size_t set = m_y[ad];
768
769 for ( size_t way = 0 ; way < m_ways && !hit ; way++ )
770 {
771 if ( (tag == cache_tag(way, set)) and
772 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
773 {
774 hit = true;
775 cache_state(way, set) = CACHE_SLOT_STATE_EMPTY;
776 cache_lru(way, set) = false;
777 }
778 }
779 return hit;
780 }
781
782 ////////////////////////////////////////////////////////////////////////////////
783 // This function is deprecated as it is difficult to implement in 1 cycle.
784 ////////////////////////////////////////////////////////////////////////////////
785 __attribute__((deprecated))
786 inline bool inval( addr_t ad,
787 size_t* selway,
788 size_t* selset )
789 {
790 bool hit = false;
791 const tag_t tag = m_z[ad];
792 const size_t set = m_y[ad];
793
794 for ( size_t way = 0 ; way < m_ways && !hit ; way++ )
795 {
796 if ( (tag == cache_tag(way, set)) and
797 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
798 {
799 hit = true;
800 cache_state(way, set) = CACHE_SLOT_STATE_EMPTY;
801 cache_lru(way, set) = false;
802 *selway = way;
803 *selset = set;
804 }
805 }
806 return hit;
807 }
808
809 ////////////////////////////////////////////////////////////////////////////////
810 // This function is deprecated as the directory must be a dual port RAM...
811 ////////////////////////////////////////////////////////////////////////////////
812 __attribute__((deprecated))
813 inline bool update( addr_t ad,
814 data_t* buf,
815 addr_t* victim )
816 {
817 size_t set, way;
818 bool cleanup = victim_select(ad, victim, &way, &set);
819 victim_update_tag (ad, way, set);
820
821 for ( size_t word = 0 ; word < m_words ; word++ ) {
822 cache_data(way, set, word) = buf[word] ;
823 }
824
825 return cleanup;
826 }
827
828 ////////////////////////////////////////////////////////////////////////////
829 // this function is deprecated, as it is difficult to implement in 1 cycle.
830 ////////////////////////////////////////////////////////////////////////////
831 __attribute__((deprecated))
832 inline bool write(addr_t ad,
833 data_t dt)
834 {
835 const tag_t tag = m_z[ad];
836 const size_t set = m_y[ad];
837 const size_t word = m_x[ad];
838
839 for ( size_t way = 0; way < m_ways; way++ )
840 {
841 if ( (tag == cache_tag(way, set)) and
842 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
843 {
844 cache_data(way, set, word) = dt;
845 cache_set_lru(way, set);
846 return true;
847 }
848 }
849 return false;
850 }
851
852 ////////////////////////////////////////////////////////////////////////////
853 // this function is deprecated, as it is difficult to implement in 1 cycle.
854 ////////////////////////////////////////////////////////////////////////////
855 __attribute__((deprecated))
856 inline bool write(addr_t ad,
857 data_t dt,
858 be_t be)
859 {
860 tag_t tag = m_z[ad];
861 const size_t set = m_y[ad];
862 const size_t word = m_x[ad];
863
864 for ( size_t way = 0; way < m_ways; way++ )
865 {
866 if ( (tag == cache_tag(way, set)) and
867 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
868 {
869 data_t mask = be2mask(be);
870 data_t prev = cache_data(way, set, word);
871 cache_data(way, set, word) = (mask & dt) | (~mask & prev);
872 cache_set_lru(way, set);
873 return true;
874 }
875 }
876 return false;
877 }
878
879 /////////////////////////////////////////////////////////////////////////////
880 // this function is deprecated, as it is difficult to implement in 1 cycle.
881 /////////////////////////////////////////////////////////////////////////////
882 __attribute__((deprecated))
883 inline bool write(addr_t ad,
884 data_t dt,
885 size_t* nway)
886 {
887 const tag_t tag = m_z[ad];
888 const size_t set = m_y[ad];
889 const size_t word = m_x[ad];
890
891 for ( size_t way = 0; way < m_ways; way++ )
892 {
893 if ( (tag == cache_tag(way, set)) and
894 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
895 {
896 cache_data(way, set, word) = dt;
897 cache_set_lru(way, set);
898 *nway = way;
899 return true;
900 }
901 }
902 return false;
903 }
904
905 /////////////////////////////////////////////////////////////////////////////
906 // this function is deprecated, as it is difficult to implement in 1 cycle.
907 /////////////////////////////////////////////////////////////////////////////
908 __attribute__((deprecated))
909 inline bool write(addr_t ad,
910 data_t dt,
911 size_t* nway,
912 be_t be)
913 {
914 const tag_t tag = m_z[ad];
915 const size_t set = m_y[ad];
916 const size_t word = m_x[ad];
917
918 for ( size_t way = 0; way < m_ways; way++ )
919 {
920 if ( (tag == cache_tag(way, set)) and
921 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
922 {
923 data_t mask = be2mask(be);
924 data_t prev = cache_data(way, set, word);
925 cache_data(way, set, word) = (mask & dt) | (~mask & prev);
926 cache_set_lru(way, set);
927 *nway = way;
928 return true;
929 }
930 }
931 return false;
932 }
933
934};
935
936} // namespace soclib
937
938#endif
939
940// Local Variables:
941// tab-width: 4
942// c-basic-offset: 4
943// c-file-offsets:((innamespace . 0)(inline-open . 0))
944// indent-tabs-mode: nil
945// End:
946
947// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
948
Note: See TracBrowser for help on using the repository browser.