source: branches/v4/platforms/almos-tsarv3-platforms/common/generic_tlb/include/generic_tlb.h

Last change on this file 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: 39.6 KB
Line 
1/*****************************************************************
2 * File         : generic_tlb_40bits.h
3 * Date         : 02/06/2009
4 * Authors      : Alain Greiner, Yang GAO
5 * Copyright    : UPMC/LIP6
6 *
7 * This file is distributed under the LGPL licence agreement.
8 ******************************************************************
9 * This object is a generic TLB (Translation Lookaside Buffer) to
10 * translate a 40 bits physical address for Hypertransport.
11 * It is implemented as a set-associative cache.
12 * The replacement algorithm is pseudo-LRU.
13 * Each TLB entry has the following format:
14 * - bool       valid            (0: unmapped; 1: mapped)
15 * - bool       locally accessed
16 * - bool       remotely accessed
17 * - bool       cacheable   (cached)
18 * - bool       writable    (writable access bit)
19 * - bool       executable  (executable access bit)
20 * - bool       user        (access in user mode allowed)
21 * - bool       global      (PTE not invalidated by a TLB flush)
22 * - bool       dirty       (page has been modified)
23 * Additional flag bits for every tlb entry:
24 * - bool       pagesize    (0: 4K page size; 1: 2M page size)
25 * - bool       lru         (recently used for replace in TLB)
26 * - uint32_t   vpn         (virtual page number)
27 * - uint32_t   ppn         (physical page number)
28 *
29 * valid, lru and global are stored in registers, others are in ram.
30 *
31 *****************************************************************
32 * This file has three constructor parameters:
33 * - nways  : number of ways per associative set.
34 * - nsets  : number of associative sets.
35 * Both nways & nsets must be power of 2 no larger than 64.
36 *****************************************************************/
37
38#ifndef SOCLIB_CABA_GENERIC_TLB_H
39#define SOCLIB_CABA_GENERIC_TLB_H
40
41#include <inttypes.h>
42#include <systemc>
43#include <assert.h>
44#include "static_assert.h"
45#include "arithmetics.h"
46
47namespace soclib { 
48namespace caba {
49
50using namespace sc_core;
51
52    // PTE information struct
53    typedef struct pte_info_s {
54        bool v;    // valid             
55        bool t;    // type             
56        bool l;    // locally accessed     
57        bool r;    // remotely accessed
58        bool c;    // cacheable   
59        bool w;    // writable   
60        bool x;    // executable 
61        bool u;    // user       
62        bool g;    // global     
63        bool d;    // dirty       
64    }pte_info_t;
65
66    enum { 
67        PTD_ID2_MASK  = 0x001FF000,
68        PAGE_K_MASK   = 0x00000FFF,
69        PAGE_M_MASK   = 0x001FFFFF,
70    };
71
72    enum {
73        PTE_V_MASK = 0x80000000,
74        PTE_T_MASK = 0x40000000,
75        PTE_L_MASK = 0x20000000,
76        PTE_R_MASK = 0x10000000,
77        PTE_C_MASK = 0x08000000,
78        PTE_W_MASK = 0x04000000,
79        PTE_X_MASK = 0x02000000,
80        PTE_U_MASK = 0x01000000,
81        PTE_G_MASK = 0x00800000,
82        PTE_D_MASK = 0x00400000,
83    };
84
85    enum { 
86        PTE_V_SHIFT = 31,
87        PTE_T_SHIFT = 30,
88        PTE_L_SHIFT = 29,
89        PTE_R_SHIFT = 28,
90        PTE_C_SHIFT = 27,
91        PTE_W_SHIFT = 26,
92        PTE_X_SHIFT = 25,
93        PTE_U_SHIFT = 24,
94        PTE_G_SHIFT = 23,
95        PTE_D_SHIFT = 22,
96    };
97
98    enum { 
99        PAGE_M_NBITS = 21,
100        PAGE_K_NBITS = 12,
101        INDEX1_NBITS = 11,
102    };
103
104using soclib::common::uint32_log2;
105
106// registers describing a TLB entry state
107typedef struct tlb_entry_state {
108        sc_signal<bool> v; //valid
109        sc_signal<bool> g; //global
110        sc_signal<bool> l; //LRU
111} tlb_entry_state_t;
112
113// registers describing a tlb set state
114typedef class tlb_set_state {
115private:
116        tlb_entry_state_t *entries;
117        size_t nways;
118public:
119        tlb_set_state()
120        {
121        }
122
123        ~tlb_set_state()
124        {
125                delete [] entries;
126        }
127
128        void
129        init(size_t m_nways)
130        {
131                nways = m_nways;
132                entries = new tlb_entry_state_t[nways];
133        }
134
135        bool get_valid(size_t way)
136        {
137                return entries[way].v;
138        }
139        void set_valid(size_t way)
140        {
141                assert(entries[way].l == false &&
142                    "invalid entry should not have LRU");
143                entries[way].v = true;
144        }
145        void clear_valid(size_t way)
146        {
147                entries[way].v = false;
148                entries[way].l = false;
149        }
150
151        bool get_global(size_t way)
152        {
153                return entries[way].g;
154        }
155        void set_global(size_t way)
156        {
157                entries[way].g = true;
158        }
159        void clear_global(size_t way)
160        {
161                entries[way].g = false;
162        }
163
164        bool get_lru(size_t way)
165        {
166                return entries[way].l;
167        }
168        void set_lru(size_t way)
169        {
170                entries[way].l = true;
171                /*
172                 * if all LRU bits for the set are true, clear them
173                 */
174                for (size_t i = 0; i < nways; i++) 
175        {
176                        if (i == way)
177                                continue;
178                        if (entries[i].l == false)
179                                return;
180                }
181                // all LRU bits are set
182                for (size_t i = 0; i < nways; i++) 
183        {
184                        entries[i].l = false;
185                }
186        }
187        void clear_lru(size_t way)
188        {
189                entries[way].l = false;
190        }
191
192        void reset()
193        {
194                for (size_t i = 0; i < nways; i++) 
195        {
196                        entries[i].l = false;
197                        entries[i].g = false;
198                        entries[i].v = false;
199                }
200        }
201} tlb_set_state_t;
202
203template<typename paddr_t>
204class GenericTlb
205{
206protected:
207    typedef uint32_t vaddr_t;
208    typedef uint32_t data_t;
209
210    const size_t  m_nways;
211    const size_t  m_nsets;
212    const size_t  m_paddr_nbits;
213    const size_t  m_sets_shift;
214    const size_t  m_sets_mask;
215
216    data_t  *m_ppn; 
217    data_t  *m_vpn;
218    bool    *m_pagesize; 
219    bool    *m_locacc;
220    bool    *m_remacc;
221    bool    *m_cacheable;
222    bool    *m_writable;
223    bool    *m_executable;
224    bool    *m_user;
225    bool    *m_dirty;
226
227    tlb_set_state_t *m_setsstate;
228
229public:
230    // access methods
231    void setlru(size_t way, size_t set)
232    { 
233        m_setsstate[set].set_lru(way); 
234    }
235
236    void clearlru(size_t way, size_t set)
237    { 
238        m_setsstate[set].clear_lru(way); 
239    }
240
241    bool lru(size_t way, size_t set)
242    { 
243        return m_setsstate[set].get_lru(way); 
244    }
245
246    void setvalid(size_t way, size_t set)
247    { 
248        m_setsstate[set].set_valid(way); 
249    }
250
251    void clearvalid(size_t way, size_t set)
252    { 
253        m_setsstate[set].clear_valid(way); 
254    }
255
256    bool valid(size_t way, size_t set)
257    { 
258        return m_setsstate[set].get_valid(way); 
259    }
260
261    void setglobal(size_t way, size_t set)
262    { 
263        m_setsstate[set].set_global(way); 
264    }
265
266    void clearglobal(size_t way, size_t set)
267    { 
268        m_setsstate[set].clear_global(way); 
269    }
270
271    bool global(size_t way, size_t set)
272    { 
273        return m_setsstate[set].get_global(way); 
274    }
275
276    data_t &ppn(size_t way, size_t set)
277    { 
278        return m_ppn[(way*m_nsets)+set]; 
279    }
280
281    data_t &vpn(size_t way, size_t set)
282    { 
283        return m_vpn[(way*m_nsets)+set]; 
284    }
285
286    bool &pagesize(size_t way, size_t set)
287    { 
288        return m_pagesize[(way*m_nsets)+set]; 
289    }
290
291    bool &locacc(size_t way, size_t set)
292    { 
293        return m_locacc[(way*m_nsets)+set]; 
294    }
295
296    bool &remacc(size_t way, size_t set)
297    { 
298        return m_remacc[(way*m_nsets)+set]; 
299    }
300
301    bool &cacheable(size_t way, size_t set)
302    { 
303        return m_cacheable[(way*m_nsets)+set]; 
304    }
305
306    bool &writable(size_t way, size_t set)
307    { 
308        return m_writable[(way*m_nsets)+set]; 
309    }
310
311    bool &executable(size_t way, size_t set)
312    { 
313        return m_executable[(way*m_nsets)+set]; 
314    }
315
316    bool &user(size_t way, size_t set)
317    { 
318        return m_user[(way*m_nsets)+set]; 
319    }
320
321    bool &dirty(size_t way, size_t set)
322    { 
323        return m_dirty[(way*m_nsets)+set]; 
324    }
325
326    //////////////////////////////////////////////////////////////
327    // constructor checks parameters, allocates the memory
328    // and computes m_page_mask, m_sets_mask and m_sets_shift
329    //////////////////////////////////////////////////////////////
330    GenericTlb(size_t nways, size_t nsets, size_t paddr_nbits):
331    m_nways(nways),
332    m_nsets(nsets),
333    m_paddr_nbits(paddr_nbits),
334    m_sets_shift(uint32_log2(nsets)),
335    m_sets_mask((1<<(int)uint32_log2(nsets))-1)
336    {
337        assert(IS_POW_OF_2(nsets));
338        assert(IS_POW_OF_2(nways));
339        assert(nsets <= 64);
340        assert(nways <= 64);
341
342        if((m_paddr_nbits < 32) || (m_paddr_nbits > 42))
343        {
344            printf("Error in the genericTlb component\n");
345            printf("The physical address parameter must be in the range [32,42]\n");
346            exit(1);
347        } 
348
349        m_ppn        = new data_t[nways * nsets];
350        m_vpn        = new data_t[nways * nsets];
351        m_pagesize   = new bool[nways * nsets];
352        m_locacc     = new bool[nways * nsets];
353        m_remacc     = new bool[nways * nsets];
354        m_cacheable   = new bool[nways * nsets];
355        m_writable   = new bool[nways * nsets];
356        m_executable = new bool[nways * nsets];
357        m_user       = new bool[nways * nsets];
358        m_dirty      = new bool[nways * nsets];
359            m_setsstate = new tlb_set_state_t[nsets];
360            for (size_t i = 0; i < nsets; i++)
361                    m_setsstate[i].init(nways);
362
363    } // end constructor
364
365    ~GenericTlb()
366    {
367        delete [] m_ppn;
368        delete [] m_vpn;
369        delete [] m_pagesize;
370        delete [] m_locacc;
371        delete [] m_remacc;
372        delete [] m_cacheable;
373        delete [] m_writable;
374        delete [] m_executable;
375        delete [] m_user;
376        delete [] m_dirty;
377            delete [] m_setsstate;
378    }
379
380    /////////////////////////////////////////////////////////////
381    //  This method resets all the TLB entry.
382    /////////////////////////////////////////////////////////////
383    void reset() 
384    {
385            for (size_t i = 0; i < m_nsets; i++)
386                    m_setsstate[i].reset();
387    } 
388
389    /////////////////////////////////////////////////////////
390    //  This method returns "false" in case of MISS
391    //  In case of HIT, the physical address,
392    //  the pte informations, way and set are returned.
393    /////////////////////////////////////////////////////////
394    bool translate(  vaddr_t vaddress,      // virtual address
395                            paddr_t *paddress,     // return physique address
396                            pte_info_t *pte_info,  // return pte information
397                            size_t *tw,            // return way 
398                            size_t *ts )           // return set   
399    {
400        size_t m_set = (vaddress >> PAGE_M_NBITS) & m_sets_mask; 
401        size_t k_set = (vaddress >> PAGE_K_NBITS) & m_sets_mask; 
402
403        for( size_t way = 0; way < m_nways; way++ ) 
404        {
405            // TLB hit test for 2M page size
406            if( valid(way,m_set) && pagesize(way,m_set) &&
407               (vpn(way,m_set) == (vaddress >> (PAGE_M_NBITS + m_sets_shift))) ) 
408            {
409                pte_info->l = locacc(way,m_set);
410                pte_info->r = remacc(way,m_set);
411                pte_info->c = cacheable(way,m_set);
412                pte_info->w = writable(way,m_set);
413                pte_info->x = executable(way,m_set);
414                pte_info->u = user(way,m_set);
415                pte_info->g = global(way,m_set);
416                pte_info->d = dirty(way,m_set);
417                *tw = way;
418                *ts = m_set;
419                *paddress = (paddr_t)((paddr_t)ppn(way,m_set) << PAGE_M_NBITS) | (paddr_t)(vaddress & PAGE_M_MASK);
420                setlru(way, m_set);
421                return true;
422            }
423
424            // TLB hit test for 4K page size
425            if( valid(way,k_set) && !pagesize(way,k_set) &&
426               (vpn(way,k_set) == (vaddress >> (PAGE_K_NBITS + m_sets_shift))) ) 
427            { 
428                pte_info->l = locacc(way,k_set);
429                pte_info->r = remacc(way,k_set);
430                pte_info->c = cacheable(way,k_set);
431                pte_info->w = writable(way,k_set);
432                pte_info->x = executable(way,k_set);
433                pte_info->u = user(way,k_set);
434                pte_info->g = global(way,k_set);
435                pte_info->d = dirty(way,k_set);
436                *tw = way;
437                *ts = k_set;
438                *paddress = (paddr_t)((paddr_t)ppn(way,k_set) << PAGE_K_NBITS) | (paddr_t)(vaddress & PAGE_K_MASK);
439                setlru(way, k_set);
440                return true;   
441            } 
442        } 
443        return false;
444    } // end translate()
445
446    /////////////////////////////////////////////////////////
447    //  This method returns "false" in case of MISS
448    //  In case of HIT, the physical page number is returned.
449    /////////////////////////////////////////////////////////
450    bool translate(vaddr_t vaddress, paddr_t *paddress) 
451    {
452        size_t m_set = (vaddress >> PAGE_M_NBITS) & m_sets_mask; 
453        size_t k_set = (vaddress >> PAGE_K_NBITS) & m_sets_mask; 
454        for( size_t way = 0; way < m_nways; way++ ) 
455        {
456            // TLB hit test for 2M page size
457            if( valid(way,m_set) && pagesize(way,m_set) &&
458               (vpn(way,m_set) == (vaddress >> (PAGE_M_NBITS + m_sets_shift))) ) 
459            {
460                *paddress = (paddr_t)((paddr_t)ppn(way,m_set) << PAGE_M_NBITS) | (paddr_t)(vaddress & PAGE_M_MASK);
461                setlru(way, m_set);
462                return true;
463            }
464
465            // TLB hit test for 4K page size
466            if( valid(way,k_set) && !pagesize(way,k_set) &&
467               (vpn(way,k_set) == (vaddress >> (PAGE_K_NBITS + m_sets_shift))) ) 
468            { 
469                *paddress = (paddr_t)((paddr_t)ppn(way,k_set) << PAGE_K_NBITS) | (paddr_t)(vaddress & PAGE_K_MASK);
470                setlru(way, k_set);
471                return true;   
472            } 
473        }
474        return false;
475    } // end translate()
476    /////////////////////////////////////////////////////////////
477    //  This method resets all VALID bits in one cycle,
478    //  when the the argument is true.
479    //  Locked descriptors are preserved when it is false.
480    /////////////////////////////////////////////////////////////
481    void flush(bool all) 
482    {
483        for( size_t way = 0; way < m_nways; way++ ) 
484        {
485            for(size_t set = 0; set < m_nsets; set++) 
486            {
487                        if (!valid (way,set))
488                                continue;
489                if(global(way,set)) 
490                {
491                    if(all) 
492                    {
493                                    clearvalid(way,set); // forced reset, the locked page invalid too
494                            }
495                } 
496                else 
497                {
498                    clearvalid(way,set); // not forced reset, the locked page conserve 
499                }
500            } 
501        } 
502    } // end flush
503
504    uint32_t getpte(size_t way,size_t set)   
505    {
506        data_t pte = 0; 
507        if ( pagesize(way,set) )    // 2M page size
508        {
509           pte = (data_t)ppn(way,set) | (PTE_V_MASK & (valid(way,set) << PTE_V_SHIFT));
510   
511           if ( locacc(way,set) )
512               pte = pte | PTE_L_MASK;
513           if ( remacc(way,set) )
514               pte = pte | PTE_R_MASK;
515           if ( cacheable(way,set) )
516               pte = pte | PTE_C_MASK;
517           if ( writable(way,set) )
518               pte = pte | PTE_W_MASK;
519           if ( executable(way,set) )
520               pte = pte | PTE_X_MASK;
521           if ( user(way,set) )
522               pte = pte | PTE_U_MASK;
523           if ( global(way,set) )
524               pte = pte | PTE_G_MASK;
525           if ( dirty(way,set) )
526               pte = pte | PTE_D_MASK;
527        }
528        else    // 4K page size
529        {
530           pte = (data_t)(PTE_V_MASK & (valid(way,set) << PTE_V_SHIFT));
531   
532           if ( locacc(way,set) )
533               pte = pte | PTE_L_MASK;
534           if ( remacc(way,set) )
535               pte = pte | PTE_R_MASK;
536           if ( cacheable(way,set) )
537               pte = pte | PTE_C_MASK;
538           if ( writable(way,set) )
539               pte = pte | PTE_W_MASK;
540           if ( executable(way,set) )
541               pte = pte | PTE_X_MASK;
542           if ( user(way,set) )
543               pte = pte | PTE_U_MASK;
544           if ( global(way,set) )
545               pte = pte | PTE_G_MASK;
546           if ( dirty(way,set) )
547               pte = pte | PTE_D_MASK;
548        }
549        return pte;
550    } // end getpte()
551
552    /////////////////////////////////////////////////////////////
553    //  This method return the index of the least recently
554    //  used descriptor in the associative set.
555    /////////////////////////////////////////////////////////////
556    size_t getlru(size_t set)
557    {
558        // check val bit firstly, replace the invalid PTE
559        for(size_t way = 0; way < m_nways; way++) 
560        {
561            if( !valid(way,set) ) 
562            {
563                return way;
564            }
565        } 
566
567        // then we check bit lock, remplace and old way which is not global
568        for( size_t way = 0; way < m_nways; way++ ) 
569        {
570            if( !global(way,set) && !lru(way,set) ) 
571            {
572                return way;
573            } 
574        }
575       
576            // finally remplace the first old way
577        for( size_t way = 0; way < m_nways; way++ ) 
578        {
579            if( !lru(way,set) ) 
580            {
581                return way;
582            } 
583        }
584
585        assert(0 && "all TLB ways can't be new at the same time");
586            return 0; /* avoid gcc warning */
587    } // end getlru()
588
589    /////////////////////////////////////////////////////////////
590    //  This method writes a new 2M page size entry in the TLB.
591    /////////////////////////////////////////////////////////////
592    void update(data_t pte, vaddr_t vaddress) 
593    {
594        size_t set = (vaddress >> PAGE_M_NBITS) & m_sets_mask; 
595        size_t way = getlru(set);
596     
597        vpn(way,set) = vaddress >> (PAGE_M_NBITS + m_sets_shift);
598        ppn(way,set) = pte & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1);
599
600        setvalid(way,set);
601        pagesize(way,set)   = true;
602        setlru(way,set);
603        locacc(way,set)     = (((pte & PTE_L_MASK) >> PTE_L_SHIFT) == 1) ? true : false;
604        remacc(way,set)     = (((pte & PTE_R_MASK) >> PTE_R_SHIFT) == 1) ? true : false;
605        cacheable(way,set)  = (((pte & PTE_C_MASK) >> PTE_C_SHIFT) == 1) ? true : false;
606        writable(way,set)   = (((pte & PTE_W_MASK) >> PTE_W_SHIFT) == 1) ? true : false;       
607        executable(way,set) = (((pte & PTE_X_MASK) >> PTE_X_SHIFT) == 1) ? true : false;
608        user(way,set)       = (((pte & PTE_U_MASK) >> PTE_U_SHIFT) == 1) ? true : false;
609            if (((pte & PTE_G_MASK) >> PTE_G_SHIFT) == 1)
610                    setglobal(way,set);
611            else
612                    clearglobal(way,set);
613
614        dirty(way,set)      = (((pte & PTE_D_MASK) >> PTE_D_SHIFT) == 1) ? true : false; 
615    } // end update()
616
617    /////////////////////////////////////////////////////////////
618    //  This method writes a new 4K page size entry in the TLB.
619    /////////////////////////////////////////////////////////////
620    void update(data_t pte, data_t ppn2 , vaddr_t vaddress) 
621    {
622        size_t set = (vaddress >> PAGE_K_NBITS) & m_sets_mask; 
623        size_t way = getlru(set);
624     
625        vpn(way,set) = vaddress >> (PAGE_K_NBITS + m_sets_shift);
626        ppn(way,set) = ppn2 & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1); 
627
628        setvalid(way,set);
629        pagesize(way,set)   = false;
630        setlru(way,set);
631        locacc(way,set)     = (((pte & PTE_L_MASK) >> PTE_L_SHIFT) == 1) ? true : false;
632        remacc(way,set)     = (((pte & PTE_R_MASK) >> PTE_R_SHIFT) == 1) ? true : false;
633        cacheable(way,set)  = (((pte & PTE_C_MASK) >> PTE_C_SHIFT) == 1) ? true : false;
634        writable(way,set)   = (((pte & PTE_W_MASK) >> PTE_W_SHIFT) == 1) ? true : false;       
635        executable(way,set) = (((pte & PTE_X_MASK) >> PTE_X_SHIFT) == 1) ? true : false;
636        user(way,set)       = (((pte & PTE_U_MASK) >> PTE_U_SHIFT) == 1) ? true : false;
637            if (((pte & PTE_G_MASK) >> PTE_G_SHIFT) == 1)
638                    setglobal(way,set);
639            else
640                    clearglobal(way,set);
641        dirty(way,set)      = (((pte & PTE_D_MASK) >> PTE_D_SHIFT) == 1) ? true : false; 
642    } // end update()
643
644    //////////////////////////////////////////////////////////////
645    //  This method invalidates a TLB entry
646    //  identified by the virtual page number.
647    //////////////////////////////////////////////////////////////
648    bool inval(vaddr_t vaddress) 
649    {
650        size_t m_set = (vaddress >> PAGE_M_NBITS) & m_sets_mask; 
651        size_t k_set = (vaddress >> PAGE_K_NBITS) & m_sets_mask; 
652        for( size_t way = 0; way < m_nways; way++ ) 
653        {
654            // TLB hit test for 2M page size
655            if( valid(way,m_set) && pagesize(way,m_set) &&
656               (vpn(way,m_set) == (vaddress >> (PAGE_M_NBITS + m_sets_shift))) ) 
657            {
658                clearvalid(way,m_set);
659                return true;
660            }
661
662            // TLB hit test for 4K page size
663            if( valid(way,k_set) && !pagesize(way,k_set) &&
664               (vpn(way,k_set) == (vaddress >> (PAGE_K_NBITS + m_sets_shift))) ) 
665            { 
666                clearvalid(way,k_set);
667                return true;   
668            } 
669        } 
670        return false;
671    } // end translate()
672
673    /////////////////////////////////////////////////////////////
674    //  This method writes a new entry in the TLB.
675    /////////////////////////////////////////////////////////////
676    void setdirty(size_t way, size_t set)
677    {
678        dirty(way,set) = true;
679    } // end setdirty()
680
681    /////////////////////////////////////////////////////////////
682    //  This method return the page size.
683    /////////////////////////////////////////////////////////////
684    bool getpagesize(size_t way, size_t set)
685    {
686        return pagesize(way,set);
687    }
688
689}; // GenericTlb
690
691template<typename paddr_t>
692class GenericCcTlb : public GenericTlb<paddr_t>
693{
694public:
695    typedef uint32_t vaddr_t;
696    typedef uint32_t data_t;
697
698    paddr_t  *m_nline; 
699
700    // access methods
701    paddr_t &nline(size_t way, size_t set)
702    { 
703        return m_nline[(way*this->m_nsets)+set]; 
704    }
705
706public:
707    //////////////////////////////////////////////////////////////
708    // constructor checks parameters, allocates the memory
709    // and computes m_page_mask, m_sets_mask and m_sets_shift
710    //////////////////////////////////////////////////////////////
711    GenericCcTlb(size_t nways, size_t nsets, size_t paddr_nbits):GenericTlb<paddr_t>::GenericTlb(nways, nsets, paddr_nbits)
712    {
713        m_nline = new paddr_t[this->m_nways * this->m_nsets];
714    } // end constructor
715
716    ~GenericCcTlb()
717    {
718        delete [] m_nline;
719    }
720
721    /////////////////////////////////////////////////////////
722    //  This method returns "false" in case of MISS
723    //  In case of HIT, the physical address,
724    //  the pte informations, way and set are returned.
725    /////////////////////////////////////////////////////////
726    bool cctranslate( vaddr_t vaddress,      // virtual address
727                             paddr_t *paddress,     // return physique address
728                             pte_info_t *pte_info,  // return pte information
729                             paddr_t *victim_index, // return nline
730                             size_t *tw,            // return way 
731                             size_t *ts )           // return set   
732    {
733        size_t m_set = (vaddress >> PAGE_M_NBITS) & this->m_sets_mask; 
734        size_t k_set = (vaddress >> PAGE_K_NBITS) & this->m_sets_mask; 
735
736        for( size_t way = 0; way < this->m_nways; way++ ) 
737        {
738            // TLB hit test for 2M page size
739            if( this->valid(way,m_set) && this->pagesize(way,m_set) &&
740               (this->vpn(way,m_set) == (vaddress >> (PAGE_M_NBITS + this->m_sets_shift))) ) 
741            {
742                pte_info->l = this->locacc(way,m_set);
743                pte_info->r = this->remacc(way,m_set);
744                pte_info->c = this->cacheable(way,m_set);
745                pte_info->w = this->writable(way,m_set);
746                pte_info->x = this->executable(way,m_set);
747                pte_info->u = this->user(way,m_set);
748                pte_info->g = this->global(way,m_set);
749                pte_info->d = this->dirty(way,m_set);
750                *victim_index = nline(way,m_set);
751                *tw = way;
752                *ts = m_set;
753                *paddress = (paddr_t)((paddr_t)this->ppn(way,m_set) << PAGE_M_NBITS) | (paddr_t)(vaddress & PAGE_M_MASK);
754                //this->setlru(way, m_set);
755                return true;
756            }
757
758            // TLB hit test for 4K page size
759            if( this->valid(way,k_set) && !(this->pagesize(way,k_set)) &&
760               (this->vpn(way,k_set) == (vaddress >> (PAGE_K_NBITS + this->m_sets_shift))) ) 
761            { 
762                pte_info->l = this->locacc(way,k_set);
763                pte_info->r = this->remacc(way,k_set);
764                pte_info->c = this->cacheable(way,k_set);
765                pte_info->w = this->writable(way,k_set);
766                pte_info->x = this->executable(way,k_set);
767                pte_info->u = this->user(way,k_set);
768                pte_info->g = this->global(way,k_set);
769                pte_info->d = this->dirty(way,k_set);
770                *victim_index = nline(way,k_set);
771                *tw = way;
772                *ts = k_set;
773                *paddress = (paddr_t)((paddr_t)this->ppn(way,k_set) << PAGE_K_NBITS) | (paddr_t)(vaddress & PAGE_K_MASK);
774                //this->setlru(way, k_set);
775                return true;   
776            } 
777        } 
778        return false;
779    } // end translate()
780
781    //////////////////////////////////////////////////////////////
782    //  This method invalidates a TLB entry for cc_vcache2
783    //  identified by the virtual page number.
784    //////////////////////////////////////////////////////////////
785    bool inval(vaddr_t vaddress, paddr_t* victim)
786    {
787        paddr_t vic_nline = 0;
788        size_t m_set = (vaddress >> PAGE_M_NBITS) & this->m_sets_mask; 
789        size_t k_set = (vaddress >> PAGE_K_NBITS) & this->m_sets_mask; 
790
791        for( size_t way = 0; way < this->m_nways; way++ ) 
792        {
793            if( this->valid(way,m_set) && this->pagesize(way,m_set) &&
794                (this->vpn(way,m_set) == (vaddress >> (PAGE_M_NBITS + this->m_sets_shift))) ) 
795            {
796                vic_nline = nline(way,m_set);
797                this->clearvalid(way,m_set);
798                break;
799            } 
800
801            if( this->valid(way,k_set) && !(this->pagesize(way,k_set)) &&
802                (this->vpn(way,k_set) == (vaddress >> (PAGE_K_NBITS + this->m_sets_shift))) ) 
803            {
804                vic_nline = nline(way,k_set);
805                this->clearvalid(way,k_set);
806                break;
807            }
808            if ( way == (this->m_nways-1)) return false; 
809        } 
810
811        *victim = vic_nline;
812        // verify whether need a cleanup
813        for( size_t way = 0; way < this->m_nways; way++ ) 
814        {
815            for( size_t set = 0; set < this->m_nsets; set++ ) 
816            {
817                if( (nline(way,set) == vic_nline) && (this->valid(way,set)) ) 
818                {
819                    return false;
820                }
821            } 
822        } 
823        return true;
824    } // end inval()
825
826    //////////////////////////////////////////////////////////////
827    //  This method invalidates a TLB entry for cc_vcache
828    //  identified by the virtual page number.
829    //////////////////////////////////////////////////////////////
830    bool inval1(vaddr_t vaddress, paddr_t* victim)
831    {
832        paddr_t vic_nline = 0;
833        size_t m_set = (vaddress >> PAGE_M_NBITS) & this->m_sets_mask; 
834        size_t k_set = (vaddress >> PAGE_K_NBITS) & this->m_sets_mask; 
835
836        for( size_t way = 0; way < this->m_nways; way++ ) 
837        {
838            if( this->valid(way,m_set) && this->pagesize(way,m_set) &&
839                (this->vpn(way,m_set) == (vaddress >> (PAGE_M_NBITS + this->m_sets_shift))) ) 
840            {
841                vic_nline = nline(way,m_set);
842                this->clearvalid(way,m_set);
843                break;
844            } 
845
846            if( this->valid(way,k_set) && !(this->pagesize(way,k_set)) &&
847                (this->vpn(way,k_set) == (vaddress >> (PAGE_K_NBITS + this->m_sets_shift))) ) 
848            {
849                vic_nline = nline(way,k_set);
850                this->clearvalid(way,k_set);
851                break;
852            }
853            if ( way == (this->m_nways-1)) return false; 
854        } 
855
856        *victim = vic_nline;
857        return true;
858    } // end inval1()
859
860    //////////////////////////////////////////////////////////////
861    //  This method coherence invalidates a TLB entry
862    //  identified by the virtual page number.
863    //////////////////////////////////////////////////////////////
864    void ccinval(size_t invway, size_t invset)
865    {
866        this->clearvalid(invway,invset);
867    } // end ccinval()
868
869    //////////////////////////////////////////////////////////////
870    //  This method coherence invalidates a TLB entry
871    //  identified by the virtual page number.
872    //////////////////////////////////////////////////////////////
873    size_t getnline(size_t way, size_t set)
874    {
875        return nline(way,set);
876    } // end getnline()
877
878    /////////////////////////////////////////////////////////////
879    //  This method for cc_vcache2 is used for context switch. 
880    //  In this case, allTLB entries should be invalidated except
881    //  global entries.All the entries that are in the same data
882    //  cache line have the same NLINE. Therefore only all the 
883    //  entries of one datacache line are not global, it send a 
884    //  cleanup request todata cache. The return value indicates
885    //  whether need a cleanupand cleanup_nline contains the NLINE
886    //  that is for cleanup.   
887    /////////////////////////////////////////////////////////////
888    bool checkcleanup(size_t nway, size_t nset, paddr_t* cleanup_nline)
889    {
890        bool cleanup = false;
891        bool isglobal = false;
892        if ( this->valid(nway,nset) )
893        {
894            size_t inval_line = nline(nway,nset);
895            for (size_t start = (nway*this->m_nsets+nset); start < this->m_nways*this->m_nsets; start++)
896            {
897                if ( this->valid(start/this->m_nsets,start%this->m_nsets) && (inval_line == nline(start/this->m_nsets,start%this->m_nsets)) )
898                {
899                    if (!this->global(start/this->m_nsets,start%this->m_nsets))
900                    {
901                        this->clearvalid(start/this->m_nsets,start%this->m_nsets);
902                    }
903                    else
904                    {
905                        isglobal = true;
906                    }
907                }
908            }
909
910            cleanup = !isglobal;
911            if(cleanup)
912                *cleanup_nline = inval_line;
913        }
914        return cleanup;
915    } // end checkcleanup
916
917    /////////////////////////////////////////////////////////////
918    //  This method for cc_vcache is used for context switch. 
919    //  In this case, allTLB entries should be invalidated except
920    //  global entries.All the entries that are in the same data
921    //  cache line have the same NLINE. Therefore only all the 
922    //  entries of one datacache line are not global, it send a 
923    //  cleanup request todata cache. The return value indicates
924    //  whether need a cleanupand cleanup_nline contains the NLINE
925    //  that is for cleanup.   
926    /////////////////////////////////////////////////////////////
927    bool checkcleanup1(size_t nway, size_t nset, paddr_t* cleanup_nline)
928    {
929        bool cleanup = false;
930        bool isglobal = false;
931        if ( this->valid(nway,nset) )
932        {
933            size_t inval_line = nline(nway,nset);
934            if (!this->global(nway,nset))
935            {
936                this->clearvalid(nway,nset);
937            }
938            else
939            {
940                isglobal = true;
941            }
942
943            cleanup = !isglobal;
944            if(cleanup)
945                *cleanup_nline = inval_line;
946        }
947        return cleanup;
948    } // end checkcleanup1
949
950    //////////////////////////////////////////////////////////////////////////
951    //  This method searchs a place for the missed TLB entry, if there is victim,
952    //  a cleanup must be sent.
953    //////////////////////////////////////////////////////////////////////////
954    bool select(vaddr_t vaddress, paddr_t* victim, size_t *newway, size_t *newset)
955    {
956        size_t selset = vaddress & this->m_sets_mask;
957        size_t selway = this->getlru(selset);
958        bool cleanup = this->valid(selway,selset);
959
960            if (cleanup) {
961            for( size_t way = 0; way < this->m_nways; way++ ) 
962            {
963                for( size_t set = 0; set < this->m_nsets; set++ ) 
964                {
965                            if ((way == selway) && (set == selset))
966                                continue;
967                    if ((nline(way,set) == nline(selway,selset)) && this->valid(way,set)) 
968                    {
969                        cleanup = false;
970                        break;
971                    }
972                } 
973            } 
974        }
975       
976        if (cleanup) *victim = nline(selway,selset);
977        *newway = selway;
978        *newset = selset;
979        return cleanup;
980    }
981
982    //////////////////////////////////////////////////////////////////////////
983    //  This method searchs a place for the missed TLB entry, if there is victim,
984    //  a cleanup must be sent.
985    //////////////////////////////////////////////////////////////////////////
986    bool select1(vaddr_t vaddress, paddr_t* victim, size_t *newway, size_t *newset)
987    {
988        size_t selset = vaddress & this->m_sets_mask;
989        size_t selway = this->getlru(selset);
990        bool cleanup = this->valid(selway,selset);
991     
992        if (cleanup) *victim = nline(selway,selset);
993        *newway = selway;
994        *newset = selset;
995        return cleanup;
996    }
997
998    //////////////////////////////////////////////////////////////////////////
999    //  This method writes a new 2M page size entry in the TLB for cc_vcache2.
1000    //////////////////////////////////////////////////////////////////////////
1001    void update(data_t pte, vaddr_t vaddress, size_t selway, size_t selset, paddr_t line) 
1002    {
1003        this->vpn(selway,selset) = vaddress >> (PAGE_M_NBITS + this->m_sets_shift);
1004        this->ppn(selway,selset) = pte & ((1<<(this->m_paddr_nbits - PAGE_M_NBITS))-1); 
1005 
1006        this->setvalid(selway,selset);
1007        this->pagesize(selway,selset)   = true;
1008            this->setlru(selway,selset);
1009
1010        this->locacc(selway,selset)     = (((pte & PTE_L_MASK) >> PTE_L_SHIFT) == 1) ? true : false;
1011        this->remacc(selway,selset)     = (((pte & PTE_R_MASK) >> PTE_R_SHIFT) == 1) ? true : false;
1012        this->cacheable(selway,selset)  = (((pte & PTE_C_MASK) >> PTE_C_SHIFT) == 1) ? true : false;
1013        this->writable(selway,selset)   = (((pte & PTE_W_MASK) >> PTE_W_SHIFT) == 1) ? true : false;       
1014        this->executable(selway,selset) = (((pte & PTE_X_MASK) >> PTE_X_SHIFT) == 1) ? true : false;
1015        this->user(selway,selset)       = (((pte & PTE_U_MASK) >> PTE_U_SHIFT) == 1) ? true : false;
1016            if (((pte & PTE_G_MASK) >> PTE_G_SHIFT) == 1)
1017                    this->setglobal(selway,selset);
1018            else
1019                    this->clearglobal(selway,selset);
1020        this->dirty(selway,selset)      = (((pte & PTE_D_MASK) >> PTE_D_SHIFT) == 1) ? true : false; 
1021        nline(selway,selset) = line; 
1022    } // end update()
1023
1024    //////////////////////////////////////////////////////////////////////////
1025    //  This method writes a new 4K page size entry in the TLB for cc_vcache2.
1026    //////////////////////////////////////////////////////////////////////////
1027    void update(data_t pte, data_t ppn2, vaddr_t vaddress, size_t selway, size_t selset, paddr_t line) 
1028    {
1029        this->vpn(selway,selset) = vaddress >> (PAGE_K_NBITS + this->m_sets_shift);
1030        this->ppn(selway,selset) = ppn2 & ((1<<(this->m_paddr_nbits - PAGE_K_NBITS))-1); 
1031        this->setvalid(selway,selset);
1032        this->pagesize(selway,selset)   = false;
1033            this->setlru(selway,selset);
1034
1035        this->locacc(selway,selset)     = (((pte & PTE_L_MASK) >> PTE_L_SHIFT) == 1) ? true : false;
1036        this->remacc(selway,selset)     = (((pte & PTE_R_MASK) >> PTE_R_SHIFT) == 1) ? true : false;
1037        this->cacheable(selway,selset)  = (((pte & PTE_C_MASK) >> PTE_C_SHIFT) == 1) ? true : false;
1038        this->writable(selway,selset)   = (((pte & PTE_W_MASK) >> PTE_W_SHIFT) == 1) ? true : false;       
1039        this->executable(selway,selset) = (((pte & PTE_X_MASK) >> PTE_X_SHIFT) == 1) ? true : false;
1040        this->user(selway,selset)       = (((pte & PTE_U_MASK) >> PTE_U_SHIFT) == 1) ? true : false;
1041            if (((pte & PTE_G_MASK) >> PTE_G_SHIFT) == 1)
1042                    this->setglobal(selway,selset);
1043            else
1044                    this->clearglobal(selway,selset);
1045               
1046        this->dirty(selway,selset)      = (((pte & PTE_D_MASK) >> PTE_D_SHIFT) == 1) ? true : false; 
1047       
1048        nline(selway,selset) = line; 
1049    } // end update()
1050#if 0
1051    //////////////////////////////////////////////////////////////////////////
1052    //  This method writes a new 4K page size entry in the TLB for cc_vcache.
1053    //////////////////////////////////////////////////////////////////////////
1054    bool update1(data_t pte, data_t ppn2, vaddr_t vaddress, paddr_t line, paddr_t* victim )
1055    {
1056        size_t set = (vaddress >> PAGE_K_NBITS) & this->m_sets_mask;
1057        size_t selway = this->getlru(set);
1058        bool cleanup = this->valid(selway,set);
1059
1060        this->vpn(selway,set) = vaddress >> (PAGE_K_NBITS + this->m_sets_shift);
1061        this->ppn(selway,set) = ppn2 & ((1<<(this->m_paddr_nbits - PAGE_K_NBITS))-1); 
1062        this->setvalid(selway,set);
1063        this->pagesize(selway,set)   = false;
1064        this->setlru(selway,set);
1065
1066        this->locacc(selway,set)     = (((pte & PTE_L_MASK) >> PTE_L_SHIFT) == 1) ? true : false;
1067        this->remacc(selway,set)     = (((pte & PTE_R_MASK) >> PTE_R_SHIFT) == 1) ? true : false;
1068        this->cacheable(selway,set)  = (((pte & PTE_C_MASK) >> PTE_C_SHIFT) == 1) ? true : false;
1069        this->writable(selway,set)   = (((pte & PTE_W_MASK) >> PTE_W_SHIFT) == 1) ? true : false;       
1070        this->executable(selway,set) = (((pte & PTE_X_MASK) >> PTE_X_SHIFT) == 1) ? true : false;
1071        this->user(selway,set)       = (((pte & PTE_U_MASK) >> PTE_U_SHIFT) == 1) ? true : false;
1072            if (((pte & PTE_G_MASK) >> PTE_G_SHIFT) == 1)
1073                    this->setglobal(selway,set);
1074            else
1075                    this->clearglobal(selway,set);
1076        this->dirty(selway,set)      = (((pte & PTE_D_MASK) >> PTE_D_SHIFT) == 1) ? true : false;
1077       
1078        *victim = nline(selway,set);
1079        nline(selway,set) = line;
1080
1081        return cleanup;
1082    } // end update1()
1083#endif
1084    //////////////////////////////////////////////////////////////
1085    //  This method verify whether all 16 words of a data cache line
1086    //  that are as PTE don't exist in TLB. If is true, a cleanup
1087    //  request is actived.
1088    //////////////////////////////////////////////////////////////
1089    bool cleanupcheck( paddr_t n_line ) 
1090    {
1091        for( size_t way = 0; way < this->m_nways; way++ ) 
1092        {
1093            for( size_t set = 0; set < this->m_nsets; set++ ) 
1094            {
1095                if ( (nline(way,set) == n_line) && this->valid(way,set) ) 
1096                {
1097                    return true;
1098                }
1099            } 
1100        } 
1101        return false;
1102    } // end cccheck()
1103
1104    //////////////////////////////////////////////////////////////
1105    //  This method invalidates a TLB entry
1106    //  identified by the virtual page number.
1107    //////////////////////////////////////////////////////////////
1108    bool cccheck( paddr_t n_line, 
1109                         size_t start_way, size_t start_set, 
1110                         size_t* n_way, size_t* n_set,
1111                         bool* end )
1112    {
1113        for ( size_t start = start_way*(this->m_nsets)+start_set; start < this->m_nways*this->m_nsets; start++ )
1114        {
1115            if (( nline((start/this->m_nsets),(start%this->m_nsets)) == n_line ) && this->valid((start/this->m_nsets),(start%this->m_nsets))) 
1116            {
1117                *n_way = start/this->m_nsets;
1118                *n_set = start%this->m_nsets;
1119                if ( ((start/this->m_nsets) == (this->m_nways-1)) && ((start%this->m_nsets) == (this->m_nsets-1)) )
1120                {
1121                    *end = true;
1122                }
1123                else
1124                {
1125                    *end = false;
1126                }
1127                return true;
1128            }
1129        }
1130        *end = true;
1131        return false;
1132    } // end cccheck()
1133}; // GenericCcTlb
1134
1135}}
1136
1137#endif /* SOCLIB_CABA_GENERIC_TLB_H */
1138
1139// Local Variables:
1140// tab-width: 4
1141// c-basic-offset: 4
1142// c-file-offsets:((innamespace . 0)(inline-open . 0))
1143// indent-tabs-mode: nil
1144// End:
1145
1146// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1147
1148
1149
Note: See TracBrowser for help on using the repository browser.