1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 34
35
36 package ti.sysbios.family.arm.v8a;
37
38 import xdc.rov.ViewInfo;
39 import xdc.runtime.Assert;
40
41 import ti.sysbios.hal.Hwi;
42
43 /*!
44 * ======== Pmu ========
45 * ARM Performance Monitoring Unit module
46 *
47 * This module manages the performance monitor unit's counters on ARM v8A
48 * processors. This module does not manage the cycle counter. The cycle
49 * counter is managed by the Timestamp module on most ARM cores.
50 *
51 * The following is an example of how to configure one of the Pmu counters
52 * to count L2 cache access events on a Cortex-A53 processor:
53 *
54 * C source file:
55 * @p(code)
56 * #include <ti/sysbios/family/arm/v8a/Pmu.h>
57 *
58 * Int main(Int argc, char *argv[])
59 * {
60 * // Set L2 cache access as the event type for event counter 0.
61 * // The event number corresponding to each event type can be determined
62 * // using the ARMv8A architecture reference manual.
63 * Pmu_configureCounter(0, 0x16, FALSE);
64 *
65 * // Reset the count
66 * Pmu_resetCount(0);
67 *
68 * // Start the counter
69 * Pmu_startCounter(0);
70 *
71 * // code
72 * ...
73 *
74 * // Stop the counter
75 * Pmu_stopCounter(0);
76 *
77 * // Read and print the count
78 * System_printf("L2 access count: %d\n", Pmu_getCount(0));
79 *
80 * return 0;
81 * }
82 * @p
83 *
84 * *.cfg file:
85 * @p(code)
86 * var Pmu = xdc.useModule('ti.sysbios.family.arm.v8a.Pmu');
87 * @p
88 *
89 * @p(html)
90 * <h3> Calling Context </h3>
91 * <table border="1" cellpadding="3">
92 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
93 * </colgroup>
94 *
95 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
96 * <th> Task </th><th> Main </th><th> Startup </th></tr>
97 * <!-- -->
98 * <tr><td> {@link #configureCounter} </td><td> Y </td>
99 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
100 * <tr><td> {@link #clearOverflowStatus} </td><td> Y </td>
101 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
102 * <tr><td> {@link #disableInterrupt} </td><td> Y </td>
103 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
104 * <tr><td> {@link #enableInterrupt} </td><td> Y </td>
105 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
106 * <tr><td> {@link #getCount} </td><td> Y </td><td> Y </td>
107 * <td> Y </td><td> Y </td><td> N </td></tr>
108 * <tr><td> {@link #getOverflowStatus} </td><td> Y </td>
109 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
110 * <tr><td> {@link #resetCount} </td><td> Y </td><td> Y </td>
111 * <td> Y </td><td> Y </td><td> N </td></tr>
112 * <tr><td> {@link #setCount} </td><td> Y </td><td> Y </td>
113 * <td> Y </td><td> Y </td><td> N </td></tr>
114 * <tr><td> {@link #setInterruptFunc} </td><td> Y </td>
115 * <td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
116 * <tr><td> {@link #startCounter} </td><td> Y </td><td> Y </td>
117 * <td> Y </td><td> Y </td><td> N </td></tr>
118 * <tr><td> {@link #stopCounter} </td><td> Y </td><td> Y </td>
119 * <td> Y </td><td> Y </td><td> N </td></tr>
120 * <tr><td colspan="6"> Definitions: <br />
121 * <ul>
122 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
123 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
124 * <li> <b>Task</b>: API is callable from a Task thread. </li>
125 * <li> <b>Main</b>: API is callable during any of these phases: </li>
126 * <ul>
127 * <li> In your module startup after this module is started
128 * (e.g. PerfMonitor_Module_startupDone() returns TRUE). </li>
129 * <li> During xdc.runtime.Startup.lastFxns. </li>
130 * <li> During main().</li>
131 * <li> During BIOS.startupFxns.</li>
132 * </ul>
133 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
134 * <ul>
135 * <li> During xdc.runtime.Startup.firstFxns.</li>
136 * <li> In your module startup before this module is started
137 * (e.g. Cache_Module_startupDone() returns FALSE).</li>
138 * </ul>
139 * </ul>
140 * </td></tr>
141 *
142 * </table>
143 * @p
144 */
145
146 @ModuleStartup
147 @DirectCall
148 module Pmu
149 {
150 /*!
151 * ======== intNum ========
152 * A Hwi is created for the interrupt number 'pmuIntNum'
153 *
154 * pmuIntNum specifies the interrupt number that is connected to the
155 * nPMUIRQ signal from the PMU module.
156 */
157 config UInt intNum = (~0);
158
159 /*! Pmu interrupt handler function type definition. */
160 typedef Void (*IntHandlerFuncPtr)(UArg);
161
162 /*!
163 * ======== ModView ========
164 * @_nodoc
165 */
166 metaonly struct PmuInfoView {
167 UInt numEventCounters; 168
169 };
170
171 /*!
172 * ======== rovViewInfo ========
173 * @_nodoc
174 */
175 @Facet
176 metaonly config ViewInfo.Instance rovViewInfo =
177 ViewInfo.create({
178 viewMap: [
179 ['Pmu Info', { type: ViewInfo.MODULE_DATA,
180 viewInitFxn: 'viewInitPmuInfo',
181 structName: 'PmuInfoView'}],
182 ]
183 });
184
185 /*!
186 * ======== A_badIntNum ========
187 * Assert raised when module cannot determine PMU interrupt number
188 * for the given target/platform and the user is not providing the
189 * interrupt number using intNum config param.
190 */
191 config xdc.runtime.Assert.Id A_badIntNum = {
192 msg: "A_badIntNum: Set PMU interrupt number using Pmu.intNum config param."
193 };
194
195 /*!
196 * ======== A_invalidCounterId ========
197 * Assert raised when invalid PMU counter Id passed.
198 */
199 config xdc.runtime.Assert.Id A_invalidCounterId = {
200 msg: "A_invalidCounterId: Invalid PMU counter Id passed."
201 };
202
203 /*!
204 * ======== interruptFunc ========
205 * PMU overflow interrupt callback function pointer
206 *
207 * When a counter overflow interrupt occurs, the registered
208 * callback function is called with the contents of the Overflow
209 * Flag Status Register passed as an argument. The overflow
210 * status flag can be used to determine which counter generated
211 * the interrupt when multiple counters are running with
212 * overflow interrupt enabled.
213 */
214 metaonly config IntHandlerFuncPtr interruptFunc = null;
215
216 /*!
217 * ======== setInterruptFunc ========
218 * Set callback function
219 *
220 * When a counter overflow interrupt occurs, the registered
221 * callback function is called with the contents of the Overflow
222 * Flag Status Register passed as an argument. The overflow
223 * status flag can be used to determine which counter generated
224 * the interrupt when multiple counters are running with
225 * overflow interrupt enabled.
226 *
227 * Setting the callback function through this API overrides
228 * the callback function set through {@link #interruptFunc} config param.
229 *
230 * @param(interruptFunc) Callback function
231 */
232 Void setInterruptFunc(IntHandlerFuncPtr interruptFunc);
233
234 /*!
235 * ======== startCounter ========
236 * Start an event counter
237 *
238 * @param(counterId) Event counter Id
239 */
240 Void startCounter(UInt counterId);
241
242 /*!
243 * ======== stopCounter ========
244 * Stop an event counter
245 *
246 * @param(counterId) Event counter Id
247 */
248 Void stopCounter(UInt counterId);
249
250 /*!
251 * ======== resetCount ========
252 * Reset the event counter's count to 0
253 *
254 * @param(counterId) Event counter Id
255 */
256 Void resetCount(UInt counterId);
257
258 /*!
259 * ======== setCount ========
260 * Set the event counter's count to counterVal.
261 *
262 * @param(counterId) Event counter Id
263 * @param(counterVal) Counter value to set
264 */
265 Void setCount(UInt counterId, UInt32 counterVal);
266
267 /*!
268 * ======== configureCounter ========
269 * Set the event type for an event counter and enable/disable
270 * interrupt generation on a counter overflow
271 *
272 * This function disables/stops the counter, sets the new event type,
273 * enables/disables interrupt generation and then re-enables the
274 * counter if it was enabled before.
275 *
276 * Please refer the device's Technical Reference Manual for a list of
277 * supported event types and their corresponding event numbers.
278 *
279 * @param(counterId) Event counter Id
280 * @param(eventNum) Event number
281 * @param(interruptEnable) Enable/Disable Interrupt generation
282 */
283 Void configureCounter(UInt counterId, UInt eventNum, Bool interruptEnable);
284
285 /*!
286 * ======== enableInterrupt ========
287 * Enable interrupt generation on a counter overflow
288 *
289 * @param(counterId) Event counter Id
290 */
291 Void enableInterrupt(UInt counterId);
292
293 /*!
294 * ======== disableInterrupt ========
295 * Disable interrupt generation on a counter overflow
296 *
297 * @param(counterId) Event counter Id
298 */
299 Void disableInterrupt(UInt counterId);
300
301 /*!
302 * ======== clearOverflowStatus ========
303 * Clear overflow status flag
304 *
305 * @param(counterId) Event counter Id
306 */
307 Void clearOverflowStatus(UInt counterId);
308
309 /*!
310 * ======== getCount ========
311 * Read the event count
312 *
313 * @param(counterId) Event counter Id
314 * @b(returns) Event count
315 */
316 UInt32 getCount(UInt counterId);
317
318 /*!
319 * ======== getNumCounters ========
320 * Reads and returns the number of event counters
321 * implemented in HW.
322 */
323 UInt getNumCounters();
324
325 /*!
326 * ======== getOverflowStatus ========
327 * Returns a boolean indicating status of overflow flag
328 *
329 * @param(counterId) Event counter Id
330 * @b(returns) Overflow status
331 */
332 Bool getOverflowStatus(UInt counterId);
333
334 /*!
335 * @_nodoc
336 * ======== getEnabled ========
337 * Get the bit mask of counter enable.
338 */
339 UInt32 getEnabled();
340
341 /*!
342 * @_nodoc
343 * ======== startCounterI ========
344 * Internal inline asm implementation.
345 */
346 Void startCounterI(UInt counterId);
347
348 /*!
349 * @_nodoc
350 * ======== stopCounterI ========
351 * Internal inline asm implementation.
352 */
353 Void stopCounterI(UInt counterId);
354
355 /*!
356 * @_nodoc
357 * ======== resetCountI ========
358 * Internal inline asm implementation.
359 */
360 Void resetCountI(UInt counterId);
361
362 /*!
363 * @_nodoc
364 * ======== setCountI ========
365 * Internal inline asm implementation.
366 */
367 Void setCountI(UInt counterId, UInt32 counterVal);
368
369 /*!
370 * @_nodoc
371 * ======== enableInterruptI ========
372 * Internal inline asm implementation.
373 */
374 Void enableInterruptI(UInt counterId);
375
376 /*!
377 * @_nodoc
378 * ======== disableInterruptI ========
379 * Internal inline asm implementation.
380 */
381 Void disableInterruptI(UInt counterId);
382
383 /*!
384 * @_nodoc
385 * ======== clearOverflowStatusI ========
386 * Internal inline asm implementation.
387 */
388 Void clearOverflowStatusI(UInt counterId);
389
390 /*!
391 * @_nodoc
392 * ======== getCountI ========
393 * Internal inline asm implementation.
394 */
395 UInt32 getCountI(UInt counterId);
396
397 /*!
398 * @_nodoc
399 * ======== getOverflowStatusI ========
400 * Internal inline asm implementation.
401 */
402 UInt32 getOverflowStatusI(UInt counterId);
403
404 internal:
405
406 407 408 409
410 Void configureCounterI(UInt counterId, UInt eventNum);
411
412 413 414 415
416 Void clearOverflowStatusReg(UInt32 clearMask);
417
418 419 420 421
422 UInt32 getOverflowStatusReg();
423
424 425 426 427 428 429 430
431 Void initCounters(UInt32 counterMask);
432
433 434 435 436
437 Void interruptHandler(UArg arg);
438
439 struct Module_State {
440 UInt numCounters; 441
442 Hwi.Handle hwiHandle;
443 IntHandlerFuncPtr interruptFunc;
444 }
445 }