RE: Tips on inspecting / debuging cache

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Wayne,

Enclosed please find routines that I developed for PMC-Sierra RM52x1 and RM7000 processors.
Enjoy!

Adam


# Cache Dump - will dump the cache contents from I or D cache.
# Arguments:
# a0 is 0 for I Cache or 1 for D Cache
# a1 is the pointer to the Tag/States Array. Size is Cache Size / 4. There are 2 words per line.
# a2 is the pointer to the Data Array (size equal to the Cache size, MUST be Set Size aligned)
# Note: For user's convenience the pointers can be in KSeg1 or KSeg0.
#
# The TagHi/TagLo registers are stored in an array pointed to by the 2nd argument.
#
# TagHi_Address(Set, Index) = a1 + Set*(SET_SIZE/4) + 8*Index
# TagLo_Address(Set, Index) = a1 + Set*(SET_SIZE/4) + 8*Index + 4
#
# In case of RM52x1 Caches are 32KB total, 2-way set-associative so SET_SIZE is 16KB.
# With 32B line size there are 16KB/32B = 512 lines per Set.
# Thus:
#
# TagHi_Address(Set, Index) = a1 + Set*4096 + 8*Index
# TagLo_Address(Set, Index) = a1 + Set*4096 + 8*Index + 4
#
# Where Set is 0..1 and Index is 0..511.
#
# Cache Data fields are stored in an array pointed to by the 3rd argument.
#
# Line_Data_Address(Set, Index) = a2 + Set*SET_SIZE + Index*32
#
# In case of RM52x1 it is:
#
# Line_Data_Address(Set, Index) = a2 + Set*16384 + Index*32
#
# Note: The Original Physical Address of a cache line has to be calculated based on Tag and Index.
#
# In case of RM52x1 the Physical Address of the cache line is calculated as follows:
#
# PA = ((TagLo & 0xffffff00) << 4) | ((Index*32) & 0x00000fff)
#
# Note: The PA and Data Field are only valid if the line is marked Valid in the TagLo.
# This means that the State field (TagLo[7:6]) must be 3 for D Cache or 2 for I Cache.



#define C0_TAGLO			$28
#define C0_TAGHI			$29

#define Index_Load_Tag_I		4
#define Index_Load_Tag_D		5
#define Index_Store_Tag_I		8
#define Index_Store_Tag_D		9
#define Hit_Writeback_I			24
#define Hit_Writeback_D			25
#define Create_Dirty_Exclusive_D	13

#define ICACHE_VALID			2
#define DCACHE_VALID			3


# Now: 1 is for RM52x1 and 0 is for RM7000

#define RM52x1				1

#if RM52x1
#define CACHE_SIZE			0x00008000
#else
#define CACHE_SIZE			0x00004000
#endif


	.text

	.set noreorder
	.set noat

	.globl cachedmp
	.ent	cachedmp

	.align 5

cachedmp:

# Switch to K1 (optional for D Cache dumping)

	la	t0, 1f
	li	t1, 0x20000000
	or	t0, t1
	jr	t0
	nop
1:

# Read and Modify the Tags/States

	li	t0, 0x80000000				# base address for Index cache ops in t0
	li	t1, 0x80000000+CACHE_SIZE-32		# end address in t1
	li	at, 0x20000000
	or	t2, a1, at				# convert a1 to a K1 address and put to t2
	or	a2, at
	xor	a2, at					# make sure pointer in a2 is a K0 address
	or	t3, a2, zero				# copy a2 to t3
L1:	bne	a0, zero, 1f
	nop
	cache	Index_Load_Tag_I, (t0)
	b	2f
	nop
1:	cache	Index_Load_Tag_D, (t0)
2:	nop ; nop ; nop ; nop
	mfc0	t4, C0_TAGHI
	mfc0	t5, C0_TAGLO
	sw	t4, 0(t2)				# preserve the original Tags/States
	sw	t5, 4(t2)
	li	t7, 0x1ffff000				# mask for PA[28:12]
	and	t7, t3					# mask bits of the pointer in t3
	srl	t7, 4					# t7 is now a Tag for the pointer
#if RM52x1
	li	t6, 0x0000003f
	and	t6, t5					# mask off the PTagLo and PState
	or	t6, t7					# "paste" the Tag value to t6
#else
	mtc0	t7, C0_TAGHI				# in RM7k the Tag is in TAGHI
	li	t6, 0xfff0003f
	and	t6, t5					# mask off the PState
#endif
	bne	a0, zero, 1f				# now set the PState field as valid
	nop
	b	2f
	ori	t6, ICACHE_VALID<<6
