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

Last change on this file since 300 was 295, checked in by cfuguet, 12 years ago

Introducing branches/v5/ components directory. This branch
will be used to version control of new TSAR V5 which implements the
DHCCP new modifications. All components version suffixes is not used
anymore

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