source: branches/RWT/modules/vci_mem_cache/caba/source/include/mem_cache_directory.h @ 823

Last change on this file since 823 was 823, checked in by devigne, 10 years ago

RWT Commit : Cosmetic

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