1:	ori	t6, DCACHE_VALID<<6
2:	mtc0	t6, C0_TAGLO				# write the new value to TAGLO
	nop ; nop ; nop ; nop
	bne	a0, zero, 1f
	nop
	cache	Index_Store_Tag_I, (t0)			# write back to the cache line states
	b	2f
	nop
1:	cache	Index_Store_Tag_D, (t0)
2:	addiu	t2, 8
	addiu	t3, 32
	bne	t0, t1, L1
	addiu	t0, 32

# For D Cache need to touch the lines in order to set the W bits (make them Dirty)
# We can not use Create_Dirty_Exclusive because it would clear the data fields.
# Therefore we read and store back a word in every line.

	beq	a0, zero, 1f				# Skip for I Cache
	nop

	or	t0, a2, zero
	li	t1, CACHE_SIZE-32
	addu	t1, t0
L2:	lw	t2, (t0)
	sw	t2, (t0)
	bne	t0, t1, L2
	addiu	t0, 32
1:

# Now Write Back the cache contents

	or	t0, a2, zero
	li	t1, CACHE_SIZE-32
	addu	t1, t0
L3:	bne	a0, zero, 1f
	nop
	cache	Hit_Writeback_I, (t0)
	b	2f
	nop
1:	cache	Hit_Writeback_D, (t0)
2:	bne	t0, t1, L3
	addiu	t0, 32

	jr	ra
	nop

	.end	cachedmp

##############################

/* Now: 1 is for RM52x1 and 0 is for RM7000 */

#define RM52x1				1


#if RM52x1
#define CACHE_SIZE	0x00008000
#define SET			2
#else
#define CACHE_SIZE	0x00004000
#define SET			4
#endif

#define SET_SIZE		(CACHE_SIZE/SET)
#define INDEX		SET_SIZE/32

#define Tag_Array_1	0xa0208000
#define Data_Array_1	0xa0200000
#define Tag_Array_2	0xa0218000
#define Data_Array_2	0xa0210000

unsigned char serial_buffer[250];

CacheDisplay(unsigned long TagsAddr, unsigned long DataAddr)
{ int Set, Index, i;
  unsigned long TAGHI, TAGLO, PA, State, Word, *CurrentTags, *CurrentWord;

CurrentTags=(unsigned long *)TagsAddr;

#if RM52x1
CurrentWord=(unsigned long *)DataAddr;
#else
CurrentWord=(unsigned long *)(DataAddr&0xdfffffff);
#endif
/* For RM7k we need to read the written-back data cached just in case it ends up in L2 */

for(Set=0; Set<SET; Set++)
    for(Index=0; Index<INDEX; Index++)
        { sprintf(serial_buffer, "\n\rSet: %d, Index: %03d", Set, Index);
          dumpstr(serial_buffer);
          TAGHI=*CurrentTags++;
          TAGLO=*CurrentTags++;
          sprintf(serial_buffer, "\n\rTAGHI=0x%08x, TAGLO=0x%08x", TAGHI, TAGLO);
          dumpstr(serial_buffer);
#if RM52x1
          PA=((TAGLO & 0xffffff00) << 4) | ((Index*32) & 0x00000fff);
#else
          PA=((TAGHI & 0xffffff00) << 4) | ((Index*32) & 0x00000fff);
#endif
          State=(TAGLO & 0x000000c0)>>6;
          sprintf(serial_buffer, "\n\rPA=0x%08x, State=0x%x, Data Words:\n\r", PA, State);
          dumpstr(serial_buffer);
          for(i=0; i<8; i++)
             { Word=*CurrentWord++;
               sprintf(serial_buffer, "%08x ", Word);
               dumpstr(serial_buffer);
             }
          dumpstr("\n\r");
        }
}

main()
{ 
dumpstr("\n\rRunning the cachedmp for D Cache\n\r");
cachedmp(1, Tag_Array_1, Data_Array_1);
CacheDisplay(Tag_Array_1, Data_Array_1);
dumpstr("\n\rRunning the cachedmp for I Cache\n\r");
cachedmp(0, Tag_Array_2, Data_Array_2);
CacheDisplay(Tag_Array_2, Data_Array_2);
}




-----Original Message-----
From: Wayne Gowcher [mailto:wgowcher@yahoo.com]
Sent: Thursday, March 13, 2003 6:13 PM
To: linux-mips@linux-mips.org
Subject: Tips on inspecting / debuging cache


Dear List,

I am wondering if someone could point me towards
articles / source code that would give me a little
insight into how to debug cache problems in mips.

For example , how do I inspect the contents of the
cache ? Are there routines to dump out the contents of
the cache ?

Any help, tips , pointers would be appreciated.

TIA

Wayne 



__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - establish your business online
http://webhosting.yahoo.com


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux