275 lines
5.5 KiB
C
275 lines
5.5 KiB
C
#include "pm_types.h"
|
|
#include "./pm.h"
|
|
#include "./pm_i.h"
|
|
|
|
static __u32 cpu_freq = 0;
|
|
static __u32 overhead = 0;
|
|
static __u32 backup_perf_counter_ctrl_reg = 0;
|
|
static __u32 backup_perf_counter_enable_reg = 0;
|
|
|
|
static __u32 match_event_counter(enum counter_type_e type);
|
|
|
|
void init_perfcounters (__u32 do_reset, __u32 enable_divider)
|
|
{
|
|
// in general enable all counters (including cycle counter)
|
|
__u32 value = 1;
|
|
|
|
// peform reset:
|
|
if (do_reset)
|
|
{
|
|
value |= 2; // reset all counters to zero.
|
|
value |= 4; // reset cycle counter to zero.
|
|
}
|
|
|
|
if (enable_divider)
|
|
value |= 8; // enable "by 64" divider for CCNT.
|
|
|
|
value |= 16;
|
|
|
|
// program the performance-counter control-register:
|
|
asm volatile ("mcr p15, 0, %0, c9, c12, 0" : : "r"(value));
|
|
|
|
// enable all counters:
|
|
value = 0x8000000f;
|
|
asm volatile ("mcr p15, 0, %0, c9, c12, 1" : : "r"(value));
|
|
|
|
// clear overflows:
|
|
asm volatile ("MCR p15, 0, %0, c9, c12, 3" : : "r"(value));
|
|
asm volatile ("dsb");
|
|
asm volatile ("isb");
|
|
|
|
return;
|
|
}
|
|
|
|
void backup_perfcounter(void)
|
|
{
|
|
//backup performance-counter ctrl reg
|
|
asm volatile ("MRC p15, 0, %0, c9, c12, 0\t\n": "=r"(backup_perf_counter_ctrl_reg));
|
|
|
|
//backup enable reg
|
|
asm volatile ("MRC p15, 0, %0, c9, c12, 1\t\n": "=r"(backup_perf_counter_enable_reg));
|
|
|
|
}
|
|
|
|
void restore_perfcounter(void)
|
|
{
|
|
|
|
// restore performance-counter control-register:
|
|
asm volatile ("mcr p15, 0, %0, c9, c12, 0" : : "r"(backup_perf_counter_ctrl_reg));
|
|
|
|
// restore enable reg
|
|
asm volatile ("mcr p15, 0, %0, c9, c12, 1" : : "r"(backup_perf_counter_enable_reg));
|
|
|
|
}
|
|
|
|
__u32 get_cyclecount (void)
|
|
{
|
|
__u32 value;
|
|
// Read CCNT Register
|
|
asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
|
|
return value;
|
|
}
|
|
|
|
void reset_counter(void)
|
|
{
|
|
__u32 value = 0;
|
|
|
|
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(value));
|
|
value |= 4; // reset cycle counter to zero.
|
|
// program the performance-counter control-register:
|
|
//__asm {MCR p15, 0, value, c9, c12, 0}
|
|
asm volatile ("mcr p15, 0, %0, c9, c12, 0" : : "r"(value));
|
|
}
|
|
|
|
void change_runtime_env(void)
|
|
{
|
|
__u32 start = 0;
|
|
__u32 end = 0;
|
|
|
|
//init counters:
|
|
//init_perfcounters (1, 0);
|
|
// measure the counting overhead:
|
|
start = get_cyclecount();
|
|
end = get_cyclecount();
|
|
overhead = (end >= start) ? (end-start) : (0xffffffff - start + end);
|
|
//busy_waiting();
|
|
cpu_freq = mem_clk_get_cpu_freq();
|
|
}
|
|
|
|
/*
|
|
* input para range: 1-1000 us, so the max us_cnt equal = 1008*1000;
|
|
*/
|
|
void delay_us(__u32 us)
|
|
{
|
|
__u32 us_cnt = 0;
|
|
__u32 cur = 0;
|
|
__u32 target = 0;
|
|
__u32 counter_enable = 0;
|
|
//__u32 cnt = 0;
|
|
|
|
|
|
if(cpu_freq > 1000){
|
|
us_cnt = ((raw_lib_udiv(cpu_freq, 1000)) + 1)*us;
|
|
}else{
|
|
//32 <--> 32k, 1cycle = 1s/32k =32us
|
|
goto out;
|
|
}
|
|
|
|
cur = get_cyclecount();
|
|
target = cur - overhead + us_cnt;
|
|
|
|
//judge whether counter is enable
|
|
asm volatile ("mrc p15, 0, %0, c9, c12, 1" :"=r"(counter_enable));
|
|
if( 0x8000000f != (counter_enable&0x8000000f) ){
|
|
init_perfcounters (1, 0);
|
|
}
|
|
#if 1
|
|
while(!counter_after_eq(cur, target)){
|
|
cur = get_cyclecount();
|
|
//cnt++;
|
|
}
|
|
#endif
|
|
|
|
|
|
#if 0
|
|
__s32 s_cur = 0;
|
|
__s32 s_target = 0;
|
|
__s32 result = 0;
|
|
|
|
s_cur = (__s32)(cur);
|
|
s_target = (__s32)(target);
|
|
result = s_cur - s_target;
|
|
if(s_cur - s_target >= 0){
|
|
cnt++;
|
|
}
|
|
while((typecheck(__u32, cur) && \
|
|
typecheck(__u32, target) && \
|
|
((__s32)(cur) - (__s32)(target) >= 0))){
|
|
|
|
s_cur = (__s32)(cur);
|
|
s_target = (__s32)(target);
|
|
if(s_cur - s_target >= 0){
|
|
cnt++;
|
|
}
|
|
cur = get_cyclecount();
|
|
}
|
|
#endif
|
|
//busy_waiting();
|
|
|
|
out:
|
|
|
|
asm("dmb");
|
|
asm("isb");
|
|
return;
|
|
}
|
|
|
|
|
|
//the overflow limit is: 0x7fff,ffff / 720M = 2982ms;
|
|
//each delay cycle can not exceed 10ms, in case of overflow.
|
|
void delay_ms(__u32 ms)
|
|
{
|
|
while(ms > 10){
|
|
delay_us(10*1000);
|
|
ms -= 10;
|
|
}
|
|
|
|
delay_us(ms*1000);
|
|
return;
|
|
}
|
|
|
|
/*============================================== event counter ==========================*/
|
|
static __u32 match_event_counter(enum counter_type_e type)
|
|
{
|
|
int cnter = 0;
|
|
|
|
switch(type){
|
|
case I_CACHE_MISS:
|
|
cnter = 0;
|
|
break;
|
|
case I_TLB_MISS:
|
|
cnter = 1;
|
|
break;
|
|
case D_CACHE_MISS:
|
|
cnter = 2;
|
|
break;
|
|
case D_TLB_MISS:
|
|
cnter = 3;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
return cnter;
|
|
|
|
}
|
|
|
|
void init_event_counter (__u32 do_reset, __u32 enable_divider)
|
|
{
|
|
// in general enable all counters (including cycle counter)
|
|
__u32 value = 1;
|
|
|
|
// peform reset:
|
|
if (do_reset)
|
|
{
|
|
value |= 2; // reset all counters to zero.
|
|
value |= 4; // reset cycle counter to zero.
|
|
}
|
|
|
|
if (enable_divider)
|
|
value |= 8; // enable "by 64" divider for CCNT.
|
|
|
|
value |= 16;
|
|
|
|
// program the performance-counter control-register:
|
|
asm volatile ("mcr p15, 0, %0, c9, c12, 0" : : "r"(value));
|
|
|
|
// enable all counters:
|
|
value = 0x8000000f;
|
|
asm volatile ("mcr p15, 0, %0, c9, c12, 1" : : "r"(value));
|
|
|
|
// clear overflows:
|
|
asm volatile ("MCR p15, 0, %0, c9, c12, 3" : : "r"(value));
|
|
|
|
return;
|
|
}
|
|
|
|
void set_event_counter(enum counter_type_e type)
|
|
{
|
|
|
|
__u32 cnter = 0;
|
|
cnter = match_event_counter(type);
|
|
|
|
//set counter selection reg
|
|
asm volatile ("MCR p15, 0, %0, c9, c12, 5" : : "r"(cnter));
|
|
|
|
//set event type
|
|
asm volatile ("MCR p15, 0, %0, c9, c13, 1" : : "r"(type));
|
|
|
|
asm volatile ("dsb");
|
|
asm volatile ("isb");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
int get_event_counter(enum counter_type_e type)
|
|
{
|
|
int cnter = 0;
|
|
int event_cnt = 0;
|
|
cnter = match_event_counter(type);
|
|
|
|
//set counter selection reg
|
|
asm volatile ("MCR p15, 0, %0, c9, c12, 5" : : "r"(cnter));
|
|
|
|
//read event counter
|
|
asm volatile ("MRC p15, 0, %0, c9, c13, 2\t\n": "=r"(event_cnt));
|
|
|
|
asm volatile ("dsb");
|
|
asm volatile ("isb");
|
|
|
|
return event_cnt;
|
|
}
|
|
|
|
|