source: branches/ODCCP/modules/vci_mem_cache/caba/source/include/mem_cache_directory.h @ 544

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

ODCCP merge the components with the version 543 in trunk.

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