source: branches/v5/modules/vci_mem_cache/caba/source/include/mem_cache_directory.h @ 440

Last change on this file since 440 was 440, checked in by cfuguet, 11 years ago

Merging branch/v5/vci_mem_cache with trunk modifications to
start the development of new coherence protocol modifications
in this component

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