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

Last change on this file since 752 was 752, checked in by meunier, 10 years ago
  • Added initialization to some components in order to avoid valgrind errors
  • Corrected two bugs which caused the simulations to be non-deterministic:
    • one in the memcache (possibly uninitialized paddr variable used for cache access, modifying LRU bits)
    • one in the run_simus.py script (replacing a file with an identical file in a hdd image does modify its size)
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    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        {
234            bool equal = ( m_dir_tab[set][i].tag == tag );
235            bool valid = m_dir_tab[set][i].valid;
236            hit        = equal && valid;
237            if ( hit ) 
238            {                   
239                way = i;
240                break;
241            } 
242        }
243        if ( hit ) 
244        {
245            m_lru_tab[set][way].recent = true;
246            return DirectoryEntry(m_dir_tab[set][way]);
247        } 
248        else 
249        {
250            return DirectoryEntry();
251        }
252    } // end read()
253
254    /////////////////////////////////////////////////////////////////////
255    // The inval function invalidate an entry defined by the set and
256    // way arguments.
257    /////////////////////////////////////////////////////////////////////
258    void inval( const size_t &way, const size_t &set )
259    {
260        m_dir_tab[set][way].init();
261    }
262
263    /////////////////////////////////////////////////////////////////////
264    // The read_neutral() function reads a directory entry, without
265    // changing the LRU
266    // Arguments :
267    // - address : the address of the entry
268    // The function returns a copy of a (valid or invalid) entry 
269    /////////////////////////////////////////////////////////////////////
270    DirectoryEntry read_neutral( const addr_t &address, 
271                                 size_t*      ret_way,
272                                 size_t*      ret_set )
273    {
274
275#define L2 soclib::common::uint32_log2
276        size_t set = (size_t)(address >> (L2(m_words) + 2)) & (m_sets - 1);
277        tag_t  tag = (tag_t)(address >> (L2(m_sets) + L2(m_words) + 2));
278#undef L2
279
280        for ( size_t way = 0 ; way < m_ways ; way++ ) 
281        {
282            bool equal = ( m_dir_tab[set][way].tag == tag );
283            bool valid = m_dir_tab[set][way].valid;
284            if ( equal and valid )
285            {
286                *ret_set = set;
287                *ret_way = way; 
288                return DirectoryEntry(m_dir_tab[set][way]);
289            }
290        } 
291        return DirectoryEntry();
292    } // end read_neutral()
293
294    /////////////////////////////////////////////////////////////////////
295    // The write function writes a new entry,
296    // and updates the LRU bits if necessary.
297    // Arguments :
298    // - set : the set of the entry
299    // - way : the way of the entry
300    // - entry : the entry value
301    /////////////////////////////////////////////////////////////////////
302    void write( const size_t         &set, 
303                const size_t         &way, 
304                const DirectoryEntry &entry)
305    {
306      assert( (set<m_sets) 
307          && "Cache Directory write : The set index is invalid");
308      assert( (way<m_ways) 
309          && "Cache Directory write : The way index is invalid");
310
311      // update Directory
312      m_dir_tab[set][way].copy(entry);
313
314      // update LRU bits
315      bool all_recent = true;
316      for ( size_t i=0 ; i<m_ways ; i++ ) 
317      {
318          if ( i != way ) all_recent = m_lru_tab[set][i].recent && all_recent;
319      }
320      if ( all_recent ) 
321      {
322          for( size_t i=0 ; i<m_ways ; i++ ) m_lru_tab[set][i].recent = false;
323      } 
324      else 
325      {
326          m_lru_tab[set][way].recent = true;
327      }
328    } // end write()
329
330    /////////////////////////////////////////////////////////////////////
331    // The print() function prints a selected directory entry
332    // Arguments :
333    // - set : the set of the entry to print
334    // - way : the way of the entry to print
335    /////////////////////////////////////////////////////////////////////
336    void print(const size_t &set, const size_t &way)
337    {
338      std::cout << std::dec << " set : " << set << " ; way : " << way << " ; " ;
339      m_dir_tab[set][way].print();
340    } // end print()
341
342    /////////////////////////////////////////////////////////////////////
343    // The select() function selects a directory entry to evince.
344    // Arguments :
345    // - set   : (input argument) the set to modify
346    // - way   : (return argument) the way to evince
347    /////////////////////////////////////////////////////////////////////
348    DirectoryEntry select(const size_t &set, size_t &way)
349    {
350        assert( (set < m_sets) 
351          && "Cache Directory : (select) The set index is invalid");
352
353        // looking for an empty slot
354        for(size_t i=0; i<m_ways; i++)
355        {
356            if( not m_dir_tab[set][i].valid )
357            {
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        // looking for a not locked and not recently used entry
370        for(size_t i=0; i<m_ways; i++)
371        {
372            if((not m_lru_tab[set][i].recent) && (not m_dir_tab[set][i].lock) )
373            {
374                way=i;
375                return DirectoryEntry(m_dir_tab[set][way]);
376            }
377        }
378
379        // looking for a locked not recently used entry
380        for(size_t i=0; i<m_ways; i++)
381        {
382            if( (not m_lru_tab[set][i].recent) && (m_dir_tab[set][i].lock))
383            {
384                way=i;
385                return DirectoryEntry(m_dir_tab[set][way]);
386            }
387        }
388
389        // looking for a recently used entry not locked
390        for(size_t i=0; i<m_ways; i++)
391        {
392            if( (m_lru_tab[set][i].recent) && (not m_dir_tab[set][i].lock))
393            {
394                way=i;
395                return DirectoryEntry(m_dir_tab[set][way]);
396            }
397        }
398
399        // select way 0 (even if entry is locked and recently used)
400        way = 0;
401        return DirectoryEntry(m_dir_tab[set][0]);
402    } // end select()
403
404    /////////////////////////////////////////////////////////////////////
405    //          Global initialisation function
406    /////////////////////////////////////////////////////////////////////
407    void init()
408    {
409      for ( size_t set=0 ; set<m_sets ; set++ ) 
410      {
411        for ( size_t way=0 ; way<m_ways ; way++ ) 
412        {
413          m_dir_tab[set][way].init();
414          m_lru_tab[set][way].init();
415        }
416      }
417    } // end init()
418
419  }; // end class CacheDirectory
420
421  ///////////////////////////////////////////////////////////////////////
422  //                    A Heap Entry
423  ///////////////////////////////////////////////////////////////////////
424  class HeapEntry{
425
426    public:
427    // Fields of the entry
428      Owner     owner;
429      size_t    next;
430
431    ////////////////////////
432    // Constructor
433    ////////////////////////
434      HeapEntry()
435      :owner(false,0)
436      {
437        next = 0;
438      } // end constructor
439
440    ////////////////////////
441    // Constructor
442    ////////////////////////
443      HeapEntry(const HeapEntry &entry)
444      {
445        owner.inst  = entry.owner.inst;
446        owner.srcid = entry.owner.srcid;
447        next           = entry.next;
448      } // end constructor
449
450    /////////////////////////////////////////////////////////////////////
451    // The copy() function copies an existing source entry to a target
452    /////////////////////////////////////////////////////////////////////
453      void copy(const HeapEntry &entry)
454      {
455        owner.inst     = entry.owner.inst;
456        owner.srcid    = entry.owner.srcid;
457        next           = entry.next;
458      } // end copy()
459
460    ////////////////////////////////////////////////////////////////////
461    // The print() function prints the entry
462    ////////////////////////////////////////////////////////////////////
463      void print(){
464        std::cout
465        << " -- owner.inst     : " << std::dec << owner.inst << std::endl
466        << " -- owner.srcid    : " << std::dec << owner.srcid << std::endl
467        << " -- next           : " << std::dec << next << std::endl;
468
469      } // end print()
470
471  }; // end class HeapEntry
472
473  ////////////////////////////////////////////////////////////////////////
474  //                        The Heap
475  ////////////////////////////////////////////////////////////////////////
476  class HeapDirectory{
477   
478    private:
479    // Registers and the heap
480      size_t    ptr_free;
481      bool      full;
482      HeapEntry *m_heap_tab;
483
484    // Constants for debugging purpose
485      size_t    tab_size;
486
487    public:
488    ////////////////////////
489    // Constructor
490    ////////////////////////
491      HeapDirectory(uint32_t size){
492        assert(size>0 && "Memory Cache, HeapDirectory constructor : invalid size");
493        ptr_free    = 0;
494        full        = false;
495        m_heap_tab  = new HeapEntry[size];
496        tab_size    = size;
497      } // end constructor
498
499    /////////////////
500    // Destructor
501    /////////////////
502      ~HeapDirectory(){
503        delete [] m_heap_tab;
504      } // end destructor
505
506    /////////////////////////////////////////////////////////////////////
507    //          Global initialisation function
508    /////////////////////////////////////////////////////////////////////
509      void init(){
510        ptr_free=0;
511        full=false;
512        for(size_t i=0; i< tab_size-1;i++){
513          m_heap_tab[i].next = i+1;
514        }
515        m_heap_tab[tab_size-1].next = tab_size-1;
516        return;
517      }
518
519    /////////////////////////////////////////////////////////////////////
520    // The print() function prints a selected directory entry
521    // Arguments :
522    // - ptr : the pointer to the entry to print
523    /////////////////////////////////////////////////////////////////////
524      void print(const size_t &ptr){
525        std::cout << "Heap, printing the entry : " << std::dec << ptr << std::endl;
526        m_heap_tab[ptr].print();
527      } // end print()
528
529    /////////////////////////////////////////////////////////////////////
530    // The print_list() function prints a list from selected directory entry
531    // Arguments :
532    // - ptr : the pointer to the first entry to print
533    /////////////////////////////////////////////////////////////////////
534      void print_list(const size_t &ptr){
535        bool end = false;
536        size_t ptr_temp = ptr;
537        std::cout << "Heap, printing the list from : " << std::dec << ptr << std::endl;
538        while(!end){
539            m_heap_tab[ptr_temp].print();
540            if(ptr_temp == m_heap_tab[ptr_temp].next) end = true;
541            ptr_temp = m_heap_tab[ptr_temp].next;
542        } 
543      } // end print_list()
544
545    /////////////////////////////////////////////////////////////////////
546    // The is_full() function return true if the heap is full.
547    /////////////////////////////////////////////////////////////////////
548      bool is_full(){
549        return full;
550      } // end is_full()
551
552    /////////////////////////////////////////////////////////////////////
553    // The next_free_ptr() function returns the pointer
554    // to the next free entry.
555    /////////////////////////////////////////////////////////////////////
556      size_t next_free_ptr(){
557        return ptr_free;
558      } // end next_free_ptr()
559
560    /////////////////////////////////////////////////////////////////////
561    // The next_free_entry() function returns
562    // a copy of the next free entry.
563    /////////////////////////////////////////////////////////////////////
564      HeapEntry next_free_entry(){
565        return HeapEntry(m_heap_tab[ptr_free]);
566      } // end next_free_entry()
567   
568    /////////////////////////////////////////////////////////////////////
569    // The write_free_entry() function modify the next free entry.
570    // Arguments :
571    // - entry : the entry to write
572    /////////////////////////////////////////////////////////////////////
573      void write_free_entry(const HeapEntry &entry){
574        m_heap_tab[ptr_free].copy(entry);
575      } // end write_free_entry()
576
577    /////////////////////////////////////////////////////////////////////
578    // The write_free_ptr() function writes the pointer
579    // to the next free entry
580    /////////////////////////////////////////////////////////////////////
581      void write_free_ptr(const size_t &ptr){
582        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
583        ptr_free = ptr;
584      } // end write_free_ptr()
585
586    /////////////////////////////////////////////////////////////////////
587    // The set_full() function sets the full bit (to true).
588    /////////////////////////////////////////////////////////////////////
589      void set_full(){
590        full = true;
591      } // end set_full()
592
593    /////////////////////////////////////////////////////////////////////
594    // The unset_full() function unsets the full bit (to false).
595    /////////////////////////////////////////////////////////////////////
596      void unset_full(){
597        full = false;
598      } // end unset_full()
599
600    /////////////////////////////////////////////////////////////////////
601    // The read() function returns a copy of
602    // the entry pointed by the argument
603    // Arguments :
604    //  - ptr : the pointer to the entry to read
605    /////////////////////////////////////////////////////////////////////
606      HeapEntry read(const size_t &ptr){
607        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
608        return HeapEntry(m_heap_tab[ptr]);
609      } // end read()
610
611    /////////////////////////////////////////////////////////////////////
612    // The write() function writes an entry in the heap
613    // Arguments :
614    //  - ptr : the pointer to the entry to replace
615    //  - entry : the entry to write
616    /////////////////////////////////////////////////////////////////////
617      void write(const size_t &ptr, const HeapEntry &entry){
618        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
619        m_heap_tab[ptr].copy(entry);
620      } // end write()
621
622  }; // end class HeapDirectory
623
624  ////////////////////////////////////////////////////////////////////////
625  //                        Cache Data
626  ////////////////////////////////////////////////////////////////////////
627  class CacheData
628  {
629    private:
630      const uint32_t m_sets;
631      const uint32_t m_ways;
632      const uint32_t m_words;
633
634      uint32_t *** m_cache_data;
635
636    public:
637
638      ///////////////////////////////////////////////////////
639      CacheData(uint32_t ways, uint32_t sets, uint32_t words)
640        : m_sets(sets), m_ways(ways), m_words(words) 
641      {
642          m_cache_data = new uint32_t ** [ways];
643          for ( size_t i=0 ; i < ways ; i++ ) 
644          {
645              m_cache_data[i] = new uint32_t * [sets];
646          }
647          for ( size_t i=0; i<ways; i++ ) 
648          {
649              for ( size_t j=0; j<sets; j++ ) 
650              {
651                  m_cache_data[i][j] = new uint32_t [words];
652                  // Init to avoid potential errors from memory checkers
653                  std::memset(m_cache_data[i][j], 0, sizeof(uint32_t) * words);
654              }
655          }
656      }
657      ////////////
658      ~CacheData() 
659      {
660          for(size_t i=0; i<m_ways ; i++)
661          {
662              for(size_t j=0; j<m_sets ; j++)
663              {
664                  delete [] m_cache_data[i][j];
665              }
666          }
667          for(size_t i=0; i<m_ways ; i++)
668          {
669              delete [] m_cache_data[i];
670          }
671          delete [] m_cache_data;
672      }
673      //////////////////////////////////////////
674      uint32_t read ( const uint32_t &way,
675                      const uint32_t &set,
676                      const uint32_t &word) const 
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          assert((word < m_words) && "Cache data error: Trying to read a wrong word");
681
682          return m_cache_data[way][set][word];
683      }
684      //////////////////////////////////////////
685      void read_line( const uint32_t &way,
686                      const uint32_t &set,
687                      sc_core::sc_signal<uint32_t> * cache_line)
688      {
689          assert((set < m_sets ) && "Cache data error: Trying to read a wrong set" );
690          assert((way < m_ways ) && "Cache data error: Trying to read a wrong way" );
691
692          for (uint32_t word=0; word<m_words; word++)
693              cache_line[word].write(m_cache_data[way][set][word]);
694      }
695      /////////////////////////////////////////
696      void write ( const uint32_t &way,
697                   const uint32_t &set,
698                   const uint32_t &word,
699                   const uint32_t &data,
700                   const uint32_t &be = 0xF) 
701      {
702
703          assert((set  < m_sets ) && "Cache data error: Trying to write a wrong set" );
704          assert((way  < m_ways ) && "Cache data error: Trying to write a wrong way" );
705          assert((word < m_words) && "Cache data error: Trying to write a wrong word");
706          assert((be  <= 0xF    ) && "Cache data error: Trying to write a wrong be");
707
708          if (be == 0x0) return;
709
710          if (be == 0xF) 
711          {
712              m_cache_data[way][set][word] = data; 
713              return;
714          }
715
716          uint32_t mask = 0;
717          if  (be & 0x1) mask = mask | 0x000000FF;
718          if  (be & 0x2) mask = mask | 0x0000FF00;
719          if  (be & 0x4) mask = mask | 0x00FF0000;
720          if  (be & 0x8) mask = mask | 0xFF000000;
721
722          m_cache_data[way][set][word] = 
723              (data & mask) | (m_cache_data[way][set][word] & ~mask);
724      }
725  }; // end class CacheData
726
727}} // end namespaces
728
729#endif
730
731// Local Variables:
732// tab-width: 4
733// c-basic-offset: 4
734// c-file-offsets:((innamespace . 0)(inline-open . 0))
735// indent-tabs-mode: nil
736// End:
737
738// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
739
Note: See TracBrowser for help on using the repository browser.