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

Last change on this file since 297 was 297, checked in by alain, 11 years ago

Introducing the 3 states (EMPTY,VALID,ZOMBI) states in cache directory

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