Merge branch 'feature/single_sysview_file_for_multicore' into 'master'

apptrace: Adds support for multi-core traces in single file to SystemView processing scripts

See merge request espressif/esp-idf!7298
This commit is contained in:
Ivan Grokhotkov
2020-03-19 17:45:15 +08:00
9 changed files with 272485 additions and 42 deletions

View File

@@ -63,7 +63,6 @@ tools/docker/hooks/build
tools/esp_app_trace/logtrace_proc.py tools/esp_app_trace/logtrace_proc.py
tools/esp_app_trace/sysviewtrace_proc.py tools/esp_app_trace/sysviewtrace_proc.py
tools/esp_app_trace/test/logtrace/test.sh tools/esp_app_trace/test/logtrace/test.sh
tools/esp_app_trace/test/sysview/compare_json.py
tools/esp_app_trace/test/sysview/test.sh tools/esp_app_trace/test/sysview/test.sh
tools/find_apps.py tools/find_apps.py
tools/format.sh tools/format.sh

View File

@@ -1,3 +1,4 @@
from __future__ import print_function
import sys import sys
import os import os
try: try:
@@ -593,7 +594,7 @@ class BaseLogTraceDataProcessorImpl:
msg = event.get_message(self.felf) msg = event.get_message(self.felf)
self.messages.append(msg) self.messages.append(msg)
if self.print_log_events: if self.print_log_events:
print(msg), print(msg, end='')
class HeapTraceParseError(ParseError): class HeapTraceParseError(ParseError):

View File

