source: trunk/modules/vci_mem_cache/caba/source/include/mem_cache_directory.h @ 385

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

VCI port to XRAM switched to DATA == 64 bits
=> two template parameters vci_param_int & vci_param_ext
This has been validated in tsar_generic_xbar platform...

File size: 23.0 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 read_neutral() function reads a directory entry, without
277    // changing the LRU
278    // Arguments :
279    // - address : the address of the entry
280    // The function returns a copy of a (valid or invalid) entry 
281    /////////////////////////////////////////////////////////////////////
282    DirectoryEntry read_neutral(const addr_t &address)
283    {
284
285#define L2 soclib::common::uint32_log2
286      const size_t set = (size_t)(address >> (L2(m_words) + 2)) & (m_sets - 1);
287      const tag_t  tag = (tag_t)(address >> (L2(m_sets) + L2(m_words) + 2));
288#undef L2
289
290      bool hit       = false;
291      for ( size_t i=0 ; i<m_ways ; i++ ) {
292        bool equal = ( m_dir_tab[set][i].tag == tag );
293        bool valid = m_dir_tab[set][i].valid;
294        hit = equal && valid;
295        if ( hit ) {                   
296          return DirectoryEntry(m_dir_tab[set][i]);
297        } 
298      }
299      return DirectoryEntry();
300    } // end read_neutral()
301
302    /////////////////////////////////////////////////////////////////////
303    // The write function writes a new entry,
304    // and updates the LRU bits if necessary.
305    // Arguments :
306    // - set : the set of the entry
307    // - way : the way of the entry
308    // - entry : the entry value
309    /////////////////////////////////////////////////////////////////////
310    void write(const size_t &set, const size_t &way, const DirectoryEntry &entry)
311    {
312      assert( (set<m_sets) 
313          && "Cache Directory write : The set index is invalid");
314      assert( (way<m_ways) 
315          && "Cache Directory write : The way index is invalid");
316
317      // update Directory
318      m_dir_tab[set][way].copy(entry);
319
320      // update LRU bits
321      bool all_recent = true;
322      for ( size_t i=0 ; i<m_ways ; i++ ) {
323        if ( i != way ) all_recent = m_lru_tab[set][i].recent && all_recent;
324      }
325      if ( all_recent ) {
326        for( size_t i=0 ; i<m_ways ; i++ ) m_lru_tab[set][i].recent = false;
327      } else {
328        m_lru_tab[set][way].recent = true;
329      }
330    } // end write()
331
332    /////////////////////////////////////////////////////////////////////
333    // The print() function prints a selected directory entry
334    // Arguments :
335    // - set : the set of the entry to print
336    // - way : the way of the entry to print
337    /////////////////////////////////////////////////////////////////////
338    void print(const size_t &set, const size_t &way)
339    {
340      std::cout << std::dec << " set : " << set << " ; way : " << way << " ; " ;
341      m_dir_tab[set][way].print();
342    } // end print()
343
344    /////////////////////////////////////////////////////////////////////
345    // The select() function selects a directory entry to evince.
346    // Arguments :
347    // - set   : (input argument) the set to modify
348    // - way   : (return argument) the way to evince
349    /////////////////////////////////////////////////////////////////////
350    DirectoryEntry select(const size_t &set, size_t &way)
351    {
352      assert( (set < m_sets) 
353          && "Cache Directory : (select) The set index is invalid");
354
355      for(size_t i=0; i<m_ways; i++){
356        if(!m_dir_tab[set][i].valid){
357          way=i;
358          return DirectoryEntry(m_dir_tab[set][way]);
359        }
360      }
361
362#ifdef RANDOM_EVICTION
363      lfsr = (lfsr >> 1) ^ ((-(lfsr & 1)) & 0xd0000001);
364      way = lfsr % m_ways;
365      return DirectoryEntry(m_dir_tab[set][way]);
366#endif
367
368      for(size_t i=0; i<m_ways; i++){
369        if(!(m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
370          way=i;
371          return DirectoryEntry(m_dir_tab[set][way]);
372        }
373      }
374      for(size_t i=0; i<m_ways; i++){
375        if( !(m_lru_tab[set][i].recent) && (m_dir_tab[set][i].lock)){
376          way=i;
377          return DirectoryEntry(m_dir_tab[set][way]);
378        }
379      }
380      for(size_t i=0; i<m_ways; i++){
381        if( (m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
382          way=i;
383          return DirectoryEntry(m_dir_tab[set][way]);
384        }
385      }
386      way = 0;
387      return DirectoryEntry(m_dir_tab[set][0]);
388    } // end select()
389
390    /////////////////////////////////////////////////////////////////////
391    //          Global initialisation function
392    /////////////////////////////////////////////////////////////////////
393    void init()
394    {
395      for ( size_t set=0 ; set<m_sets ; set++ ) {
396        for ( size_t way=0 ; way<m_ways ; way++ ) {
397          m_dir_tab[set][way].init();
398          m_lru_tab[set][way].init();
399        }
400      }
401    } // end init()
402
403  }; // end class CacheDirectory
404
405  ///////////////////////////////////////////////////////////////////////
406  //                    A Heap Entry
407  ///////////////////////////////////////////////////////////////////////
408  class HeapEntry{
409
410    public:
411    // Fields of the entry
412      Owner     owner;
413      size_t    next;
414
415    ////////////////////////
416    // Constructor
417    ////////////////////////
418      HeapEntry()
419      :owner(false,0
420#if L1_MULTI_CACHE
421             ,0
422#endif
423             )
424      {
425        next = 0;
426      } // end constructor
427
428    ////////////////////////
429    // Constructor
430    ////////////////////////
431      HeapEntry(const HeapEntry &entry){
432        owner.inst  = entry.owner.inst;
433        owner.srcid = entry.owner.srcid;
434#if L1_MULTI_CACHE
435        owner.cache_id = entry.owner.cache_id;
436#endif       
437        next           = entry.next;
438      } // end constructor
439
440    /////////////////////////////////////////////////////////////////////
441    // The copy() function copies an existing source entry to a target
442    /////////////////////////////////////////////////////////////////////
443      void copy(const HeapEntry &entry){
444        owner.inst     = entry.owner.inst;
445        owner.srcid    = entry.owner.srcid;
446#if L1_MULTI_CACHE
447        owner.cache_id = entry.owner.cache_id;
448#endif
449        next           = entry.next;
450      } // end copy()
451
452    ////////////////////////////////////////////////////////////////////
453    // The print() function prints the entry
454    ////////////////////////////////////////////////////////////////////
455      void print(){
456        std::cout
457        << " -- owner.inst     : " << std::dec << owner.inst << std::endl
458        << " -- owner.srcid    : " << std::dec << owner.srcid << std::endl
459#if L1_MULTI_CACHE
460        << " -- owner.cache_id : " << std::dec << owner.cache_id << std::endl
461#endif
462        << " -- next           : " << std::dec << next << std::endl;
463
464      } // end print()
465
466  }; // end class HeapEntry
467
468  ////////////////////////////////////////////////////////////////////////
469  //                        The Heap
470  ////////////////////////////////////////////////////////////////////////
471  class HeapDirectory{
472   
473    private:
474    // Registers and the heap
475      size_t    ptr_free;
476      bool      full;
477      HeapEntry *m_heap_tab;
478
479    // Constants for debugging purpose
480      size_t    tab_size;
481
482    public:
483    ////////////////////////
484    // Constructor
485    ////////////////////////
486      HeapDirectory(uint32_t size){
487        assert(size>0 && "Memory Cache, HeapDirectory constructor : invalid size");
488        ptr_free    = 0;
489        full        = false;
490        m_heap_tab  = new HeapEntry[size];
491        tab_size    = size;
492      } // end constructor
493
494    /////////////////
495    // Destructor
496    /////////////////
497      ~HeapDirectory(){
498        delete [] m_heap_tab;
499      } // end destructor
500
501    /////////////////////////////////////////////////////////////////////
502    //          Global initialisation function
503    /////////////////////////////////////////////////////////////////////
504      void init(){
505        ptr_free=0;
506        full=false;
507        for(size_t i=0; i< tab_size-1;i++){
508          m_heap_tab[i].next = i+1;
509        }
510        m_heap_tab[tab_size-1].next = tab_size-1;
511        return;
512      }
513
514    /////////////////////////////////////////////////////////////////////
515    // The print() function prints a selected directory entry
516    // Arguments :
517    // - ptr : the pointer to the entry to print
518    /////////////////////////////////////////////////////////////////////
519      void print(const size_t &ptr){
520        std::cout << "Heap, printing the entry : " << std::dec << ptr << std::endl;
521        m_heap_tab[ptr].print();
522      } // end print()
523
524    /////////////////////////////////////////////////////////////////////
525    // The print_list() function prints a list from selected directory entry
526    // Arguments :
527    // - ptr : the pointer to the first entry to print
528    /////////////////////////////////////////////////////////////////////
529      void print_list(const size_t &ptr){
530        bool end = false;
531        size_t ptr_temp = ptr;
532        std::cout << "Heap, printing the list from : " << std::dec << ptr << std::endl;
533        while(!end){
534            m_heap_tab[ptr_temp].print();
535            if(ptr_temp == m_heap_tab[ptr_temp].next) end = true;
536            ptr_temp = m_heap_tab[ptr_temp].next;
537        } 
538      } // end print_list()
539
540    /////////////////////////////////////////////////////////////////////
541    // The is_full() function return true if the heap is full.
542    /////////////////////////////////////////////////////////////////////
543      bool is_full(){
544        return full;
545      } // end is_full()
546
547    /////////////////////////////////////////////////////////////////////
548    // The next_free_ptr() function returns the pointer
549    // to the next free entry.
550    /////////////////////////////////////////////////////////////////////
551      size_t next_free_ptr(){
552        return ptr_free;
553      } // end next_free_ptr()
554
555    /////////////////////////////////////////////////////////////////////
556    // The next_free_entry() function returns
557    // a copy of the next free entry.
558    /////////////////////////////////////////////////////////////////////
559      HeapEntry next_free_entry(){
560        return HeapEntry(m_heap_tab[ptr_free]);
561      } // end next_free_entry()
562   
563    /////////////////////////////////////////////////////////////////////
564    // The write_free_entry() function modify the next free entry.
565    // Arguments :
566    // - entry : the entry to write
567    /////////////////////////////////////////////////////////////////////
568      void write_free_entry(const HeapEntry &entry){
569        m_heap_tab[ptr_free].copy(entry);
570      } // end write_free_entry()
571
572    /////////////////////////////////////////////////////////////////////
573    // The write_free_ptr() function writes the pointer
574    // to the next free entry
575    /////////////////////////////////////////////////////////////////////
576      void write_free_ptr(const size_t &ptr){
577        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
578        ptr_free = ptr;
579      } // end write_free_ptr()
580
581    /////////////////////////////////////////////////////////////////////
582    // The set_full() function sets the full bit (to true).
583    /////////////////////////////////////////////////////////////////////
584      void set_full(){
585        full = true;
586      } // end set_full()
587
588    /////////////////////////////////////////////////////////////////////
589    // The unset_full() function unsets the full bit (to false).
590    /////////////////////////////////////////////////////////////////////
591      void unset_full(){
592        full = false;
593      } // end unset_full()
594
595    /////////////////////////////////////////////////////////////////////
596    // The read() function returns a copy of
597    // the entry pointed by the argument
598    // Arguments :
599    //  - ptr : the pointer to the entry to read
600    /////////////////////////////////////////////////////////////////////
601      HeapEntry read(const size_t &ptr){
602        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
603        return HeapEntry(m_heap_tab[ptr]);
604      } // end read()
605
606    /////////////////////////////////////////////////////////////////////
607    // The write() function writes an entry in the heap
608    // Arguments :
609    //  - ptr : the pointer to the entry to replace
610    //  - entry : the entry to write
611    /////////////////////////////////////////////////////////////////////
612      void write(const size_t &ptr, const HeapEntry &entry){
613        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
614        m_heap_tab[ptr].copy(entry);
615      } // end write()
616
617  }; // end class HeapDirectory
618
619  ////////////////////////////////////////////////////////////////////////
620  //                        Cache Data
621  ////////////////////////////////////////////////////////////////////////
622  class CacheData {
623    private:
624      const uint32_t m_sets;
625      const uint32_t m_ways;
626      const uint32_t m_words;
627
628      uint32_t *** m_cache_data;
629
630    public:
631
632      CacheData(uint32_t ways, uint32_t sets, uint32_t words)
633        : m_sets(sets), m_ways(ways), m_words(words) {
634
635          m_cache_data = new uint32_t ** [ways];
636          for ( size_t i=0 ; i < ways ; i++ ) {
637            m_cache_data[i] = new uint32_t * [sets];
638          }
639          for ( size_t i=0; i<ways; i++ ) {
640            for ( size_t j=0; j<sets; j++ ) {
641              m_cache_data[i][j] = new uint32_t [words];
642            }
643          }
644        }
645
646      ~CacheData() {
647          for(size_t i=0; i<m_ways ; i++){
648              for(size_t j=0; j<m_sets ; j++){
649                  delete [] m_cache_data[i][j];
650              }
651          }
652          for(size_t i=0; i<m_ways ; i++){
653              delete [] m_cache_data[i];
654          }
655          delete [] m_cache_data;
656      }
657
658      uint32_t read (
659          const uint32_t &way,
660          const uint32_t &set,
661          const uint32_t &word) const {
662
663        assert((set  < m_sets ) && "Cache data error: Trying to read a wrong set" );
664        assert((way  < m_ways ) && "Cache data error: Trying to read a wrong way" );
665        assert((word < m_words) && "Cache data error: Trying to read a wrong word");
666
667        return m_cache_data[way][set][word];
668      }
669
670      void read_line(
671          const uint32_t &way,
672          const uint32_t &set,
673          sc_core::sc_signal<uint32_t> * cache_line)
674      {
675        assert((set < m_sets ) && "Cache data error: Trying to read a wrong set" );
676        assert((way < m_ways ) && "Cache data error: Trying to read a wrong way" );
677     
678        for (uint32_t word=0; word<m_words; word++)
679          cache_line[word].write(m_cache_data[way][set][word]);
680      }
681
682      void write (
683          const uint32_t &way,
684          const uint32_t &set,
685          const uint32_t &word,
686          const uint32_t &data,
687          const uint32_t &be = 0xF) {
688
689        assert((set  < m_sets ) && "Cache data error: Trying to write a wrong set" );
690        assert((way  < m_ways ) && "Cache data error: Trying to write a wrong way" );
691        assert((word < m_words) && "Cache data error: Trying to write a wrong word");
692        assert((be  <= 0xF    ) && "Cache data error: Trying to write a wrong word cell");
693
694        if (be == 0x0) return;
695
696        if (be == 0xF) {
697            m_cache_data[way][set][word] = data; 
698            return;
699        }
700
701        uint32_t mask = 0;
702        if  (be & 0x1) mask = mask | 0x000000FF;
703        if  (be & 0x2) mask = mask | 0x0000FF00;
704        if  (be & 0x4) mask = mask | 0x00FF0000;
705        if  (be & 0x8) mask = mask | 0xFF000000;
706
707        m_cache_data[way][set][word] = 
708          (data & mask) | (m_cache_data[way][set][word] & ~mask);
709      }
710  }; // end class CacheData
711
712}} // end namespaces
713
714#endif
715
716// Local Variables:
717// tab-width: 4
718// c-basic-offset: 4
719// c-file-offsets:((innamespace . 0)(inline-open . 0))
720// indent-tabs-mode: nil
721// End:
722
723// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
724
Note: See TracBrowser for help on using the repository browser.