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