Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "types.h"
  2. #include "CPU.h"
  3. #include "icache.h"
  4.  
  5. //#define ICACHE_DEBUGGING
  6.  
  7.  
  8.  
  9. #ifdef ICACHE_DEBUGGING
  10.         #define _icache_fetch_func      icacheFetch_
  11.         #define _icache_test_func       icacheFetch
  12. #else
  13.         #define _icache_fetch_func      icacheFetch
  14.         #define _icache_test_func       icacheFetch_test
  15. #endif
  16.  
  17. void icacheInval(icache* ic){
  18.  
  19.         UInt8 i, j;
  20.        
  21.         for(i = 0; i < ICACHE_BUCKET_NUM; i++){
  22.                 for(j = 0; j < ICACHE_BUCKET_SZ; j++) ic->lines[i][j].info = 0;
  23.                 ic->ptr[i] = 0;
  24.         }
  25. }
  26.  
  27. void icacheInit(icache* ic, ArmCpu* cpu, ArmCpuMemF memF){
  28.  
  29.         ic->cpu = cpu;
  30.         ic->memF = memF;
  31.        
  32.         icacheInval(ic);       
  33. }
  34.  
  35.  
  36. static UInt8 icachePrvHash(UInt32 addr){
  37.  
  38.         addr >>= ICACHE_L;
  39.         addr &= (1UL << ICACHE_S) - 1UL;
  40.  
  41.         return addr;
  42. }
  43.  
  44. void icacheInvalAddr(icache* ic, UInt32 va){
  45.  
  46.         UInt32 off = va % ICACHE_LINE_SZ;
  47.         Int8 i, j, bucket;
  48.         icacheLine* lines;
  49.        
  50.         va -= off;
  51.  
  52.         bucket = icachePrvHash(va);
  53.         lines = ic->lines[bucket];
  54.        
  55.         for(i = 0, j = ic->ptr[bucket]; (UInt8)i < ICACHE_BUCKET_SZ; i++){
  56.                
  57.                 if(--j == -1) j = ICACHE_BUCKET_SZ - 1;
  58.                
  59.                 if((lines[j].info & (ICACHE_ADDR_MASK | ICACHE_USED_MASK)) == (va | ICACHE_USED_MASK)){ //found it!
  60.                
  61.                         lines[j].info = 0;
  62.                 }
  63.         }
  64. }
  65.  
  66. /*
  67.         we cannot have data overlap cachelines since data is self aligned (word on 4-byte boundary, halfwords on2, etc. this is enforced elsewhere
  68. */
  69.  
  70. Boolean _icache_fetch_func(icache* ic, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
  71.  
  72.         UInt32 off = va % ICACHE_LINE_SZ;
  73.         Int8 i, j, bucket;
  74.         icacheLine* lines;
  75.         icacheLine* line;
  76.        
  77.         va -= off;
  78.  
  79.         bucket = icachePrvHash(va);
  80.         lines = ic->lines[bucket];
  81.        
  82.         for(i = 0, j = ic->ptr[bucket]; (UInt8)i < ICACHE_BUCKET_SZ; i++){
  83.                
  84.                 if(--j == -1) j = ICACHE_BUCKET_SZ - 1;
  85.                
  86.                 if((lines[j].info & (ICACHE_ADDR_MASK | ICACHE_USED_MASK)) == (va | ICACHE_USED_MASK)){ //found it!
  87.                
  88.                         if(sz == 4){
  89.                                 *(UInt32*)buf = *(UInt32*)(lines[j].data + off);
  90.                         }
  91.                         else if(sz == 2){
  92.                                 *(UInt16*)buf = *(UInt16*)(lines[j].data + off);
  93.                         }
  94.                         else __mem_copy(buf, lines[j].data + off, sz);
  95.                         return priviledged || !(lines[j].info & ICACHE_PRIV_MASK);     
  96.                 }
  97.         }
  98.         //if we're here, we found nothing - time to populate the cache
  99.         j = ic->ptr[bucket]++;
  100.         if(ic->ptr[bucket] == ICACHE_BUCKET_SZ) ic->ptr[bucket] = 0;
  101.         line = lines + j;
  102.        
  103.         line->info = va | (priviledged ? ICACHE_PRIV_MASK : 0);
  104.         if(!ic->memF(ic->cpu, line->data, va, ICACHE_LINE_SZ, false, priviledged, fsrP)){
  105.        
  106.                 return false;  
  107.         }
  108.         line->info |= ICACHE_USED_MASK;
  109.        
  110.         if(sz == 4){
  111.                 *(UInt32*)buf = *(UInt32*)(line->data + off);
  112.         }
  113.         else if(sz == 2){
  114.                 *(UInt16*)buf = *(UInt16*)(line->data + off);
  115.         }
  116.         else __mem_copy(buf, line->data + off, sz);
  117.         return true;
  118. }
  119.  
  120. #include "stdio.h"
  121. Boolean _icache_test_func(icache* ic, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
  122.  
  123.         UInt8 fsrO = -1, fsrT = -1;
  124.         UInt8 dataO[4] = {0}, dataT[4] = {0};
  125.         Boolean retO, retT;
  126.         UInt8 i;
  127.        
  128.         retO = _icache_fetch_func(ic, va, sz, priviledged, &fsrO, dataO);
  129.         retT = ic->memF(ic->cpu, dataT, va, sz, false, priviledged, &fsrT);
  130.        
  131.         if((retT != retO) || (fsrT != fsrO) || (dataT[0] != dataO[0]) || (dataT[1] != dataO[1]) || (dataT[2] != dataO[2]) || (dataT[3] != dataO[3])){
  132.        
  133.                 fprintf(stderr, "icache fail!");       
  134.         }
  135.  
  136.         for(i = 0; i < sz; i++) ((UInt8*)buf)[i] = dataT[i];
  137.         if(retT) *fsrP = fsrT;
  138.         return retT;
  139. }
  140.  
  141.