source: trunk/modules/vci_mem_cache/caba/source/include/mem_cache_directory.h @ 489

Last change on this file since 489 was 489, checked in by alain, 11 years ago

Implement both the SYNC and INVAL configuration commands.
Uses the TRT to transmit the cache line to XRAM in cPUT transactions.
Improve the debug.

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