1 //
2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "JSONTimelineDecoder.hpp"
7 #include "../profiling/ProfilingUtils.hpp"
8
9 #include <string>
10
11 namespace armnn
12 {
13 namespace timelinedecoder
14 {
15
16 static const char *const CONNECTION = "connection";
17 static const char *const BACKEND_ID = "backendId";
18 static const char *const NAME = "name";
19 static const char *const TYPE = "type";
20 static const char *const WORKLOAD = "workload";
21 static const char *const WORKLOAD_EXECUTION = "workload_execution";
22 static const char *const INFERENCE = "inference";
23 static const char *const LAYER = "layer";
24 static const char *const ENTITY = "Entity";
25 static const char *const EVENTCLASS = "EventClass";
26 static const char *const EVENT = "Event";
27
CreateEntity(const Entity & entity)28 JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateEntity(const Entity& entity)
29 {
30 JSONEntity jsonEntity(entity.m_Guid);
31 jsonEntity.SetType(ENTITY);
32 this->m_Model.jsonEntities.insert({entity.m_Guid, jsonEntity});
33 return TimelineStatus::TimelineStatus_Success;
34 }
35
CreateEventClass(const EventClass & eventClass)36 JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateEventClass(const EventClass& eventClass)
37 {
38 JSONEntity jsonEntity(eventClass.m_Guid);
39 jsonEntity.SetType(EVENTCLASS);
40 this->m_Model.eventClasses.insert({eventClass.m_Guid, eventClass});
41 this->m_Model.jsonEntities.insert({eventClass.m_Guid, jsonEntity});
42 return TimelineStatus::TimelineStatus_Success;
43 }
44
CreateEvent(const Event & event)45 JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateEvent(const Event& event)
46 {
47 JSONEntity jsonEntity(event.m_Guid);
48 jsonEntity.SetType(EVENT);
49 this->m_Model.events.insert({event.m_Guid, event});
50 this->m_Model.jsonEntities.insert({jsonEntity.GetGuid(), jsonEntity});
51 return TimelineStatus::TimelineStatus_Success;
52 }
53
CreateLabel(const Label & label)54 JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateLabel(const Label& label)
55 {
56 this->m_Model.labels.insert({label.m_Guid, label});
57 return TimelineStatus::TimelineStatus_Success;
58 }
59
CreateRelationship(const Relationship & relationship)60 JSONTimelineDecoder::TimelineStatus JSONTimelineDecoder::CreateRelationship(const Relationship& relationship)
61 {
62 if (relationship.m_RelationshipType == ITimelineDecoder::RelationshipType::RetentionLink)
63 {
64 HandleRetentionLink(relationship);
65 }
66 else if (relationship.m_RelationshipType == ITimelineDecoder::RelationshipType::LabelLink)
67 {
68 HandleLabelLink(relationship);
69 }
70 else if (relationship.m_RelationshipType == ITimelineDecoder::RelationshipType::ExecutionLink)
71 {
72 HandleExecutionLink(relationship);
73 }
74 else
75 {
76 /*
77 * TODO Handle DataLink
78 */
79 m_Model.relationships.insert({relationship.m_Guid, relationship});
80 }
81
82 return TimelineStatus::TimelineStatus_Success;
83 }
84
85
HandleExecutionLink(const ITimelineDecoder::Relationship & relationship)86 void JSONTimelineDecoder::HandleExecutionLink(const ITimelineDecoder::Relationship& relationship)
87 {
88 uint64_t tailGuid = relationship.m_TailGuid;
89 uint64_t headGuid = relationship.m_HeadGuid;
90
91 if (m_Model.jsonEntities.count(relationship.m_HeadGuid) != 0)
92 {
93 JSONEntity& tailJSONEntity = m_Model.jsonEntities.at(tailGuid);
94 JSONEntity& headJSONEntity = m_Model.jsonEntities.at(headGuid);
95 tailJSONEntity.SetParent(headJSONEntity);
96 m_Model.jsonEntities.insert({headGuid, headJSONEntity});
97 m_Model.relationships.insert({relationship.m_Guid, relationship});
98 }
99 else
100 {
101 /*
102 * TODO Add some protection against packet ordering issues
103 */
104 m_Model.relationships.insert({relationship.m_Guid, relationship});
105 }
106 }
107
HandleLabelLink(const ITimelineDecoder::Relationship & relationship)108 void JSONTimelineDecoder::HandleLabelLink(const ITimelineDecoder::Relationship& relationship)
109 {
110 if (m_Model.labels.count(relationship.m_TailGuid) != 0)
111 {
112 if (m_Model.labels.at(relationship.m_TailGuid).m_Name == CONNECTION)
113 {
114 HandleConnectionLabel(relationship);
115 }
116 else if (m_Model.labels.at(relationship.m_TailGuid).m_Name == BACKEND_ID)
117 {
118 HandleBackendIdLabel(relationship);
119 }
120 else if (m_Model.labels.at(relationship.m_TailGuid).m_Name == NAME)
121 {
122 HandleNameLabel(relationship);
123 }
124 else if (m_Model.labels.at(relationship.m_TailGuid).m_Name == TYPE)
125 {
126 HandleTypeLabel(relationship);
127 }
128 else
129 {
130 /*
131 * TODO Add some protection against packet ordering issues
132 */
133 m_Model.relationships.insert({relationship.m_Guid, relationship});
134 }
135 } else
136 {
137 /*
138 * TODO Add some protection against packet ordering issues
139 */
140 m_Model.relationships.insert({relationship.m_Guid, relationship});
141 }
142 }
143
HandleTypeLabel(const ITimelineDecoder::Relationship & relationship)144 void JSONTimelineDecoder::HandleTypeLabel(const ITimelineDecoder::Relationship& relationship)
145 {
146 if (m_Model.relationships.count(relationship.m_HeadGuid) != 0)
147 {
148 Relationship labelRelation = m_Model.relationships.at(relationship.m_HeadGuid);
149 if (m_Model.jsonEntities.count(labelRelation.m_HeadGuid) != 0)
150 {
151 JSONEntity& headEntity = m_Model.jsonEntities.at(labelRelation.m_HeadGuid);
152 std::string type = m_Model.labels.at(labelRelation.m_TailGuid).m_Name;
153 headEntity.SetType(type);
154 }
155 }
156 else
157 {
158 /*
159 * TODO Add some protection against packet ordering issues
160 */
161 m_Model.relationships.insert({relationship.m_Guid, relationship});
162 }
163 }
164
HandleNameLabel(const ITimelineDecoder::Relationship & relationship)165 void JSONTimelineDecoder::HandleNameLabel(const ITimelineDecoder::Relationship& relationship)
166 {
167 if (m_Model.relationships.count(relationship.m_HeadGuid) != 0)
168 {
169 Relationship labelRelation = m_Model.relationships.at(relationship.m_HeadGuid);
170 JSONEntity& headEntity = m_Model.jsonEntities.at(labelRelation.m_HeadGuid);
171 std::string name = m_Model.labels.at(labelRelation.m_TailGuid).m_Name;
172 headEntity.SetName(name);
173 }
174 else
175 {
176 /*
177 * TODO Add some protection against packet ordering issues
178 */
179 m_Model.relationships.insert({relationship.m_Guid, relationship});
180 }
181 }
182
HandleBackendIdLabel(const ITimelineDecoder::Relationship & relationship)183 void JSONTimelineDecoder::HandleBackendIdLabel(const ITimelineDecoder::Relationship& relationship)
184 {
185 if (m_Model.relationships.count(relationship.m_HeadGuid) != 0)
186 {
187 Relationship labelRelation = m_Model.relationships.at(relationship.m_HeadGuid);
188 JSONEntity& headEntity = m_Model.jsonEntities.at(labelRelation.m_HeadGuid);
189 std::string backendName = m_Model.labels.at(labelRelation.m_TailGuid).m_Name;
190 headEntity.extendedData.insert({BACKEND_ID, backendName});
191 }
192 else
193 {
194 /*
195 * TODO Add some protection against packet ordering issues
196 */
197 m_Model.relationships.insert({relationship.m_Guid, relationship});
198 }
199 }
200
HandleConnectionLabel(const ITimelineDecoder::Relationship & relationship)201 void JSONTimelineDecoder::HandleConnectionLabel(const ITimelineDecoder::Relationship& relationship)
202 {
203 if (m_Model.relationships.count(relationship.m_HeadGuid) != 0)
204 {
205 Relationship retentionRelation = m_Model.relationships.at(relationship.m_HeadGuid);
206 JSONEntity& headEntity = m_Model.jsonEntities.at(retentionRelation.m_HeadGuid);
207 JSONEntity& tailEntity = m_Model.jsonEntities.at(retentionRelation.m_TailGuid);
208 headEntity.AddConnection(headEntity, tailEntity);
209 }
210 else
211 {
212 /*
213 * TODO Add some protection against packet ordering issues
214 */
215 m_Model.relationships.insert({relationship.m_Guid, relationship});
216 }
217 }
218
HandleRetentionLink(const ITimelineDecoder::Relationship & relationship)219 void JSONTimelineDecoder::HandleRetentionLink(const ITimelineDecoder::Relationship& relationship)
220 {
221 if (m_Model.jsonEntities.count(relationship.m_TailGuid) != 0 && m_Model.jsonEntities
222 .count(relationship.m_HeadGuid) != 0)
223 {
224 JSONEntity& tailJSONEntity = m_Model.jsonEntities.at(relationship.m_TailGuid);
225 JSONEntity& headJSONEntity = m_Model.jsonEntities.at(relationship.m_HeadGuid);
226 tailJSONEntity.SetParent(headJSONEntity);
227 m_Model.jsonEntities.insert({relationship.m_HeadGuid, headJSONEntity});
228 m_Model.relationships.insert({relationship.m_Guid, relationship});
229 }
230 else
231 {
232 /*
233 * TODO Add some protection against packet ordering issues
234 */
235 m_Model.relationships.insert({relationship.m_Guid, relationship});
236 }
237 }
238
SetParent(JSONEntity & parent)239 void JSONTimelineDecoder::JSONEntity::SetParent(JSONEntity& parent)
240 {
241 parent.childEntities.push_back(GetGuid());
242 }
243
PrintJSON(JSONTimelineDecoder::JSONEntity & rootEntity,std::ostream & os)244 void JSONTimelineDecoder::PrintJSON(JSONTimelineDecoder::JSONEntity& rootEntity, std::ostream& os)
245 {
246 std::string jsonString = GetJSONString(rootEntity);
247 os << jsonString;
248 }
249
GetJSONString(JSONTimelineDecoder::JSONEntity & rootEntity)250 std::string JSONTimelineDecoder::GetJSONString(JSONTimelineDecoder::JSONEntity& rootEntity)
251 {
252 int counter = 0;
253 std::string json;
254 json.append("{\n");
255 if(rootEntity.GetType() != "")
256 {
257 json.append("\tArmNN");
258 json.append(": {\n");
259
260 for (uint64_t childEntityId : rootEntity.childEntities)
261 {
262 JSONEntity& childEntity = this->m_Model.jsonEntities.at(childEntityId);
263 json.append(GetJSONEntityString(childEntity, counter));
264 }
265 }
266 json.append("}\n");
267 return json;
268 }
269
GetJSONEntityString(JSONTimelineDecoder::JSONEntity & entity,int & counter)270 std::string JSONTimelineDecoder::GetJSONEntityString(JSONTimelineDecoder::JSONEntity& entity, int& counter)
271 {
272 std::string jsonEntityString;
273 if(entity.GetType() == LAYER)
274 {
275 return GetLayerJSONString(entity, counter, jsonEntityString);
276 }
277 else if (entity.GetType() == WORKLOAD)
278 {
279 return GetWorkloadJSONString(entity, counter, jsonEntityString);
280 }
281 else if (entity.GetType() == WORKLOAD_EXECUTION)
282 {
283 return GetWorkloadExecutionJSONString(entity, jsonEntityString);
284 }
285 else if (entity.GetType() == INFERENCE)
286 {
287 return jsonEntityString;
288 }
289 else
290 {
291 for (uint64_t child_entity_id : entity.childEntities)
292 {
293 JSONEntity& childEntity = this->m_Model.jsonEntities.at(child_entity_id);
294 jsonEntityString.append(GetJSONEntityString(childEntity, ++counter));
295 }
296 return jsonEntityString;
297 }
298 }
299
GetWorkloadExecutionJSONString(const JSONTimelineDecoder::JSONEntity & entity,std::string & jsonEntityString) const300 std::string JSONTimelineDecoder::GetWorkloadExecutionJSONString(const JSONTimelineDecoder::JSONEntity& entity,
301 std::string& jsonEntityString) const
302 {
303 if(entity.childEntities.size() < 2)
304 {
305 throw Exception("Workload Execution Entity Packet does not have the expected Event packets attached");
306 }
307 JSONEntity jsonEventOne = entity.childEntities[0];
308 JSONEntity jsonEventTwo = entity.childEntities[1];
309
310 Event event1 = m_Model.events.at(jsonEventOne.GetGuid());
311 Event event2 = m_Model.events.at(jsonEventTwo.GetGuid());
312
313 uint64_t wall_clock_time = event2.m_TimeStamp - event1.m_TimeStamp;
314 jsonEntityString.append("\t\t\t");
315 jsonEntityString.append("raw : [");
316 jsonEntityString.append(std::to_string(wall_clock_time));
317 jsonEntityString.append("], \n");
318 jsonEntityString.append("\t\t\t");
319 jsonEntityString.append("unit : us,\n");
320 jsonEntityString.append("\t\t\t");
321 jsonEntityString.append("}\n");
322
323 return jsonEntityString;
324 }
325
GetWorkloadJSONString(const JSONTimelineDecoder::JSONEntity & entity,int & counter,std::string & jsonEntityString)326 std::string JSONTimelineDecoder::GetWorkloadJSONString(const JSONTimelineDecoder::JSONEntity& entity, int& counter,
327 std::string& jsonEntityString)
328 {
329 jsonEntityString.append("\t\t\t");
330 jsonEntityString.append("backendId :");
331 jsonEntityString.append(entity.extendedData.at(BACKEND_ID));
332 jsonEntityString.append(",\n");
333 for (uint64_t child_entity_id : entity.childEntities)
334 {
335 JSONEntity &childEntity = m_Model.jsonEntities.at(child_entity_id);
336 jsonEntityString.append(GetJSONEntityString(childEntity, ++counter));
337 }
338 return jsonEntityString;
339 }
340
GetLayerJSONString(JSONTimelineDecoder::JSONEntity & entity,int & counter,std::string & jsonEntityString)341 std::string JSONTimelineDecoder::GetLayerJSONString(JSONTimelineDecoder::JSONEntity& entity, int& counter,
342 std::string& jsonEntityString)
343 {
344 jsonEntityString.append("\t\t");
345 jsonEntityString.append(entity.GetName());
346 jsonEntityString.append("_");
347 jsonEntityString.append(std::to_string(counter));
348 jsonEntityString.append(": {\n");
349 jsonEntityString.append("\t\t\t");
350 jsonEntityString.append("type: Measurement,\n");
351 for (uint64_t child_entity_id : entity.childEntities)
352 {
353 JSONEntity& childEntity = m_Model.jsonEntities.at(child_entity_id);
354 jsonEntityString.append(GetJSONEntityString(childEntity, ++counter));
355 }
356 return jsonEntityString;
357 }
358
AddConnection(JSONEntity & headEntity,JSONEntity & connectedEntity)359 void JSONTimelineDecoder::JSONEntity::AddConnection(JSONEntity& headEntity, JSONEntity& connectedEntity)
360 {
361 std::vector<uint64_t>::iterator it = std::find(headEntity.childEntities.begin(),
362 headEntity.childEntities.end(), connectedEntity.GetGuid());
363 headEntity.childEntities.erase(it);
364 headEntity.connected_entities.push_back(connectedEntity.m_Guid);
365 }
366
GetGuid()367 uint64_t JSONTimelineDecoder::JSONEntity::GetGuid()
368 {
369 return m_Guid;
370 }
371
GetModel()372 const JSONTimelineDecoder::Model &JSONTimelineDecoder::GetModel()
373 {
374 return m_Model;
375 }
376
SetName(std::string entityName)377 void JSONTimelineDecoder::JSONEntity::SetName(std::string entityName)
378 {
379 this->name = entityName;
380 }
381
GetName()382 std::string JSONTimelineDecoder::JSONEntity::GetName()
383 {
384 return this->name;
385 }
386
SetType(std::string entityType)387 void JSONTimelineDecoder::JSONEntity::SetType(std::string entityType)
388 {
389 this->type = entityType;
390 }
391
GetType()392 std::string JSONTimelineDecoder::JSONEntity::GetType()
393 {
394 return this->type;
395 }
396
397 }
398 }