source: branches/MESI/lib/generic_cache_tsar/include/generic_cache.h @ 965

Last change on this file since 965 was 670, checked in by haoliu, 11 years ago

TSAR branches -- Adding the first version of protocol MESI in TSAR architecture:

File size: 31.0 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_INVALID,
78    CACHE_SLOT_STATE_EXCLUSIVE,
79    CACHE_SLOT_STATE_SHARED,
80    CACHE_SLOT_STATE_MODIFIED,
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    be_t;
91
92    data_t              *r_data ;
93    addr_t               *r_tag ;
94    int                 *r_state;
95    bool                *r_lru ;
96
97    size_t              m_ways; 
98    size_t              m_sets; 
99    size_t              m_words;
100
101    const soclib::common::AddressMaskingTable<addr_t>  m_x ;
102    const soclib::common::AddressMaskingTable<addr_t>  m_y ;
103    const soclib::common::AddressMaskingTable<addr_t>  m_z ;
104
105    //////////////////////////////////////////////////////////////
106    inline data_t &cache_data(size_t way, size_t set, size_t word)
107    {
108        return r_data[(way*m_sets*m_words)+(set*m_words)+word];
109    }
110
111    //////////////////////////////////////////////
112    inline addr_t &cache_tag(size_t way, size_t set)
113    {
114        return r_tag[(way*m_sets)+set];
115    }
116
117    //////////////////////////////////////////////
118    inline bool &cache_lru(size_t way, size_t set)
119    {
120        return r_lru[(way*m_sets)+set];
121    }
122   
123    //////////////////////////////////////////////
124    inline int &cache_state(size_t way, size_t set)
125    {
126        return r_state[(way*m_sets)+set];
127    }
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
189std::cout << "constructing " << name << std::endl
190          << "- nways  = " << nways << std::endl
191          << "- nsets  = " << nsets << std::endl
192          << "- nwords = " << nwords << std::endl
193          << " m_x: " << m_x
194          << " m_y: " << m_y
195          << " m_z: " << m_z
196          << std::endl;
197#endif
198
199        r_data    = new data_t[nways*nsets*nwords];
200        r_tag     = new addr_t[nways*nsets];
201        r_state   = new int[nways*nsets];
202        r_lru     = new bool[nways*nsets];
203    }
204
205    ////////////////
206    ~GenericCache()
207    {
208        delete [] r_data;
209        delete [] r_tag;
210        delete [] r_state;
211        delete [] r_lru;
212    }
213
214    ////////////////////
215    inline void reset( )
216    {
217        std::memset(r_data, 0, sizeof(*r_data)*m_ways*m_sets*m_words);
218        std::memset(r_tag, 0, sizeof(*r_tag)*m_ways*m_sets);
219        std::memset(r_state, CACHE_SLOT_STATE_INVALID, sizeof(*r_state)*m_ways*m_sets);
220        std::memset(r_lru, 0, sizeof(*r_lru)*m_ways*m_sets);
221    }
222
223    inline int get_cache_state(int way, int set)
224    {
225        return cache_state(way,set);
226    }
227   
228    /////////////////////////////////////////////////////////////////////
229    // Read a single 32 bits word.
230    // returns true if (matching tag) and (state == VALID)
231    // Both data & directory are accessed.
232    /////////////////////////////////////////////////////////////////////
233    inline bool read( addr_t    ad, 
234                      data_t*   dt)
235    {
236        const addr_t      tag  = m_z[ad];
237        const size_t      set  = m_y[ad];
238        const size_t      word = m_x[ad];
239
240        for ( size_t way = 0; way < m_ways; way++ ) 
241        {
242            if ( (tag == cache_tag(way, set)) 
243                   && ( (cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE) or (cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED) or (cache_state(way, set) == CACHE_SLOT_STATE_SHARED)) )
244            {
245                *dt = cache_data(way, set, word);
246                cache_set_lru(way, set);
247                return true;
248            }
249        }
250        return false;
251    }
252
253    ////////////////////////////////////////////////////////////////////
254    // Read a single 32 bits word.
255    // returns true if (matching tag) and (state == VALID)
256    // Both data & directory are accessed.
257    // The selected way, set and word index are returned in case of hit.
258    /////////////////////////////////////////////////////////////////////
259    inline bool read( addr_t    ad, 
260                      data_t*   dt,
261                      size_t*   selway,
262                      size_t*   selset,
263                      size_t*   selword) 
264    {
265        const addr_t      tag  = m_z[ad];
266        const size_t      set  = m_y[ad];
267        const size_t      word = m_x[ad];
268
269        for ( size_t way = 0; way < m_ways; way++ ) 
270        {
271            if ( (tag == cache_tag(way, set)) and
272                 ( (cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE) or (cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED) or (cache_state(way, set) == CACHE_SLOT_STATE_SHARED)) )
273            {
274                *selway  = way;
275                *selset  = set;
276                *selword = word;
277                *dt = cache_data(way, set, word);
278                cache_set_lru(way, set);
279                return true;
280            }
281        }
282        return false;
283    }
284
285    ////////////////////////////////////////////////////////////////////
286    // Read a single 32 bits word when the ZOMBI state is used.
287    // Both data and directory are accessed.
288    // returns the access status in the state argument:
289    // - VALID : (matching tag) and (state == VALID)
290    // - ZOMBI : (matching tag) and (state == ZOMBI)
291    // - MISS  : no matching tag or EMPTY state
292    // If VALID or ZOMBI, the data, the way, set and word index are
293    // returned in the other arguments.
294    ////////////////////////////////////////////////////////////////////
295    inline void read( addr_t    ad,
296                      data_t*   dt,
297                      size_t*   selway,
298                      size_t*   selset,
299                      size_t*   selword,
300                      int*      state ) 
301    {
302        const addr_t      tag  = m_z[ad];
303        const size_t      set  = m_y[ad];
304        const size_t      word = m_x[ad];
305
306        // default return values
307        *state   = CACHE_SLOT_STATE_INVALID;
308        *selway  = 0;
309        *selset  = 0;
310        *selword = 0;
311        *dt      = 0;
312
313        for ( size_t way = 0; way < m_ways; way++ ) 
314        {
315            if ( tag == cache_tag(way, set) )  // matching tag
316            {
317
318                if ( cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE )
319                {
320                    *state   = CACHE_SLOT_STATE_EXCLUSIVE;
321                    *selway  = way;
322                    *selset  = set;
323                    *selword = word;
324                    *dt      = cache_data(way, set, word);
325                    cache_set_lru(way, set);
326                }
327                else if ( cache_state(way, set) == CACHE_SLOT_STATE_SHARED )
328                {
329                    *state   = CACHE_SLOT_STATE_SHARED;
330                    *selway  = way;
331                    *selset  = set;
332                    *selword = word;
333                    *dt      = cache_data(way, set, word);
334                    cache_set_lru(way, set);
335                }
336                else if ( cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED )
337                {
338                    *state   = CACHE_SLOT_STATE_MODIFIED;
339                    *selway  = way;
340                    *selset  = set;
341                    *selword = word;
342                    *dt      = cache_data(way, set, word);
343                    cache_set_lru(way, set);
344                }
345                else if ( cache_state(way, set) == CACHE_SLOT_STATE_ZOMBI )
346                {
347                    *state   = CACHE_SLOT_STATE_ZOMBI;
348                    *selway  = way;
349                    *selset  = set;
350                    *selword = word;
351                }
352            }
353        }
354    }
355             
356    ////////////////////////////////////////////////////////////////////
357    // Read a single 32 bits word, without LRU update.
358    // returns true if (matching tag) and (state == VALID)
359    // Both data & directory are accessed.
360    // The selected way, set and word index are returned in case of hit.
361    /////////////////////////////////////////////////////////////////////
362    inline bool read_neutral( addr_t    ad, 
363                                      data_t*   dt,
364                                          size_t*   selway,
365                                          size_t*   selset,
366                                          size_t*   selword) 
367    {
368        const addr_t      tag  = m_z[ad];
369        const size_t      set  = m_y[ad];
370        const size_t      word = m_x[ad];
371
372        for ( size_t way = 0; way < m_ways; way++ ) 
373        {
374            if ( (tag == cache_tag(way, set)) 
375                   && ( (cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE) or (cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED) or (cache_state(way, set) == CACHE_SLOT_STATE_SHARED)) )
376            {
377                *selway  = way;
378                *selset  = set;
379                *selword = word;
380                *dt = cache_data(way, set, word);
381                return true;
382            }
383        }
384        return false;
385    }
386
387    /////////////////////////////////////////////////////////////////////////////
388    // Read one or two 32 bits word.
389    // Both data & directory are accessed.
390    // Hit if (matching tag) and (valid == true) and (zombi == false)
391    // If the addressed word is not the last in the cache line,
392    // two successive words are returned.
393    // The selected way, set and first word index are returned in case of hit.
394    // This function is used by the cc_vcache to get a 64 bits page table entry.
395    /////////////////////////////////////////////////////////////////////////////
396    inline bool read( addr_t    ad, 
397                      data_t*   dt, 
398                      data_t*   dt_next,
399                      size_t*   selway,
400                      size_t*   selset,
401                      size_t*   selword)
402    {
403        const addr_t      tag  = m_z[ad];
404        const size_t      set  = m_y[ad];
405        const size_t      word = m_x[ad];
406
407        for ( size_t way = 0; way < m_ways; way++ ) 
408        {
409            if ( (tag == cache_tag(way, set))   
410                   && ( (cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE) or (cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED) or (cache_state(way, set) == CACHE_SLOT_STATE_SHARED)) )
411            {
412                *dt      = cache_data(way, set, word);
413                if ( word+1 < m_words) 
414                {
415                    *dt_next = cache_data(way, set, word+1);
416                }
417                *selway  = way;
418                *selset  = set;
419                *selword = word;
420                cache_set_lru(way, set);
421                return true;
422            }
423        }
424        return false;
425    }
426
427    ////////////////////////////////////////////////////////////////////
428    // Read one or two 32 bits word.
429    // Both data and directory are accessed.
430    // returns the access status in the state argument:
431    // - VALID : (matching tag) and (state == VALID)
432    // - ZOMBI : (matching tag) and (state == ZOMBI)
433    // - MISS  : no matching tag or EMPTY state
434    // If VALID or ZOMBI, the data, the way, set and word index are
435    // returned in the other arguments.
436    ////////////////////////////////////////////////////////////////////
437    inline void read( addr_t    ad,
438                      data_t*   dt,
439                      data_t*   dt_next,
440                      size_t*   selway,
441                      size_t*   selset,
442                      size_t*   selword,
443                      int*      state ) 
444    {
445        const addr_t      tag  = m_z[ad];
446        const size_t      set  = m_y[ad];
447        const size_t      word = m_x[ad];
448
449        // default return values
450        *state   = CACHE_SLOT_STATE_INVALID;
451        *selway  = 0;
452        *selset  = 0;
453        *selword = 0;
454        *dt      = 0;
455
456        for ( size_t way = 0; way < m_ways; way++ ) 
457        {
458            if ( tag == cache_tag(way, set) )  // matching tag
459            {
460
461                if ( cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE )
462                {
463                    *state   = CACHE_SLOT_STATE_EXCLUSIVE;
464                    *selway  = way;
465                    *selset  = set;
466                    *selword = word;
467                    *dt      = cache_data(way, set, word);
468                    if ( word+1 < m_words) 
469                    {
470                        *dt_next = cache_data(way, set, word+1);
471                    }
472                    cache_set_lru(way, set);
473                }
474
475                else if ( cache_state(way, set) == CACHE_SLOT_STATE_SHARED )
476                {
477                    *state   = CACHE_SLOT_STATE_SHARED;
478                    *selway  = way;
479                    *selset  = set;
480                    *selword = word;
481                    *dt      = cache_data(way, set, word);
482                    if ( word+1 < m_words) 
483                    {
484                        *dt_next = cache_data(way, set, word+1);
485                    }
486                    cache_set_lru(way, set);
487                }
488
489                else if ( cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED )
490                {
491                    *state   = CACHE_SLOT_STATE_MODIFIED;
492                    *selway  = way;
493                    *selset  = set;
494                    *selword = word;
495                    *dt      = cache_data(way, set, word);
496                    if ( word+1 < m_words) 
497                    {
498                        *dt_next = cache_data(way, set, word+1);
499                    }
500                    cache_set_lru(way, set);
501                }
502
503                else if ( cache_state(way, set) == CACHE_SLOT_STATE_ZOMBI )
504                {
505                    *state   = CACHE_SLOT_STATE_ZOMBI;
506                    *selway  = way;
507                    *selset  = set;
508                    *selword = word;
509                }
510            }
511        }
512    }
513
514    ///////////////////////////////////////////////////////////////////////////////
515    // Checks the cache state for a given address.
516    // Only the directory is accessed.
517    // returns true if (matching tag) and (state == VALID)
518    // The selected way, set and first word index are returned in case of hit.
519    // This function can be used when we need to access the directory
520    // while we write in the data part with a different address in the same cycle.
521    ///////////////////////////////////////////////////////////////////////////////
522    inline bool hit(  addr_t    ad, 
523                      size_t*   selway,
524                      size_t*   selset,
525                      size_t*   selword)
526    {
527        const addr_t      tag  = m_z[ad];
528        const size_t      set  = m_y[ad];
529        const size_t      word = m_x[ad];
530
531        for ( size_t way = 0; way < m_ways; way++ ) 
532        {
533            if ( (tag == cache_tag(way, set)) 
534                   && ( (cache_state(way, set) == CACHE_SLOT_STATE_EXCLUSIVE) or (cache_state(way, set) == CACHE_SLOT_STATE_MODIFIED) or (cache_state(way, set) == CACHE_SLOT_STATE_SHARED)) )
535            {
536                *selway  = way;
537                *selset  = set;
538                *selword = word;
539                cache_set_lru(way, set);
540                return true;
541            }
542        }
543        return false;
544    }
545 
546    ///////////////////////////////////////////////////////////////////////////////
547    // Checks the cache state for a given address, when the ZOMBI state is used.
548    // Only the directory is accessed.
549    // Returns the access status in the state argument:
550    // - VALID if (matching tag) and (state == VALID)
551    // - ZOMBI if (matching tag) and (state == ZOMBI)
552    // - EMPTY if no match or (state == EMPTY)
553    // The selected way, set and first word index are returned if not empty.
554    // This function can be used when we need to access the directory
555    // while we write in the data part with a different address in the same cycle.
556    ///////////////////////////////////////////////////////////////////////////////
557    inline void read_dir(  addr_t       ad, 
558                           int*     state,
559                           size_t*      way,
560                           size_t*      set,
561                           size_t*  word)
562    {
563        const addr_t      ad_tag  = m_z[ad];
564        const size_t      ad_set  = m_y[ad];
565        const size_t      ad_word = m_x[ad];
566        for ( size_t _way = 0; _way < m_ways; _way++ ) 
567        {
568            if ( (ad_tag == cache_tag(_way, ad_set) ) and
569                 (cache_state(_way, ad_set) != CACHE_SLOT_STATE_INVALID) ) 
570            {
571                *state = cache_state(_way, ad_set);
572                *way   = _way;
573                *set   = ad_set;
574                *word  = ad_word;
575                return;
576            }
577        }
578       
579        // return value if not (VALID or ZOMBI)
580        *state = CACHE_SLOT_STATE_INVALID;
581    }
582
583    ///////////////////////////////////////////////////////////////////////////////
584    // Checks the cache state for a slot (set,way), when the ZOMBI state is used.
585    // Only the directory is accessed.
586    // Returns the access status and the tag value in the state and tag argument.
587    ///////////////////////////////////////////////////////////////////////////////
588    inline void read_dir(  size_t       way,
589                           size_t       set,
590                           addr_t*   tag,
591                           int*     state )
592    {
593        *state = cache_state(way, set);
594        *tag   = cache_tag(way, set);
595    }
596
597    ////////////////////////////////////////////
598    inline addr_t get_tag(size_t way, size_t set)
599    {
600        return cache_tag(way, set);
601    }
602
603    ///////////////////////////////////////////////////////////////////
604    // This function writes a complete 32 bits word
605    // It does not use the directory and cannot miss.
606    //////////////////////////////////////////////////////////////////
607    inline void write(size_t    way, 
608                      size_t    set, 
609                      size_t    word, 
610                      data_t    data)
611    {
612       /**/ //std::cout << "write cache : way = "<<way<<" | set = "<<set<<" | word = "<<word<<" | data = "<<(uint32_t)data << std::endl;
613        cache_data(way, set, word) = data;
614        cache_set_lru(way, set);
615    }
616
617    ////////////////////////////////////////////////////////////////////////////
618    // this function writes up to 4 bytes, taking into account the byte enable.
619    // It does not use the directory and cannot miss.
620    ////////////////////////////////////////////////////////////////////////////
621    inline void write(size_t    way, 
622                      size_t    set, 
623                      size_t    word, 
624                      data_t    data, 
625                      be_t          be)
626    {
627        data_t mask = be2mask(be);
628        data_t prev = cache_data(way, set, word);
629        cache_data(way, set, word) = (mask & data) | (~mask & prev);
630        cache_set_lru(way, set);
631    }
632
633    //////////////////////////////////////////////////////////////////////////
634    // This function invalidates a cache line identified by the set and way.
635    // It returns true if the line was valid, and returns the line index.
636    //////////////////////////////////////////////////////////////////////////
637    inline bool inval(size_t    way, 
638                      size_t    set, 
639                      addr_t*   nline)
640    {
641        if( (cache_state(way,set) == CACHE_SLOT_STATE_EXCLUSIVE) or  (cache_state(way,set) == CACHE_SLOT_STATE_MODIFIED) or (cache_state(way,set) == CACHE_SLOT_STATE_SHARED))
642        {
643            cache_state(way,set) = CACHE_SLOT_STATE_INVALID;
644            *nline = (data_t)cache_tag(way,set)* m_sets + set;
645            return true;
646        }
647        return false;
648    }
649
650    //////////////////////////////////////////////////////////////////////////////////
651    // This function selects a victim slot in an associative set.
652    // It cannot fail, as a slot in ZOMBI state is considered EMPTY.
653    // - we search first an EMPTY slot
654    // - if no EMPTY slot, we search an OLD slot, using lru
655    // It returns the line index (Z + Y fields), the selected slot way and set,
656    // and a Boolean indicating that a cleanup is requested.
657    //////////////////////////////////////////////////////////////////////////////////
658    inline bool victim_select(addr_t    ad, 
659                              addr_t*   victim, 
660                              size_t*   way, 
661                              size_t*   set)
662    {
663        bool   found   = false;
664        bool   cleanup = false;
665
666        *set = m_y[ad];
667        *way = 0;
668
669        // Search first empty slot
670        for ( size_t _way = 0 ; _way < m_ways && !found ; _way++ )
671        {
672            if( ( cache_state(_way, *set) != CACHE_SLOT_STATE_EXCLUSIVE ) and ( cache_state(_way, *set) != CACHE_SLOT_STATE_SHARED ) and ( cache_state(_way, *set) != CACHE_SLOT_STATE_MODIFIED ))  // empty
673            {
674                found   = true;
675                cleanup = false;
676                *way    = _way;
677            }
678        }
679
680        // If no empty slot, search first  old slot (lru == false)
681        if ( !found )
682        { 
683            for ( size_t _way = 0 ; _way < m_ways && !found ; _way++ )
684            {
685                if ( not cache_lru(_way, *set) )
686                {
687                    found   = true;
688                    cleanup = true;
689                    *way    = _way;
690                }
691            }
692        }
693
694        assert(found && "all ways can't be new at the same time");
695        *victim = (addr_t)((cache_tag(*way,*set) * m_sets) + *set);
696        return cleanup;
697    }
698
699    //////////////////////////////////////////////////////////////////////////////////
700    // This function selects a victim slot in an associative set.
701    // It can fail if all ways are in ZOMBI state.
702    // - we search first an EMPTY slot
703    // - if no empty slot, we search an OLD slot not in ZOMBI state,
704    // - if not found, we take the first not ZOMBI slot.
705    // It returns the line index (Z + Y fields), the selected slot way and set,
706    // and two Boolean indicating success and a required cleanup.
707    //////////////////////////////////////////////////////////////////////////////////
708    inline void read_select(addr_t        ad, 
709                            addr_t*   victim, 
710                            size_t*   way, 
711                            size_t*   set,
712                            bool*     found,
713                            bool*     cleanup )
714    {
715        size_t _set = m_y[ad];
716
717        *found = false;
718
719        // Search first empty slot
720        for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
721        {
722            if ( cache_state(_way, _set) == CACHE_SLOT_STATE_INVALID )
723            {
724                *found   = true;
725                *cleanup = false;
726                *way     = _way;
727                *set     = m_y[ad];
728                return;
729            }
730        }
731        //////////////////////////////////////////////////////////////
732        /*for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
733        {
734            if ( not cache_lru(_way, _set) and
735                 (cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI) and
736                 (cache_state(_way, _set) == CACHE_SLOT_STATE_VALID_NCC) )
737            {
738                *found   = true;
739                *cleanup = true;
740                *way     = _way;
741                *set     = m_y[ad];
742                *victim  = (addr_t)((cache_tag(*way,_set) * m_sets) + _set);
743                return;
744            }
745        }*/
746        // Search first not zombi old slot
747        for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
748        {
749            if ( not cache_lru(_way, _set) and
750                 (cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI) )
751            {
752                *found   = true;
753                *cleanup = true;
754                *way     = _way;
755                *set     = m_y[ad];
756                *victim  = cache_tag(*way,_set) * m_sets + _set;
757                return;
758            }
759        }
760        // Search first not zombi slot
761        for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
762        {
763            if ( cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI) 
764            {
765                *found   = true;
766                *cleanup = true;
767                *way    = _way;
768                *set     = m_y[ad];
769                *victim  = cache_tag(*way,_set) * m_sets + _set;
770                return;
771            }
772        }
773
774        // no slot found...
775        *found   = false;
776        *cleanup = false;
777    }
778
779    //////////////////////////////////////////////////////////////////
780    // This function write the directory part of a slot
781    // identified by the way & set, when using the ZOMBI state.
782    //////////////////////////////////////////////////////////////////
783    inline void write_dir( addr_t       ad, 
784                           size_t       way, 
785                           size_t       set,
786                           int      state)
787    {
788        addr_t  tag     = m_z[ad];
789
790        assert( ( (state == CACHE_SLOT_STATE_EXCLUSIVE) or
791                  (state == CACHE_SLOT_STATE_SHARED) or
792                  (state == CACHE_SLOT_STATE_MODIFIED) or
793                  (state == CACHE_SLOT_STATE_INVALID) or
794                  (state == CACHE_SLOT_STATE_ZOMBI)) and
795        "illegal slot state argument in Generic Cache write_dir()");
796
797        assert( (way < m_ways) and
798        "too large way index argument in Generic Cache write_dir()");
799
800        assert( (set < m_sets) and
801        "too large set index argument in Generic Cache write_dir()");
802
803        cache_tag(way, set)   = tag;
804        cache_state(way, set) = state;
805
806        if ( (state == CACHE_SLOT_STATE_EXCLUSIVE) or (state == CACHE_SLOT_STATE_MODIFIED) or (state == CACHE_SLOT_STATE_SHARED) ) cache_set_lru(way, set);
807    }
808
809    //////////////////////////////////////////////////////////////////
810    // This function change the state of a slot
811    // identified by the way & set, when using the ZOMBI state.
812    // It does not affect the tag
813    //////////////////////////////////////////////////////////////////
814    inline void write_dir( size_t       way, 
815                           size_t       set,
816                           int      state)
817    {
818        assert( ( (state == CACHE_SLOT_STATE_EXCLUSIVE) or
819                  (state == CACHE_SLOT_STATE_SHARED) or
820                  (state == CACHE_SLOT_STATE_MODIFIED) or
821                  (state == CACHE_SLOT_STATE_INVALID) or
822                  (state == CACHE_SLOT_STATE_ZOMBI)) and
823        "illegal slot state argument in Generic Cache write_dir()");
824
825        assert( (way < m_ways) and
826        "too large way index argument in Generic Cache write_dir()");
827
828        assert( (set < m_sets) and
829        "too large set index argument in Generic Cache write_dir()");
830
831        cache_state(way, set) = state;
832
833        if ( (state == CACHE_SLOT_STATE_EXCLUSIVE) or (state == CACHE_SLOT_STATE_MODIFIED) or (state == CACHE_SLOT_STATE_SHARED) ) cache_set_lru(way, set);
834
835    }
836
837   
838};
839
840} // namespace soclib
841
842#endif
843
844// Local Variables:
845// tab-width: 4
846// c-basic-offset: 4
847// c-file-offsets:((innamespace . 0)(inline-open . 0))
848// indent-tabs-mode: nil
849// End:
850
851// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
852
Note: See TracBrowser for help on using the repository browser.