blob: 57f646291862da249616390a3c1c8c9a766b19f1 [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
29enum enum_types {u32, boolT};
30typedef 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;
111 }
112 }
113 return tc;
114}
115
116/*
117 * Generic method to copy the fields from this trace source to the params
118 * member in other trace source. Optionally a list of field names can be
119 * passed to filter the list of field names copied.
120 * The params member is a Map of with the Field Id (name) as the key.
121*/
122void PassFieldstoParams(TraceSourceContext *target,
123 vector<string> field_names={}) {
124 TraceFieldsMap::iterator it;
125 for (it = fields.begin(); it != fields.end(); ++it) {
126 bool found = std::find(field_names.begin(), field_names.end(),
127 it->first) != field_names.end();
128 if ((!field_names.empty()) && (!found))
129 continue;
130 target->params[it->first].t = it->second.t;
131 switch (it->second.t) {
132 case u32:
133 target->params[it->first].value =
134 new uint32_t(*((uint32_t*)it->second.value));
135 break;
136 case boolT:
137 target->params[it->first].value =
138 new bool(*((bool*)it->second.value));
139 break;
140 }
141 }
142}
143/*
144 * Method that creates an event object in the trace source based in the
145 * fields given in the constructor. It then registers the given callback
146 * to this event.
147*/
148MTI::EventClass *CreateEvent(ComponentTraceInterface **ptr_cti,
149 MTI::CallbackT callback) {
150
151 ComponentTraceInterface *cti = *ptr_cti;
152 std::stringstream ss;
153 ComponentTraceInterface *mti = 0;
154
155 if (cti->GetTraceSource(name.c_str()) != 0) {
156 TraceSource* ts = cti->GetTraceSource(name.c_str());
157 printf("Trace source attached: %s\n", ts->GetName());
158
159 size_t map_size = fields.size();
160 ValueBind_t *values_array = new ValueBind_t[map_size + 1];
161 TraceFieldsMap::iterator it;
162 int i = 0;
163 for (it = fields.begin(); it != fields.end(); ++it) {
164 values_array[i]= ((ValueBind_t) { it->first.c_str(),
165 &it->second.index });
166 ++i;
167 };
168 values_array[map_size] = {0, 0}; //sentinel
169
170 mti = static_cast<ModelTraceInterface *>(cti);
171 if (!RegisterCallbackForComponent(mti, name.c_str(), values_array,
172 this, callback, &event_class, ss)) {
173 Error(ss.str().c_str());
174 return 0;
175 }
176 return event_class;
177 }
178 return 0;
179}
180};
181
182/*
183 * Class and types used to handle trace sources belonging to a
184 * component.
185*/
186typedef map<string, TraceSourceContext*> MapTraceSourcesType;
187class TraceComponentContext {
188 public:
189 string trace_path;
190 MapTraceSourcesType trace_sources;
191
192TraceComponentContext(string tpath) {
193 trace_path = tpath;
194}
195
196void AddTraceSource(TraceSourceContext *ts) {
197 trace_sources[ts->name] = ts;
198}
199};
200
201/*
202 * Class used to instantiate a Instruction trace source
203*/
204class InstructionTraceContext: public TraceSourceContext {
205 public:
206 using TraceSourceContext::TraceSourceContext;
207 InstStatMap stats;
208 uint64_t nb_insts;
209
210 static void Callback(void* user_data,
211 const MTI::EventClass *event_class,
212 const MTI::EventRecord *record) {
213 InstructionTraceContext* itc = static_cast<InstructionTraceContext*>
214 (user_data);
215 itc->nb_insts++; // Number of instructions
216 // Filled by Component
217 uint32_t pc = record->GetAs<uint32_t>(event_class,
218 itc->fields["PC"].index);
219 uint32_t size = record->Get<uint32_t>(event_class,
220 itc->fields["SIZE"].index);
221 // Save PC stats. If not already present in the map, a counter with
222 // value 0 will be created before incrementing.
223 InstStat& is = itc->stats[pc];
224 is.cnt++;
225 is.size = size;
226 };
227};
228
229#endif // _COVERAGE_TOOL_COVERAGE_PLUGIN_TRACE_SOURCES_H_