source: branches/RWT/modules/vci_mem_cache/caba/source/include/mem_cache_directory.h @ 780

Last change on this file since 780 was 495, checked in by haoliu, 11 years ago

This version for RWT has merged with the lastest version of classic tsar.
It pass the test with giet_vm.

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