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
2 years ago
|
#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;
|
||
|
}
|