1 /*
2 * Copyright (c) 2015 - 2018, 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 profilingHooksC66.c
34 *
35 * @brief DSP Implementations of the runtime programming hooks of the Processor SDK Profiling Tool.
36 *
37 * ## Usage ##
38 *
39 * For more information, see:
40 * - @subpage profCCS
41 * - @subpage profDSS
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 * For best results, ensure that the optimization levels are consistent between
50 * the library and the project (typically -O3, or optimization level 3).
51 *
52 */
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <stdint.h>
57 #include "profilingHooks.h"
58 #include <ti/csl/csl_chip.h>
60 int32_t CurrentTaskHookSetId, MaxTaskHookSetId;
62 /*!
63 * @brief Maximum log count
64 *
65 * This is a predefined value to indicate when the instrumentation hooks should
66 * stop logging data. This is important for applications that have long polling
67 * loops or a device that has a small cache.
68 */
69 #define MAX_LOG (4U*1024U*1024U)
70 #define MAX_CORES (8U)
72 uint32_t log_idx = 0;
73 uint32_t waddress = 0;
74 uint32_t lvl = 0;
76 /*!
77 * @brief Utils profiling log structure
78 *
79 * Utils log elements have a predefined structure of four words (to avoid the
80 * need of malloc) and are stored in an array of predefined length, `elemlog`.
81 */
82 typedef struct{
83 /*! Indicates either enter or exit */
84 int32_t isEnter;
85 /*! Pointer address of the function in current context */
86 int32_t this_fn;
87 /*! Optional: Pointer address of calling function in current context */
88 int32_t call_site;
89 /*! Timestamp of the entry or exit */
90 uint32_t timestamp;
91 }utilsProfilingElem;
93 #ifdef __cplusplus
94 #pragma DATA_SECTION (".fardata:benchmarking")
95 #else
96 #pragma DATA_SECTION (elemlog, ".fardata:benchmarking");
97 #endif
98 utilsProfilingElem elemlog[MAX_LOG] = {{0}};
99 utilsProfilingElem *pElemLog;
101 /*!
102 * @brief Empty function for time adjustment
103 *
104 * Nothing more than an empty function that is referenced to measure the time
105 * used by the instrumentation functions themselves. This is recorded and
106 * passed into post-processing for a more accurate result.
107 */
109 #ifdef __cplusplus
110 #pragma FUNC_CANNOT_INLINE
111 #else
112 #pragma FUNC_CANNOT_INLINE(empty_fn);
113 #endif
114 void empty_fn(void); /*for misra warnings*/
115 void empty_fn(void){
116 }
118 extern cregister volatile uint32_t TSCL;
120 /*!
121 * @brief TI Toolchain Utils Entry Hook
122 *
123 * @ingroup pdk_profiling_hooks
124 *
125 * Instruments the entry point and timestamp of the current function into
126 * memory. Note that this function is automatically referenced at entry of
127 * every function by TI Toolchain.
128 *
129 * @param *func_addr Function Assembly Address (Hexadecimal)
130 */
131 void ti_utils_entry(void (* func_addr)(void)){
132 if (log_idx == 0){
133 TSCL = 0;
134 uint32_t val = TSCL;
135 uint32_t entry_offset = 0;
136 uint32_t exit_offset = 0;
137 waddress = DNUM*MAX_LOG/MAX_CORES;
138 pElemLog = &elemlog[waddress];
139 log_idx++;
140 log_idx++;
141 int32_t i;
142 for (i = 0; i < 10; i++){
143 empty_fn();
144 }
145 pElemLog[0].isEnter = 2;
146 pElemLog[0].this_fn = 2;
147 pElemLog[0].call_site = 1;
148 /*Taking 10 sample and subtracting (exit_log - entry log) of present for calculating the entry offset*/
149 for(i=1;i<=10;i++)
150 {
151 entry_offset += (pElemLog[(2*i)+1].timestamp - pElemLog[(2*i)].timestamp);
152 }
153 /* Saving the average of 10 sample */
154 pElemLog[0].timestamp = entry_offset/10U;
155 pElemLog[1].isEnter = 2;
156 pElemLog[1].this_fn = 2;
157 pElemLog[1].call_site = 2;
158 /* Taking 9 sample and subtracting (entry_log of next - exit_log of present) for calculating the exit offset*/
159 for(i=2;i<=10;i++)
160 {
161 exit_offset += (pElemLog[(2*i)].timestamp - pElemLog[(2*i)-1].timestamp);
162 }
163 /* Saving the average of 9 sample */
164 pElemLog[1].timestamp = exit_offset/9U;
165 log_idx = 2U;
166 }
167 uint32_t uiOldGIE = _disable_interrupts();
168 if (log_idx < MAX_LOG){
169 pElemLog[log_idx].isEnter = 1;
170 pElemLog[log_idx].this_fn = (int32_t)func_addr;
171 pElemLog[log_idx].timestamp = TSCL;
172 log_idx++;
173 }
174 _restore_interrupts(uiOldGIE);
175 }
177 /*!
178 * @brief TI Toolchain Utils Exit Hook
179 *
180 * @ingroup pdk_profiling_hooks
181 *
182 * Instruments the exit point and timestamp of the current function into
183 * memory. Note that this function is automatically referenced at end of
184 * every function by TI Toolchain.
185 *
186 * @param *func_addr Function Assembly Address (Hexadecimal)
187 */
188 void ti_utils_exit(void (* func_addr)(void)){
189 uint32_t uiOldGIE = _disable_interrupts();
190 if (log_idx < MAX_LOG){
191 pElemLog[log_idx].isEnter = 0;
192 pElemLog[log_idx].this_fn = (int32_t)func_addr;
193 pElemLog[log_idx].timestamp = TSCL;
194 log_idx++;
195 }
196 _restore_interrupts(uiOldGIE);
197 }
199 void TaskRegisterId(int32_t hookSetId); /*for misra warnings*/
200 #ifdef __cplusplus
201 #pragma NO_HOOKS
202 #else
203 #pragma NO_HOOKS (TaskRegisterId)
204 #endif
205 void TaskRegisterId(int32_t hookSetId)
206 {
207 CurrentTaskHookSetId = hookSetId;
208 if(MaxTaskHookSetId < CurrentTaskHookSetId)
209 {
210 MaxTaskHookSetId = CurrentTaskHookSetId;
211 }
212 }
214 /* ======== mySwitch ========
215 * invoked whenever a Task switch occurs/is made ready to run */
216 void mySwitch(const void* prev, const void* next); /*for misra warnings*/
217 #ifdef __cplusplus
218 #pragma NO_HOOKS
219 #else
220 #pragma NO_HOOKS (mySwitch)
221 #endif
222 void mySwitch(const void* prev, const void* next)
223 {
224 if (log_idx < MAX_LOG){
225 pElemLog[log_idx].isEnter = 3;
226 pElemLog[log_idx].this_fn = (int32_t)next;
227 pElemLog[log_idx].call_site = (int32_t)prev;
228 pElemLog[log_idx].timestamp = TSCL;
229 log_idx++;
230 }
231 }