source: trunk/IPs/systemC/hierarchy_memory/cache/cache_onelevel.h @ 2

Last change on this file since 2 was 2, checked in by kane, 17 years ago

Import Morpheo

File size: 17.6 KB
Line 
1#ifndef CACHE_ONELEVEL_H
2#define CACHE_ONELEVEL_H
3
4#include <stdint.h>
5#include <math.h>
6#include <iostream>
7#include <iomanip>
8#include "../file/sort_file_dynamic.h"
9#include "type_req_cache.h"
10#include "tag.h"
11#include "address.h"
12#include "access_port.h"
13#include "write_buffer.h"
14
15using namespace std;
16using namespace hierarchy_memory::sort_file;
17using namespace hierarchy_memory::cache::cache_multilevel;
18
19namespace hierarchy_memory          {
20namespace cache                     {
21namespace cache_multilevel          {
22namespace cache_onelevel            {
23
24  class param_cache_t
25  {
26  public : const char *   name         ;
27  public : uint32_t nb_line      ;
28  public : uint32_t size_line    ;
29  public : uint32_t size_word    ;
30  public : uint32_t associativity;
31  public : uint32_t hit_latence  ;
32  public : uint32_t miss_penality;
33   
34  public : param_cache_t () {};
35
36  public : param_cache_t (const char   * name         ,
37                          uint32_t nb_line      ,
38                          uint32_t size_line    ,
39                          uint32_t size_word    ,
40                          uint32_t associativity,
41                          uint32_t hit_latence  ,
42                          uint32_t miss_penality
43                          ) :
44    name (name)
45    {
46      //this->name          = name         ;
47      this->nb_line       = nb_line      ;
48      this->size_line     = size_line    ;
49      this->size_word     = size_word    ;
50      this->associativity = associativity;
51      this->hit_latence   = hit_latence  ;
52      this->miss_penality = miss_penality;
53    }
54
55    friend ostream& operator<< (ostream& output_stream, const param_cache_t & x)
56    {
57      output_stream << "<" << x.name   << "> "
58                    << x.nb_line       << " "
59                    << x.size_line     << " "
60                    << x.size_word     << " "
61                    << x.associativity << " "
62                    << x.hit_latence   << " "
63                    << x.miss_penality;
64   
65      return output_stream;
66    }
67  };//end param_cache_t
68 
69  class param_t
70  {
71  public : uint32_t      nb_port    ;
72  public : param_cache_t param_cache;
73   
74  public : param_t (uint32_t      nb_port    ,
75                    param_cache_t param_cache)
76    {
77      this->nb_port     = nb_port      ;
78      this->param_cache = param_cache  ;
79    }
80
81    friend ostream& operator<< (ostream& output_stream, const param_t & x)
82    {
83      output_stream << x.nb_port << " " 
84                    << x.param_cache;
85      return output_stream;
86    }
87
88  };//end param_t
89
90  class Cache_OneLevel
91  {
92  protected : const uint32_t  nb_port       ;
93  protected : const uint32_t  nb_line       ;
94  protected : const uint32_t  size_line     ;
95  protected : const uint32_t  size_word     ;
96  protected : const uint32_t  associativity ;
97  protected : const uint32_t  hit_latence   ;
98  protected : const uint32_t  miss_penality ;
99   
100  private   : char          *  name;
101  private   : tag_t         ** tag;
102  private   : access_port_t *  access_port;
103  private   : address_t        size_address;
104  private   : Sort_File_Dynamic<write_buffer_t> * write_buffer;
105
106    //*****[ constructor ]*****
107  public : Cache_OneLevel (param_t param):
108      nb_port       (param.nb_port                  ),
109      nb_line       (param.param_cache.nb_line      ),
110      size_line     (param.param_cache.size_line    ),
111      size_word     (param.param_cache.size_word    ),
112      associativity (param.param_cache.associativity),
113      hit_latence   (param.param_cache.hit_latence  ),
114      miss_penality (param.param_cache.miss_penality)
115      {
116        uint32_t size_name = strlen(param.param_cache.name)+1;
117        name               = new char [size_name];
118        strncpy(name,param.param_cache.name,size_name);
119
120        if ((nb_line * size_line * associativity) == 0)
121          {
122            cerr << "<" << name << ".{Cache_OneLevel}> all parameter must be greater that 0" << endl;
123            cerr << " nb_line       : " << nb_line       << endl;
124            cerr << " size_line     : " << size_line     << endl;
125            cerr << " associativity : " << associativity << endl;
126            exit(1);
127          }
128        if ((nb_line % associativity) != 0)
129          {
130            cerr << "<" << name << ".{Cache_OneLevel}> nb_line must be a mutiple of associativity" << endl;
131            cerr << "  * nb_line       : " << nb_line       << endl;
132            cerr << "  * associativity : " << associativity << endl;
133            exit(1);
134          }
135
136        if ((double)nb_line    != ::pow(2,::log2(nb_line)))
137          {
138            cerr << "<" << name << ".{Cache_OneLevel}> nb_line must be a mutiple of 2^n" << endl;
139            cerr << "  * nb_line       : " << nb_line       << endl;
140            exit(1);
141          }
142
143        if ((double)size_line != ::pow(2,::log2(size_line)))
144          {
145            cerr << "<" << name << ".{Cache_OneLevel}> size_line must be a mutiple of 2^n" << endl;
146            cerr << "  * size_line     : " << size_line     << endl;
147            exit(1);
148          }
149
150        if ((double)size_word != ::pow(2,::log2(size_word)))
151          {
152            cerr << "<" << name << ".{Cache_OneLevel}> size_word must be a mutiple of 2^n" << endl;
153            cerr << "  * size_word     : " << size_word     << endl;
154            exit(1);
155          }
156       
157        write_buffer= new Sort_File_Dynamic<write_buffer_t> (sort_file::param_t("write_buffer",5));
158        access_port = new access_port_t [nb_port];
159        tag         = new tag_t *       [nb_line/associativity];
160        for (uint32_t it = 0; it < nb_line/associativity; it ++)
161          tag [it] = new tag_t [associativity];
162
163        size_address.offset  = (uint32_t) log2(size_line * size_word);
164        size_address.familly = (uint32_t) log2(nb_line/associativity);
165        size_address.tag     = 32 - size_address.familly - size_address.offset;
166     }
167     
168      //*****[ destructor ]*****
169    public : ~Cache_OneLevel ()
170      {
171//      delete tag;
172//      delete access_port;
173      };
174
175      //*****[ reset ]*****
176    public : void reset ()
177      {
178        for (uint32_t x = 0; x < nb_port; x ++)
179          access_port[x].valid = false;
180
181        for (uint32_t x = 0; x < nb_line/associativity; x ++)
182          for (uint32_t y = 0; y < associativity; y ++)
183            {
184              tag[x][y].valid      = false;
185              tag[x][y].index_lru  = y;
186            }
187        write_buffer->reset();
188      }
189
190      //*****[ transition ]*****
191    public : void transition ()
192    {
193        // scan all port - test if have a transaction
194        for (int32_t x = nb_port-1; x >= 0; x --)
195          {
196            if (access_port[x].valid == true)
197              {
198                access_port[x].valid = false;
199               
200                // Update LRU
201                //  * hit  : now
202                //  * miss : after the return of next cache
203               
204                if (access_port[x].hit == HIT_CACHE)
205                  {// Hit
206                    update_lru(access_port[x].address.familly,access_port[x].num_associativity);
207                  }
208
209                if (access_port[x].hit == MISS)
210                  {// Miss
211                    // Write in write_buffer
212                    write_buffer->push(access_port[x].latence,write_buffer_t(access_port[x].address,access_port[x].trdid));
213                  }
214              }
215          }
216       
217        // Test if a write_buffer have the result
218        while ((write_buffer->empty() == false) && (write_buffer->read(0).delay == 0))
219          {
220            // Save in the cache
221            write_buffer_t val         = write_buffer->pop();
222           
223            uint32_t num_tag           = val.address.tag;
224            uint32_t num_familly       = val.address.familly;
225            uint32_t num_associativity = index_victim(num_familly);
226           
227            tag [num_familly][num_associativity].valid    = true;
228            tag [num_familly][num_associativity].address  = num_tag;
229            tag [num_familly][num_associativity].trdid    = val.trdid;
230           
231            update_lru(num_familly,num_associativity);
232          }
233
234        write_buffer->transition();
235      }
236      //*****[ update_lru ]*****
237    private : void update_lru (uint32_t familly, uint32_t num_associativity)
238      {
239        uint32_t current_lru = tag [familly][num_associativity].index_lru;
240       
241        for (uint32_t k = 0; k < associativity; k ++)
242          if (tag [familly][k].index_lru < current_lru)
243            tag [familly][k].index_lru ++;
244        tag [familly][num_associativity].index_lru = 0;
245      }
246     
247    //*****[ index_victim ]*****
248    // return the index of the nex victim
249  public : uint32_t index_victim (uint32_t familly)
250    {
251      uint32_t victim = 0;
252      while (tag [familly][victim].index_lru != (associativity-1))
253        {
254          victim ++;
255        }
256
257      return victim;
258    }
259
260      //*****[ translate_address ]*****
261    private : address_t translate_address (uint32_t address)
262      {
263        address_t address_translated;
264        uint32_t  shift;
265
266        address_translated.offset  = (address & ((uint32_t)-1 >> (32-(size_address.offset          ))));
267        address                   -= address_translated.offset;
268        shift                      = size_address.offset;
269        address_translated.familly = (address & ((uint32_t)-1 >> (32-(size_address.familly + shift))))>>shift;
270        address                   -= address_translated.familly;
271        shift                     += size_address.familly;
272        address_translated.tag     = (address & ((uint32_t)-1 >> (32-(size_address.tag     + shift))))>>shift;
273
274        return address_translated;
275      }
276
277    //********************
278    //********************
279
280    //*****[ access ]*****
281    // Return hit (true)
282      // uncache is to stocke the address on the cache
283  public : type_rsp_cache_t access (uint32_t nb_port, uint32_t address, uint32_t trdid, type_req_cache_t type, direction_req_cache_t dir)
284    {
285      switch (type)
286        {
287        case UNCACHED   : return access_uncached   (nb_port,address,trdid    ); break;
288        case INVALIDATE : return access_invalidate (nb_port,address,trdid    ); break;
289        case FLUSH      : return access_flush      (nb_port,address,trdid    ); break;
290        case PREFETCH   : // no difference with the simple read cached (have no add a prefetch cache)
291        case CACHED     : return access_cached     (nb_port,address,trdid,dir); break;
292        default         : cout << "<Cache_Onelevel.access> unkonow type : " << endl; exit(1); break;
293        }
294    }
295
296    // *****[ access_cached ]*****
297  public : type_rsp_cache_t access_cached (uint32_t nb_port, uint32_t address, uint32_t trdid, direction_req_cache_t dir)
298    {
299        address_t        address_translate  = translate_address(address);
300        uint32_t         num_associativity  = hit_cache        (trdid, address_translate);
301        uint32_t         num_port           = hit_access_port  (trdid, address_translate);
302        uint32_t         num_write_buffer   = hit_write_buffer (trdid, address_translate);
303               
304        if (num_port == this->nb_port)
305          num_port = nb_port;
306
307        uint32_t         latence            ;
308        type_rsp_cache_t res                = MISS;
309
310        bool             is_in_cache        = (num_associativity != associativity);
311        bool             is_in_access_port  = (num_port != nb_port);
312        bool             is_in_write_buffer = false;
313
314        if (is_in_access_port == true)
315          {
316            res     = HIT_BYPASS;
317            latence = access_port[num_port].latence; //already compute
318          }
319        else
320          if (is_in_cache == true)
321            {   
322              res     = HIT_CACHE;
323              latence = 0; // Hit !!!
324            }
325          else
326            {
327              // Search in the write buffer, and test if have a miss
328              if ( num_write_buffer == write_buffer->nb_slot_use())
329                  {
330                    res     = MISS;
331                    latence = miss_penality; // miss -> access at down of cache,  + respons at the up of cache
332                  }
333              else
334                {
335                  res                = HIT_WRITE_BUFFER;
336                  is_in_write_buffer = true;
337                  latence            = write_buffer->read(num_write_buffer).delay;
338                }
339            }
340
341        // access_port valid = there are a new request to update
342        //  -> no previous request in the same     cycle (hit in a access port)
343        //  -> no previous request in the previous cycle (hit in the write buffer)
344       
345        access_port[nb_port].valid             = ((is_in_access_port || is_in_write_buffer) == false);
346        access_port[nb_port].address           = address_translate;
347        access_port[nb_port].trdid             = trdid;
348        access_port[nb_port].hit               = res;
349        access_port[nb_port].num_associativity = num_associativity;
350        access_port[nb_port].latence           = latence;
351
352        return res;
353    }
354
355    // *****[ access_uncached ]*****
356  public : type_rsp_cache_t access_uncached (uint32_t nb_port, uint32_t address, uint32_t trdid)
357    {
358      access_port[nb_port].valid             = false;
359      access_port[nb_port].trdid             = trdid;
360      access_port[nb_port].hit               = MISS;
361      access_port[nb_port].latence           = miss_penality;
362     
363      return MISS;
364    }
365    // *****[ access_invalidate ]*****
366  public : type_rsp_cache_t access_invalidate (uint32_t nb_port, uint32_t address, uint32_t trdid)
367    {
368      cerr << "<" << name << ".{Cache_OneLevel}.access_invalidate> Not implemented" << endl;
369      exit (0);
370      return MISS;
371    }
372
373    // *****[ access_flush ]*****
374  public : type_rsp_cache_t access_flush (uint32_t nb_port, uint32_t address, uint32_t trdid)
375    {
376      cerr << "<" << name << ".{Cache_OneLevel}.access_flush> Not implemented" << endl;
377      exit (0);
378      return MISS;
379    }
380
381    //******************************
382    //******************************
383
384    //*****[ hit_write_buffer ]*****
385
386    // If a instruction is in the write_buffer, return the position
387    // else, return the number of elt in the write_buffer
388  public : uint32_t hit_write_buffer (uint32_t trdid, address_t address)
389    {
390        uint32_t num_write_buffer = 0;
391        // Scan the write_buffer
392        for (num_write_buffer = 0; num_write_buffer < write_buffer->nb_slot_use(); num_write_buffer ++)
393          {
394            slot_t<write_buffer_t> val = write_buffer->read(num_write_buffer);
395
396            if ( (val.data.trdid           == trdid          ) &&
397                 (val.data.address.tag     == address.tag    ) &&
398                 (val.data.address.familly == address.familly))
399              break;
400          }
401       
402        return num_write_buffer;
403    }
404
405    //*****[ hit_access_port ]*****
406    // return the number of associativity if hit
407    // return nb_accosiativity if miss
408  public : uint32_t hit_cache (uint32_t trdid, address_t address)
409      {
410        uint32_t num_associativity;
411        for (num_associativity = 0; num_associativity < associativity; num_associativity ++)
412          // Hit if :
413          //  * in the line
414          //  * in a way associative
415          //  -> there are the same tag
416          //               the same trdid
417          //               is valid
418          if ( (tag [address.familly][num_associativity].address == address.tag) && 
419               (tag [address.familly][num_associativity].valid   == true       ) &&
420               (tag [address.familly][num_associativity].trdid   == trdid      ) )
421              break;
422
423        return num_associativity;
424      }
425
426    //*****[ hit_access_port ]*****
427    // Return the number of port if hit
428    // Return nb_port if miss
429  public : uint32_t hit_access_port (uint32_t trdid, address_t address)
430      {
431        uint32_t it_num_port = 0;
432
433        // scan all port - test if have a transaction
434        for (it_num_port = 0; it_num_port < nb_port; it_num_port ++)
435          if ( (access_port[it_num_port].valid           == true           ) &&
436               (access_port[it_num_port].trdid           == trdid          ) &&
437               (access_port[it_num_port].address.tag     == address.tag    ) &&
438               (access_port[it_num_port].address.familly == address.familly))
439            break;
440
441        return it_num_port;
442      }
443
444      //*****[ need_slot ]*****
445    public : uint32_t need_slot ()
446      {
447        uint32_t res = 0;
448        // scan all port - test if have a transaction
449        for (uint32_t x = 0; x < nb_port; x ++)
450          if (access_port[x].valid == true)
451            res ++;
452
453        return res;
454      }
455
456      //*****[ latence ]*****
457      // Return the time to have the data
458      // uncache is to stocke the address on the cache
459    public : uint32_t latence (uint32_t num_port)
460      {
461        uint32_t res = hit_latence + access_port[num_port].latence;
462
463        return res;
464      }
465
466      //*****[ update_latence ]*****
467      // Return the time to have the data
468      // uncache is to stocke the address on the cache
469  public : bool update_latence (uint32_t nb_port, uint32_t latence)
470      {
471        access_port[nb_port].latence = latence-hit_latence;
472        return access_port[nb_port].valid;
473      }
474
475    //*****[ information ]*****
476  public : void information (void)
477    {
478      cout << "<" << name << ">"                                                      << endl
479           << "  * Information"                                                       << endl
480           << "  * Capacity        : " << nb_line * size_line * size_word << " bytes" << endl
481           << "    * Nb line       : " << nb_line                                     << endl
482           << "    * Size line     : " << size_line                                   << endl
483           << "    * Size word     : " << size_word                                   << endl
484           << "    * Associativity : " << associativity                               << endl
485           << "  * Timing          : "                                                << endl
486           << "    * Hit  latence  : " << hit_latence                                 << endl
487           << "    * Miss penality : " << miss_penality                               << endl
488           << "    * Nb port       : " << nb_port                                     << endl
489           << endl;
490    }
491   
492      friend ostream& operator<< (ostream& output_stream, const Cache_OneLevel & x)
493      {
494        output_stream << "<" << x.name << ">"                                                          << endl
495                      << "  * Capacity        : " << x.nb_line * x.size_line * x.size_word << " bytes" << endl
496                      << "    * Nb line       : " << x.nb_line                                         << endl
497                      << "    * Size line     : " << x.size_line                                       << endl
498                      << "    * Size word     : " << x.size_word                                       << endl
499                      << "    * Associativity : " << x.associativity                                   << endl
500                      << "  * Timing          : "                                                      << endl
501                      << "    * Hit  latence  : " << x.hit_latence                                     << endl
502                      << "    * Miss penality : " << x.miss_penality                                   << endl
503                      << "    * Nb port       : " << x.nb_port                                         << endl
504                      << endl;
505
506        output_stream << "  * Tag"                                                                     << endl;
507        for (uint32_t i = 0; i < x.nb_line / x.associativity; i ++)
508          {
509            for (uint32_t j = 0; j < x.associativity; j ++)
510                output_stream << x.tag [i][j] << " | ";
511            output_stream << endl;
512          }
513       
514        output_stream << endl;
515        output_stream << *x.write_buffer << endl;
516
517        return output_stream;
518      }
519
520    };
521};};};};
522#endif //!CACHE_ONELEVEL_H
523
Note: See TracBrowser for help on using the repository browser.