OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_47/] [or1ksim/] [testbench/] [cache.c] - Rev 349

Go to most recent revision | Compare with Previous | Blame | View Log

/* Cache test */
#include "support.h"
#include "spr_defs.h"
 
/* 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);
 
void dummy();
 
void jump_and_link(void) 
{
	asm("_jalr:");
}
 
void jump(void)
{
	asm("_jr:");
	/* Read and increment index */
	asm("l.lwz\t\tr3,0(r0)");
	asm("l.addi\t\tr3,r3,4");
	asm("l.sw\t\t0(r0),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.mtspr\t\tr0,r3,0x1234");
}
 
void copy_jr(unsigned long add)
{
	memcpy((void *)add, (void *)&jr, 24);
}
 
void call(unsigned long add)
{
	asm("l.jr\t\t%0" : : "r" (add) : "r11");
	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)&dummy / (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)&dummy / (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 */
                REG32(0x3c*i + 0x04) = add + 2*IC_BLOCK_SIZE + 4;
                REG32(0x3c*i + 0x08) = add + 4*IC_BLOCK_SIZE + 8;
                REG32(0x3c*i + 0x0c) = add + 6*IC_BLOCK_SIZE + 12;
                /* Cache hit/miss */
                REG32(0x3c*i + 0x10) = add;
                REG32(0x3c*i + 0x14) = add + (IC_SETS - 2)*IC_BLOCK_SIZE + 0;
                REG32(0x3c*i + 0x18) = add + 2*IC_BLOCK_SIZE + 4;
                REG32(0x3c*i + 0x1c) = add + (IC_SETS - 4)*IC_BLOCK_SIZE + 4;
                REG32(0x3c*i + 0x20) = add + 4*IC_BLOCK_SIZE + 8;
                REG32(0x3c*i + 0x24) = add + (IC_SETS - 6)*IC_BLOCK_SIZE + 8;
                REG32(0x3c*i + 0x28) = add + 6*IC_BLOCK_SIZE + 12;
                REG32(0x3c*i + 0x2c) = add + (IC_SETS - 8)*IC_BLOCK_SIZE + 12;
                /* Cache hit */
                REG32(0x3c*i + 0x30) = add + (IC_SETS - 2)*IC_BLOCK_SIZE + 0;
                REG32(0x3c*i + 0x34) = add + (IC_SETS - 4)*IC_BLOCK_SIZE + 4;
                REG32(0x3c*i + 0x38) = add + (IC_SETS - 6)*IC_BLOCK_SIZE + 8;
                REG32(0x3c*i + 0x3c) = add + (IC_SETS - 8)*IC_BLOCK_SIZE + 12;
 
                add += IC_SETS*IC_BLOCK_SIZE;
        }
 
        /* Go home */
        REG32(0x3c*i + 4) = (unsigned long)&jalr;
 
        /* Initilalize table index */
        REG32(0) = 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);
}
 
/* just for size calculation */
void dummy() 
{
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.