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

Last change on this file since 215 was 212, checked in by bouyer, 12 years ago

Introduce read_neutral(), which returns a directory entry without updating
the LRU bit.
Use read_neutral() in cache_monitor(), so that it doesn't affect the
cache state

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