PRSDK-7323: utils/profiling: Fixing errors with CPLUSPLUS build
[processor-sdk/pdk.git] / packages / ti / utils / profiling / src / profilingHooksR5.c
1 /*
2  * Copyright (c) 2018-2019, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /**
33  *  @file    profilingHooksR5.c
34  *
35  *  @brief   R5 Implementations of the runtime programming hooks of the Processor SDK Profiling Tool.
36  *
37  *  For more information, see:
38  *  - @subpage profCCS
39  *  - @subpage profDSS
40  *
41  *  ## Usage ##
42  *
43  *  Applications that are included in a profiling session must  set these
44  *  compiler flags for the desired platform:
45  *    - ARM: `-finstrument-functions -gdwarf-3 -g`
46  *    - DSP: `--entry_parm=address --exit_hook=ti_utils_exit --exit_parm=address --entry_hook=ti_utils_entry -g`
47  *    - M4: `--entry_parm=address --exit_hook=ti_utils_exit --exit_parm=address --entry_hook=ti_utils_entry -g`
48  *
49  *  The `_ENABLE_BM` flag is used to indicate in a class at compiletime whether
50  *  or not profiling is being used.
51  *
52  *  For best results, ensure that the optimization levels are consistent between
53  *  the library and the project (typically -O3, or optimization level 3).
54  *
55  */
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <stdint.h>
60 #include "profilingHooks.h"
61 #include <ti/csl/arch/r5/csl_arm_r5_pmu.h>
63 int32_t CurrentTaskHookSetId, MaxTaskHookSetId;
65 /*!
66  *  @brief    Maximum log count
67  *
68  *  This is a predefined value to indicate when the instrumentation hooks should
69  *  stop logging data. This is important for applications that have long polling
70  *  loops or a device that has a small cache.
71  */
72 #define MAX_LOG (1U*1024U*1024U)
74 uint32_t log_idx = 0;
75 uint32_t lvl = 0;
77 /*!
78  *  @brief    Utils profiling log structure
79  *
80  *  Utils log elements have a predefined structure of four words (to avoid the
81  *  need of malloc) and are stored in an array of predefined length, `elemlog`.
82  */
83 typedef struct{
84     /*! Indicates either enter or exit */
85     int32_t isEnter;
86     /*! Pointer address of the function in current context */
87     int32_t this_fn;
88     /*! Optional: Pointer address of calling function in current context */
89     int32_t call_site;
90     /*! Timestamp of the entry or exit */
91     uint32_t timestamp;
92 }utilsProfilingElem;
94 utilsProfilingElem elemlog[MAX_LOG] = {{0}};
96 /*!
97  *  @brief    Empty function for time adjustment
98  *
99  *  @ingroup pdk_profiling_hooks
100  *
101  *  Nothing more than an empty function that is referenced to measure the time
102  *  used by the instrumentation functions themselves. This is recorded and
103  *  passed into post-processing for a more accurate result.
104  */
105 void empty_fn(void); /*for misra warnings*/
106 #ifdef __cplusplus
107 #pragma FUNC_CANNOT_INLINE
108 #else
109 #pragma FUNC_CANNOT_INLINE(empty_fn);
110 #endif
111 void empty_fn(void){
114 /*!
115  *  @brief    TI Toolchain Utils Entry Hook
116  *
117  *  @ingroup pdk_profiling_hooks
118  *
119  *  Instruments the entry point and timestamp of the current function into
120  *  memory. Note that this function is automatically referenced at entry of
121  *  every function by TI Toolchain.
122  *
123  *  @param    *func_addr  Function Assembly Address (Hexadecimal)
124  */
125 void ti_utils_entry(void (* func_addr)(void)){
126     if (log_idx == 0){
127         uint32_t entry_offset = 0;
128         uint32_t exit_offset = 0;
129         log_idx++;
130         log_idx++;
131         int32_t i;
132         for (i = 0; i < 10; i++){
133             empty_fn();
134         }
135         elemlog[0].isEnter = 2;
136         elemlog[0].this_fn = 3;
137         elemlog[0].call_site = 1;
138         /*Taking 10 sample and subtracting (exit_log - entry log) of present for calculating the entry offset*/
139         for(i=1;i<=10;i++)
140         {
141             entry_offset += (elemlog[(2*i)+1].timestamp - elemlog[(2*i)].timestamp);
142         }
143         /* Saving the average of 10 sample */
144         elemlog[0].timestamp = entry_offset/10U;
145         elemlog[1].isEnter = 2;
146         elemlog[1].this_fn = 3;
147         elemlog[1].call_site = 2;
148         /* Taking 9 sample and subtracting (entry_log of next - exit_log of present) for calculating the exit offset*/
149         for(i=2;i<=10;i++)
150         {
151             exit_offset += (elemlog[(2*i)].timestamp - elemlog[(2*i)-1].timestamp);
152         }
153         /* Saving the average of 9 sample */
154         elemlog[1].timestamp = exit_offset/9U;
155         log_idx = 2U;
156     }
157     if (log_idx < MAX_LOG){
158         elemlog[log_idx].isEnter = 1;
159         elemlog[log_idx].this_fn = (int32_t)func_addr;
160         elemlog[log_idx].timestamp = CSL_armR5PmuReadCntr(CSL_ARM_R5_PMU_CYCLE_COUNTER_NUM);
161       log_idx++;
162     }
165 /*!
166  *  @brief    TI Toolchain Utils Exit Hook
167  *
168  *  @ingroup pdk_profiling_hooks
169  *
170  *  Instruments the exit point and timestamp of the current function into
171  *  memory. Note that this function is automatically referenced at end of
172  *  every function by TI Toolchain.
173  *
174  *  @param    *func_addr  Function Assembly Address (Hexadecimal)
175  */
176 void ti_utils_exit(void (* func_addr)(void)){
177     if (log_idx < MAX_LOG){
178         elemlog[log_idx].isEnter = 0;
179         elemlog[log_idx].this_fn = (int32_t)func_addr;
180         elemlog[log_idx].timestamp = CSL_armR5PmuReadCntr(CSL_ARM_R5_PMU_CYCLE_COUNTER_NUM);
181         log_idx++;
182     }
185 void TaskRegisterId(int32_t hookSetId); /*for misra warnings*/
186 #ifdef __cplusplus
187 #pragma NO_HOOKS
188 #else
189 #pragma NO_HOOKS(TaskRegisterId);
190 #endif
191 void TaskRegisterId(int32_t hookSetId)
193         CurrentTaskHookSetId = hookSetId;
194     if(MaxTaskHookSetId < CurrentTaskHookSetId)
195     {
196         MaxTaskHookSetId = CurrentTaskHookSetId;
197     }
200 /* ======== mySwitch ========
201 * invoked whenever a Task switch occurs/is made ready to run */
202 void mySwitch(const void* prev, const void* next); /*for misra warnings*/
203 #ifdef __cplusplus
204 #pragma NO_HOOKS
205 #else
206 #pragma NO_HOOKS(mySwitch);
207 #endif
208 void mySwitch(const void* prev, const void* next)
210     if (log_idx < MAX_LOG){
211         elemlog[log_idx].isEnter = 3;
212         elemlog[log_idx].this_fn = (int32_t)next;
213         elemlog[log_idx].call_site = (int32_t)prev;
214         elemlog[log_idx].timestamp = CSL_armR5PmuReadCntr(CSL_ARM_R5_PMU_CYCLE_COUNTER_NUM);
215         log_idx++;
216     }