source: branches/wt_ideal/modules/vci_mem_cache/caba/source/include/mem_cache_directory.h

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