source: trunk/platforms/almos-tsarv3-platforms/common/vci_mem_cache_v3/caba/source/include/mem_cache_directory_v3.h @ 259

Last change on this file since 259 was 259, checked in by almaless, 12 years ago

Introduce ALMOS used platforms for TSAR.
See the package's README file for more information.

File size: 18.2 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(std::ostream &output)
142    {
143        output << "Valid = " << valid
144                  << " ; IS COUNT = " << is_cnt
145                  << " ; Dirty = " << dirty
146                  << " ; Lock = "  << lock
147                  << " ; Inst = " << inst
148                  << " ; Tag = " << std::hex << tag
149                  << std::dec << " ; Count = " << count
150                  << " ; Owner = " << owner.srcid << " " 
151                  << owner.inst << " ; Pointer = " << ptr << std::endl;
152    }
153
154  }; // end class DirectoryEntry
155
156  ////////////////////////////////////////////////////////////////////////
157  //                       The directory 
158  ////////////////////////////////////////////////////////////////////////
159  class CacheDirectory {
160
161    typedef sc_dt::sc_uint<40> addr_t;
162    typedef uint32_t data_t;
163    typedef uint32_t tag_t;
164    typedef uint32_t size_t;
165
166    private:
167
168    // Directory constants
169    size_t                                      m_ways;
170    size_t                                      m_sets;
171    size_t                                      m_words;
172    size_t                                      m_width;
173
174    // the directory & lru tables
175    DirectoryEntry                              **m_dir_tab;
176    LruEntry                                    **m_lru_tab;
177
178    public:
179
180    ////////////////////////
181    // Constructor
182    ////////////////////////
183    CacheDirectory( size_t ways, size_t sets, size_t words, size_t address_width)       
184    {
185      m_ways  = ways; 
186      m_sets  = sets;
187      m_words = words;
188      m_width = address_width;
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        bool equal = ( m_dir_tab[set][i].tag == tag );
234        bool valid = m_dir_tab[set][i].valid;
235        hit = equal && valid;
236        if ( hit ) {                   
237          way = i;
238          break;
239        } 
240      }
241      if ( hit ) {
242        m_lru_tab[set][way].recent = true;
243        return DirectoryEntry(m_dir_tab[set][way]);
244      } else {
245        return DirectoryEntry();
246      }
247    } // end read()
248
249    /////////////////////////////////////////////////////////////////////
250    // The write function writes a new entry,
251    // and updates the LRU bits if necessary.
252    // Arguments :
253    // - set : the set of the entry
254    // - way : the way of the entry
255    // - entry : the entry value
256    /////////////////////////////////////////////////////////////////////
257    void write(const size_t &set, const size_t &way, const DirectoryEntry &entry)
258    {
259      assert( (set<m_sets) 
260          && "Cache Directory write : The set index is invalid");
261      assert( (way<m_ways) 
262          && "Cache Directory write : The way index is invalid");
263
264      // update Directory
265      m_dir_tab[set][way].copy(entry);
266
267      // update LRU bits
268      bool all_recent = true;
269      for ( size_t i=0 ; i<m_ways ; i++ ) {
270        if ( i != way ) all_recent = m_lru_tab[set][i].recent && all_recent;
271      }
272      if ( all_recent ) {
273        for( size_t i=0 ; i<m_ways ; i++ ) m_lru_tab[set][i].recent = false;
274      } else {
275        m_lru_tab[set][way].recent = true;
276      }
277    } // end write()
278
279    /////////////////////////////////////////////////////////////////////
280    // The print() function prints a selected directory entry
281    // Arguments :
282    // - set : the set of the entry to print
283    // - way : the way of the entry to print
284    /////////////////////////////////////////////////////////////////////
285    void print(const size_t &set, const size_t &way, std::ostream &output)
286    {
287      output << std::dec << " set : " << set << " ; way : " << way << " ; " ;
288      m_dir_tab[set][way].print(output);
289    } // end print()
290
291    /////////////////////////////////////////////////////////////////////
292    // The select() function selects a directory entry to evince.
293    // Arguments :
294    // - set   : (input argument) the set to modify
295    // - way   : (return argument) the way to evince
296    /////////////////////////////////////////////////////////////////////
297    DirectoryEntry select(const size_t &set, size_t &way)
298    {
299      assert( (set < m_sets) 
300          && "Cache Directory : (select) The set index is invalid");
301
302      for(size_t i=0; i<m_ways; i++){
303        if(!m_dir_tab[set][i].valid){
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      for(size_t i=0; i<m_ways; i++){
315        if( !(m_lru_tab[set][i].recent) && (m_dir_tab[set][i].lock)){
316          way=i;
317          return DirectoryEntry(m_dir_tab[set][way]);
318        }
319      }
320      for(size_t i=0; i<m_ways; i++){
321        if( (m_lru_tab[set][i].recent) && !(m_dir_tab[set][i].lock)){
322          way=i;
323          return DirectoryEntry(m_dir_tab[set][way]);
324        }
325      }
326      way = 0;
327      return DirectoryEntry(m_dir_tab[set][0]);
328    } // end select()
329
330    /////////////////////////////////////////////////////////////////////
331    //          Global initialisation function
332    /////////////////////////////////////////////////////////////////////
333    void init()
334    {
335      for ( size_t set=0 ; set<m_sets ; set++ ) {
336        for ( size_t way=0 ; way<m_ways ; way++ ) {
337          m_dir_tab[set][way].init();
338          m_lru_tab[set][way].init();
339        }
340      }
341    } // end init()
342
343  }; // end class CacheDirectory
344
345  ///////////////////////////////////////////////////////////////////////
346  //                    A Heap Entry
347  ///////////////////////////////////////////////////////////////////////
348  class HeapEntry{
349    typedef uint32_t size_t;
350
351    public:
352    // Fields of the entry
353      Owner     owner;
354      size_t    next;
355
356    ////////////////////////
357    // Constructor
358    ////////////////////////
359      HeapEntry()
360      :owner(false,0)
361      {
362        next = 0;
363      } // end constructor
364
365    ////////////////////////
366    // Constructor
367    ////////////////////////
368      HeapEntry(const HeapEntry &entry){
369        owner.srcid = entry.owner.srcid;
370        owner.inst  = entry.owner.inst;
371        next        = entry.next;
372      } // end constructor
373
374    /////////////////////////////////////////////////////////////////////
375    // The copy() function copies an existing source entry to a target
376    /////////////////////////////////////////////////////////////////////
377      void copy(const HeapEntry &entry){
378        owner.srcid = entry.owner.srcid;
379        owner.inst  = entry.owner.inst;
380        next        = entry.next;
381      } // end copy()
382
383    ////////////////////////////////////////////////////////////////////
384    // The print() function prints the entry
385    ////////////////////////////////////////////////////////////////////
386      void print(std::ostream &output){
387        output
388        << " -- owner.srcid : " << std::dec << owner.srcid << std::endl
389        << " -- owner.inst  : " << std::dec << owner.inst << std::endl
390        << " -- next        : " << std::dec << next << std::endl;
391
392      } // end print()
393
394  }; // end class HeapEntry
395
396  ////////////////////////////////////////////////////////////////////////
397  //                        The Heap
398  ////////////////////////////////////////////////////////////////////////
399  class HeapDirectory{
400    typedef uint32_t size_t;
401   
402    private:
403    // Registers and the heap
404      size_t    ptr_free;
405      bool      full;
406      HeapEntry *m_heap_tab;
407
408    // Constants for debugging purpose
409      size_t    tab_size;
410
411    public:
412    ////////////////////////
413    // Constructor
414    ////////////////////////
415      HeapDirectory(uint32_t size){
416        assert(size>0 && "Memory Cache, HeapDirectory constructor : invalid size");
417        ptr_free    = 0;
418        full        = false;
419        m_heap_tab  = new HeapEntry[size];
420        tab_size    = size;
421      } // end constructor
422
423    /////////////////
424    // Destructor
425    /////////////////
426      ~HeapDirectory(){
427        delete [] m_heap_tab;
428      } // end destructor
429
430    /////////////////////////////////////////////////////////////////////
431    //          Global initialisation function
432    /////////////////////////////////////////////////////////////////////
433      void init(){
434        ptr_free=0;
435        full=false;
436        for(size_t i=0; i< tab_size-1;i++){
437          m_heap_tab[i].next = i+1;
438        }
439        m_heap_tab[tab_size-1].next = tab_size-1;
440        return;
441      }
442
443    /////////////////////////////////////////////////////////////////////
444    // The print() function prints a selected directory entry
445    // Arguments :
446    // - ptr : the pointer to the entry to print
447    /////////////////////////////////////////////////////////////////////
448      void print(const size_t &ptr, std::ostream &output){
449        output << "Heap, printing the entry : " << std::dec << ptr << std::endl;
450        m_heap_tab[ptr].print(output);
451      } // end print()
452
453    /////////////////////////////////////////////////////////////////////
454    // The print_list() function prints a list from selected directory entry
455    // Arguments :
456    // - ptr : the pointer to the first entry to print
457    /////////////////////////////////////////////////////////////////////
458      void print_list(const size_t &ptr, std::ostream &output){
459        bool end = false;
460        size_t ptr_temp = ptr;
461        output << "Heap, printing the list from : " << std::dec << ptr << std::endl;
462        while(!end){
463            m_heap_tab[ptr_temp].print(output);
464            if(ptr_temp == m_heap_tab[ptr_temp].next) end = true;
465            ptr_temp = m_heap_tab[ptr_temp].next;
466        } 
467      } // end print_list()
468
469
470    /////////////////////////////////////////////////////////////////////
471    // The is_full() function return true if the heap is full.
472    /////////////////////////////////////////////////////////////////////
473      bool is_full(){
474        return full;
475      } // end is_full()
476
477    /////////////////////////////////////////////////////////////////////
478    // The next_free_ptr() function returns the pointer
479    // to the next free entry.
480    /////////////////////////////////////////////////////////////////////
481      size_t next_free_ptr(){
482        return ptr_free;
483      } // end next_free_ptr()
484
485    /////////////////////////////////////////////////////////////////////
486    // The next_free_entry() function returns
487    // a copy of the next free entry.
488    /////////////////////////////////////////////////////////////////////
489      HeapEntry next_free_entry(){
490        return HeapEntry(m_heap_tab[ptr_free]);
491      } // end next_free_entry()
492   
493    /////////////////////////////////////////////////////////////////////
494    // The write_free_entry() function modify the next free entry.
495    // Arguments :
496    // - entry : the entry to write
497    /////////////////////////////////////////////////////////////////////
498      void write_free_entry(const HeapEntry &entry){
499        m_heap_tab[ptr_free].copy(entry);
500      } // end write_free_entry()
501
502    /////////////////////////////////////////////////////////////////////
503    // The write_free_ptr() function writes the pointer
504    // to the next free entry
505    /////////////////////////////////////////////////////////////////////
506      void write_free_ptr(const size_t &ptr){
507        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
508        ptr_free = ptr;
509      } // end write_free_ptr()
510
511    /////////////////////////////////////////////////////////////////////
512    // The set_full() function sets the full bit (to true).
513    /////////////////////////////////////////////////////////////////////
514      void set_full(){
515        full = true;
516      } // end set_full()
517
518    /////////////////////////////////////////////////////////////////////
519    // The unset_full() function unsets the full bit (to false).
520    /////////////////////////////////////////////////////////////////////
521      void unset_full(){
522        full = false;
523      } // end unset_full()
524
525    /////////////////////////////////////////////////////////////////////
526    // The read() function returns a copy of
527    // the entry pointed by the argument
528    // Arguments :
529    //  - ptr : the pointer to the entry to read
530    /////////////////////////////////////////////////////////////////////
531      HeapEntry read(const size_t &ptr){
532        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
533        return HeapEntry(m_heap_tab[ptr]);
534      } // end read()
535
536    /////////////////////////////////////////////////////////////////////
537    // The write() function writes an entry in the heap
538    // Arguments :
539    //  - ptr : the pointer to the entry to replace
540    //  - entry : the entry to write
541    /////////////////////////////////////////////////////////////////////
542      void write(const size_t &ptr, const HeapEntry &entry){
543        assert( (ptr<tab_size) && "HeapDirectory error : try to write a wrong free pointer");
544        m_heap_tab[ptr].copy(entry);
545      } // end write()
546
547  }; // end class HeapDirectory
548
549
550}} // end namespaces
551
552#endif
553
554// Local Variables:
555// tab-width: 4
556// c-basic-offset: 4
557// c-file-offsets:((innamespace . 0)(inline-open . 0))
558// indent-tabs-mode: nil
559// End:
560
561// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
562
Note: See TracBrowser for help on using the repository browser.