source: branches/reconfiguration/modules/vci_mem_cache/caba/source/include/mem_cache_directory.h @ 915

Last change on this file since 915 was 861, checked in by cfuguet, 9 years ago

reconf: creating branch for the vci_mem_cache module

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