source: trunk/platforms/almos-tsarv3-platforms/common/generic_tlb/include/generic_tlb.h @ 259

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

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

File size: 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.