@@ -90,7 +90,7 @@ def parse_trace(reader, parser, os_evt_map_file=''):
global _os_events_map global _os_events_map
# parse OS events formats file # parse OS events formats file
_os_events_map = _read_events_map(os_evt_map_file) _os_events_map = _read_events_map(os_evt_map_file)
_read_file_header(reader) parser.esp_ext = ('; ESP_Extension\n' in _read_file_header(reader))
_read_init_seq(reader) _read_init_seq(reader)
while True: while True:
event = parser.read_event(reader, _os_events_map) event = parser.read_event(reader, _os_events_map)
@@ -305,7 +305,7 @@ class SysViewEvent(apptrace.TraceEvent):
""" """
Generic SystemView event class. This is a base class for all events. Generic SystemView event class. This is a base class for all events.
""" """
def __init__(self, evt_id, reader, core_id, events_fmt_map=None): def __init__(self, evt_id, core_id, reader, events_fmt_map=None):
""" """
Constructor. Reads and optionally decodes event. Constructor. Reads and optionally decodes event.
@@ -516,11 +516,11 @@ class SysViewPredefinedEvent(SysViewEvent):
SYSVIEW_EVTID_NUMMODULES: ('svNumModules', [SysViewEventParamSimple('mod_cnt', _decode_u32)]), SYSVIEW_EVTID_NUMMODULES: ('svNumModules', [SysViewEventParamSimple('mod_cnt', _decode_u32)]),
} }
def __init__(self, evt_id, reader, core_id): def __init__(self, evt_id, core_id, reader):
""" """
see SysViewEvent.__init__() see SysViewEvent.__init__()
""" """
SysViewEvent.__init__(self, evt_id, reader, core_id, self._predef_events_fmt) SysViewEvent.__init__(self, evt_id, core_id, reader, self._predef_events_fmt)
# self.name = 'SysViewPredefinedEvent' # self.name = 'SysViewPredefinedEvent'
@@ -528,11 +528,11 @@ class SysViewOSEvent(SysViewEvent):
""" """
OS related SystemView events class. OS related SystemView events class.
""" """
def __init__(self, evt_id, reader, core_id, events_fmt_map): def __init__(self, evt_id, core_id, reader, events_fmt_map):
""" """
see SysViewEvent.__init__() see SysViewEvent.__init__()
""" """
SysViewEvent.__init__(self, evt_id, reader, core_id, events_fmt_map) SysViewEvent.__init__(self, evt_id, core_id, reader, events_fmt_map)
# self.name = 'SysViewOSEvent' # self.name = 'SysViewOSEvent'
@@ -553,7 +553,7 @@ class SysViewHeapEvent(SysViewEvent):
SysViewEventParamArray('callers', _decode_u32)]), SysViewEventParamArray('callers', _decode_u32)]),
} }
def __init__(self, evt_id, events_off, reader, core_id): def __init__(self, evt_id, core_id, events_off, reader):
""" """
Constructor. Reads and optionally decodes event. Constructor. Reads and optionally decodes event.
@@ -571,7 +571,7 @@ class SysViewHeapEvent(SysViewEvent):
cur_events_map = {} cur_events_map = {}
for id in self.events_fmt: for id in self.events_fmt:
cur_events_map[events_off + id] = self.events_fmt[id] cur_events_map[events_off + id] = self.events_fmt[id]
SysViewEvent.__init__(self, evt_id, reader, core_id, cur_events_map) SysViewEvent.__init__(self, evt_id, core_id, reader, cur_events_map)
# self.name = 'SysViewHeapEvent' # self.name = 'SysViewHeapEvent'
@@ -609,6 +609,7 @@ class SysViewTraceDataParser(apptrace.TraceDataProcessor):
self.irqs_info = {} self.irqs_info = {}
self.tasks_info = {} self.tasks_info = {}
self.core_id = core_id self.core_id = core_id
self.esp_ext = False
def _parse_irq_desc(self, desc): def _parse_irq_desc(self, desc):
""" """
@@ -646,7 +647,7 @@ class SysViewTraceDataParser(apptrace.TraceDataProcessor):
self._last_ts += ts self._last_ts += ts
return float(self._last_ts) / self.sys_info.params['sys_freq'].value return float(self._last_ts) / self.sys_info.params['sys_freq'].value
def read_extension_event(self, evt_id, reader): def read_extension_event(self, evt_id, core_id, reader):
""" """
Reads extension event. Reads extension event.
Default implementation which just reads out event. Default implementation which just reads out event.
@@ -667,9 +668,18 @@ class SysViewTraceDataParser(apptrace.TraceDataProcessor):
""" """
if self.root_proc == self: if self.root_proc == self:
# by default just read out and skip unknown event # by default just read out and skip unknown event
return SysViewEvent(evt_id, reader, self.core_id) return SysViewEvent(evt_id, core_id, reader)
return None # let decide to root parser return None # let decide to root parser
@staticmethod
def _decode_core_id(high_b):
if high_b & (1 << 6):
core_id = 1
high_b &= ~(1 << 6)
else:
core_id = 0
return high_b,core_id
def read_event(self, reader, os_evt_map): def read_event(self, reader, os_evt_map):
""" """
Reads pre-defined or OS-related event. Reads pre-defined or OS-related event.
@@ -692,17 +702,26 @@ class SysViewTraceDataParser(apptrace.TraceDataProcessor):
if evt_hdr & 0x80: if evt_hdr & 0x80:
# evt_id (2 bytes) # evt_id (2 bytes)
b, = struct.unpack('<B', reader.read(1)) b, = struct.unpack('<B', reader.read(1))
evt_id = b # higher part # higher part
if self.esp_ext:
evt_id,core_id = self._decode_core_id(b)
else:
evt_id = b
core_id = self.core_id
evt_id = (evt_id << 7) | (evt_hdr & ~0x80) # lower 7 bits evt_id = (evt_id << 7) | (evt_hdr & ~0x80) # lower 7 bits
else: else:
# evt_id (1 byte) # evt_id (1 byte)
evt_id = evt_hdr if self.esp_ext:
evt_id,core_id = self._decode_core_id(evt_hdr)
else:
evt_id = evt_hdr
core_id = self.core_id
if evt_id <= SYSVIEW_EVENT_ID_PREDEF_MAX: if evt_id <= SYSVIEW_EVENT_ID_PREDEF_MAX:
return SysViewPredefinedEvent(evt_id, reader, self.core_id) return SysViewPredefinedEvent(evt_id, core_id, reader)
elif evt_id < SYSVIEW_MODULE_EVENT_OFFSET: elif evt_id < SYSVIEW_MODULE_EVENT_OFFSET:
return SysViewOSEvent(evt_id, reader, self.core_id, os_evt_map) return SysViewOSEvent(evt_id, core_id, reader, os_evt_map)
else: else:
return self.read_extension_event(evt_id, reader) return self.read_extension_event(evt_id, core_id, reader)
def event_supported(self, event): def event_supported(self, event):
return False return False
@@ -788,7 +807,7 @@ class SysViewMultiTraceDataParser(SysViewTraceDataParser):
parser.root_proc = self parser.root_proc = self
self.stream_parsers[stream_id] = parser self.stream_parsers[stream_id] = parser
def read_extension_event(self, evt_id, reader): def read_extension_event(self, evt_id, core_id, reader):
""" """
Reads extension event. Reads extension event.
Iterates over registered stream parsers trying to find one which supports that type of event. Iterates over registered stream parsers trying to find one which supports that type of event.
@@ -806,10 +825,10 @@ class SysViewMultiTraceDataParser(SysViewTraceDataParser):
object for extension event, if extension event is not supported return SysViewEvent instance. object for extension event, if extension event is not supported return SysViewEvent instance.
""" """
for stream_id in self.stream_parsers: for stream_id in self.stream_parsers:
evt = self.stream_parsers[stream_id].read_extension_event(evt_id, reader) evt = self.stream_parsers[stream_id].read_extension_event(evt_id, core_id, reader)
if evt: if evt:
return evt return evt
return SysViewTraceDataParser.read_extension_event(self, evt_id, reader) return SysViewTraceDataParser.read_extension_event(self, evt_id, core_id, reader)
def on_new_event(self, event): def on_new_event(self, event):
""" """
@@ -976,8 +995,17 @@ class SysViewTraceDataProcessor(apptrace.TraceDataProcessor):
if SYSVIEW_EVTID_TASK_START_EXEC or SYSVIEW_EVTID_TASK_STOP_READY is received for unknown task. if SYSVIEW_EVTID_TASK_START_EXEC or SYSVIEW_EVTID_TASK_STOP_READY is received for unknown task.
""" """
if event.core_id not in self.traces: if event.core_id not in self.traces:
raise SysViewTraceParseError("Event for unknown core %d" % event.core_id) if 0 in self.traces and self.traces[0].esp_ext:
trace = self.traces[event.core_id] # for Espressif extension there is one trace for all cores
trace = self.traces[0]
if event.core_id not in self.ctx_stack:
self.ctx_stack[event.core_id] = []
if event.core_id not in self.prev_ctx:
self.prev_ctx[event.core_id] = None
else:
raise SysViewTraceParseError("Event for unknown core %d" % event.core_id)
else:
trace = self.traces[event.core_id]
if event.id == SYSVIEW_EVTID_ISR_ENTER: if event.id == SYSVIEW_EVTID_ISR_ENTER:
if event.params['irq_num'].value not in trace.irqs_info: if event.params['irq_num'].value not in trace.irqs_info:
raise SysViewTraceParseError("Enter unknown ISR %d" % event.params['irq_num'].value) raise SysViewTraceParseError("Enter unknown ISR %d" % event.params['irq_num'].value)
@@ -1113,7 +1141,11 @@ class SysViewMultiStreamTraceDataProcessor(SysViewTraceDataProcessor):
SysViewTraceDataParser SysViewTraceDataParser
parser object for specified stream and core parser object for specified stream and core
""" """
trace = self.traces[core_id] if core_id not in self.traces and 0 in self.traces and self.traces[0].esp_ext:
# for Espressif extension there is one trace for all cores
trace = self.traces[0]
else:
trace = self.traces[core_id]
if stream_id == SysViewTraceDataParser.STREAMID_SYS: if stream_id == SysViewTraceDataParser.STREAMID_SYS:
return trace return trace
if isinstance(trace, SysViewMultiTraceDataParser): if isinstance(trace, SysViewMultiTraceDataParser):
@@ -1213,15 +1245,15 @@ class SysViewHeapTraceDataParser(SysViewTraceDataExtEventParser):
""" """
SysViewTraceDataExtEventParser.__init__(self, events_num=len(SysViewHeapEvent.events_fmt.keys()), core_id=core_id, print_events=print_events) SysViewTraceDataExtEventParser.__init__(self, events_num=len(SysViewHeapEvent.events_fmt.keys()), core_id=core_id, print_events=print_events)
def read_extension_event(self, evt_id, reader): def read_extension_event(self, evt_id, core_id, reader):
""" """
Reads heap event. Reads heap event.
see SysViewTraceDataParser.read_extension_event() see SysViewTraceDataParser.read_extension_event()
""" """
if (self.events_off >= SYSVIEW_MODULE_EVENT_OFFSET and evt_id >= self.events_off and if (self.events_off >= SYSVIEW_MODULE_EVENT_OFFSET and evt_id >= self.events_off and
evt_id < self.events_off + self.events_num): evt_id < self.events_off + self.events_num):
return SysViewHeapEvent(evt_id, self.events_off, reader, self.core_id) return SysViewHeapEvent(evt_id, core_id, self.events_off, reader)
return SysViewTraceDataParser.read_extension_event(self, evt_id, reader) return SysViewTraceDataParser.read_extension_event(self, evt_id, core_id, reader)
def on_new_event(self, event): def on_new_event(self, event):
""" """

