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

Last change on this file since 534 was 534, checked in by bouyer, 13 years ago

Add an assert that *dt_next is always initialised if entry is found.

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