• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "TimelineModel.hpp"
7 
8 #include <common/include/LabelsAndEventClasses.hpp>
9 
10 #include <algorithm>
11 
12 namespace arm
13 {
14 
15 namespace pipe
16 {
17 
AddLabel(const arm::pipe::ITimelineDecoder::Label & label)18 void TimelineModel::AddLabel(const arm::pipe::ITimelineDecoder::Label& label)
19 {
20     m_LabelMap.emplace(label.m_Guid, label);
21 }
22 
FindLabel(uint64_t guid)23 std::string* TimelineModel::FindLabel(uint64_t guid)
24 {
25     auto iter = m_LabelMap.find(guid);
26     if (iter != m_LabelMap.end())
27     {
28         return &iter->second.m_Name;
29     }
30     else
31     {
32         return nullptr;
33     }
34 }
35 
AddEntity(uint64_t guid)36 void TimelineModel::AddEntity(uint64_t guid)
37 {
38     m_Entities.emplace(guid, guid);
39 }
40 
FindEntity(uint64_t id)41 Entity* TimelineModel::FindEntity(uint64_t id)
42 {
43     auto iter = m_Entities.find(id);
44     if (iter != m_Entities.end())
45     {
46         return &(iter->second);
47     }
48     else
49     {
50         return nullptr;
51     }
52 }
53 
AddRelationship(const arm::pipe::ITimelineDecoder::Relationship & relationship)54 void TimelineModel::AddRelationship(const arm::pipe::ITimelineDecoder::Relationship& relationship)
55 {
56     m_Relationships.emplace(relationship.m_Guid, relationship);
57     if (relationship.m_RelationshipType == arm::pipe::ITimelineDecoder::RelationshipType::LabelLink)
58     {
59         HandleLabelLink(relationship);
60     }
61     else if (relationship.m_RelationshipType == ITimelineDecoder::RelationshipType::RetentionLink)
62     {
63         // Take care of the special case of a connection between layers in ArmNN
64         // modelled by a retention link between two layer entities with an attribute GUID
65         // of connection
66         if (relationship.m_AttributeGuid == LabelsAndEventClasses::CONNECTION_GUID)
67         {
68             HandleConnection(relationship);
69         }
70         else if (relationship.m_AttributeGuid == LabelsAndEventClasses::CHILD_GUID)
71         {
72             HandleChild(relationship);
73         }
74         else if (relationship.m_AttributeGuid == LabelsAndEventClasses::EXECUTION_OF_GUID)
75         {
76             HandleExecutionOf(relationship);
77         }
78         else
79         {
80             // report unknown relationship type
81             std::stringstream ss;
82             ss << "Encountered a RetentionLink of unknown type [" << relationship.m_AttributeGuid << "]";
83             m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
84         }
85     }
86     else if (relationship.m_RelationshipType == arm::pipe::ITimelineDecoder::RelationshipType::ExecutionLink)
87     {
88         HandleExecutionLink(relationship);
89     }
90 }
91 
HandleLabelLink(const arm::pipe::ITimelineDecoder::Relationship & relationship)92 void TimelineModel::HandleLabelLink(const arm::pipe::ITimelineDecoder::Relationship& relationship)
93 {
94     Entity* entity = FindEntity(relationship.m_HeadGuid);
95     // we have a label attribute of an entity
96     std::string* value = nullptr;
97     std::string* attribute = nullptr;
98     value = FindLabel(relationship.m_TailGuid);
99     if (value == nullptr)
100     {
101         //report an error
102         std::stringstream ss;
103         ss << "could not find label link [" << relationship.m_Guid <<
104            "] value [" << relationship.m_TailGuid << "]";
105         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
106     }
107     if (relationship.m_AttributeGuid != 0)
108     {
109         attribute = FindLabel(relationship.m_AttributeGuid);
110         if (attribute == nullptr)
111         {
112             //report an error
113             std::stringstream ss;
114             ss << "could not find label link [" << relationship.m_Guid <<
115                "] attribute [" << relationship.m_AttributeGuid << "]";
116             m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
117         }
118     }
119     else
120     {
121         //report an error
122         std::stringstream ss;
123         ss << "label link [" << relationship.m_Guid << "] has a zero attribute guid";
124         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
125     }
126     if (entity != nullptr && attribute != nullptr && value != nullptr)
127     {
128         entity->AddAttribute(*attribute, *value);
129         // if the attribute is 'type' and the value is 'inference'
130         // we need to cache the entity guid as an inference
131         if (LabelsAndEventClasses::TYPE_LABEL.compare(*attribute) == 0 &&
132             LabelsAndEventClasses::INFERENCE.compare(*value) == 0)
133         {
134             m_InferenceGuids.push_back(relationship.m_HeadGuid);
135         }
136     }
137 
138     if (entity == nullptr)
139     {
140         //report an error
141         std::stringstream ss;
142         ss << "could not find label link [" << relationship.m_Guid <<
143            "] entity [" << relationship.m_HeadGuid << "] ";
144         if (value != nullptr)
145         {
146             ss << "value [" << *value << "] ";
147         }
148         if (attribute != nullptr)
149         {
150             ss << "attribute [" << *attribute << "] ";
151         }
152         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
153     }
154 }
155 
HandleConnection(const arm::pipe::ITimelineDecoder::Relationship & relationship)156 void TimelineModel::HandleConnection(const arm::pipe::ITimelineDecoder::Relationship& relationship)
157 {
158     Entity* outputLayer = FindEntity(relationship.m_HeadGuid);
159     if (outputLayer == nullptr)
160     {
161         std::stringstream ss;
162         ss << "could not find output entity [" << relationship.m_HeadGuid << "]";
163         ss << " of connection [" << relationship.m_Guid << "]";
164         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
165         return;
166     }
167     Entity* inputLayer = FindEntity(relationship.m_TailGuid);
168     if (inputLayer == nullptr)
169     {
170         std::stringstream ss;
171         ss << "could not find input entity [" << relationship.m_TailGuid << "]";
172         ss << " of connection [" << relationship.m_Guid << "]";
173         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
174         return;
175     }
176     Connection connection(relationship.m_Guid, outputLayer, inputLayer);
177     outputLayer->AddConnection(connection);
178 }
179 
HandleChild(const arm::pipe::ITimelineDecoder::Relationship & relationship)180 void TimelineModel::HandleChild(const arm::pipe::ITimelineDecoder::Relationship& relationship)
181 {
182     Entity* parentEntity = FindEntity(relationship.m_HeadGuid);
183     if (parentEntity == nullptr)
184     {
185         std::stringstream ss;
186         ss << "could not find parent entity [" << relationship.m_HeadGuid << "]";
187         ss << " of child relationship [" << relationship.m_Guid << "]";
188         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
189         return;
190     }
191     Entity* childEntity = FindEntity(relationship.m_TailGuid);
192     if (childEntity == nullptr)
193     {
194         std::stringstream ss;
195         ss << "could not find child entity [" << relationship.m_TailGuid << "]";
196         ss << " of child relationship [" << relationship.m_Guid << "]";
197         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
198         return;
199     }
200     parentEntity->AddChild(childEntity);
201 }
202 
HandleExecutionOf(const arm::pipe::ITimelineDecoder::Relationship & relationship)203 void TimelineModel::HandleExecutionOf(const arm::pipe::ITimelineDecoder::Relationship& relationship)
204 {
205     Entity* parentEntity = FindEntity(relationship.m_HeadGuid);
206     if (parentEntity == nullptr)
207     {
208         std::stringstream ss;
209         ss << "could not find parent entity [" << relationship.m_HeadGuid << "]";
210         ss << " of execution relationship [" << relationship.m_Guid << "]";
211         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
212         return;
213     }
214     Entity* executedEntity = FindEntity(relationship.m_TailGuid);
215     if (executedEntity == nullptr)
216     {
217         std::stringstream ss;
218         ss << "could not find executed entity [" << relationship.m_TailGuid << "]";
219         ss << " of execution relationship [" << relationship.m_Guid << "]";
220         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
221         return;
222     }
223     parentEntity->AddExecution(executedEntity);
224 }
225 
HandleExecutionLink(const arm::pipe::ITimelineDecoder::Relationship & relationship)226 void TimelineModel::HandleExecutionLink(const arm::pipe::ITimelineDecoder::Relationship& relationship)
227 {
228     // entityGuid,
229     Entity* parentEntity = FindEntity(relationship.m_HeadGuid);
230     if (parentEntity == nullptr)
231     {
232         std::stringstream ss;
233         ss << "could not find entity [" << relationship.m_HeadGuid << "]";
234         ss << " of ExecutionLink [" << relationship.m_Guid << "]";
235         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
236         return;
237     }
238     // eventGuid,
239     EventObj* eventObj = FindEvent(relationship.m_TailGuid);
240     if (eventObj == nullptr)
241     {
242         std::stringstream ss;
243         ss << "could not find event [" << relationship.m_TailGuid << "]";
244         ss << " of ExecutionLink [" << relationship.m_Guid << "]";
245         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
246         return;
247     }
248     // eventClassGuid
249     EventClassObj* eventClassObj = FindEventClass(relationship.m_AttributeGuid);
250     if (eventClassObj == nullptr)
251     {
252         std::stringstream ss;
253         ss << "could not find event class [" << relationship.m_TailGuid << "]";
254         ss << " of ExecutionLink [" << relationship.m_Guid << "]";
255         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
256         return;
257     }
258     eventObj->SetEventClass(eventClassObj);
259     parentEntity->AddEvent(eventObj);
260 }
261 
FindRelationship(uint64_t id)262 ModelRelationship* TimelineModel::FindRelationship(uint64_t id)
263 {
264     auto iter = m_Relationships.find(id);
265     if (iter != m_Relationships.end())
266     {
267         return &(iter->second);
268     }
269     else
270     {
271         return nullptr;
272     }
273 }
274 
IsInferenceGuid(uint64_t guid) const275 bool TimelineModel::IsInferenceGuid(uint64_t guid) const
276 {
277     auto it = std::find(m_InferenceGuids.begin(), m_InferenceGuids.end(), guid);
278     return it != m_InferenceGuids.end();
279 }
280 
AddEventClass(const arm::pipe::ITimelineDecoder::EventClass & eventClass)281 void TimelineModel::AddEventClass(const arm::pipe::ITimelineDecoder::EventClass& eventClass)
282 {
283     std::string* eventClassName = FindLabel(eventClass.m_NameGuid);
284     if (eventClassName != nullptr)
285     {
286         EventClassObj eventClassObj(eventClass.m_Guid, *eventClassName);
287         m_EventClasses.emplace(eventClassObj.GetGuid(), eventClassObj);
288     }
289     else
290     {
291         std::stringstream ss;
292         ss << "could not find name [" << eventClass.m_NameGuid << "]";
293         ss << " of of event class  [" << eventClass.m_Guid << "]";
294         m_Errors.push_back(arm::pipe::ProfilingException(ss.str()));
295     }
296 }
297 
FindEventClass(uint64_t id)298 EventClassObj* TimelineModel::FindEventClass(uint64_t id)
299 {
300     auto iter = m_EventClasses.find(id);
301     if (iter != m_EventClasses.end())
302     {
303         return &(iter->second);
304     }
305     else
306     {
307         return nullptr;
308     }
309 }
310 
AddEvent(const arm::pipe::ITimelineDecoder::Event & event)311 void TimelineModel::AddEvent(const arm::pipe::ITimelineDecoder::Event& event)
312 {
313     EventObj evt(event.m_Guid, event.m_TimeStamp, event.m_ThreadId);
314     m_Events.emplace(event.m_Guid, evt);
315 }
316 
FindEvent(uint64_t id)317 EventObj* TimelineModel::FindEvent(uint64_t id)
318 {
319     auto iter = m_Events.find(id);
320     if (iter != m_Events.end())
321     {
322         return &(iter->second);
323     }
324     else
325     {
326         return nullptr;
327     }
328 }
329 
GetModelDescription(const TimelineModel & model)330 std::vector<std::string> GetModelDescription(const TimelineModel& model)
331 {
332     std::vector<std::string> desc;
333     for (auto& entry : model.GetEntities())
334     {
335         auto& entity = entry.second;
336         desc.push_back(GetEntityDescription(entity));
337         for (auto& connection : entity.GetConnections())
338         {
339             desc.push_back(GetConnectionDescription(connection));
340         }
341         for (auto child : entity.GetChildren())
342         {
343             desc.push_back(GetChildDescription(child));
344         }
345         for (auto execution : entity.GetExecutions())
346         {
347             desc.push_back(GetExecutionDescription(execution));
348         }
349         for (auto event : entity.GetEvents())
350         {
351             desc.push_back(GetEventDescription(event));
352         }
353     }
354     return desc;
355 }
356 
GetEntityDescription(const Entity & entity)357 std::string GetEntityDescription(const Entity& entity)
358 {
359     std::stringstream ss;
360     ss << "Entity [" << entity.GetGuid() << "]";
361     for (auto& attributeEntry : entity.GetAttributes())
362     {
363         if (LabelsAndEventClasses::PROCESS_ID_LABEL == attributeEntry.second.first)
364         {
365             ss << " " << attributeEntry.second.first << " = [processId]";
366         }
367         else {
368             ss << " " << attributeEntry.second.first << " = " << attributeEntry.second.second;
369         }
370     }
371     return ss.str();
372 }
373 
GetChildDescription(Entity * entity)374 std::string GetChildDescription(Entity* entity)
375 {
376     std::stringstream ss;
377     ss << "   child: " << GetEntityDescription(*entity);
378     return ss.str();
379 }
380 
GetConnectionDescription(const Connection & connection)381 std::string GetConnectionDescription(const Connection& connection)
382 {
383     std::stringstream ss;
384     ss << "   connection [" << connection.GetGuid() << "] from entity [";
385     ss << connection.GetHead()->GetGuid() << "] to entity [" << connection.GetTail()->GetGuid() << "]";
386     return ss.str();
387 }
388 
GetExecutionDescription(Entity * execution)389 std::string GetExecutionDescription(Entity* execution)
390 {
391     std::stringstream ss;
392     ss << "   execution: " << GetEntityDescription(*execution);
393     return ss.str();
394 }
395 
GetEventDescription(EventObj * event)396 std::string GetEventDescription(EventObj* event)
397 {
398     std::stringstream ss;
399     ss << "   event: [" << event->GetGuid() << "] class [" << event->GetEventClass() << "]";
400     return ss.str();
401 }
402 
403 } // namespace pipe
404 
405 } // namespace arm