source: branches/v4/lib/generic_cache_tsar/include/generic_cache.h@ 513

Last change on this file since 513 was 365, checked in by joannou, 13 years ago

In generic_cache_tsar, added a new write_dir function that does not affect the tag

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 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 // 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 tag_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 tag_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, wehn 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 tag_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 tag_t* tag,
537 int* state )
538 {
539 *state = cache_state(way, set);
540 *tag = cache_tag(way, set);
541 }
542
543 ////////////////////////////////////////////
544 inline tag_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 = (addr_t)((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 = (addr_t)((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 tag_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 tag_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 write the directory part of a slot
754 // identified by the way & set, when using the ZOMBI state.
755 // 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 tag_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 std::cout << std::dec << cache_state(way, set) << " | " ;
828 std::cout << "way " << way << " | " ;
829 std::cout << "set " << set << std::hex << " | " ;
830 std::cout << "@ " << (cache_tag(way,set)*m_words*m_sets+m_words*set)*4 ;
831 for ( size_t word = 0 ; word < m_words ; word++ )
832 {
833 std::cout << " | " << cache_data(way,set,word) ;
834 }
835 std::cout << std::endl ;
836 }
837 }
838 }
839
840 ///////////////////////////////////////////////////////////////////////////
841 // This function is deprecated as it is difficult to implement in 1 cycle.
842 ///////////////////////////////////////////////////////////////////////////
843 __attribute__((deprecated))
844 inline bool inval(addr_t ad)
845 {
846 bool hit = false;
847 const tag_t tag = m_z[ad];
848 const size_t set = m_y[ad];
849
850 for ( size_t way = 0 ; way < m_ways && !hit ; way++ )
851 {
852 if ( (tag == cache_tag(way, set)) and
853 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
854 {
855 hit = true;
856 cache_state(way, set) = CACHE_SLOT_STATE_EMPTY;
857 cache_lru(way, set) = false;
858 }
859 }
860 return hit;
861 }
862
863 ////////////////////////////////////////////////////////////////////////////////
864 // This function is deprecated as it is difficult to implement in 1 cycle.
865 ////////////////////////////////////////////////////////////////////////////////
866 __attribute__((deprecated))
867 inline bool inval( addr_t ad,
868 size_t* selway,
869 size_t* selset )
870 {
871 bool hit = false;
872 const tag_t tag = m_z[ad];
873 const size_t set = m_y[ad];
874
875 for ( size_t way = 0 ; way < m_ways && !hit ; way++ )
876 {
877 if ( (tag == cache_tag(way, set)) and
878 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
879 {
880 hit = true;
881 cache_state(way, set) = CACHE_SLOT_STATE_EMPTY;
882 cache_lru(way, set) = false;
883 *selway = way;
884 *selset = set;
885 }
886 }
887 return hit;
888 }
889
890 ////////////////////////////////////////////////////////////////////////////////
891 // This function is deprecated as the directory must be a dual port RAM...
892 ////////////////////////////////////////////////////////////////////////////////
893 __attribute__((deprecated))
894 inline bool update( addr_t ad,
895 data_t* buf,
896 addr_t* victim )
897 {
898 size_t set, way;
899 bool cleanup = victim_select(ad, victim, &way, &set);
900 victim_update_tag (ad, way, set);
901
902 for ( size_t word = 0 ; word < m_words ; word++ ) {
903 cache_data(way, set, word) = buf[word] ;
904 }
905
906 return cleanup;
907 }
908
909 ////////////////////////////////////////////////////////////////////////////
910 // this function is deprecated, as it is difficult to implement in 1 cycle.
911 ////////////////////////////////////////////////////////////////////////////
912 __attribute__((deprecated))
913 inline bool write(addr_t ad,
914 data_t dt)
915 {
916 const tag_t tag = m_z[ad];
917 const size_t set = m_y[ad];
918 const size_t word = m_x[ad];
919
920 for ( size_t way = 0; way < m_ways; way++ )
921 {
922 if ( (tag == cache_tag(way, set)) and
923 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
924 {
925 cache_data(way, set, word) = dt;
926 cache_set_lru(way, set);
927 return true;
928 }
929 }
930 return false;
931 }
932
933 ////////////////////////////////////////////////////////////////////////////
934 // this function is deprecated, as it is difficult to implement in 1 cycle.
935 ////////////////////////////////////////////////////////////////////////////
936 __attribute__((deprecated))
937 inline bool write(addr_t ad,
938 data_t dt,
939 be_t be)
940 {
941 tag_t tag = m_z[ad];
942 const size_t set = m_y[ad];
943 const size_t word = m_x[ad];
944
945 for ( size_t way = 0; way < m_ways; way++ )
946 {
947 if ( (tag == cache_tag(way, set)) and
948 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
949 {
950 data_t mask = be2mask(be);
951 data_t prev = cache_data(way, set, word);
952 cache_data(way, set, word) = (mask & dt) | (~mask & prev);
953 cache_set_lru(way, set);
954 return true;
955 }
956 }
957 return false;
958 }
959
960 /////////////////////////////////////////////////////////////////////////////
961 // this function is deprecated, as it is difficult to implement in 1 cycle.
962 /////////////////////////////////////////////////////////////////////////////
963 __attribute__((deprecated))
964 inline bool write(addr_t ad,
965 data_t dt,
966 size_t* nway)
967 {
968 const tag_t tag = m_z[ad];
969 const size_t set = m_y[ad];
970 const size_t word = m_x[ad];
971
972 for ( size_t way = 0; way < m_ways; way++ )
973 {
974 if ( (tag == cache_tag(way, set)) and
975 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
976 {
977 cache_data(way, set, word) = dt;
978 cache_set_lru(way, set);
979 *nway = way;
980 return true;
981 }
982 }
983 return false;
984 }
985
986 /////////////////////////////////////////////////////////////////////////////
987 // this function is deprecated, as it is difficult to implement in 1 cycle.
988 /////////////////////////////////////////////////////////////////////////////
989 __attribute__((deprecated))
990 inline bool write(addr_t ad,
991 data_t dt,
992 size_t* nway,
993 be_t be)
994 {
995 const tag_t tag = m_z[ad];
996 const size_t set = m_y[ad];
997 const size_t word = m_x[ad];
998
999 for ( size_t way = 0; way < m_ways; way++ )
1000 {
1001 if ( (tag == cache_tag(way, set)) and
1002 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) )
1003 {
1004 data_t mask = be2mask(be);
1005 data_t prev = cache_data(way, set, word);
1006 cache_data(way, set, word) = (mask & dt) | (~mask & prev);
1007 cache_set_lru(way, set);
1008 *nway = way;
1009 return true;
1010 }
1011 }
1012 return false;
1013 }
1014
1015};
1016
1017} // namespace soclib
1018
1019#endif
1020
1021// Local Variables:
1022// tab-width: 4
1023// c-basic-offset: 4
1024// c-file-offsets:((innamespace . 0)(inline-open . 0))
1025// indent-tabs-mode: nil
1026// End:
1027
1028// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1029
Note: See TracBrowser for help on using the repository browser.