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

Last change on this file since 393 was 393, checked in by alain, 13 years ago

Introducing support for addresses larger than 32 bits.

File size: 36.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 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,
79 CACHE_SLOT_STATE_ZOMBI,
80};
81
82//////////////////////////
83template<typename addr_t>
84class GenericCache
85//////////////////////////
86{
87 typedef uint32_t data_t;
88 typedef uint32_t be_t;
89
90 data_t *r_data ;
91 addr_t *r_tag ;
92 int *r_state;
93 bool *r_lru ;
94
95 size_t m_ways;
96 size_t m_sets;
97 size_t m_words;
98
99 const soclib::common::AddressMaskingTable<addr_t> m_x ;
100 const soclib::common::AddressMaskingTable<addr_t> m_y ;
101 const soclib::common::AddressMaskingTable<addr_t> m_z ;
102
103 //////////////////////////////////////////////////////////////
104 inline data_t &cache_data(size_t way, size_t set, size_t word)
105 {
106 return r_data[(way*m_sets*m_words)+(set*m_words)+word];
107 }
108
109 //////////////////////////////////////////////
110 inline addr_t &cache_tag(size_t way, size_t set)
111 {
112 return r_tag[(way*m_sets)+set];
113 }
114
115 //////////////////////////////////////////////
116 inline bool &cache_lru(size_t way, size_t set)
117 {
118 return r_lru[(way*m_sets)+set];
119 }
120
121 //////////////////////////////////////////////
122 inline int &cache_state(size_t way, size_t set)
123 {
124 return r_state[(way*m_sets)+set];
125 }
126
127 /////////////////////////////////////////////////
128 inline void cache_set_lru(size_t way, size_t set)
129 {
130 size_t way2;
131
132 cache_lru(way, set) = true;
133
134 for (way2 = 0; way2 < m_ways; way2++ )
135 {
136 if (cache_lru(way2, set) == false) return;
137 }
138 // all lines are new -> they all become old
139 for (way2 = 0; way2 < m_ways; way2++ )
140 {
141 cache_lru(way2, set) = false;
142 }
143 }
144
145 ////////////////////////////////
146 inline data_t be2mask( be_t be )
147 {
148 data_t mask = 0;
149 if ( (be & 0x1) == 0x1 ) mask = mask | 0x000000FF;
150 if ( (be & 0x2) == 0x2 ) mask = mask | 0x0000FF00;
151 if ( (be & 0x4) == 0x4 ) mask = mask | 0x00FF0000;
152 if ( (be & 0x8) == 0x8 ) mask = mask | 0xFF000000;
153 return mask;
154 }
155
156public:
157
158 //////////////////////////////////////////
159 GenericCache( const std::string &name,
160 size_t nways,
161 size_t nsets,
162 size_t nwords)
163 : m_ways(nways),
164 m_sets(nsets),
165 m_words(nwords),
166
167#define l2 soclib::common::uint32_log2
168
169 m_x( l2(nwords), l2(sizeof(data_t))),
170 m_y( l2(nsets), l2(nwords) + l2(sizeof(data_t))),
171 m_z( 8*sizeof(addr_t) - l2(nsets) - l2(nwords) - l2(sizeof(data_t)),
172 l2(nsets) + l2(nwords) + l2(sizeof(data_t)))
173#undef l2
174 {
175 assert(IS_POW_OF_2(nways));
176 assert(IS_POW_OF_2(nsets));
177 assert(IS_POW_OF_2(nwords));
178 assert(nwords);
179 assert(nsets);
180 assert(nways);
181 assert(nwords <= 64);
182 assert(nsets <= 1024);
183 assert(nways <= 16);
184
185#ifdef GENERIC_CACHE_DEBUG
186std::cout << "constructing " << name << std::endl
187 << "- nways = " << nways << std::endl
188 << "- nsets = " << nsets << std::endl
189 << "- nwords = " << nwords << std::endl
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 addr_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 addr_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 addr_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 addr_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 addr_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 addr_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 // Read one or two 32 bits word.
403 // Both data and directory are accessed.
404 // returns the access status in the state argument:
405 // - VALID : (matching tag) and (state == VALID)
406 // - ZOMBI : (matching tag) and (state == ZOMBI)
407 // - MISS : no matching tag or EMPTY state
408 // If VALID or ZOMBI, the data, the way, set and word index are
409 // returned in the other arguments.
410 ////////////////////////////////////////////////////////////////////
411 inline void read( addr_t ad,
412 data_t* dt,
413 data_t* dt_next,
414 size_t* selway,
415 size_t* selset,
416 size_t* selword,
417 int* state )
418 {
419 const addr_t tag = m_z[ad];
420 const size_t set = m_y[ad];
421 const size_t word = m_x[ad];
422
423 // default return values
424 *state = CACHE_SLOT_STATE_EMPTY;
425 *selway = 0;
426 *selset = 0;
427 *selword = 0;
428 *dt = 0;
429
430 for ( size_t way = 0; way < m_ways; way++ )
431 {
432 if ( tag == cache_tag(way, set) ) // matching tag
433 {
434
435 if ( cache_state(way, set) == CACHE_SLOT_STATE_VALID )
436 {
437 *state = CACHE_SLOT_STATE_VALID;
438 *selway = way;
439 *selset = set;
440 *selword = word;
441 *dt = cache_data(way, set, word);
442 if ( word+1 < m_words)
443 {
444 *dt_next = cache_data(way, set, word+1);
445 }
446 cache_set_lru(way, set);
447 }
448 else if ( cache_state(way, set) == CACHE_SLOT_STATE_ZOMBI )
449 {
450 *state = CACHE_SLOT_STATE_ZOMBI;
451 *selway = way;
452 *selset = set;
453 *selword = word;
454 }
455 }
456 }
457 }
458
459 ///////////////////////////////////////////////////////////////////////////////
460 // Checks the cache state for a given address.
461 // Only the directory is accessed.
462 // returns true if (matching tag) and (state == VALID)
463 // The selected way, set and first word index are returned in case of hit.
464 // This function can be used when we need to access the directory
465 // while we write in the data part with a different address in the same cycle.
466 ///////////////////////////////////////////////////////////////////////////////
467 inline bool hit( addr_t ad,
468 size_t* selway,
469 size_t* selset,
470 size_t* selword)
471 {
472 const addr_t tag = m_z[ad];
473 const size_t set = m_y[ad];
474 const size_t word = m_x[ad];
475
476 for ( size_t way = 0; way < m_ways; way++ )
477 {
478 if ( (tag == cache_tag(way, set))
479 && (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
480 {
481 *selway = way;
482 *selset = set;
483 *selword = word;
484 cache_set_lru(way, set);
485 return true;
486 }
487 }
488 return false;
489 }
490
491 ///////////////////////////////////////////////////////////////////////////////
492 // Checks the cache state for a given address, when the ZOMBI state is used.
493 // Only the directory is accessed.
494 // Returns the access status in the state argument:
495 // - VALID if (matching tag) and (state == VALID)
496 // - ZOMBI if (matching tag) and (state == ZOMBI)
497 // - EMPTY if no match or (state == EMPTY)
498 // The selected way, set and first word index are returned if not empty.
499 // This function can be used when we need to access the directory
500 // while we write in the data part with a different address in the same cycle.
501 ///////////////////////////////////////////////////////////////////////////////
502 inline void read_dir( addr_t ad,
503 int* state,
504 size_t* way,
505 size_t* set,
506 size_t* word)
507 {
508 const addr_t ad_tag = m_z[ad];
509 const size_t ad_set = m_y[ad];
510 const size_t ad_word = m_x[ad];
511
512 for ( size_t _way = 0; _way < m_ways; _way++ )
513 {
514 if ( (ad_tag == cache_tag(_way, ad_set) ) and
515 (cache_state(_way, ad_set) != CACHE_SLOT_STATE_EMPTY) )
516 {
517 *state = cache_state(_way, ad_set);
518 *way = _way;
519 *set = ad_set;
520 *word = ad_word;
521 return;
522 }
523 }
524
525 // return value if not (VALID or ZOMBI)
526 *state = CACHE_SLOT_STATE_EMPTY;
527 }
528
529 ///////////////////////////////////////////////////////////////////////////////
530 // Checks the cache state for a slot (set,way), when the ZOMBI state is used.
531 // Only the directory is accessed.
532 // Returns the access status and the tag value in the state and tag argument.
533 ///////////////////////////////////////////////////////////////////////////////
534 inline void read_dir( size_t way,
535 size_t set,
536 addr_t* tag,
537 int* state )
538 {
539 *state = cache_state(way, set);
540 *tag = cache_tag(way, set);
541 }
542
543 ////////////////////////////////////////////
544 inline addr_t get_tag(size_t way, size_t set)
545 {
546 return cache_tag(way, set);
547 }
548
549 ///////////////////////////////////////////////////////////////////
550 // This function writes a complete 32 bits word
551 // It does not use the directory and cannot miss.
552 //////////////////////////////////////////////////////////////////
553 inline void write(size_t way,
554 size_t set,
555 size_t word,
556 data_t data)
557 {
558 cache_data(way, set, word) = data;
559 cache_set_lru(way, set);
560 }
561
562 ////////////////////////////////////////////////////////////////////////////
563 // this function writes up to 4 bytes, taking into account the byte enable.
564 // It does not use the directory and cannot miss.
565 ////////////////////////////////////////////////////////////////////////////
566 inline void write(size_t way,
567 size_t set,
568 size_t word,
569 data_t data,
570 be_t be)
571 {
572 data_t mask = be2mask(be);
573 data_t prev = cache_data(way, set, word);
574 cache_data(way, set, word) = (mask & data) | (~mask & prev);
575 cache_set_lru(way, set);
576 }
577
578 //////////////////////////////////////////////////////////////////////////
579 // This function invalidates a cache line identified by the set and way.
580 // It returns true if the line was valid, and returns the line index.
581 //////////////////////////////////////////////////////////////////////////
582 inline bool inval(size_t way,
583 size_t set,
584 addr_t* nline)
585 {
586 if ( cache_state(way,set) == CACHE_SLOT_STATE_VALID )
587 {
588 cache_state(way,set) = CACHE_SLOT_STATE_EMPTY;
589 *nline = (data_t)cache_tag(way,set)* m_sets + set;
590 return true;
591 }
592 return false;
593 }
594
595 //////////////////////////////////////////////////////////////////////////////////
596 // This function selects a victim slot in an associative set.
597 // It cannot fail, as a slot in ZOMBI state is considered EMPTY.
598 // - we search first an EMPTY slot
599 // - if no EMPTY slot, we search an OLD slot, using lru
600 // It returns the line index (Z + Y fields), the selected slot way and set,
601 // and a Boolean indicating that a cleanup is requested.
602 //////////////////////////////////////////////////////////////////////////////////
603 inline bool victim_select(addr_t ad,
604 addr_t* victim,
605 size_t* way,
606 size_t* set)
607 {
608 bool found = false;
609 bool cleanup = false;
610
611 *set = m_y[ad];
612 *way = 0;
613
614 // Search first empty slot
615 for ( size_t _way = 0 ; _way < m_ways && !found ; _way++ )
616 {
617 if ( cache_state(_way, *set) != CACHE_SLOT_STATE_VALID ) // empty
618 {
619 found = true;
620 cleanup = false;
621 *way = _way;
622 }
623 }
624
625 // If no empty slot, search first old slot (lru == false)
626 if ( !found )
627 {
628 for ( size_t _way = 0 ; _way < m_ways && !found ; _way++ )
629 {
630 if ( not cache_lru(_way, *set) )
631 {
632 found = true;
633 cleanup = true;
634 *way = _way;
635 }
636 }
637 }
638
639 assert(found && "all ways can't be new at the same time");
640 *victim = (addr_t)((cache_tag(*way,*set) * m_sets) + *set);
641 return cleanup;
642 }
643
644 //////////////////////////////////////////////////////////////////////////////////
645 // This function selects a victim slot in an associative set.
646 // It can fail if all ways are in ZOMBI state.
647 // - we search first an EMPTY slot
648 // - if no empty slot, we search an OLD slot not in ZOMBI state,
649 // - if not found, we take the first not ZOMBI slot.
650 // It returns the line index (Z + Y fields), the selected slot way and set,
651 // and two Boolean indicating success and a required cleanup.
652 //////////////////////////////////////////////////////////////////////////////////
653 inline void read_select(addr_t ad,
654 addr_t* victim,
655 size_t* way,
656 size_t* set,
657 bool* found,
658 bool* cleanup )
659 {
660 size_t _set = m_y[ad];
661
662 *found = false;
663
664 // Search first empty slot
665 for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
666 {
667 if ( cache_state(_way, _set) == CACHE_SLOT_STATE_EMPTY )
668 {
669 *found = true;
670 *cleanup = false;
671 *way = _way;
672 *set = m_y[ad];
673 return;
674 }
675 }
676 // Search first not zombi old slot
677 for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
678 {
679 if ( not cache_lru(_way, _set) and
680 (cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI) )
681 {
682 *found = true;
683 *cleanup = true;
684 *way = _way;
685 *set = m_y[ad];
686 *victim = cache_tag(*way,_set) * m_sets + _set;
687 return;
688 }
689 }
690 // Search first not zombi slot
691 for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
692 {
693 if ( cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI)
694 {
695 *found = true;
696 *cleanup = true;
697 *way = _way;
698 *set = m_y[ad];
699 *victim = cache_tag(*way,_set) * m_sets + _set;
700 return;
701 }
702 }
703
704 // no slot found...
705 *found = false;
706 *cleanup = false;
707 }
708
709 //////////////////////////////////////////////////////////////////
710 // This function update the directory part of a slot
711 // identified by the way & set.
712 //////////////////////////////////////////////////////////////////
713 inline void victim_update_tag( addr_t ad,
714 size_t way,
715 size_t set )
716 {
717 addr_t tag = m_z[ad];
718
719 cache_tag(way, set) = tag;
720 cache_state(way, set) = CACHE_SLOT_STATE_VALID;
721 cache_set_lru(way, set);
722 }
723
724 //////////////////////////////////////////////////////////////////
725 // This function write the directory part of a slot
726 // identified by the way & set, when using the ZOMBI state.
727 //////////////////////////////////////////////////////////////////
728 inline void write_dir( addr_t ad,
729 size_t way,
730 size_t set,
731 int state)
732 {
733 addr_t tag = m_z[ad];
734
735 assert( ( (state == CACHE_SLOT_STATE_VALID) or
736 (state == CACHE_SLOT_STATE_ZOMBI) or
737 (state == CACHE_SLOT_STATE_EMPTY) ) and
738 "illegal slot state argument in Generic Cache write_dir()");
739
740 assert( (way < m_ways) and
741 "too large way index argument in Generic Cache write_dir()");
742
743 assert( (set < m_sets) and
744 "too large set index argument in Generic Cache write_dir()");
745
746 cache_tag(way, set) = tag;
747 cache_state(way, set) = state;
748
749 if ( state == CACHE_SLOT_STATE_VALID ) cache_set_lru(way, set);
750 }
751
752 //////////////////////////////////////////////////////////////////
753 // This function change the state of a slot
754 // identified by the way & set, when using the ZOMBI state.
755 // It does not affect the tag
756 //////////////////////////////////////////////////////////////////
757 inline void write_dir( size_t way,
758 size_t set,
759 int state)
760 {
761 assert( ( (state == CACHE_SLOT_STATE_VALID) or
762 (state == CACHE_SLOT_STATE_ZOMBI) or
763 (state == CACHE_SLOT_STATE_EMPTY) ) and
764 "illegal slot state argument in Generic Cache write_dir()");
765
766 assert( (way < m_ways) and
767 "too large way index argument in Generic Cache write_dir()");
768
769 assert( (set < m_sets) and
770 "too large set index argument in Generic Cache write_dir()");
771
772 cache_state(way, set) = state;
773
774 if ( state == CACHE_SLOT_STATE_VALID ) cache_set_lru(way, set);
775 }
776
777 ///////////////////////////////////////////////////////////////////
778 // This function writes a full cache line in one single cycle.
779 // The target slot is identified by the way & set arguments.
780 // Both DATA and DIRECTORY are written
781 ///////////////////////////////////////////////////////////////////
782 inline void update(addr_t ad,
783 size_t way,
784 size_t set,
785 data_t* buf)
786 {
787 addr_t tag = m_z[ad];
788
789 cache_tag(way, set) = tag;
790 cache_state(way, set) = CACHE_SLOT_STATE_VALID;
791 cache_set_lru(way, set);
792 for ( size_t word = 0 ; word < m_words ; word++ )
793 {
794 cache_data(way, set, word) = buf[word] ;
795 }
796 }
797
798 ///////////////////////////
799 void fileTrace(FILE* file)
800 {
801 for( size_t nway = 0 ; nway < m_ways ; nway++)
802 {
803 for( size_t nset = 0 ; nset < m_sets ; nset++)
804 {
805 fprintf(file, "%d / ", (int)cache_state(nway, nset));
806 fprintf(file, "way %d / ", (int)nway);
807 fprintf(file, "set %d / ", (int)nset);
808 fprintf(file, "@ = %08zX / ",
809 ((cache_tag(nway, nset)*m_sets+nset)*m_words*4));
810 for( size_t nword = m_words ; nword > 0 ; nword--)
811 {
812 unsigned int data = cache_data(nway, nset, nword-1);
813 fprintf(file, "%08X ", data );
814 }
815 fprintf(file, "\n");
816 }
817 }
818 }
819
820 ////////////////////////
821 inline void printTrace()
822 {
823 for ( size_t way = 0; way < m_ways ; way++ )
824 {
825 for ( size_t set = 0 ; set < m_sets ; set++ )
826 {
827 addr_t addr = (((addr_t)cache_tag(way,set))*m_words*m_sets+m_words*set)*4;
828 std::cout << std::dec << cache_state(way, set)
829 << " | way " << way
830 << " | set " << set
831 << std::hex << " | @ " << addr;
832
833 for ( size_t word = 0 ; word < m_words ; word++ )
834 {
835 std::cout << " | " << cache_data(way,set,word) ;
836 }
837 std::cout << std::endl ;
838 }
839 }
840 }
841
842 ///////////////////////////////////////////////////////////////////////////
843 // This function is deprecated as it is difficult to implement in 1 cycle.
844 ///////////////////////////////////////////////////////////////////////////
845 __attribute__((deprecated))
846 inline bool inval(addr_t ad)
847 {
848 bool hit = false;
849 const addr_t tag = m_z[ad];
850 const size_t set = m_y[ad];
851
852 for ( size_t way = 0 ; way < m_ways && !hit ; way++ )
853 {
854 if ( (tag == cache_tag(way, set)) and
855 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
856 {
857 hit = true;
858 cache_state(way, set) = CACHE_SLOT_STATE_EMPTY;
859 cache_lru(way, set) = false;
860 }
861 }
862 return hit;
863 }
864
865 ////////////////////////////////////////////////////////////////////////////////
866 // This function is deprecated as it is difficult to implement in 1 cycle.
867 ////////////////////////////////////////////////////////////////////////////////
868 __attribute__((deprecated))
869 inline bool inval( addr_t ad,
870 size_t* selway,
871 size_t* selset )
872 {
873 bool hit = false;
874 const addr_t tag = m_z[ad];
875 const size_t set = m_y[ad];
876
877 for ( size_t way = 0 ; way < m_ways && !hit ; way++ )
878 {
879 if ( (tag == cache_tag(way, set)) and
880 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
881 {
882 hit = true;
883 cache_state(way, set) = CACHE_SLOT_STATE_EMPTY;
884 cache_lru(way, set) = false;
885 *selway = way;
886 *selset = set;
887 }
888 }
889 return hit;
890 }
891
892 ////////////////////////////////////////////////////////////////////////////////
893 // This function is deprecated as the directory must be a dual port RAM...
894 ////////////////////////////////////////////////////////////////////////////////
895 __attribute__((deprecated))
896 inline bool update( addr_t ad,
897 data_t* buf,
898 addr_t* victim )
899 {
900 size_t set, way;
901 bool cleanup = victim_select(ad, victim, &way, &set);
902 victim_update_tag (ad, way, set);
903
904 for ( size_t word = 0 ; word < m_words ; word++ ) {
905 cache_data(way, set, word) = buf[word] ;
906 }
907
908 return cleanup;
909 }
910
911 ////////////////////////////////////////////////////////////////////////////
912 // this function is deprecated, as it is difficult to implement in 1 cycle.
913 ////////////////////////////////////////////////////////////////////////////
914 __attribute__((deprecated))
915 inline bool write(addr_t ad,
916 data_t dt)
917 {
918 const addr_t tag = m_z[ad];
919 const size_t set = m_y[ad];
920 const size_t word = m_x[ad];
921
922 for ( size_t way = 0; way < m_ways; way++ )
923 {
924 if ( (tag == cache_tag(way, set)) and
925 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
926 {
927 cache_data(way, set, word) = dt;
928 cache_set_lru(way, set);
929 return true;
930 }
931 }
932 return false;
933 }
934
935 ////////////////////////////////////////////////////////////////////////////
936 // this function is deprecated, as it is difficult to implement in 1 cycle.
937 ////////////////////////////////////////////////////////////////////////////
938 __attribute__((deprecated))
939 inline bool write(addr_t ad,
940 data_t dt,
941 be_t be)
942 {
943 const addr_t tag = m_z[ad];
944 const size_t set = m_y[ad];
945 const size_t word = m_x[ad];
946
947 for ( size_t way = 0; way < m_ways; way++ )
948 {
949 if ( (tag == cache_tag(way, set)) and
950 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
951 {
952 data_t mask = be2mask(be);
953 data_t prev = cache_data(way, set, word);
954 cache_data(way, set, word) = (mask & dt) | (~mask & prev);
955 cache_set_lru(way, set);
956 return true;
957 }
958 }
959 return false;
960 }
961
962 /////////////////////////////////////////////////////////////////////////////
963 // this function is deprecated, as it is difficult to implement in 1 cycle.
964 /////////////////////////////////////////////////////////////////////////////
965 __attribute__((deprecated))
966 inline bool write(addr_t ad,
967 data_t dt,
968 size_t* nway)
969 {
970 const addr_t tag = m_z[ad];
971 const size_t set = m_y[ad];
972 const size_t word = m_x[ad];
973
974 for ( size_t way = 0; way < m_ways; way++ )
975 {
976 if ( (tag == cache_tag(way, set)) and
977 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
978 {
979 cache_data(way, set, word) = dt;
980 cache_set_lru(way, set);
981 *nway = way;
982 return true;
983 }
984 }
985 return false;
986 }
987
988 /////////////////////////////////////////////////////////////////////////////
989 // this function is deprecated, as it is difficult to implement in 1 cycle.
990 /////////////////////////////////////////////////////////////////////////////
991 __attribute__((deprecated))
992 inline bool write(addr_t ad,
993 data_t dt,
994 size_t* nway,
995 be_t be)
996 {
997 const addr_t tag = m_z[ad];
998 const size_t set = m_y[ad];
999 const size_t word = m_x[ad];
1000
1001 for ( size_t way = 0; way < m_ways; way++ )
1002 {
1003 if ( (tag == cache_tag(way, set)) and
1004 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
1005 {
1006 data_t mask = be2mask(be);
1007 data_t prev = cache_data(way, set, word);
1008 cache_data(way, set, word) = (mask & dt) | (~mask & prev);
1009 cache_set_lru(way, set);
1010 *nway = way;
1011 return true;
1012 }
1013 }
1014 return false;
1015 }
1016
1017};
1018
1019} // namespace soclib
1020
1021#endif
1022
1023// Local Variables:
1024// tab-width: 4
1025// c-basic-offset: 4
1026// c-file-offsets:((innamespace . 0)(inline-open . 0))
1027// indent-tabs-mode: nil
1028// End:
1029
1030// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1031
Note: See TracBrowser for help on using the repository browser.