2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include "mvCpuCntrs.h"
21 const static MV_CPU_CNTRS_OPS mvCpuCntrsOpsTbl
[MV_CPU_CNTRS_NUM
][MV_CPU_CNTRS_OPS_NUM
] =
25 MV_CPU_CNTRS_CYCLES
, MV_CPU_CNTRS_DCACHE_READ_HIT
, MV_CPU_CNTRS_DCACHE_READ_MISS
,
26 MV_CPU_CNTRS_DCACHE_WRITE_HIT
, MV_CPU_CNTRS_DCACHE_WRITE_MISS
, MV_CPU_CNTRS_INSTRUCTIONS
,
27 MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_INVALID
,
28 MV_CPU_CNTRS_MMU_READ_LATENCY
, MV_CPU_CNTRS_ICACHE_READ_LATENCY
, MV_CPU_CNTRS_WB_WRITE_LATENCY
,
29 MV_CPU_CNTRS_LDM_STM_HOLD
, MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_INVALID
,
30 MV_CPU_CNTRS_DATA_WRITE_ACCESS
, MV_CPU_CNTRS_DATA_READ_ACCESS
, MV_CPU_CNTRS_INVALID
,
31 MV_CPU_CNTRS_BRANCH_PREDICT_COUNT
,
35 MV_CPU_CNTRS_CYCLES
, MV_CPU_CNTRS_ICACHE_READ_MISS
, MV_CPU_CNTRS_DCACHE_READ_MISS
,
36 MV_CPU_CNTRS_DCACHE_WRITE_MISS
, MV_CPU_CNTRS_ITLB_MISS
, MV_CPU_CNTRS_SINGLE_ISSUE
,
37 MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_BRANCH_RETIRED
, MV_CPU_CNTRS_INVALID
,
38 MV_CPU_CNTRS_MMU_READ_BEAT
, MV_CPU_CNTRS_ICACHE_READ_LATENCY
, MV_CPU_CNTRS_WB_WRITE_BEAT
,
39 MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_IS_HOLD
, MV_CPU_CNTRS_DATA_READ_ACCESS
,
40 MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_INVALID
,
45 MV_CPU_CNTRS_CYCLES
, MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_DCACHE_ACCESS
,
46 MV_CPU_CNTRS_DTLB_MISS
, MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_INVALID
,
47 MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_BRANCH_PREDICT_MISS
, MV_CPU_CNTRS_WB_WRITE_BEAT
,
48 MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_DCACHE_READ_LATENCY
, MV_CPU_CNTRS_DCACHE_WRITE_LATENCY
,
49 MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_BIU_SIMULT_ACCESS
,
50 MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_INVALID
,
55 MV_CPU_CNTRS_CYCLES
, MV_CPU_CNTRS_DCACHE_READ_MISS
, MV_CPU_CNTRS_DCACHE_WRITE_MISS
,
56 MV_CPU_CNTRS_TLB_MISS
, MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_INVALID
,
57 MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_BRANCH_TAKEN
, MV_CPU_CNTRS_WB_FULL_CYCLES
,
58 MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_DCACHE_READ_BEAT
, MV_CPU_CNTRS_DCACHE_WRITE_BEAT
,
59 MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_BIU_ANY_ACCESS
,
60 MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_INVALID
, MV_CPU_CNTRS_DATA_WRITE_ACCESS
,
65 MV_CPU_CNTRS_ENTRY mvCpuCntrsTbl
[MV_CPU_CNTRS_NUM
];
67 MV_CPU_CNTRS_EVENT
* mvCpuCntrsEventTbl
[128];
69 void mvCpuCntrsReset(void)
73 MV_ASM ("mcr p15, 0, %0, c15, c13, 0" : : "r" (reg
));
74 MV_ASM ("mcr p15, 0, %0, c15, c13, 1" : : "r" (reg
));
75 MV_ASM ("mcr p15, 0, %0, c15, c13, 2" : : "r" (reg
));
76 MV_ASM ("mcr p15, 0, %0, c15, c13, 3" : : "r" (reg
));
77 MV_ASM ("mcr p15, 0, %0, c15, c13, 4" : : "r" (reg
));
78 MV_ASM ("mcr p15, 0, %0, c15, c13, 5" : : "r" (reg
));
79 MV_ASM ("mcr p15, 0, %0, c15, c13, 6" : : "r" (reg
));
80 MV_ASM ("mcr p15, 0, %0, c15, c13, 7" : : "r" (reg
));
83 void program_counter(int counter
, int op
)
85 MV_U32 reg
= (1 << op
) | 0x1; /*enable*/
90 __asm__
__volatile__ ("mcr p15, 0, %0, c15, c12, 0" : : "r" (reg
));
94 __asm__
__volatile__ ("mcr p15, 0, %0, c15, c12, 1" : : "r" (reg
));
98 __asm__
__volatile__ ("mcr p15, 0, %0, c15, c12, 2" : : "r" (reg
));
102 __asm__
__volatile__ ("mcr p15, 0, %0, c15, c12, 3" : : "r" (reg
));
106 mvOsPrintf("error in program_counter: bad counter number (%d)\n", counter
);
111 void mvCpuCntrsEventClear(MV_CPU_CNTRS_EVENT
* pEvent
)
115 for(i
=0; i
<MV_CPU_CNTRS_NUM
; i
++)
117 pEvent
->counters_sum
[i
] = 0;
119 pEvent
->num_of_measurements
= 0;
123 MV_CPU_CNTRS_EVENT
* mvCpuCntrsEventCreate(char* name
, MV_U32 print_threshold
)
126 MV_CPU_CNTRS_EVENT
* event
= mvOsMalloc(sizeof(MV_CPU_CNTRS_EVENT
));
130 strncpy(event
->name
, name
, sizeof(event
->name
));
131 event
->num_of_measurements
= 0;
132 event
->avg_sample_count
= print_threshold
;
133 for(i
=0; i
<MV_CPU_CNTRS_NUM
; i
++)
135 event
->counters_before
[i
] = 0;
136 event
->counters_after
[i
] = 0;
137 event
->counters_sum
[i
] = 0;
143 void mvCpuCntrsEventDelete(MV_CPU_CNTRS_EVENT
* event
)
150 MV_STATUS
mvCpuCntrsProgram(int counter
, MV_CPU_CNTRS_OPS op
,
151 char* name
, MV_U32 overhead
)
155 /* Find required operations */
156 for(i
=0; i
<MV_CPU_CNTRS_OPS_NUM
; i
++)
158 if( mvCpuCntrsOpsTbl
[counter
][i
] == op
)
160 strncpy(mvCpuCntrsTbl
[counter
].name
, name
, sizeof(mvCpuCntrsTbl
[counter
].name
));
161 mvCpuCntrsTbl
[counter
].operation
= op
;
162 mvCpuCntrsTbl
[counter
].opIdx
= i
+1;
163 mvCpuCntrsTbl
[counter
].overhead
= overhead
;
164 program_counter(counter
, mvCpuCntrsTbl
[counter
].opIdx
);
165 mvOsPrintf("Counter=%d, opIdx=%d, overhead=%d\n",
166 counter
, mvCpuCntrsTbl
[counter
].opIdx
, mvCpuCntrsTbl
[counter
].overhead
);
173 void mvCpuCntrsShow(MV_CPU_CNTRS_EVENT
* pEvent
)
178 if(pEvent
->num_of_measurements
< pEvent
->avg_sample_count
)
181 mvOsPrintf("%16s: ", pEvent
->name
);
182 for(i
=0; i
<MV_CPU_CNTRS_NUM
; i
++)
184 counters_avg
= mvOsDivMod64(pEvent
->counters_sum
[i
],
185 pEvent
->num_of_measurements
, NULL
);
186 if(counters_avg
>= mvCpuCntrsTbl
[i
].overhead
)
187 counters_avg
-= mvCpuCntrsTbl
[i
].overhead
;
191 mvOsPrintf("%s=%5llu, ", mvCpuCntrsTbl
[i
].name
, counters_avg
);
194 mvCpuCntrsEventClear(pEvent
);
198 void mvCpuCntrsStatus(void)
202 for(i
=0; i
<MV_CPU_CNTRS_NUM
; i
++)
204 mvOsPrintf("#%d: %s, overhead=%d\n",
205 i
, mvCpuCntrsTbl
[i
].name
, mvCpuCntrsTbl
[i
].overhead
);