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

Last change on this file since 57 was 57, checked in by guthmull, 14 years ago

Fix a bug with uncached reads, add more debug capabilities

  • 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.7 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][i].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 print_list() function prints a list from selected directory entry
443    // Arguments :
444    // - ptr : the pointer to the first entry to print
445    /////////////////////////////////////////////////////////////////////
446      void print_list(const size_t &ptr){
447        bool end = false;
448        size_t ptr_temp = ptr;
449        std::cout << "Heap, printing the list from : " << std::dec << ptr << std::endl;
450        while(!end){
451            m_heap_tab[ptr_temp].print();
452            if(ptr_temp == m_heap_tab[ptr_temp].next) end = true;
453            ptr_temp = m_heap_tab[ptr_temp].next;
454        }
455      } // end print_list()
456
457    /////////////////////////////////////////////////////////////////////
458    // The is_full() function return true if the heap is full.
459    /////////////////////////////////////////////////////////////////////
460      bool is_full(){
461        return full;
462      } // end is_full()
463
464    /////////////////////////////////////////////////////////////////////
465    // The next_free_ptr() function returns the pointer
466    // to the next free entry.
467    /////////////////////////////////////////////////////////////////////
468      size_t next_free_ptr(){
469        return ptr_free;
470      } // end next_free_ptr()
471
472    /////////////////////////////////////////////////////////////////////
473    // The next_free_entry() function returns
474    // a copy of the next free entry.
475    /////////////////////////////////////////////////////////////////////
476      HeapEntry next_free_entry(){
477        return HeapEntry(m_heap_tab[ptr_free]);
478      } // end next_free_entry()
479   
480    /////////////////////////////////////////////////////////////////////
481    // The write_free_entry() function modify the next free entry.
482    // Arguments :
483    // - entry : the entry to write
484    /////////////////////////////////////////////////////////////////////
485      void write_free_entry(const HeapEntry &entry){
486        m_heap_tab[ptr_free].copy(entry);
487      } // end write_free_entry()
488
489    /////////////////////////////////////////////////////////////////////
490    // The write_free_ptr() function writes the pointer
491    // to the next free entry
492    /////////////////////////////////////////////////////////////////////
493      void write_free_ptr(const size_t &ptr){
494        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
495        ptr_free = ptr;
496      } // end write_free_ptr()
497
498    /////////////////////////////////////////////////////////////////////
499    // The set_full() function sets the full bit (to true).
500    /////////////////////////////////////////////////////////////////////
501      void set_full(){
502        full = true;
503      } // end set_full()
504
505    /////////////////////////////////////////////////////////////////////
506    // The unset_full() function unsets the full bit (to false).
507    /////////////////////////////////////////////////////////////////////
508      void unset_full(){
509        full = false;
510      } // end unset_full()
511
512    /////////////////////////////////////////////////////////////////////
513    // The read() function returns a copy of
514    // the entry pointed by the argument
515    // Arguments :
516    //  - ptr : the pointer to the entry to read
517    /////////////////////////////////////////////////////////////////////
518      HeapEntry read(const size_t &ptr){
519        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
520        return HeapEntry(m_heap_tab[ptr]);
521      } // end read()
522
523    /////////////////////////////////////////////////////////////////////
524    // The write() function writes an entry in the heap
525    // Arguments :
526    //  - ptr : the pointer to the entry to replace
527    //  - entry : the entry to write
528    /////////////////////////////////////////////////////////////////////
529      void write(const size_t &ptr, const HeapEntry &entry){
530        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
531        m_heap_tab[ptr].copy(entry);
532      } // end write()
533
534  }; // end class HeapDirectory
535
536
537}} // end namespaces
538
539#endif
540
541// Local Variables:
542// tab-width: 4
543// c-basic-offset: 4
544// c-file-offsets:((innamespace . 0)(inline-open . 0))
545// indent-tabs-mode: nil
546// End:
547
548// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
549
Note: See TracBrowser for help on using the repository browser.