URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [branches/] [stable_0_2_x/] [or1ksim/] [testbench/] [cache.c] - Rev 575
Go to most recent revision | Compare with Previous | Blame | View Log
/* Cache test */ #include "support.h" #include "spr_defs.h" #define MEM_RAM 0x40100000 /* Number of IC sets (power of 2) */ #define IC_SETS 512 #define DC_SETS 512 /* Block size in bytes (1, 2, 4, 8, 16, 32 etc.) */ #define IC_BLOCK_SIZE 16 #define DC_BLOCK_SIZE 16 /* Number of IC ways (1, 2, 3 etc.). */ #define IC_WAYS 1 #define DC_WAYS 1 /* Cache size */ #define IC_SIZE (IC_WAYS*IC_SETS*IC_BLOCK_SIZE) #define DC_SIZE (DC_WAYS*DC_SETS*DC_BLOCK_SIZE) /* Memory access macros */ #define REG8(add) *((volatile unsigned char *)(add)) #define REG16(add) *((volatile unsigned short *)(add)) #define REG32(add) *((volatile unsigned long *)(add)) extern void (*jalr)(void); extern void (*jr)(void); /* Index on jump table */ unsigned long jump_indx; /* Jump address table */ unsigned long jump_add[15*IC_WAYS]; void dummy(); void jump_and_link(void) { asm("_jalr:"); asm("l.jr\tr9"); asm("l.nop"); } void jump(void) { asm("_jr:"); /* Read and increment index */ asm("l.lwz\t\tr3,0(r11)"); asm("l.addi\t\tr3,r3,4"); asm("l.sw\t\t0(r11),r3"); /* Load next executin address from table */ asm("l.lwz\t\tr3,0(r3)"); /* Jump to that address */ asm("l.jr\t\tr3") ; /* Report that we succeeded */ asm("l.nop\t2"); } void copy_jr(unsigned long add) { memcpy((void *)add, (void *)&jr, 24); } void call(unsigned long add) { asm("l.movhi\tr11,hi(_jump_indx)" : :); asm("l.ori\tr11,r11,lo(_jump_indx)" : :); asm("l.jalr\t\t%0" : : "r" (add) : "r11", "r9"); asm("l.nop" : :); } void icache_enable(void) { unsigned long add; /* First invalidate the cache. As at this point cache is disabled, the cache acts as it contains image of lowest memory block */ for(add = 1; add <= IC_SIZE; add += IC_BLOCK_SIZE) mtspr(SPR_ICBIR, add); mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_ICE); } void dcache_enable(void) { unsigned long add; /* First invalidate the cache. As at this point cache is disabled, the cache acts as it contains image of lowest memory block */ for(add = 1; add <= DC_SIZE; add += DC_BLOCK_SIZE) mtspr(SPR_DCBIR, add); mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_DCE); } void icache_disable(void) { /* This is write trough cache so we dont have to flush it */ mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_ICE); } void dcache_disable(void) { /* This is write trough cache so we dont have to flush it */ mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_DCE); } int dc_test(void) { int i; unsigned long base, add, ul; base = (((unsigned long)MEM_RAM / (IC_SETS*IC_BLOCK_SIZE)) * IC_SETS*IC_BLOCK_SIZE) + IC_SETS*IC_BLOCK_SIZE; dcache_enable(); /* Cache miss r */ add = base; for(i = 0; i < DC_WAYS; i++) { ul = REG32(add); ul = REG32(add + DC_BLOCK_SIZE); ul = REG32(add + 2*DC_BLOCK_SIZE); ul = REG32(add + 3*DC_BLOCK_SIZE); add += DC_SETS*DC_BLOCK_SIZE; } /* Cache hit w */ add = base; for(i = 0; i < DC_WAYS; i++) { REG32(add + 0) = 0x00000001; REG32(add + DC_BLOCK_SIZE + 4) = 0x00000002; REG32(add + 2*DC_BLOCK_SIZE + 8) = 0x00000003; REG32(add + 3*DC_BLOCK_SIZE + 12) = 0x00000004; add += DC_SETS*DC_BLOCK_SIZE; } /* Cache hit r/w */ add = base; for(i = 0; i < DC_WAYS; i++) { REG8(add + DC_BLOCK_SIZE - 4) = REG8(add + 3); REG8(add + 2*DC_BLOCK_SIZE - 8) = REG8(add + DC_BLOCK_SIZE + 7); REG8(add + 3*DC_BLOCK_SIZE - 12) = REG8(add + 2*DC_BLOCK_SIZE + 11); REG8(add + 4*DC_BLOCK_SIZE - 16) = REG8(add + 3*DC_BLOCK_SIZE + 15); add += DC_SETS*DC_BLOCK_SIZE; } /* Cache hit/miss r/w */ add = base; for(i = 0; i < DC_WAYS; i++) { REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE) = REG16(add + DC_BLOCK_SIZE - 4) + REG16(add + 2); REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE + 2) = REG16(add + DC_BLOCK_SIZE - 8) + REG16(add + DC_BLOCK_SIZE + 6); REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE + 4) = REG16(add + DC_BLOCK_SIZE - 12) + REG16(add + 2*DC_BLOCK_SIZE + 10); REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE + 6) = REG16(add+ DC_BLOCK_SIZE - 16) + REG16(add + 2*DC_BLOCK_SIZE + 14); add += DC_SETS*DC_BLOCK_SIZE; } /* Fill cache with unused data */ add = base + DC_WAYS*DC_SETS*DC_BLOCK_SIZE; for(i = 0; i < DC_WAYS; i++) { ul = REG32(add); ul = REG32(add + DC_BLOCK_SIZE); ul = REG32(add + 2*DC_BLOCK_SIZE); ul = REG32(add + 3*DC_BLOCK_SIZE); add += DC_SETS*DC_BLOCK_SIZE; } /* Cache hit/miss r */ ul = 0; add = base; for(i = 0; i < DC_WAYS; i++) { ul += REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE) + REG16(add + DC_BLOCK_SIZE - 4) + REG16(add + 2); ul += REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE + 2) + REG16(add + DC_BLOCK_SIZE - 8) + REG16(add + DC_BLOCK_SIZE + 6); ul += REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE + 4) + REG16(add + DC_BLOCK_SIZE - 12) + REG16(add + 2*DC_BLOCK_SIZE + 10); ul += REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE + 6) + REG16(add+ DC_BLOCK_SIZE - 16) + REG16(add + 2*DC_BLOCK_SIZE + 14); add += DC_SETS*DC_BLOCK_SIZE; } dcache_disable(); return ul; } int ic_test(void) { int i; unsigned long base, add; base = (((unsigned long)MEM_RAM / (IC_SETS*IC_BLOCK_SIZE)) * IC_SETS*IC_BLOCK_SIZE) + IC_SETS*IC_BLOCK_SIZE; /* Copy jr to various location */ add = base; for(i = 0; i < IC_WAYS; i++) { copy_jr(add); copy_jr(add + 2*IC_BLOCK_SIZE + 4); copy_jr(add + 4*IC_BLOCK_SIZE + 8); copy_jr(add + 6*IC_BLOCK_SIZE + 12); copy_jr(add + (IC_SETS - 2)*IC_BLOCK_SIZE + 0); copy_jr(add + (IC_SETS - 4)*IC_BLOCK_SIZE + 4); copy_jr(add + (IC_SETS - 6)*IC_BLOCK_SIZE + 8); copy_jr(add + (IC_SETS - 8)*IC_BLOCK_SIZE + 12); add += IC_SETS*IC_BLOCK_SIZE; } /* Load execution table which starts at address 4 (at address 0 is table index) */ add = base; for(i = 0; i < IC_WAYS; i++) { /* Cache miss */ jump_add[15*i + 0] = add + 2*IC_BLOCK_SIZE + 4; jump_add[15*i + 1] = add + 4*IC_BLOCK_SIZE + 8; jump_add[15*i + 2] = add + 6*IC_BLOCK_SIZE + 12; /* Cache hit/miss */ jump_add[15*i + 3] = add; jump_add[15*i + 4] = add + (IC_SETS - 2)*IC_BLOCK_SIZE + 0; jump_add[15*i + 5] = add + 2*IC_BLOCK_SIZE + 4; jump_add[15*i + 6] = add + (IC_SETS - 4)*IC_BLOCK_SIZE + 4; jump_add[15*i + 7] = add + 4*IC_BLOCK_SIZE + 8; jump_add[15*i + 8] = add + (IC_SETS - 6)*IC_BLOCK_SIZE + 8; jump_add[15*i + 9] = add + 6*IC_BLOCK_SIZE + 12; jump_add[15*i + 10] = add + (IC_SETS - 8)*IC_BLOCK_SIZE + 12; /* Cache hit */ jump_add[15*i + 11] = add + (IC_SETS - 2)*IC_BLOCK_SIZE + 0; jump_add[15*i + 12] = add + (IC_SETS - 4)*IC_BLOCK_SIZE + 4; jump_add[15*i + 13] = add + (IC_SETS - 6)*IC_BLOCK_SIZE + 8; jump_add[15*i + 14] = add + (IC_SETS - 8)*IC_BLOCK_SIZE + 12; add += IC_SETS*IC_BLOCK_SIZE; } /* Go home */ jump_add[15*i] = (unsigned long)&jalr; /* Initilalize table index */ jump_indx = &jump_add[0]; icache_enable(); /* Go */ call(base); icache_disable(); return 0xdeaddead; } int main(void) { int rc; rc = dc_test(); report(rc + 0xdeaddca1); /* Be aware that this test doesn't report result troug report call. It writes to spr 0x1234 directly (in jump function)!!! This test can not be run on or1ksim. */ rc = ic_test(); report(rc); exit(0); return 0; } /* just for size calculation */ void dummy() { }
Go to most recent revision | Compare with Previous | Blame | View Log