156 lines
3.5 KiB
C
156 lines
3.5 KiB
C
|
#include "types.h"
|
||
|
#include "CPU.h"
|
||
|
#include "dcache.h"
|
||
|
|
||
|
//#define DCACHE_DEBUGGING
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef DCACHE_DEBUGGING
|
||
|
#define _dcache_fetch_func dcacheFetch_
|
||
|
#define _dcache_test_func dcacheFetch
|
||
|
#else
|
||
|
#define _dcache_fetch_func dcacheFetch
|
||
|
#define _dcache_test_func dcacheFetch_test
|
||
|
#endif
|
||
|
|
||
|
void dcacheInval(dcache* dc){
|
||
|
|
||
|
UInt8 i, j;
|
||
|
|
||
|
for(i = 0; i < DCACHE_BUCKET_NUM; i++){
|
||
|
for(j = 0; j < DCACHE_BUCKET_SZ; j++) dc->lines[i][j].info = 0;
|
||
|
dc->ptr[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void dcacheInit(dcache* dc, ArmCpu* cpu, ArmCpuMemF memF){
|
||
|
|
||
|
dc->cpu = cpu;
|
||
|
dc->memF = memF;
|
||
|
|
||
|
dcacheInval(dc);
|
||
|
}
|
||
|
|
||
|
|
||
|
static UInt8 dcachePrvHash(UInt32 addr){
|
||
|
|
||
|
addr >>= DCACHE_L;
|
||
|
addr &= (1UL << DCACHE_S) - 1UL;
|
||
|
|
||
|
return addr;
|
||
|
}
|
||
|
|
||
|
void dcacheInvalAddr(dcache* dc, UInt32 va){
|
||
|
|
||
|
UInt32 off = va % DCACHE_LINE_SZ;
|
||
|
Int8 i, j, bucket;
|
||
|
dcacheLine* lines;
|
||
|
|
||
|
va -= off;
|
||
|
|
||
|
bucket = dcachePrvHash(va);
|
||
|
lines = dc->lines[bucket];
|
||
|
|
||
|
for(i = 0, j = dc->ptr[bucket]; i < DCACHE_BUCKET_SZ; i++){
|
||
|
|
||
|
if(--j == -1) j = DCACHE_BUCKET_SZ - 1;
|
||
|
|
||
|
if((lines[j].info & (DCACHE_ADDR_MASK | DCACHE_USED_MASK)) == (va | DCACHE_USED_MASK)){ //found it!
|
||
|
|
||
|
lines[j].info = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void dcacheFlush(dcache* dc){
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void dcacheFlushAddr(dcache* dc, UInt32 va){
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
we cannot have data overlap cachelines since data is self aligned (word on 4-byte boundary, halfwords on2, etc. this is enforced elsewhere
|
||
|
*/
|
||
|
|
||
|
Boolean dcacheWrite(dcache* dc, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
Boolean _dcache_fetch_func(dcache* dc, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
|
||
|
|
||
|
UInt32 off = va % DCACHE_LINE_SZ;
|
||
|
Int8 i, j, bucket;
|
||
|
dcacheLine* lines;
|
||
|
dcacheLine* line;
|
||
|
|
||
|
va -= off;
|
||
|
|
||
|
bucket = dcachePrvHash(va);
|
||
|
lines = dc->lines[bucket];
|
||
|
|
||
|
for(i = 0, j = dc->ptr[bucket]; i < DCACHE_BUCKET_SZ; i++){
|
||
|
|
||
|
if(--j == -1) j = DCACHE_BUCKET_SZ - 1;
|
||
|
|
||
|
if((lines[j].info & (DCACHE_ADDR_MASK | DCACHE_USED_MASK)) == (va | DCACHE_USED_MASK)){ //found it!
|
||
|
|
||
|
if(sz == 4){
|
||
|
*(UInt32*)buf = *(UInt32*)(lines[j].data + off);
|
||
|
}
|
||
|
else if(sz == 2){
|
||
|
*(UInt16*)buf = *(UInt16*)(lines[j].data + off);
|
||
|
}
|
||
|
else __mem_copy(buf, lines[j].data + off, sz);
|
||
|
return priviledged || !(lines[j].info & DCACHE_PRIV_MASK);
|
||
|
}
|
||
|
}
|
||
|
//if we're here, we found nothing - time to populate the cache
|
||
|
j = dc->ptr[bucket]++;
|
||
|
if(dc->ptr[bucket] == DCACHE_BUCKET_SZ) dc->ptr[bucket] = 0;
|
||
|
line = lines + j;
|
||
|
|
||
|
line->info = va | (priviledged ? DCACHE_PRIV_MASK : 0);
|
||
|
if(!dc->memF(dc->cpu, line->data, va, DCACHE_LINE_SZ, false, priviledged, fsrP)){
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
line->info |= DCACHE_USED_MASK;
|
||
|
|
||
|
if(sz == 4){
|
||
|
*(UInt32*)buf = *(UInt32*)(line->data + off);
|
||
|
}
|
||
|
else if(sz == 2){
|
||
|
*(UInt16*)buf = *(UInt16*)(line->data + off);
|
||
|
}
|
||
|
else __mem_copy(buf, line->data + off, sz);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
#include "stdio.h"
|
||
|
Boolean _dcache_test_func(dcache* dc, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
|
||
|
|
||
|
UInt8 fsrO = -1, fsrT = -1;
|
||
|
UInt8 dataO[4] = {0}, dataT[4] = {0};
|
||
|
Boolean retO, retT;
|
||
|
UInt8 i;
|
||
|
|
||
|
retO = _dcache_fetch_func(dc, va, sz, priviledged, &fsrO, dataO);
|
||
|
retT = dc->memF(dc->cpu, dataT, va, sz, false, priviledged, &fsrT);
|
||
|
|
||
|
if((retT != retO) || (fsrT != fsrO) || (dataT[0] != dataO[0]) || (dataT[1] != dataO[1]) || (dataT[2] != dataO[2]) || (dataT[3] != dataO[3])){
|
||
|
|
||
|
fprintf(stderr, "dcache fail!");
|
||
|
}
|
||
|
|
||
|
for(i = 0; i < sz; i++) ((UInt8*)buf)[i] = dataT[i];
|
||
|
if(retT) *fsrP = fsrT;
|
||
|
return retT;
|
||
|
}
|
||
|
|