You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			174 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
			
		
		
	
	
			174 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
| #include <stdint.h>
 | |
| #include <stdbool.h>
 | |
| 
 | |
| #include "console.h"
 | |
| 
 | |
| 
 | |
| #define asm     __asm__ volatile
 | |
| 
 | |
| #define MMCR0   795
 | |
| #define MMCR1   798
 | |
| #define MMCR2   785
 | |
| #define MMCRA   786
 | |
| #define PMC1    771
 | |
| #define PMC2    772
 | |
| #define PMC3    773
 | |
| #define PMC4    774
 | |
| #define PMC5    775
 | |
| #define PMC6    776
 | |
| 
 | |
| #define MMCR0_FC    0x80000000 // Freeze Counters
 | |
| #define PMC1SEL_FC  0xFC000000 // Load Completed
 | |
| #define PMC2SEL_F0  0x00F00000 // Store Completed
 | |
| 
 | |
| #define TEST "Test "
 | |
| #define PASS "PASS\n"
 | |
| #define FAIL "FAIL\n"
 | |
| 
 | |
| static inline unsigned long mfspr(int sprnum)
 | |
| {
 | |
| 	unsigned long val;
 | |
| 
 | |
| 	asm("mfspr %0,%1" : "=r" ((unsigned long) val) : "i" (sprnum));
 | |
| 	return val;
 | |
| }
 | |
| 
 | |
| static inline void mtspr(int sprnum, unsigned long val)
 | |
| {
 | |
| 	asm("mtspr %0,%1" : : "i" (sprnum), "r" ((unsigned long) val));
 | |
| }
 | |
| 
 | |
| void print_test_number(int i)
 | |
| {
 | |
| 	puts(TEST);
 | |
| 	putchar(48 + i/10);
 | |
| 	putchar(48 + i%10);
 | |
| 	putchar(':');
 | |
| }
 | |
| 
 | |
| void reset_pmu() {
 | |
| 	mtspr(MMCR0, MMCR0_FC);
 | |
| 	mtspr(MMCR1, 0);
 | |
| 	mtspr(PMC1, 0);
 | |
| 	mtspr(PMC2, 0);
 | |
| 	mtspr(PMC3, 0);
 | |
| 	mtspr(PMC4, 0);
 | |
| 	mtspr(PMC5, 0);
 | |
| 	mtspr(PMC6, 0);
 | |
| }
 | |
| 
 | |
| /*
 | |
| 	Sets PMC1 to count finished load instructions
 | |
| 	Runs 50 load instructions
 | |
| 	Expects PMC1 to be 50 at the end
 | |
| */
 | |
| int test_load_complete()
 | |
| {
 | |
| 	reset_pmu();
 | |
| 	unsigned long volatile b = 0;
 | |
| 	mtspr(MMCR1, PMC1SEL_FC);
 | |
| 	mtspr(MMCR0, 0);
 | |
| 
 | |
| 	for(int i = 0; i < 50; i++)
 | |
| 		++b;
 | |
| 
 | |
| 	mtspr(MMCR0, MMCR0_FC);
 | |
| 
 | |
| 	return mfspr(PMC1) == 50;
 | |
| }
 | |
| 
 | |
| /*
 | |
| 	Sets PMC2 to count finished store instructions
 | |
| 	Runs 50 store instructions
 | |
| 	Expects PMC2 to be 50 at the end
 | |
| */
 | |
| int test_store_complete()
 | |
| {
 | |
| 	reset_pmu();
 | |
| 	unsigned long volatile b = 0;
 | |
| 	mtspr(MMCR1, PMC2SEL_F0);
 | |
| 	mtspr(MMCR0, 0);
 | |
| 
 | |
| 	for(int i = 0; i < 50; i++)
 | |
| 		++b;
 | |
| 
 | |
| 	mtspr(MMCR0, MMCR0_FC);
 | |
| 
 | |
| 	return mfspr(PMC2) == 50;
 | |
| }
 | |
| 
 | |
| /*
 | |
| 	Allow PMC5 to count finished instructions
 | |
| 	Runs a loop 50 times
 | |
| 	Expects PMC5 to be more than zero at the end
 | |
| */
 | |
| int test_instruction_complete()
 | |
| {
 | |
| 	reset_pmu();
 | |
| 	unsigned long volatile b = 0;
 | |
| 	mtspr(MMCR0, 0);
 | |
| 
 | |
| 	for(int i = 0; i < 50; i++)
 | |
| 		++b;
 | |
| 
 | |
| 	mtspr(MMCR0, MMCR0_FC);
 | |
| 
 | |
| 	return mfspr(PMC5) > 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
| 	Allow PMC6 to count cycles
 | |
| 	Runs a loop 50 times
 | |
| 	Expects PMC6 to be more than zero at the end
 | |
| */
 | |
| int test_count_cycles()
 | |
| {
 | |
|     reset_pmu();
 | |
|     unsigned long volatile b = 0;
 | |
|     mtspr(MMCR0, 0);
 | |
| 
 | |
|     for(int i = 0; i < 50; i++)
 | |
| 	    ++b;
 | |
| 
 | |
|     mtspr(MMCR0, MMCR0_FC);
 | |
| 
 | |
|     return mfspr(PMC6) > 0;
 | |
| }
 | |
| 
 | |
| int main(void)
 | |
| {
 | |
|     int fail = 0;
 | |
| 
 | |
|     console_init();
 | |
| 
 | |
|     print_test_number(1);
 | |
| 	if (test_load_complete() != 1) {
 | |
| 		fail = 1;
 | |
| 		puts(FAIL);
 | |
| 	} else
 | |
| 		puts(PASS);
 | |
| 
 | |
| 	print_test_number(2);
 | |
| 	if (test_store_complete() != 1) {
 | |
| 		fail = 1;
 | |
| 		puts(FAIL);
 | |
| 	} else
 | |
| 		puts(PASS);
 | |
| 
 | |
| 	print_test_number(3);
 | |
| 	if (test_instruction_complete() == 0) {
 | |
| 		fail = 1;
 | |
| 		puts(FAIL);
 | |
| 	} else
 | |
| 		puts(PASS);
 | |
| 
 | |
| 	print_test_number(4);
 | |
| 	if (test_count_cycles() == 0) {
 | |
| 		fail = 1;
 | |
| 		puts(FAIL);
 | |
| 	} else
 | |
| 		puts(PASS);
 | |
| 
 | |
|     return fail;
 | |
| }
 |