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

Last change on this file since 323 was 303, checked in by joannou, 12 years ago

Bug fix in generic_cache_tsar component :
In the read_select function,

  • Added an _set variable uset instead of the argument for inner tests.
  • Initialized found argument to false, and use it for inner tests.
  • Removed the if(!found) tests.
File size: 33.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    // 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        size_t _set = m_y[ad];
603
604        *found = false;
605
606        // Search first empty slot
607        for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
608        {
609            if ( cache_state(_way, _set) == CACHE_SLOT_STATE_EMPTY )
610            {
611                *found   = true;
612                *cleanup = false;
613                *way     = _way;
614                *set     = m_y[ad];
615                return;
616            }
617        }
618        // Search first not zombi old slot
619        for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
620        {
621            if ( not cache_lru(_way, _set) and
622                 (cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI) )
623            {
624                *found   = true;
625                *cleanup = true;
626                *way     = _way;
627                *set     = m_y[ad];
628                *victim  = (addr_t)((cache_tag(*way,_set) * m_sets) + _set);
629                return;
630            }
631        }
632        // Search first not zombi slot
633        for ( size_t _way = 0 ; _way < m_ways && !(*found) ; _way++ )
634        {
635            if ( cache_state(_way, _set) != CACHE_SLOT_STATE_ZOMBI) 
636            {
637                *found   = true;
638                *cleanup = true;
639                *way    = _way;
640                *set     = m_y[ad];
641                *victim  = (addr_t)((cache_tag(*way,_set) * m_sets) + _set);
642                return;
643            }
644        }
645
646        // no slot found...
647        *found   = false;
648        *cleanup = false;
649    }
650
651    //////////////////////////////////////////////////////////////////
652    // This function update the directory part of a slot
653    // identified by the way & set.
654    //////////////////////////////////////////////////////////////////
655    inline void victim_update_tag( addr_t       ad, 
656                                   size_t       way, 
657                                   size_t       set )
658    {
659        tag_t  tag     = m_z[ad];
660
661        cache_tag(way, set)   = tag;
662        cache_state(way, set) = CACHE_SLOT_STATE_VALID;
663        cache_set_lru(way, set);
664    }
665
666    //////////////////////////////////////////////////////////////////
667    // This function write the directory part of a slot
668    // identified by the way & set, when using the ZOMBI state.
669    //////////////////////////////////////////////////////////////////
670    inline void write_dir( addr_t       ad, 
671                           size_t       way, 
672                           size_t       set,
673                           int      state)
674    {
675        tag_t  tag     = m_z[ad];
676
677        assert( ( (state == CACHE_SLOT_STATE_VALID) or
678                  (state == CACHE_SLOT_STATE_ZOMBI) or
679                  (state == CACHE_SLOT_STATE_EMPTY) ) and
680        "illegal slot state argument in Generic Cache write_dir()");
681
682        assert( (way < m_ways) and
683        "too large way index argument in Generic Cache write_dir()");
684
685        assert( (set < m_sets) and
686        "too large set index argument in Generic Cache write_dir()");
687
688        cache_tag(way, set)   = tag;
689        cache_state(way, set) = state;
690
691        if ( state == CACHE_SLOT_STATE_VALID ) cache_set_lru(way, set);
692    }
693
694    ///////////////////////////////////////////////////////////////////
695    // This function writes a full cache line in one single cycle.
696    // The target slot is identified by the way & set arguments.
697    // Both DATA and DIRECTORY are written
698    ///////////////////////////////////////////////////////////////////
699    inline void update(addr_t   ad, 
700                       size_t   way, 
701                       size_t   set, 
702                       data_t*  buf)
703    {
704        tag_t tag = m_z[ad];
705
706        cache_tag(way, set)   = tag;
707        cache_state(way, set) = CACHE_SLOT_STATE_VALID;
708        cache_set_lru(way, set);
709        for ( size_t word = 0 ; word < m_words ; word++ ) 
710        {
711            cache_data(way, set, word) = buf[word] ;
712        }
713    }
714
715    ///////////////////////////
716    void fileTrace(FILE* file)
717    {
718        for( size_t nway = 0 ; nway < m_ways ; nway++) 
719        {
720            for( size_t nset = 0 ; nset < m_sets ; nset++) 
721            {
722                fprintf(file, "%d / ", (int)cache_state(nway, nset));
723                fprintf(file, "way %d / ", (int)nway);
724                fprintf(file, "set %d / ", (int)nset);
725                fprintf(file, "@ = %08zX / ", 
726                        ((cache_tag(nway, nset)*m_sets+nset)*m_words*4));
727                for( size_t nword = m_words ; nword > 0 ; nword--) 
728                {
729                    unsigned int data = cache_data(nway, nset, nword-1);
730                    fprintf(file, "%08X ", data );
731                }
732                fprintf(file, "\n");
733            }
734        }
735    }
736
737    ////////////////////////
738    inline void printTrace()
739    {
740        for ( size_t way = 0; way < m_ways ; way++ ) 
741        {
742            for ( size_t set = 0 ; set < m_sets ; set++ )
743            {
744                std::cout << std::dec << cache_state(way, set) << " | " ;
745                std::cout << "way " << way << " | " ;
746                std::cout << "set " << set << std::hex << " | " ;
747                std::cout << "@ " << (cache_tag(way,set)*m_words*m_sets+m_words*set)*4 ;
748                for ( size_t word = 0 ; word < m_words ; word++ )
749                {
750                    std::cout << " | " << cache_data(way,set,word) ;
751                }
752                std::cout << std::endl ;
753            }
754        }
755    }
756
757    ///////////////////////////////////////////////////////////////////////////
758    // This function is deprecated as it is difficult to implement in 1 cycle.
759    ///////////////////////////////////////////////////////////////////////////
760    __attribute__((deprecated))
761    inline bool inval(addr_t    ad)
762    {
763        bool              hit = false;
764        const tag_t       tag = m_z[ad];
765        const size_t      set = m_y[ad];
766
767        for ( size_t way = 0 ; way < m_ways && !hit ; way++ ) 
768        {
769            if ( (tag == cache_tag(way, set)) and
770                 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) ) 
771            {
772                hit                   = true;
773                cache_state(way, set) = CACHE_SLOT_STATE_EMPTY;
774                cache_lru(way, set)   = false;
775            }
776        }
777        return hit;
778    }
779
780    ////////////////////////////////////////////////////////////////////////////////
781    // This function is deprecated as it is difficult to implement in 1 cycle.
782    ////////////////////////////////////////////////////////////////////////////////
783    __attribute__((deprecated))
784    inline bool inval( addr_t   ad, 
785                       size_t*  selway, 
786                       size_t*  selset )
787    {
788        bool            hit = false;
789        const tag_t     tag = m_z[ad];
790        const size_t    set = m_y[ad];
791
792        for ( size_t way = 0 ; way < m_ways && !hit ; way++ ) 
793        {
794            if ( (tag == cache_tag(way, set)) and
795                 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) ) 
796            {
797                hit                   = true;
798                cache_state(way, set) = CACHE_SLOT_STATE_EMPTY;
799                cache_lru(way, set)   = false;
800                *selway             = way;
801                *selset             = set;
802            }
803        }
804        return hit;
805    }
806
807    ////////////////////////////////////////////////////////////////////////////////
808    // This function is deprecated as the directory must be a dual port RAM...
809    ////////////////////////////////////////////////////////////////////////////////
810    __attribute__((deprecated))
811    inline bool update( addr_t  ad, 
812                        data_t* buf, 
813                        addr_t* victim )
814    {
815        size_t set, way;
816        bool   cleanup = victim_select(ad, victim, &way, &set);
817        victim_update_tag (ad, way, set);
818
819        for ( size_t word = 0 ; word < m_words ; word++ ) {
820            cache_data(way, set, word) = buf[word] ;
821        }
822
823        return cleanup;
824    }
825
826    ////////////////////////////////////////////////////////////////////////////
827    // this function is deprecated, as it is difficult to implement in 1 cycle.
828    ////////////////////////////////////////////////////////////////////////////
829    __attribute__((deprecated))
830    inline bool write(addr_t    ad, 
831                      data_t    dt)
832    {
833        const tag_t       tag  = m_z[ad];
834        const size_t      set  = m_y[ad];
835        const size_t      word = m_x[ad];
836
837        for ( size_t way = 0; way < m_ways; way++ ) 
838        {
839            if ( (tag == cache_tag(way, set)) and
840                 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) ) 
841            {
842                cache_data(way, set, word) = dt;
843                cache_set_lru(way, set);
844                return true;
845            }
846        }
847        return false;
848    }
849
850    ////////////////////////////////////////////////////////////////////////////
851    // this function is deprecated, as it is difficult to implement in 1 cycle.
852    ////////////////////////////////////////////////////////////////////////////
853    __attribute__((deprecated))
854    inline bool write(addr_t    ad, 
855                      data_t    dt, 
856                      be_t      be)
857    {
858        tag_t       tag  = m_z[ad];
859        const size_t      set  = m_y[ad];
860        const size_t      word = m_x[ad];
861
862        for ( size_t way = 0; way < m_ways; way++ ) 
863        {
864            if ( (tag == cache_tag(way, set)) and
865                 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) ) 
866            {
867                data_t mask = be2mask(be);
868                data_t prev = cache_data(way, set, word);
869                cache_data(way, set, word) = (mask & dt) | (~mask & prev);
870                cache_set_lru(way, set);
871                return true;
872            }
873        }
874        return false;
875    }
876   
877    /////////////////////////////////////////////////////////////////////////////
878    // this function is deprecated, as it is difficult to implement in 1 cycle.
879    /////////////////////////////////////////////////////////////////////////////
880    __attribute__((deprecated))
881    inline bool write(addr_t    ad, 
882                      data_t    dt, 
883                      size_t*   nway)
884    {
885        const tag_t       tag  = m_z[ad];
886        const size_t      set  = m_y[ad];
887        const size_t      word = m_x[ad];
888
889        for ( size_t way = 0; way < m_ways; way++ ) 
890        {
891            if ( (tag == cache_tag(way, set)) and
892                 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) ) 
893            {
894                cache_data(way, set, word) = dt;
895                cache_set_lru(way, set);
896                *nway = way;
897                return true;
898            }
899        }
900        return false;
901    }
902
903    /////////////////////////////////////////////////////////////////////////////
904    // this function is deprecated, as it is difficult to implement in 1 cycle.
905    /////////////////////////////////////////////////////////////////////////////
906    __attribute__((deprecated))
907    inline bool write(addr_t    ad, 
908                      data_t    dt, 
909                      size_t*   nway, 
910                      be_t      be)
911    {
912        const tag_t       tag  = m_z[ad];
913        const size_t      set  = m_y[ad];
914        const size_t      word = m_x[ad];
915
916        for ( size_t way = 0; way < m_ways; way++ ) 
917        {
918            if ( (tag == cache_tag(way, set)) and
919                 (cache_state(way, set) == CACHE_SLOT_STATE_VALID) ) 
920            {
921                data_t mask = be2mask(be);
922                data_t prev = cache_data(way, set, word);
923                cache_data(way, set, word) = (mask & dt) | (~mask & prev);
924                cache_set_lru(way, set);
925                *nway = way;
926                return true;
927            }
928        }
929        return false;
930    }
931   
932};
933
934} // namespace soclib
935
936#endif
937
938// Local Variables:
939// tab-width: 4
940// c-basic-offset: 4
941// c-file-offsets:((innamespace . 0)(inline-open . 0))
942// indent-tabs-mode: nil
943// End:
944
945// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
946
Note: See TracBrowser for help on using the repository browser.