source: branches/ODCCP/modules/vci_mem_cache/caba/source/include/mem_cache_directory.h @ 460

Last change on this file since 460 was 460, checked in by devigne, 11 years ago

Introducing merged components between the last trunk TSAR version
and the ODCCP modifications

File size: 23.7 KB
Line 
1#ifndef SOCLIB_CABA_MEM_CACHE_DIRECTORY_H
2#define SOCLIB_CABA_MEM_CACHE_DIRECTORY_H
3
4#include <inttypes.h>
5#include <systemc>
6#include <cassert>
7#include "arithmetics.h"
8
9// !!!
10// The L1_MULTI_CACHE mechanism does no longer work with the new pktid encoding
11// of TSAR. Turning the define below to a non null value will cause the memcache
12// to behave in an unpredicted way.
13// TODO Either remove the mechanism from the mem cache or update its behaviour.
14
15#define L1_MULTI_CACHE 0
16
17//#define RANDOM_EVICTION
18
19namespace soclib { namespace caba {
20
21  using namespace sc_core;
22
23  ////////////////////////////////////////////////////////////////////////
24  //                    A LRU entry
25  ////////////////////////////////////////////////////////////////////////
26  class LruEntry {
27
28    public:
29
30      bool recent;           
31
32      void init()
33      {
34        recent=false;
35      }
36
37  }; // end class LruEntry
38
39  ////////////////////////////////////////////////////////////////////////
40  //                    An Owner
41  ////////////////////////////////////////////////////////////////////////
42  class Owner{
43   
44    public:
45    // Fields
46      bool      inst;       // Is the owner an ICache ?
47      size_t    srcid;      // The SRCID of the owner
48#if L1_MULTI_CACHE
49      size_t    cache_id;   // In multi_cache configuration
50#endif
51
52    ////////////////////////
53    // Constructors
54    ////////////////////////
55      Owner(bool   i_inst
56            ,size_t i_srcid
57#if L1_MULTI_CACHE
58            ,size_t i_cache_id
59#endif
60            ){
61        inst    = i_inst;
62        srcid   = i_srcid;
63#if L1_MULTI_CACHE
64        cache_id= i_cache_id;
65#endif
66      }
67
68      Owner(const Owner &a){
69        inst    = a.inst;
70        srcid   = a.srcid;
71#if L1_MULTI_CACHE
72        cache_id= a.cache_id;
73#endif
74      }
75
76      Owner(){
77        inst    = false;
78        srcid   = 0;
79#if L1_MULTI_CACHE
80        cache_id= 0;
81#endif
82      }
83      // end constructors
84
85  }; // end class Owner
86
87
88  ////////////////////////////////////////////////////////////////////////
89  //                    A directory entry                               
90  ////////////////////////////////////////////////////////////////////////
91  class DirectoryEntry {
92
93    typedef uint32_t tag_t;
94
95    public:
96
97    bool    valid;                  // entry valid
98    bool    is_cnt;                 // directory entry is in counter mode
99    bool    dirty;                  // entry dirty
100    bool    lock;                   // entry locked
101    bool    coherent;               // entry coherent or not
102    tag_t   tag;                    // tag of the entry
103    size_t  count;                  // number of copies
104    Owner   owner;                  // an owner of the line
105    size_t  ptr;                    // pointer to the next owner
106
107    DirectoryEntry()
108    {
109      valid         = false;
110      is_cnt        = false;
111      dirty         = false;
112      lock          = false;
113      coherent      = true;
114      tag           = 0;
115      count         = 0;
116      owner.inst    = 0;
117      owner.srcid   = 0;
118#if L1_MULTI_CACHE
119      owner.cache_id= 0;
120#endif
121      ptr           = 0;
122    }
123
124    DirectoryEntry(const DirectoryEntry &source)
125    {
126      valid         = source.valid;
127      is_cnt        = source.is_cnt;
128      dirty         = source.dirty;
129      lock          = source.lock;
130      coherent      = source.coherent;
131      tag           = source.tag;
132      count         = source.count;
133      owner         = source.owner;
134      ptr           = source.ptr;
135    }         
136
137    /////////////////////////////////////////////////////////////////////
138    // The init() function initializes the entry
139    /////////////////////////////////////////////////////////////////////
140    void init()
141    {
142      valid     = false;
143      is_cnt    = false;
144      dirty     = false;
145      lock      = false;
146      coherent  = true;
147      count     = 0;
148    }
149
150    /////////////////////////////////////////////////////////////////////
151    // The copy() function copies an existing source entry to a target
152    /////////////////////////////////////////////////////////////////////
153    void copy(const DirectoryEntry &source)
154    {
155      valid         = source.valid;
156      is_cnt    = source.is_cnt;
157      dirty         = source.dirty;
158      lock          = source.lock;
159      coherent  = source.coherent;
160      tag           = source.tag;
161      count     = source.count;
162      owner     = source.owner;
163      ptr       = source.ptr;
164    }
165
166    ////////////////////////////////////////////////////////////////////
167    // The print() function prints the entry
168    ////////////////////////////////////////////////////////////////////
169    void print()
170    {
171      std::cout << "Valid = " << valid
172                << " ; IS COUNT = " << is_cnt
173                << " ; Dirty = " << dirty
174                << " ; Lock = " << lock
175                << " ; Tag = " << std::hex << tag << std::dec
176                << " ; Count = " << count
177                << " ; Owner = " << owner.srcid
178#if L1_MULTI_CACHE
179                << "." << owner.cache_id
180#endif
181                << " " << owner.inst
182                << " ; Pointer = " << ptr << std::endl;
183    }
184
185  }; // end class DirectoryEntry
186
187  ////////////////////////////////////////////////////////////////////////
188  //                       The directory 
189  ////////////////////////////////////////////////////////////////////////
190  class CacheDirectory {
191
192    typedef sc_dt::sc_uint<40> addr_t;
193    typedef uint32_t data_t;
194    typedef uint32_t tag_t;
195
196    private:
197
198    // Directory constants
199    size_t                                      m_ways;
200    size_t                                      m_sets;
201    size_t                                      m_words;
202    size_t                                      m_width;
203    uint32_t                lfsr;
204
205    // the directory & lru tables
206    DirectoryEntry                              **m_dir_tab;
207    LruEntry                                    **m_lru_tab;
208
209    public:
210
211    ////////////////////////
212    // Constructor
213    ////////////////////////
214    CacheDirectory( size_t ways, size_t sets, size_t words, size_t address_width)       
215    {
216      m_ways  = ways; 
217      m_sets  = sets;
218      m_words = words;
219      m_width = address_width;
220      lfsr = -1;
221
222      m_dir_tab = new DirectoryEntry*[sets];
223      for ( size_t i=0; i<sets; i++ ) {
224        m_dir_tab[i] = new DirectoryEntry[ways];
225        for ( size_t j=0 ; j<ways ; j++) m_dir_tab[i][j].init();
226      }
227      m_lru_tab = new LruEntry*[sets];
228      for ( size_t i=0; i<sets; i++ ) {
229        m_lru_tab[i] = new LruEntry[ways];
230        for ( size_t j=0 ; j<ways ; j++) m_lru_tab[i][j].init();
231      }
232    } // end constructor
233
234    /////////////////
235    // Destructor
236    /////////////////
237    ~CacheDirectory()
238    {
239      for(size_t i=0 ; i<m_sets ; i++){
240        delete [] m_dir_tab[i];
241        delete [] m_lru_tab[i];
242      }
243      delete [] m_dir_tab;
244      delete [] m_lru_tab;
245    } // end destructor
246
247    /////////////////////////////////////////////////////////////////////
248    // The read() function reads a directory entry. In case of hit, the
249    // LRU is updated.
250    // Arguments :
251    // - address : the address of the entry
252    // - way : (return argument) the way of the entry in case of hit
253    // The function returns a copy of a (valid or invalid) entry 
254    /////////////////////////////////////////////////////////////////////
255    DirectoryEntry read(const addr_t &address, size_t &way)
256    {
257
258#define L2 soclib::common::uint32_log2
259      const size_t set = (size_t)(address >> (L2(m_words) + 2)) & (m_sets - 1);
260      const tag_t  tag = (tag_t)(address >> (L2(m_sets) + L2(m_words) + 2));
261#undef L2
262
263      bool hit       = false;
264      for ( size_t i=0 ; i<m_ways ; i++ ) {
265        bool equal = ( m_dir_tab[set][i].tag == tag );
266        bool valid = m_dir_tab[set][i].valid;
267        hit = equal && valid;
268        if ( hit ) {                   
269          way = i;
270          break;
271        } 
272      }
273      if ( hit ) {
274        m_lru_tab[set][way].recent = true;
275        return DirectoryEntry(m_dir_tab[set][way]);
276      } else {
277        return DirectoryEntry();
278      }
279    } // end read()
280
281    /////////////////////////////////////////////////////////////////////
282    // The inval function invalidate an entry defined by the set and
283    // way arguments.
284    /////////////////////////////////////////////////////////////////////
285    void inval( const size_t &way, const size_t &set )
286    {
287        m_dir_tab[set][way].init();
288    }
289
290    /////////////////////////////////////////////////////////////////////
291    // The read_neutral() function reads a directory entry, without
292    // changing the LRU
293    // Arguments :
294    // - address : the address of the entry
295    // The function returns a copy of a (valid or invalid) entry 
296    /////////////////////////////////////////////////////////////////////
297    DirectoryEntry read_neutral( const addr_t &address, 
298                                 size_t*      ret_way,
299                                 size_t*      ret_set )
300    {
301
302#define L2 soclib::common::uint32_log2
303        size_t set = (size_t)(address >> (L2(m_words) + 2)) & (m_sets - 1);
304        tag_t  tag = (tag_t)(address >> (L2(m_sets) + L2(m_words) + 2));
305#undef L2
306
307        for ( size_t way = 0 ; way < m_ways ; way++ ) 
308        {
309            bool equal = ( m_dir_tab[set][way].tag == tag );
310            bool valid = m_dir_tab[set][way].valid;
311            if ( equal and valid )
312            {
313                *ret_set = set;
314                *ret_way = way; 
315                return DirectoryEntry(m_dir_tab[set][way]);
316            }
317        } 
318        return DirectoryEntry();
319    } // end read_neutral()
320
321    /////////////////////////////////////////////////////////////////////
322    // The write function writes a new entry,
323    // and updates the LRU bits if necessary.
324    // Arguments :
325    // - set : the set of the entry
326    // - way : the way of the entry
327    // - entry : the entry value
328    /////////////////////////////////////////////////////////////////////
329    void write(const size_t &set, const size_t &way, const DirectoryEntry &entry)
330    {
331      assert( (set<m_sets) 
332          && "Cache Directory write : The set index is invalid");
333      assert( (way<m_ways) 
334          && "Cache Directory write : The way index is invalid");
335
336      // update Directory
337      m_dir_tab[set][way].copy(entry);
338
339      // update LRU bits
340      bool all_recent = true;
341      for ( size_t i=0 ; i<m_ways ; i++ ) 
342      {
343          if ( i != way ) all_recent = m_lru_tab[set][i].recent && all_recent;
344      }
345      if ( all_recent ) 
346      {
347          for( size_t i=0 ; i<m_ways ; i++ ) m_lru_tab[set][i].recent = false;
348      } 
349      else 
350      {
351          m_lru_tab[set][way].recent = true;
352      }
353    } // end write()
354
355    /////////////////////////////////////////////////////////////////////
356    // The print() function prints a selected directory entry
357    // Arguments :
358    // - set : the set of the entry to print
359    // - way : the way of the entry to print
360    /////////////////////////////////////////////////////////////////////
361    void print(const size_t &set, const size_t &way)
362    {
363      std::cout << std::dec << " set : " << set << " ; way : " << way << " ; " ;
364      m_dir_tab[set][way].print();
365    } // end print()
366
367    /////////////////////////////////////////////////////////////////////
368    // The select() function selects a directory entry to evince.
369    // Arguments :
370    // - set   : (input argument) the set to modify
371    // - way   : (return argument) the way to evince
372    /////////////////////////////////////////////////////////////////////
373    DirectoryEntry select(const size_t &set, size_t &way)
374    {
375      assert( (set < m_sets) 
376          && "Cache Directory : (select) The set index is invalid");
377
378      for(size_t i=0; i<m_ways; i++){
379        if(!m_dir_tab[set][i].valid){
380          way=i;
381          return DirectoryEntry(m_dir_tab[set][way]);
382        }
383      }
384
385#ifdef RANDOM_EVICTION
386      lfsr = (lfsr >> 1) ^ ((-(lfsr & 1)) & 0xd0000001);
387      way = lfsr % m_ways;
388      return DirectoryEntry(m_dir_tab[set][way]);
389#endif
390
391      for(size_t i=0; i<m_ways; i++){
392        if(!(m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
393          way=i;
394          return DirectoryEntry(m_dir_tab[set][way]);
395        }
396      }
397      for(size_t i=0; i<m_ways; i++){
398        if( !(m_lru_tab[set][i].recent) && (m_dir_tab[set][i].lock)){
399          way=i;
400          return DirectoryEntry(m_dir_tab[set][way]);
401        }
402      }
403      for(size_t i=0; i<m_ways; i++){
404        if( (m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
405          way=i;
406          return DirectoryEntry(m_dir_tab[set][way]);
407        }
408      }
409      way = 0;
410      return DirectoryEntry(m_dir_tab[set][0]);
411    } // end select()
412
413    /////////////////////////////////////////////////////////////////////
414    //          Global initialisation function
415    /////////////////////////////////////////////////////////////////////
416    void init()
417    {
418      for ( size_t set=0 ; set<m_sets ; set++ ) 
419      {
420        for ( size_t way=0 ; way<m_ways ; way++ ) 
421        {
422          m_dir_tab[set][way].init();
423          m_lru_tab[set][way].init();
424        }
425      }
426    } // end init()
427
428  }; // end class CacheDirectory
429
430  ///////////////////////////////////////////////////////////////////////
431  //                    A Heap Entry
432  ///////////////////////////////////////////////////////////////////////
433  class HeapEntry{
434
435    public:
436    // Fields of the entry
437      Owner     owner;
438      size_t    next;
439
440    ////////////////////////
441    // Constructor
442    ////////////////////////
443      HeapEntry()
444      :owner(false,0
445#if L1_MULTI_CACHE
446             ,0
447#endif
448             )
449      {
450        next = 0;
451      } // end constructor
452
453    ////////////////////////
454    // Constructor
455    ////////////////////////
456      HeapEntry(const HeapEntry &entry){
457        owner.inst  = entry.owner.inst;
458        owner.srcid = entry.owner.srcid;
459#if L1_MULTI_CACHE
460        owner.cache_id = entry.owner.cache_id;
461#endif       
462        next           = entry.next;
463      } // end constructor
464
465    /////////////////////////////////////////////////////////////////////
466    // The copy() function copies an existing source entry to a target
467    /////////////////////////////////////////////////////////////////////
468      void copy(const HeapEntry &entry){
469        owner.inst     = entry.owner.inst;
470        owner.srcid    = entry.owner.srcid;
471#if L1_MULTI_CACHE
472        owner.cache_id = entry.owner.cache_id;
473#endif
474        next           = entry.next;
475      } // end copy()
476
477    ////////////////////////////////////////////////////////////////////
478    // The print() function prints the entry
479    ////////////////////////////////////////////////////////////////////
480      void print(){
481        std::cout
482        << " -- owner.inst     : " << std::dec << owner.inst << std::endl
483        << " -- owner.srcid    : " << std::dec << owner.srcid << std::endl
484#if L1_MULTI_CACHE
485        << " -- owner.cache_id : " << std::dec << owner.cache_id << std::endl
486#endif
487        << " -- next           : " << std::dec << next << std::endl;
488
489      } // end print()
490
491  }; // end class HeapEntry
492
493  ////////////////////////////////////////////////////////////////////////
494  //                        The Heap
495  ////////////////////////////////////////////////////////////////////////
496  class HeapDirectory{
497   
498    private:
499    // Registers and the heap
500      size_t    ptr_free;
501      bool      full;
502      HeapEntry *m_heap_tab;
503
504    // Constants for debugging purpose
505      size_t    tab_size;
506
507    public:
508    ////////////////////////
509    // Constructor
510    ////////////////////////
511      HeapDirectory(uint32_t size){
512        assert(size>0 && "Memory Cache, HeapDirectory constructor : invalid size");
513        ptr_free    = 0;
514        full        = false;
515        m_heap_tab  = new HeapEntry[size];
516        tab_size    = size;
517      } // end constructor
518
519    /////////////////
520    // Destructor
521    /////////////////
522      ~HeapDirectory(){
523        delete [] m_heap_tab;
524      } // end destructor
525
526    /////////////////////////////////////////////////////////////////////
527    //          Global initialisation function
528    /////////////////////////////////////////////////////////////////////
529      void init(){
530        ptr_free=0;
531        full=false;
532        for(size_t i=0; i< tab_size-1;i++){
533          m_heap_tab[i].next = i+1;
534        }
535        m_heap_tab[tab_size-1].next = tab_size-1;
536        return;
537      }
538
539    /////////////////////////////////////////////////////////////////////
540    // The print() function prints a selected directory entry
541    // Arguments :
542    // - ptr : the pointer to the entry to print
543    /////////////////////////////////////////////////////////////////////
544      void print(const size_t &ptr){
545        std::cout << "Heap, printing the entry : " << std::dec << ptr << std::endl;
546        m_heap_tab[ptr].print();
547      } // end print()
548
549    /////////////////////////////////////////////////////////////////////
550    // The print_list() function prints a list from selected directory entry
551    // Arguments :
552    // - ptr : the pointer to the first entry to print
553    /////////////////////////////////////////////////////////////////////
554      void print_list(const size_t &ptr){
555        bool end = false;
556        size_t ptr_temp = ptr;
557        std::cout << "Heap, printing the list from : " << std::dec << ptr << std::endl;
558        while(!end){
559            m_heap_tab[ptr_temp].print();
560            if(ptr_temp == m_heap_tab[ptr_temp].next) end = true;
561            ptr_temp = m_heap_tab[ptr_temp].next;
562        } 
563      } // end print_list()
564
565    /////////////////////////////////////////////////////////////////////
566    // The is_full() function return true if the heap is full.
567    /////////////////////////////////////////////////////////////////////
568      bool is_full(){
569        return full;
570      } // end is_full()
571
572    /////////////////////////////////////////////////////////////////////
573    // The next_free_ptr() function returns the pointer
574    // to the next free entry.
575    /////////////////////////////////////////////////////////////////////
576      size_t next_free_ptr(){
577        return ptr_free;
578      } // end next_free_ptr()
579
580    /////////////////////////////////////////////////////////////////////
581    // The next_free_entry() function returns
582    // a copy of the next free entry.
583    /////////////////////////////////////////////////////////////////////
584      HeapEntry next_free_entry(){
585        return HeapEntry(m_heap_tab[ptr_free]);
586      } // end next_free_entry()
587   
588    /////////////////////////////////////////////////////////////////////
589    // The write_free_entry() function modify the next free entry.
590    // Arguments :
591    // - entry : the entry to write
592    /////////////////////////////////////////////////////////////////////
593      void write_free_entry(const HeapEntry &entry){
594        m_heap_tab[ptr_free].copy(entry);
595      } // end write_free_entry()
596
597    /////////////////////////////////////////////////////////////////////
598    // The write_free_ptr() function writes the pointer
599    // to the next free entry
600    /////////////////////////////////////////////////////////////////////
601      void write_free_ptr(const size_t &ptr){
602        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
603        ptr_free = ptr;
604      } // end write_free_ptr()
605
606    /////////////////////////////////////////////////////////////////////
607    // The set_full() function sets the full bit (to true).
608    /////////////////////////////////////////////////////////////////////
609      void set_full(){
610        full = true;
611      } // end set_full()
612
613    /////////////////////////////////////////////////////////////////////
614    // The unset_full() function unsets the full bit (to false).
615    /////////////////////////////////////////////////////////////////////
616      void unset_full(){
617        full = false;
618      } // end unset_full()
619
620    /////////////////////////////////////////////////////////////////////
621    // The read() function returns a copy of
622    // the entry pointed by the argument
623    // Arguments :
624    //  - ptr : the pointer to the entry to read
625    /////////////////////////////////////////////////////////////////////
626      HeapEntry read(const size_t &ptr){
627        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
628        return HeapEntry(m_heap_tab[ptr]);
629      } // end read()
630
631    /////////////////////////////////////////////////////////////////////
632    // The write() function writes an entry in the heap
633    // Arguments :
634    //  - ptr : the pointer to the entry to replace
635    //  - entry : the entry to write
636    /////////////////////////////////////////////////////////////////////
637      void write(const size_t &ptr, const HeapEntry &entry){
638        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
639        m_heap_tab[ptr].copy(entry);
640      } // end write()
641
642  }; // end class HeapDirectory
643
644  ////////////////////////////////////////////////////////////////////////
645  //                        Cache Data
646  ////////////////////////////////////////////////////////////////////////
647  class CacheData {
648    private:
649      const uint32_t m_sets;
650      const uint32_t m_ways;
651      const uint32_t m_words;
652
653      uint32_t *** m_cache_data;
654
655    public:
656
657      CacheData(uint32_t ways, uint32_t sets, uint32_t words)
658        : m_sets(sets), m_ways(ways), m_words(words) {
659
660          m_cache_data = new uint32_t ** [ways];
661          for ( size_t i=0 ; i < ways ; i++ ) {
662            m_cache_data[i] = new uint32_t * [sets];
663          }
664          for ( size_t i=0; i<ways; i++ ) {
665            for ( size_t j=0; j<sets; j++ ) {
666              m_cache_data[i][j] = new uint32_t [words];
667            }
668          }
669        }
670
671      ~CacheData() {
672          for(size_t i=0; i<m_ways ; i++){
673              for(size_t j=0; j<m_sets ; j++){
674                  delete [] m_cache_data[i][j];
675              }
676          }
677          for(size_t i=0; i<m_ways ; i++){
678              delete [] m_cache_data[i];
679          }
680          delete [] m_cache_data;
681      }
682
683      uint32_t read (
684          const uint32_t &way,
685          const uint32_t &set,
686          const uint32_t &word) const {
687
688        assert((set  < m_sets ) && "Cache data error: Trying to read a wrong set" );
689        assert((way  < m_ways ) && "Cache data error: Trying to read a wrong way" );
690        assert((word < m_words) && "Cache data error: Trying to read a wrong word");
691
692        return m_cache_data[way][set][word];
693      }
694
695      void read_line(
696          const uint32_t &way,
697          const uint32_t &set,
698          sc_core::sc_signal<uint32_t> * cache_line)
699      {
700        assert((set < m_sets ) && "Cache data error: Trying to read a wrong set" );
701        assert((way < m_ways ) && "Cache data error: Trying to read a wrong way" );
702
703        for (uint32_t word=0; word<m_words; word++)
704          cache_line[word].write(m_cache_data[way][set][word]);
705      }
706
707      void write (
708          const uint32_t &way,
709          const uint32_t &set,
710          const uint32_t &word,
711          const uint32_t &data,
712          const uint32_t &be = 0xF) {
713
714        assert((set  < m_sets ) && "Cache data error: Trying to write a wrong set" );
715        assert((way  < m_ways ) && "Cache data error: Trying to write a wrong way" );
716        assert((word < m_words) && "Cache data error: Trying to write a wrong word");
717        assert((be  <= 0xF    ) && "Cache data error: Trying to write a wrong word cell");
718
719        if (be == 0x0) return;
720
721        if (be == 0xF) {
722            m_cache_data[way][set][word] = data; 
723            return;
724        }
725
726        uint32_t mask = 0;
727        if  (be & 0x1) mask = mask | 0x000000FF;
728        if  (be & 0x2) mask = mask | 0x0000FF00;
729        if  (be & 0x4) mask = mask | 0x00FF0000;
730        if  (be & 0x8) mask = mask | 0xFF000000;
731
732        m_cache_data[way][set][word] = 
733          (data & mask) | (m_cache_data[way][set][word] & ~mask);
734      }
735  }; // end class CacheData
736
737}} // end namespaces
738
739#endif
740
741// Local Variables:
742// tab-width: 4
743// c-basic-offset: 4
744// c-file-offsets:((innamespace . 0)(inline-open . 0))
745// indent-tabs-mode: nil
746// End:
747
748// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
749
Note: See TracBrowser for help on using the repository browser.