source: trunk/modules/vci_mem_cache_v3/caba/source/include/mem_cache_directory_v3.h @ 2

Last change on this file since 2 was 2, checked in by nipo, 14 years ago

Import TSAR modules in TSAR's own svn

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