blob: e200bc569f103bd503811f2300afcd392ee51280 [file] [log] [blame]
Basil Eljuse4b14afb2020-09-30 13:07:23 +01001/*!
2##############################################################################
3# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
4#
5# SPDX-License-Identifier: BSD-3-Clause
6##############################################################################
7*/
8
9#ifndef _COVERAGE_TOOL_COVERAGE_PLUGIN_TRACE_SOURCES_H_
10#define _COVERAGE_TOOL_COVERAGE_PLUGIN_TRACE_SOURCES_H_
11
12#include <map>
13#include <vector>
14#include <string>
15#include <algorithm>
16#include "MTI/ModelTraceInterface.h"
17
18using namespace MTI;
19using namespace std;
20
21struct InstStat {
22 uint64_t cnt;
23 uint64_t size;
24};
25
26typedef std::map<uint32_t, InstStat> InstStatMap;
27
28//Defining types for fields
Jelle Sels83f141e2022-08-01 15:17:40 +000029enum enum_types {u32, boolT, u8};
Basil Eljuse4b14afb2020-09-30 13:07:23 +010030typedef enum_types ValueTypes;
31
32/*
33 * Structure used to save field data
34 */
35struct TFields{
36 ValueTypes t;
37 MTI::ValueIndex index;
38 void *value;
39};
40// Map of fields => Key -> Field name
41typedef map<string, TFields> TraceFieldsMap;
42
43/*
44 * Structure used to pass field data between trace contexts
45 */
46struct TParams {
47 void *value;
48 ValueTypes t;
49};
50// Map of fields => Key -> Field name
51typedef map<string, TParams> ParamsMap;
52
53/*
54 * Generic function to output errors
55 */
56bool Error(const char *msg)
57{
58 fprintf(stderr, "%s\n", msg);
59 return false;
60}
61
62/*
63 * Base class for Trace Source contexts
64 *
65 */
66class TraceSourceContext {
67 public:
68 string name; //Trace source name
69 TraceFieldsMap fields; //Fields to be used for the event
70 MTI::EventClass *event_class; //Event object to register callback
71 ParamsMap params; //List of parameters from another trace source
72
73/*
74 * Constructor that converts/stores the pairs of <field name, field type>
75 * in the 'fields' member.
76*/
77TraceSourceContext(const char* tname,
78 vector<pair<string, ValueTypes>> fields_def) {
79 name = tname;
80 string key;
81 // Referenced by field name => field type
82 for (size_t i=0; i < fields_def.size(); ++ i) {
83 key = fields_def[i].first;
84 fields[key].t = fields_def[i].second;
85 }
86}
87
88/*
89 * Generic Callback that can be used by derived objects. It fills the
90 * 'value' member in the 'fields' structure with a void* to the value
91 * retrieved from the component.
92*/
93template <class T>
94static T *TraceCallback(void* user_data,
95 const MTI::EventClass *event_class,
96 const MTI::EventRecord *record) {
97 T *tc = static_cast<T*>(user_data);
98 // Filled by Component
99 TraceFieldsMap::iterator it;
100 for (it = tc->fields.begin(); it != tc->fields.end(); ++it) {
101 // Based in the type creates an object with initial
102 // value retrieved from the component using the index
103 // for that field.
104 switch (it->second.t) {
105 case u32: it->second.value = new uint32_t(
106 record->Get<uint32_t>(event_class, it->second.index));
107 break;
108 case boolT: it->second.value = new bool(
109 record->GetBool(event_class, it->second.index));
110 break;
Jelle Sels83f141e2022-08-01 15:17:40 +0000111 case u8: it->second.value = new uint8_t(
112 record->Get<uint8_t>(event_class, it->second.index));
113 break;
Basil Eljuse4b14afb2020-09-30 13:07:23 +0100114 }
115 }
116 return tc;
117}
118
119/*
120 * Generic method to copy the fields from this trace source to the params
121 * member in other trace source. Optionally a list of field names can be
122 * passed to filter the list of field names copied.
123 * The params member is a Map of with the Field Id (name) as the key.
124*/
125void PassFieldstoParams(TraceSourceContext *target,
126 vector<string> field_names={}) {
127 TraceFieldsMap::iterator it;
128 for (it = fields.begin(); it != fields.end(); ++it) {
129 bool found = std::find(field_names.begin(), field_names.end(),
130 it->first) != field_names.end();
131 if ((!field_names.empty()) && (!found))
132 continue;
133 target->params[it->first].t = it->second.t;
134 switch (it->second.t) {
135 case u32:
136 target->params[it->first].value =
137 new uint32_t(*((uint32_t*)it->second.value));
138 break;
139 case boolT:
140 target->params[it->first].value =
141 new bool(*((bool*)it->second.value));
142 break;
Jelle Sels83f141e2022-08-01 15:17:40 +0000143 case u8:
144 target->params[it->first].value =
145 new uint8_t(*((uint8_t*)it->second.value));
146 break;
Basil Eljuse4b14afb2020-09-30 13:07:23 +0100147 }
148 }
149}
150/*
151 * Method that creates an event object in the trace source based in the
152 * fields given in the constructor. It then registers the given callback
153 * to this event.
154*/
155MTI::EventClass *CreateEvent(ComponentTraceInterface **ptr_cti,
156 MTI::CallbackT callback) {
157
158 ComponentTraceInterface *cti = *ptr_cti;
159 std::stringstream ss;
160 ComponentTraceInterface *mti = 0;
161
162 if (cti->GetTraceSource(name.c_str()) != 0) {
163 TraceSource* ts = cti->GetTraceSource(name.c_str());
164 printf("Trace source attached: %s\n", ts->GetName());
165
166 size_t map_size = fields.size();
167 ValueBind_t *values_array = new ValueBind_t[map_size + 1];
168 TraceFieldsMap::iterator it;
169 int i = 0;
170 for (it = fields.begin(); it != fields.end(); ++it) {
171 values_array[i]= ((ValueBind_t) { it->first.c_str(),
172 &it->second.index });
173 ++i;
174 };
175 values_array[map_size] = {0, 0}; //sentinel
176
177 mti = static_cast<ModelTraceInterface *>(cti);
178 if (!RegisterCallbackForComponent(mti, name.c_str(), values_array,
179 this, callback, &event_class, ss)) {
180 Error(ss.str().c_str());
181 return 0;
182 }
183 return event_class;
184 }
185 return 0;
186}
187};
188
189/*
190 * Class and types used to handle trace sources belonging to a
191 * component.
192*/
193typedef map<string, TraceSourceContext*> MapTraceSourcesType;
194class TraceComponentContext {
195 public:
196 string trace_path;
197 MapTraceSourcesType trace_sources;
198
199TraceComponentContext(string tpath) {
200 trace_path = tpath;
201}
202
203void AddTraceSource(TraceSourceContext *ts) {
204 trace_sources[ts->name] = ts;
205}
206};
207
208/*
209 * Class used to instantiate a Instruction trace source
210*/
211class InstructionTraceContext: public TraceSourceContext {
212 public:
213 using TraceSourceContext::TraceSourceContext;
214 InstStatMap stats;
215 uint64_t nb_insts;
216
217 static void Callback(void* user_data,
218 const MTI::EventClass *event_class,
219 const MTI::EventRecord *record) {
220 InstructionTraceContext* itc = static_cast<InstructionTraceContext*>
221 (user_data);
222 itc->nb_insts++; // Number of instructions
223 // Filled by Component
224 uint32_t pc = record->GetAs<uint32_t>(event_class,
225 itc->fields["PC"].index);
226 uint32_t size = record->Get<uint32_t>(event_class,
227 itc->fields["SIZE"].index);
228 // Save PC stats. If not already present in the map, a counter with
229 // value 0 will be created before incrementing.
230 InstStat& is = itc->stats[pc];
231 is.cnt++;
232 is.size = size;
233 };
234};
235
Jelle Sels83f141e2022-08-01 15:17:40 +0000236struct mode_change_type {
237 uint8_t mode_value;
238 char name[5];
239};
240const struct mode_change_type types[] = {
241 {0x0 , "EL0t"}, //0
242 {0x4 , "EL1t"}, //1
243 {0x5 , "EL1h"}, //2
244 {0x8 , "EL2t"}, //3
245 {0x9 , "EL2h"}, //4
246 {0xc , "EL3t"}, //5
247 {0xd , "EL3h"}, //6
248 {0x10 , "usr"}, //7
249 {0x11 , "fiq"}, //8
250 {0x12 , "irq"}, //9
251 {0x13 , "svc"}, //10
252 {0x16 , "mon"}, //11
253 {0x17 , "abt"}, //12
254 {0x1a , "hyp"}, //13
255 {0x1b , "und"}, //14
256 {0x1f , "sys"}, //15
257 /* Secure modes */
258 {0x0 , "EL0t"}, //16
259 {0x4 , "EL1t"}, //17
260 {0x5 , "EL1h"}, //18
261 {0x8 , "EL2t"}, //19
262 {0x9 , "EL2h"}, //20
263 {0xc , "EL3t"}, //21
264 {0xd , "EL3h"}, //22
265 {0x10 , "usr"}, //23
266 {0x11 , "fiq"}, //24
267 {0x12 , "irq"}, //25
268 {0x13 , "svc"}, //26
269 {0x16 , "mon"}, //27
270 {0x17 , "abt"}, //28
271 {0x1a , "hyp"}, //29
272 {0x1b , "und"}, //30
273 {0x1f , "sys"} //31
274};
275
276class ModeChangeTraceContext: public TraceSourceContext {
277 public:
278 using TraceSourceContext::TraceSourceContext;
279 MTI::EventClass *event;
280 uint32_t mode_mask;
281 InstructionTraceContext* itc;
282
283
284 static void Callback(void* user_data,
285 const MTI::EventClass *event_class,
286 const MTI::EventRecord *record)
287 {
288 ModeChangeTraceContext* mtc = static_cast<ModeChangeTraceContext*>
289 (user_data);
290 static bool trace = false;
291 bool new_trace = false;
292 uint8_t mode = record->GetAs<char>(event_class,
293 mtc->fields["MODE"].index);
294 uint8_t nsecure = record->Get<char>(event_class,
295 mtc->fields["NON_SECURE"].index);
296 int start_mask = 0;
297
298 if(nsecure) {
299 start_mask = 0;
300 } else {
301 start_mask = 16;
302 }
303
304 for (int i = start_mask; i < start_mask + 16; i++) {
305 if (types[i].mode_value == mode) {
306 new_trace = new_trace || (mtc->mode_mask & (1 << i));
307 break;
308 }
309 }
310
311 if (new_trace && !trace) {
312 mtc->event->RegisterCallback(InstructionTraceContext::Callback,
313 mtc->itc);
314 } else if (!new_trace && trace){
315 mtc->event->UnregisterCallback(
316 InstructionTraceContext::Callback,
317 mtc->itc);
318 }
319 trace = new_trace;
320 };
321
322};
Basil Eljuse4b14afb2020-09-30 13:07:23 +0100323#endif // _COVERAGE_TOOL_COVERAGE_PLUGIN_TRACE_SOURCES_H_