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

Last change on this file since 455 was 455, checked in by cfuguet, 10 years ago

Merged

/trunk/modules/vci_mem_cache:449 with
/branches/v5/modules/vci_mem_cache:446.

This merge introduces into the branch the last modifications concerning
the VCI memory cache configuration interface

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