source: trunk/modules/vci_mem_cache_v4/caba/source/include/mem_cache_directory_v4.h @ 289

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

Introducing cache data ram with bit masking in the Memory Cache.
The goal of this modifications is the alignment of the SOCLIB model
against the VHDL one.

Due to this new property in the Cache Data of the Memory Cache,
the FSM's of this component do not need to read and then write when
doing a not full word write operation.

  • 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_V4_H
2#define SOCLIB_CABA_MEM_CACHE_DIRECTORY_V4_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.