View File

@@ -1,16 +0,0 @@
#!/usr/bin/env python
import json
import sys
if len(sys.argv) < 3:
sys.exit(-1)
objs = []
for i in range(1, len(sys.argv)):
f = open(sys.argv[i])
objs.append(json.load(f))
for i in range(1, len(objs)):
if objs[i - 1] != objs[i]:
sys.exit(-1)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -14,3 +14,17 @@
&& coverage report \ && coverage report \
; } || { echo 'The test for sysviewtrace_proc JSON functionality has failed. Please examine the artifacts.' ; exit 1; } ; } || { echo 'The test for sysviewtrace_proc JSON functionality has failed. Please examine the artifacts.' ; exit 1; }
{ coverage debug sys \
&& coverage erase &> output \
&& coverage run -a $IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -d -p -b sysview_tracing_heap_log.elf heap_log_mcore.svdat &>> output \
&& diff output expected_output_mcore \
&& coverage report \
; } || { echo 'The test for mcore sysviewtrace_proc functionality has failed. Please examine the artifacts.' ; exit 1; }
{ coverage debug sys \
&& coverage erase &> output.json \
&& coverage run -a $IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -j -b sysview_tracing_heap_log.elf heap_log_mcore.svdat &>> output.json \
&& diff output.json expected_output_mcore.json \
&& coverage report \
; } || { echo 'The test for mcore sysviewtrace_proc JSON functionality has failed. Please examine the artifacts.' ; exit 1; }