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

Last change on this file since 742 was 365, checked in by joannou, 12 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.