1import copy 2import json 3import re 4import struct 5 6import espytrace.apptrace as apptrace 7 8SYSVIEW_EVTID_NOP = 0 # Dummy packet. 9SYSVIEW_EVTID_OVERFLOW = 1 10SYSVIEW_EVTID_ISR_ENTER = 2 11SYSVIEW_EVTID_ISR_EXIT = 3 12SYSVIEW_EVTID_TASK_START_EXEC = 4 13SYSVIEW_EVTID_TASK_STOP_EXEC = 5 14SYSVIEW_EVTID_TASK_START_READY = 6 15SYSVIEW_EVTID_TASK_STOP_READY = 7 16SYSVIEW_EVTID_TASK_CREATE = 8 17SYSVIEW_EVTID_TASK_INFO = 9 18SYSVIEW_EVTID_TRACE_START = 10 19SYSVIEW_EVTID_TRACE_STOP = 11 20SYSVIEW_EVTID_SYSTIME_CYCLES = 12 21SYSVIEW_EVTID_SYSTIME_US = 13 22SYSVIEW_EVTID_SYSDESC = 14 23SYSVIEW_EVTID_USER_START = 15 24SYSVIEW_EVTID_USER_STOP = 16 25SYSVIEW_EVTID_IDLE = 17 26SYSVIEW_EVTID_ISR_TO_SCHEDULER = 18 27SYSVIEW_EVTID_TIMER_ENTER = 19 28SYSVIEW_EVTID_TIMER_EXIT = 20 29SYSVIEW_EVTID_STACK_INFO = 21 30SYSVIEW_EVTID_MODULEDESC = 22 31SYSVIEW_EVTID_INIT = 24 32SYSVIEW_EVENT_ID_PREDEF_LEN_MAX = SYSVIEW_EVTID_INIT 33SYSVIEW_EVTID_NAME_RESOURCE = 25 34SYSVIEW_EVTID_PRINT_FORMATTED = 26 35SYSVIEW_EVTID_NUMMODULES = 27 36SYSVIEW_EVENT_ID_PREDEF_MAX = SYSVIEW_EVTID_NUMMODULES 37 38SYSVIEW_EVENT_ID_MAX = 200 39 40SYSVIEW_MODULE_EVENT_OFFSET = 512 41 42SYSVIEW_SYNC_LEN = 10 43 44_sysview_events_map = { 45 'SYS_NOP': SYSVIEW_EVTID_NOP, 46 'SYS_OVERFLOW': SYSVIEW_EVTID_OVERFLOW, 47 'SYS_ISR_ENTER': SYSVIEW_EVTID_ISR_ENTER, 48 'SYS_ISR_EXIT': SYSVIEW_EVTID_ISR_EXIT, 49 'SYS_TASK_START_EXEC': SYSVIEW_EVTID_TASK_START_EXEC, 50 'SYS_TASK_STOP_EXEC': SYSVIEW_EVTID_TASK_STOP_EXEC, 51 'SYS_TASK_START_READY': SYSVIEW_EVTID_TASK_START_READY, 52 'SYS_TASK_STOP_READY': SYSVIEW_EVTID_TASK_STOP_READY, 53 'SYS_TASK_CREATE': SYSVIEW_EVTID_TASK_CREATE, 54 'SYS_TASK_INFO': SYSVIEW_EVTID_TASK_INFO, 55 'SYS_TRACE_START': SYSVIEW_EVTID_TRACE_START, 56 'SYS_TRACE_STOP': SYSVIEW_EVTID_TRACE_STOP, 57 'SYS_SYSTIME_CYCLES': SYSVIEW_EVTID_SYSTIME_CYCLES, 58 'SYS_SYSTIME_US': SYSVIEW_EVTID_SYSTIME_US, 59 'SYS_SYSDESC': SYSVIEW_EVTID_SYSDESC, 60 'SYS_USER_START': SYSVIEW_EVTID_USER_START, 61 'SYS_USER_STOP': SYSVIEW_EVTID_USER_STOP, 62 'SYS_IDLE': SYSVIEW_EVTID_IDLE, 63 'SYS_ISR_TO_SCHEDULER': SYSVIEW_EVTID_ISR_TO_SCHEDULER, 64 'SYS_TIMER_ENTER': SYSVIEW_EVTID_TIMER_ENTER, 65 'SYS_TIMER_EXIT': SYSVIEW_EVTID_TIMER_EXIT, 66 'SYS_STACK_INFO': SYSVIEW_EVTID_STACK_INFO, 67 'SYS_MODULEDESC': SYSVIEW_EVTID_INIT, 68 'SYS_INIT': SYSVIEW_EVTID_INIT, 69 'SYS_NAME_RESOURCE': SYSVIEW_EVTID_NAME_RESOURCE, 70 'SYS_PRINT_FORMATTED': SYSVIEW_EVTID_PRINT_FORMATTED, 71 'SYS_NUMMODULES': SYSVIEW_EVTID_NUMMODULES 72} 73 74_os_events_map = {} 75 76 77def parse_trace(reader, parser, os_evt_map_file=''): 78 """ 79 Parses trace. 80 81 Parameters 82 ---------- 83 reader : apptrace.Reader 84 Trace reader object. 85 parser : SysViewTraceDataParser 86 Top level parser object. 87 os_evt_map_file : string 88 Path to file containg events format description. 89 """ 90 global _os_events_map 91 # parse OS events formats file 92 _os_events_map = _read_events_map(os_evt_map_file) 93 parser.esp_ext = ('; ESP_Extension\n' in _read_file_header(reader)) 94 _read_init_seq(reader) 95 while True: 96 event = parser.read_event(reader, _os_events_map) 97 parser.on_new_event(event) 98 99 100def _read_events_map(os_evt_map_file): 101 """ 102 Reads SystemView events format description from file. 103 104 Parameters 105 ---------- 106 os_evt_map_file : string 107 Path to file containg events format description. 108 109 Returns 110 ------- 111 dict 112 a dict with event IDs as keys and values as tuples containg event name and a list of parameters. 113 """ 114 os_evt_map = {} 115 with open(os_evt_map_file) as f: 116 for line in f: 117 comps = line.split() 118 if len(comps) < 2: 119 continue 120 params = [] 121 if len(comps) > 2: 122 for p in comps[2:]: 123 sp = p.split('=') 124 if sp[1].startswith('%'): 125 sp[1] = sp[1][1:] 126 if sp[1] == 'u': 127 params.append(SysViewEventParamSimple(sp[0], _decode_u32)) 128 elif sp[1] == 's': 129 params.append(SysViewEventParamSimple(sp[0], _decode_str)) 130 elif sp[1] == 't' or sp[1] == 'T' or sp[1] == 'I' or sp[1] == 'p': 131 # TODO: handle shrinked task/queue ID and addresses 132 params.append(SysViewEventParamSimple(sp[0], _decode_u32)) 133 os_evt_map[int(comps[0])] = (comps[1], params) 134 return os_evt_map 135 136 137def _read_file_header(reader): 138 """ 139 Reads SystemView trace file header. 140 141 Parameters 142 ---------- 143 reader : apptrace.Reader 144 Trace reader object. 145 146 Returns 147 ------- 148 list 149 a list of header lines. 150 """ 151 empty_count = 0 152 lines = [] 153 while empty_count < 2: 154 lines.append(reader.readline(linesep='\n')) 155 if lines[-1] == ';\n': 156 empty_count += 1 157 return lines 158 159 160def _read_init_seq(reader): 161 """ 162 Reads SystemView trace initial synchronisation sequence of bytes. 163 164 Parameters 165 ---------- 166 reader : apptrace.Reader 167 Trace reader object. 168 169 Raises 170 ------- 171 SysViewTraceParseError 172 If sync sequence is broken. 173 """ 174 SYNC_SEQ_FMT = '<%dB' % SYSVIEW_SYNC_LEN 175 sync_bytes = struct.unpack(SYNC_SEQ_FMT, reader.read(struct.calcsize(SYNC_SEQ_FMT))) 176 for b in sync_bytes: 177 if b != 0: 178 raise SysViewTraceParseError('Invalid sync sequense!') 179 180 181def _decode_u32(reader): 182 """ 183 Reads and decodes unsigned 32-bit integer. 184 185 Parameters 186 ---------- 187 reader : apptrace.Reader 188 Trace reader object. 189 190 Returns 191 ------- 192 tuple 193 a tuple containg number of read bytes and decoded value. 194 """ 195 sz = 0 196 val = 0 197 while True: 198 b, = struct.unpack('<B', reader.read(1)) 199 if b & 0x80: 200 val |= (b & 0x7F) << (7 * sz) 201 else: 202 val |= b << (7 * sz) 203 break 204 sz += 1 205 return (sz + 1,val) 206 207 208def _decode_id(reader): 209 """ 210 Reads and decodes ID (task ID, queue handle, semaphore handle etc.). 211 212 Parameters 213 ---------- 214 reader : apptrace.Reader 215 Trace reader object. 216 217 Returns 218 ------- 219 tuple 220 a tuple containg number of read bytes and decoded value. 221 """ 222 return _decode_u32(reader) 223 224 225def _decode_u64(reader): 226 """ 227 Reads and decodes unsigned 64-bit integer. 228 229 Parameters 230 ---------- 231 reader : apptrace.Reader 232 Trace reader object. 233 234 Returns 235 ------- 236 tuple 237 a tuple containg number of read bytes and decoded value. 238 """ 239 sz,val = _decode_u32(reader) 240 sz2,high = _decode_u32(reader) 241 sz += sz2 242 return sz,(val | (high << 32)) 243 244 245def _decode_str(reader): 246 """ 247 Reads and decodes string. 248 249 Parameters 250 ---------- 251 reader : apptrace.Reader 252 Trace reader object. 253 254 Returns 255 ------- 256 tuple 257 a tuple containg number of read bytes and decoded value. 258 """ 259 sz = 0 260 val = '' 261 sz, = struct.unpack('<B', reader.read(1)) 262 if sz == 0xFF: 263 buf = struct.unpack('<2B', reader.read(2)) 264 sz = (buf[1] << 8) | buf[0] 265 val, = struct.unpack('<%ds' % sz, reader.read(sz)) 266 val = val.decode('utf-8') 267 if sz < 0xFF: 268 return (sz + 1,val) # one extra byte for length 269 return (sz + 3,val) # 3 extra bytes for length 270 271 272def _decode_plen(reader): 273 """ 274 Reads and decodes event's payload length. 275 276 Parameters 277 ---------- 278 reader : apptrace.Reader 279 Trace reader object. 280 281 Returns 282 ------- 283 int 284 decoded value. 285 """ 286 plen = 0 287 b0, = struct.unpack('<B', reader.read(1)) 288 if b0 & 0x80: 289 b1, = struct.unpack('<B', reader.read(1)) 290 plen = b1 # higher part 291 plen = (plen << 7) | (b0 & ~0x80) # lower 7 bits 292 else: 293 plen = b0 294 return plen 295 296 297class SysViewTraceParseError(apptrace.ParseError): 298 """ 299 SystemView parse error exception. 300 """ 301 pass 302 303 304class SysViewEvent(apptrace.TraceEvent): 305 """ 306 Generic SystemView event class. This is a base class for all events. 307 """ 308 def __init__(self, evt_id, core_id, reader, events_fmt_map=None): 309 """ 310 Constructor. Reads and optionally decodes event. 311 312 Parameters 313 ---------- 314 evt_id : int 315 Event ID. 316 reader : apptrace.Reader 317 Trace reader object. 318 core_id : int 319 Core ID event has been generated on. 320 events_fmt_map : dict 321 see return value of _read_events_map() 322 """ 323 apptrace.TraceEvent.__init__(self, 'SysViewEvent', core_id, evt_id) 324 self.plen = 0 325 if self.id >= SYSVIEW_EVENT_ID_PREDEF_LEN_MAX: 326 self.plen = _decode_plen(reader) 327 if events_fmt_map: 328 self._read_payload(reader, events_fmt_map) 329 else: 330 reader.forward(self.plen) 331 _,self.ts = _decode_u32(reader) 332 333 def _read_payload(self, reader, events_fmt_map): 334 """ 335 Reads event's payload and populates its parameters dictionary. 336 337 Parameters 338 ---------- 339 reader : apptrace.Reader 340 Trace reader object. 341 events_fmt_map : dict 342 see return value of _read_events_map() 343 344 Raises 345 ------- 346 SysViewTraceParseError 347 if event has unknown or invalid format. 348 """ 349 if self.id not in events_fmt_map: 350 raise SysViewTraceParseError('Unknown event ID %d!' % self.id) 351 self.name = events_fmt_map[self.id][0] 352 evt_params_templates = events_fmt_map[self.id][1] 353 params_len = 0 354 for i in range(len(evt_params_templates)): 355 event_param = copy.deepcopy(evt_params_templates[i]) 356 try: 357 cur_pos = reader.get_pos() 358 sz,param_val = event_param.decode(reader, self.plen - params_len) 359 except Exception as e: 360 raise SysViewTraceParseError('Failed to decode event {}({:d}) {:d} param @ 0x{:x}! {}'.format(self.name, self.id, self.plen, cur_pos, e)) 361 event_param.idx = i 362 event_param.value = param_val 363 self.params[event_param.name] = event_param 364 params_len += sz 365 if self.id >= SYSVIEW_EVENT_ID_PREDEF_LEN_MAX and self.plen != params_len: 366 raise SysViewTraceParseError('Invalid event {}({:d}) payload len {:d}! Must be {:d}.'.format(self.name, self.id, self.plen, params_len)) 367 368 def __str__(self): 369 params = '' 370 for param in sorted(self.params.values(), key=lambda x: x.idx): 371 params += '{}, '.format(param) 372 if len(params): 373 params = params[:-2] # remove trailing ', ' 374 return '{:.9f} - core[{:d}].{}({:d}), plen {:d}: [{}]'.format(self.ts, self.core_id, self.name, self.id, self.plen, params) 375 376 377class SysViewEventParam: 378 """ 379 Abstract base SystemView event's parameter class. This is a base class for all event's parameters. 380 """ 381 def __init__(self, name, decode_func): 382 """ 383 Constructor. 384 385 Parameters 386 ---------- 387 name : string 388 Event parameter name. 389 decode_func : callable object 390 Parameter decoding function. 391 """ 392 self.name = name 393 self.decode_func = decode_func 394 self.value = None 395 # positional index, used for sorting parameters before printing to make them looking as they appear in the event 396 self.idx = 0 397 398 def decode(self, reader, max_sz): 399 """ 400 Reads and decodes events parameter. 401 402 Parameters 403 ---------- 404 reader : apptrace.Reader 405 Trace reader object. 406 max_sz : int 407 Maximum number of bytes to read. 408 409 Returns 410 ------- 411 tuple 412 a tuple containg number of read bytes and decoded value. 413 """ 414 pass 415 416 def __str__(self): 417 return '{}: {}'.format(self.name, self.value) 418 419 def to_jsonable(self): 420 return {self.name: self.value} 421 422 423class SysViewEventParamSimple(SysViewEventParam): 424 """ 425 Simple SystemView event's parameter class. 426 """ 427 def decode(self, reader, max_sz): 428 """ 429 see SysViewEventParam.decode() 430 """ 431 return self.decode_func(reader) 432 433 434class SysViewEventParamArray(SysViewEventParamSimple): 435 """ 436 Array SystemView event's parameter class. 437 """ 438 def __init__(self, name, decode_func, size=-1): 439 """ 440 Constructor. 441 442 Parameters 443 ---------- 444 name : string 445 see SysViewEventParam.__init__() 446 decode_func : callable object 447 see SysViewEventParam.__init__() 448 size : int 449 Array's size. If -1 decode() will try to read all bytes from reader. 450 """ 451 SysViewEventParamSimple.__init__(self, name, decode_func) 452 self.arr_size = size 453 454 def decode(self, reader, max_sz): 455 """ 456 see SysViewEventParam.decode() 457 """ 458 tottal_sz = 0 459 vals = [] 460 i = 0 461 while tottal_sz < max_sz: 462 sz,val = self.decode_func(reader) 463 vals.append(val) 464 tottal_sz += sz 465 i += 1 466 if self.arr_size != -1 and i == self.arr_size: 467 break 468 return tottal_sz,vals 469 470 471class SysViewPredefinedEvent(SysViewEvent): 472 """ 473 Pre-defined SystemView events class. 474 """ 475 _predef_events_fmt = { 476 SYSVIEW_EVTID_NOP: ('svNop', []), 477 SYSVIEW_EVTID_OVERFLOW: ('svOverflow', [SysViewEventParamSimple('drop_cnt', _decode_u32)]), 478 SYSVIEW_EVTID_ISR_ENTER: ('svIsrEnter', [SysViewEventParamSimple('irq_num', _decode_u32)]), 479 SYSVIEW_EVTID_ISR_EXIT: ('svIsrExit', []), 480 SYSVIEW_EVTID_TASK_START_EXEC: ('svTaskStartExec', [SysViewEventParamSimple('tid', _decode_id)]), 481 SYSVIEW_EVTID_TASK_STOP_EXEC: ('svTaskStopExec', []), 482 SYSVIEW_EVTID_TASK_START_READY: ('svTaskStartReady', [SysViewEventParamSimple('tid', _decode_id)]), 483 SYSVIEW_EVTID_TASK_STOP_READY: ('svTaskStopReady', [SysViewEventParamSimple('tid', _decode_id), 484 SysViewEventParamSimple('cause', _decode_u32)]), 485 SYSVIEW_EVTID_TASK_CREATE: ('svTaskCreate', [SysViewEventParamSimple('tid', _decode_id)]), 486 SYSVIEW_EVTID_TASK_INFO: ('svTaskInfo', [SysViewEventParamSimple('tid', _decode_id), 487 SysViewEventParamSimple('prio', _decode_u32), 488 SysViewEventParamSimple('name', _decode_str)]), 489 SYSVIEW_EVTID_TRACE_START: ('svTraceStart', []), 490 SYSVIEW_EVTID_TRACE_STOP: ('svTraceStop', []), 491 SYSVIEW_EVTID_SYSTIME_CYCLES: ('svSysTimeCycles', [SysViewEventParamSimple('cycles', _decode_u32)]), 492 SYSVIEW_EVTID_SYSTIME_US: ('svSysTimeUs', [SysViewEventParamSimple('time', _decode_u64)]), 493 SYSVIEW_EVTID_SYSDESC: ('svSysDesc', [SysViewEventParamSimple('desc', _decode_str)]), 494 SYSVIEW_EVTID_USER_START: ('svUserStart', [SysViewEventParamSimple('user_id', _decode_u32)]), 495 SYSVIEW_EVTID_USER_STOP: ('svUserStart', [SysViewEventParamSimple('user_id', _decode_u32)]), 496 SYSVIEW_EVTID_IDLE: ('svIdle', []), 497 SYSVIEW_EVTID_ISR_TO_SCHEDULER: ('svExitIsrToScheduler', []), 498 SYSVIEW_EVTID_TIMER_ENTER: ('svTimerEnter', [SysViewEventParamSimple('tim_id', _decode_u32)]), 499 SYSVIEW_EVTID_TIMER_EXIT: ('svTimerExit', []), 500 SYSVIEW_EVTID_STACK_INFO: ('svStackInfo', [SysViewEventParamSimple('tid', _decode_id), 501 SysViewEventParamSimple('base', _decode_u32), 502 SysViewEventParamSimple('sz', _decode_u32), 503 SysViewEventParamSimple('unused', _decode_u32)]), 504 SYSVIEW_EVTID_MODULEDESC: ('svModuleDesc', [SysViewEventParamSimple('mod_id', _decode_u32), 505 SysViewEventParamSimple('evt_off', _decode_u32), 506 SysViewEventParamSimple('desc', _decode_str)]), 507 SYSVIEW_EVTID_INIT: ('svInit', [SysViewEventParamSimple('sys_freq', _decode_u32), 508 SysViewEventParamSimple('cpu_freq', _decode_u32), 509 SysViewEventParamSimple('ram_base', _decode_u32), 510 SysViewEventParamSimple('id_shift', _decode_u32)]), 511 SYSVIEW_EVTID_NAME_RESOURCE: ('svNameResource', [SysViewEventParamSimple('res_id', _decode_u32), 512 SysViewEventParamSimple('name', _decode_str)]), 513 SYSVIEW_EVTID_PRINT_FORMATTED: ('svPrint', [SysViewEventParamSimple('msg', _decode_str), 514 SysViewEventParamSimple('lvl', _decode_u32), 515 SysViewEventParamSimple('unused', _decode_u32)]), 516 SYSVIEW_EVTID_NUMMODULES: ('svNumModules', [SysViewEventParamSimple('mod_cnt', _decode_u32)]), 517 } 518 519 def __init__(self, evt_id, core_id, reader): 520 """ 521 see SysViewEvent.__init__() 522 """ 523 SysViewEvent.__init__(self, evt_id, core_id, reader, self._predef_events_fmt) 524 # self.name = 'SysViewPredefinedEvent' 525 526 527class SysViewOSEvent(SysViewEvent): 528 """ 529 OS related SystemView events class. 530 """ 531 def __init__(self, evt_id, core_id, reader, events_fmt_map): 532 """ 533 see SysViewEvent.__init__() 534 """ 535 SysViewEvent.__init__(self, evt_id, core_id, reader, events_fmt_map) 536 # self.name = 'SysViewOSEvent' 537 538 539class SysViewHeapEvent(SysViewEvent): 540 """ 541 Heap related SystemView events class. 542 543 Attributes 544 ---------- 545 events_fmt : dict 546 see return value of _read_events_map() 547 """ 548 events_fmt = { 549 0: ('esp_sysview_heap_trace_alloc', [SysViewEventParamSimple('addr', _decode_u32), 550 SysViewEventParamSimple('size', _decode_u32), 551 SysViewEventParamArray('callers', _decode_u32)]), 552 1: ('esp_sysview_heap_trace_free', [SysViewEventParamSimple('addr', _decode_u32), 553 SysViewEventParamArray('callers', _decode_u32)]), 554 } 555 556 def __init__(self, evt_id, core_id, events_off, reader): 557 """ 558 Constructor. Reads and optionally decodes event. 559 560 Parameters 561 ---------- 562 evt_id : int 563 see SysViewEvent.__init__() 564 events_off : int 565 Offset for heap events IDs. Greater or equal to SYSVIEW_MODULE_EVENT_OFFSET. 566 reader : apptrace.Reader 567 see SysViewEvent.__init__() 568 core_id : int 569 see SysViewEvent.__init__() 570 """ 571 cur_events_map = {} 572 for id in self.events_fmt: 573 cur_events_map[events_off + id] = self.events_fmt[id] 574 SysViewEvent.__init__(self, evt_id, core_id, reader, cur_events_map) 575 # self.name = 'SysViewHeapEvent' 576 577 578class SysViewTraceDataParser(apptrace.TraceDataProcessor): 579 """ 580 Base SystemView trace data parser class. 581 582 Attributes 583 ---------- 584 STREAMID_SYS : int 585 system events stream ID. Reserved for internal uses. 586 STREAMID_LOG : int 587 log events stream ID. 588 STREAMID_HEAP : int 589 heap events stream ID. 590 """ 591 STREAMID_SYS = -1 592 STREAMID_LOG = 0 593 STREAMID_HEAP = 1 594 595 def __init__(self, print_events=False, core_id=0): 596 """ 597 Constructor. 598 599 Parameters 600 ---------- 601 print_events : bool 602 see apptrace.TraceDataProcessor.__init__() 603 core_id : int 604 id of the core this parser object relates to. 605 """ 606 apptrace.TraceDataProcessor.__init__(self, print_events=print_events, keep_all_events=True) 607 self.sys_info = None 608 self._last_ts = 0 609 self.irqs_info = {} 610 self.tasks_info = {} 611 self.core_id = core_id 612 self.esp_ext = False 613 614 def _parse_irq_desc(self, desc): 615 """ 616 Parses IRQ description. 617 618 Parameters 619 ---------- 620 desc : string 621 IRQ description string. 622 623 Returns 624 ------- 625 tuple 626 a tuple with IRQ number and name or None on error. 627 """ 628 m = re.match('I#([0-9]+)=(.+)', desc) 629 if m: 630 return m.group(2),m.group(1) 631 return None 632 633 def _update_ts(self, ts): 634 """ 635 Calculates real event timestamp. 636 637 Parameters 638 ---------- 639 ts : int 640 Event timestamp offset. 641 642 Returns 643 ------- 644 float 645 real event timestamp. 646 """ 647 self._last_ts += ts 648 return float(self._last_ts) / self.sys_info.params['sys_freq'].value 649 650 def read_extension_event(self, evt_id, core_id, reader): 651 """ 652 Reads extension event. 653 Default implementation which just reads out event. 654 655 Parameters 656 ---------- 657 evt_id : int 658 Event ID. 659 reader : apptrace.Reader 660 Trace reader object. 661 662 Returns 663 ------- 664 SysViewEvent 665 if this is top level parser returns object for generic event, 666 otherwise returns None indicating to the calling top level parser 667 that extension event are not supported. 668 """ 669 if self.root_proc == self: 670 # by default just read out and skip unknown event 671 return SysViewEvent(evt_id, core_id, reader) 672 return None # let decide to root parser 673 674 @staticmethod 675 def _decode_core_id(high_b): 676 if high_b & (1 << 6): 677 core_id = 1 678 high_b &= ~(1 << 6) 679 else: 680 core_id = 0 681 return high_b,core_id 682 683 def read_event(self, reader, os_evt_map): 684 """ 685 Reads pre-defined or OS-related event. 686 687 Parameters 688 ---------- 689 reader : apptrace.Reader 690 Trace reader object. 691 os_evt_map : dict 692 see return value of _read_events_map() 693 694 Returns 695 ------- 696 SysViewEvent 697 pre-defined, OS-related or extension event object. 698 """ 699 evt_hdr, = struct.unpack('<B', reader.read(1)) 700 # read ID and core num 701 evt_id = 0 702 if evt_hdr & 0x80: 703 # evt_id (2 bytes) 704 b, = struct.unpack('<B', reader.read(1)) 705 # higher part 706 if self.esp_ext: 707 evt_id,core_id = self._decode_core_id(b) 708 else: 709 evt_id = b 710 core_id = self.core_id 711 evt_id = (evt_id << 7) | (evt_hdr & ~0x80) # lower 7 bits 712 else: 713 # evt_id (1 byte) 714 if self.esp_ext: 715 evt_id,core_id = self._decode_core_id(evt_hdr) 716 else: 717 evt_id = evt_hdr 718 core_id = self.core_id 719 if evt_id <= SYSVIEW_EVENT_ID_PREDEF_MAX: 720 return SysViewPredefinedEvent(evt_id, core_id, reader) 721 elif evt_id < SYSVIEW_MODULE_EVENT_OFFSET: 722 return SysViewOSEvent(evt_id, core_id, reader, os_evt_map) 723 else: 724 return self.read_extension_event(evt_id, core_id, reader) 725 726 def event_supported(self, event): 727 return False 728 729 def on_new_event(self, event): 730 """ 731 Does essential processing of event. Must be called for every read event. 732 Assigns real timestamp to event. Updates global system info: system description, 733 mapping of tasks IDs to names and IRQ names to numbers. 734 735 Parameters 736 ---------- 737 event : SysViewEvent 738 Event object. 739 """ 740 if event.id == SYSVIEW_EVTID_TRACE_START: 741 event.ts = 0 742 self._last_ts = 0 743 elif self.sys_info: 744 event.ts = self._update_ts(event.ts) 745 746 if event.id == SYSVIEW_EVTID_INIT: 747 self.sys_info = event 748 event.ts = self._update_ts(event.ts) 749 elif event.id == SYSVIEW_EVTID_TASK_INFO: 750 self.tasks_info[event.params['tid'].value] = event.params['name'].value 751 elif event.id == SYSVIEW_EVTID_SYSDESC: 752 irq = self._parse_irq_desc(event.params['desc'].value) 753 if irq: 754 irq_num = int(irq[1]) 755 self.irqs_info[irq_num] = irq[0] 756 # count event and save it to the list 757 apptrace.TraceDataProcessor.on_new_event(self, event) 758 759 760class SysViewTraceDataExtEventParser(SysViewTraceDataParser): 761 def __init__(self, events_num, print_events=False, core_id=0): 762 """ 763 Constructor. 764 765 Parameters 766 ---------- 767 print_events : bool 768 see apptrace.TraceDataProcessor.__init__() 769 core_id : int 770 id of the core this parser object relates to. 771 """ 772 SysViewTraceDataParser.__init__(self, core_id=core_id, print_events=print_events) 773 self.events_off = 0 774 self.events_num = events_num 775 776 def event_supported(self, event): 777 return False if (self.events_off < SYSVIEW_MODULE_EVENT_OFFSET or event.id < self.events_off or 778 event.id >= (self.events_off + self.events_num)) else True 779 780 781class SysViewMultiTraceDataParser(SysViewTraceDataParser): 782 """ 783 SystemView trace data parser supporting multiple event streams. 784 """ 785 def __init__(self, print_events=False, core_id=0): 786 """ 787 see SysViewTraceDataParser.__init__() 788 """ 789 SysViewTraceDataParser.__init__(self, print_events, core_id) 790 self.stream_parsers = {} 791 792 def add_stream_parser(self, stream_id, parser): 793 """ 794 Assigns parser for events stream. 795 796 Parameters 797 ---------- 798 stream_id : int 799 stream ID. See SysViewTraceDataParser.STREAMID_xxx. 800 Parsers for SysViewTraceDataParser.STREAMID_SYS are ignored. 801 Top level parser is the default for SysViewTraceDataParser.STREAMID_SYS. 802 parser : SysViewTraceDataParser 803 parser object. 804 """ 805 if stream_id == SysViewTraceDataParser.STREAMID_SYS: 806 return 807 parser.root_proc = self 808 self.stream_parsers[stream_id] = parser 809 810 def read_extension_event(self, evt_id, core_id, reader): 811 """ 812 Reads extension event. 813 Iterates over registered stream parsers trying to find one which supports that type of event. 814 815 Parameters 816 ---------- 817 evt_id : int 818 see SysViewTraceDataParser.read_extension_event() 819 reader : apptrace.Reader 820 see SysViewTraceDataParser.read_extension_event() 821 822 Returns 823 ------- 824 SysViewEvent 825 object for extension event, if extension event is not supported return SysViewEvent instance. 826 """ 827 for stream_id in self.stream_parsers: 828 evt = self.stream_parsers[stream_id].read_extension_event(evt_id, core_id, reader) 829 if evt: 830 return evt 831 return SysViewTraceDataParser.read_extension_event(self, evt_id, core_id, reader) 832 833 def on_new_event(self, event): 834 """ 835 Iterates over registered stream parsers allowing them to do 836 essential processing of event. Must be called for every read event. 837 838 Parameters 839 ---------- 840 event : SysViewEvent 841 Event object. 842 """ 843 SysViewTraceDataParser.on_new_event(self, event) 844 for stream_id in self.stream_parsers: 845 self.stream_parsers[stream_id].on_new_event(event) 846 847 848class SysViewEventContext(): 849 """ 850 SystemView event context. 851 """ 852 def __init__(self, handle, irq, name=''): 853 """ 854 Constructor. 855 856 Parameters 857 ---------- 858 handle : int 859 handle of the context: task ID or IRQ number. 860 irq : bool 861 flag indicating whether this is IRQ or task context. 862 name : string 863 name of the context: task or IRQ name. Empty if context is unknown. 864 """ 865 self.handle = handle 866 self.irq = irq 867 self.name = name 868 869 870class SysViewTraceDataProcessor(apptrace.TraceDataProcessor): 871 """ 872 Base SystemView trace data processor class. 873 """ 874 def __init__(self, traces, root_proc=None, print_events=False, keep_all_events=False): 875 """ 876 Constructor. 877 878 Parameters 879 ---------- 880 traces : list 881 list of parsers to process data from. 882 print_events : bool 883 see apptrace.TraceDataProcessor.__init__() 884 keep_all_events : bool 885 see apptrace.TraceDataProcessor.__init__() 886 """ 887 apptrace.TraceDataProcessor.__init__(self, print_events, keep_all_events) 888 self.event_ids = {} 889 self.name = '' 890 self.root_proc = root_proc if root_proc else self 891 self.traces = {} 892 self.ctx_stack = {} 893 self.prev_ctx = {} 894 self.no_ctx_events = [] 895 for t in traces: 896 self.traces[t.core_id] = t 897 # current context item is a tuple of task ID or IRQ num and 'in_irq' flag 898 # empty list means IDLE context or self.start_ctx 899 self.ctx_stack[t.core_id] = [] 900 # context is undefined, we do not know have we started the tracing in task/IDLE or IRQ context 901 # in general there are three scenarious when we can start tracing: when core is in task, IDLE task or IRQ context 902 self.prev_ctx[t.core_id] = None 903 904 def _get_curr_context(self, core_id): 905 """ 906 Returns current context. 907 908 Parameters 909 ---------- 910 core_id : int 911 core ID for requested context. 912 913 Returns 914 ------- 915 SysViewEventContext 916 context object 917 None 918 if there current is undefined 919 """ 920 if len(self.root_proc.ctx_stack[core_id]): 921 return self.root_proc.ctx_stack[core_id][-1] 922 if self._get_prev_context(core_id): 923 return SysViewEventContext(None, False, 'IDLE%d' % core_id) 924 return None 925 926 def _get_prev_context(self, core_id): 927 """ 928 Returns current context. 929 930 Parameters 931 ---------- 932 core_id : int 933 core ID for requested context. 934 935 Returns 936 ------- 937 SysViewEventContext 938 context object 939 """ 940 return self.root_proc.prev_ctx[core_id] 941 942 def get_trace_stream(self, core_id, stream_id): 943 """ 944 Retrieves parser for specified stream and core. 945 946 Parameters 947 ---------- 948 core_id : int 949 Parser's core ID. 950 stream_id : int 951 Parser's stream ID. 952 953 Returns 954 ------- 955 SysViewTraceDataParser 956 parser object for specified stream and core 957 """ 958 if self.root_proc == self: 959 return self.traces[core_id] 960 return self.root_proc.get_trace_stream(core_id, stream_id) 961 962 def event_supported(self, e): 963 """ 964 Should be overriden in child class. 965 """ 966 return False 967 968 def handle_event(self, e): 969 """ 970 Should be overriden in child class. 971 """ 972 pass 973 974 def print_report(self): 975 """ 976 see apptrace.TraceDataProcessor.print_report() 977 """ 978 apptrace.TraceDataProcessor.print_report(self) 979 980 def _process_event(self, event): 981 """ 982 Processes event. 983 Keeps track of execution context on every core. 984 985 Parameters 986 ---------- 987 event : SysViewEvent 988 Event object. 989 990 Raises 991 ---------- 992 SysViewTraceParseError 993 if there is no parser for event's core or 994 if SYSVIEW_EVTID_ISR_ENTER is received for unknown IRQ or 995 if SYSVIEW_EVTID_TASK_START_EXEC or SYSVIEW_EVTID_TASK_STOP_READY is received for unknown task. 996 """ 997 if event.core_id not in self.traces: 998 if 0 in self.traces and self.traces[0].esp_ext: 999 # for Espressif extension there is one trace for all cores 1000 trace = self.traces[0] 1001 if event.core_id not in self.ctx_stack: 1002 self.ctx_stack[event.core_id] = [] 1003 if event.core_id not in self.prev_ctx: 1004 self.prev_ctx[event.core_id] = None 1005 else: 1006 raise SysViewTraceParseError('Event for unknown core %d' % event.core_id) 1007 else: 1008 trace = self.traces[event.core_id] 1009 if event.id == SYSVIEW_EVTID_ISR_ENTER: 1010 if event.params['irq_num'].value not in trace.irqs_info: 1011 raise SysViewTraceParseError('Enter unknown ISR %d' % event.params['irq_num'].value) 1012 if len(self.ctx_stack[event.core_id]): 1013 self.prev_ctx[event.core_id] = self.ctx_stack[event.core_id][-1] 1014 else: 1015 # the 1st context switching event after trace start is SYSVIEW_EVTID_ISR_ENTER, so we have been in IDLE context 1016 self.prev_ctx[event.core_id] = SysViewEventContext(None, False, 'IDLE%d' % event.core_id) 1017 # put new ISR context on top of the stack (the last in the list) 1018 self.ctx_stack[event.core_id].append(SysViewEventContext(event.params['irq_num'].value, True, trace.irqs_info[event.params['irq_num'].value])) 1019 elif event.id == SYSVIEW_EVTID_ISR_EXIT or event.id == SYSVIEW_EVTID_ISR_TO_SCHEDULER: 1020 if len(self.ctx_stack[event.core_id]): 1021 # return to the previous context (the last in the list) 1022 self.prev_ctx[event.core_id] = self.ctx_stack[event.core_id].pop() 1023 else: 1024 # the 1st context switching event after trace start is SYSVIEW_EVTID_ISR_EXIT, so we have been in ISR context, 1025 # but we do not know which one because SYSVIEW_EVTID_ISR_EXIT do not include the IRQ number 1026 self.prev_ctx[event.core_id] = SysViewEventContext(None, True, 'IRQ_oncore%d' % event.core_id) 1027 elif event.id == SYSVIEW_EVTID_TASK_START_EXEC: 1028 if event.params['tid'].value not in trace.tasks_info: 1029 raise SysViewTraceParseError('Start exec unknown task 0x%x' % event.params['tid'].value) 1030 if len(self.ctx_stack[event.core_id]): 1031 # return to the previous context (the last in the list) 1032 self.prev_ctx[event.core_id] = self.ctx_stack[event.core_id][-1] 1033 else: 1034 # the 1st context switching event after trace start is SYSVIEW_EVTID_TASK_START_EXEC, so we have been in IDLE context 1035 self.prev_ctx[event.core_id] = SysViewEventContext(None, False, 'IDLE%d' % event.core_id) 1036 # only one task at a time in context stack (can be interrupted by a bunch of ISRs) 1037 self.ctx_stack[event.core_id] = [SysViewEventContext(event.params['tid'].value, False, trace.tasks_info[event.params['tid'].value])] 1038 elif event.id == SYSVIEW_EVTID_TASK_STOP_EXEC: 1039 # delete task from context stack 1040 for ctx in self.ctx_stack[event.core_id]: 1041 if not ctx.irq: 1042 if len(self.ctx_stack[event.core_id]) == 1: 1043 # if this is the only ctx in context stack 1044 self.prev_ctx[event.core_id] = ctx 1045 del ctx 1046 break 1047 elif event.id == SYSVIEW_EVTID_TASK_STOP_READY: 1048 if event.params['tid'].value not in trace.tasks_info: 1049 raise SysViewTraceParseError('Stop ready unknown task 0x%x' % event.params['tid'].value) 1050 if len(self.ctx_stack[event.core_id]): 1051 if (not self.ctx_stack[event.core_id][-1].irq and event.params['tid'].value == self.ctx_stack[event.core_id][-1].handle): 1052 # return to the previous context (the last in the list) 1053 self.prev_ctx[event.core_id] = self.ctx_stack[event.core_id].pop() 1054 else: 1055 # the 1st context switching event after trace start is SYSVIEW_EVTID_TASK_STOP_READY, so we have been in task context 1056 self.prev_ctx[event.core_id] = SysViewEventContext(event.params['tid'].value, False, trace.tasks_info[event.params['tid'].value]) 1057 1058 def on_new_event(self, event): 1059 """ 1060 Processes heap events. 1061 """ 1062 if self.root_proc == self: 1063 SysViewTraceDataProcessor._process_event(self, event) 1064 curr_ctx = self._get_curr_context(event.core_id) 1065 if not curr_ctx: 1066 # postpone events handling till their context is known 1067 self.no_ctx_events.append(event) 1068 return 1069 event.in_irq = curr_ctx.irq 1070 event.ctx_name = curr_ctx.name 1071 # here we know the previous context: we switched from it or implied upon the 1st context switching event 1072 prev_ctx = self._get_prev_context(event.core_id) 1073 if len(self.no_ctx_events): 1074 for cached_evt in self.no_ctx_events: 1075 cached_evt.ctx_name = prev_ctx.name 1076 cached_evt.in_irq = prev_ctx.irq 1077 # count and save the event 1078 apptrace.TraceDataProcessor.on_new_event(self, cached_evt) 1079 if self.event_supported(event): 1080 self.handle_event(event) 1081 del self.no_ctx_events[:] 1082 # count and save the event 1083 apptrace.TraceDataProcessor.on_new_event(self, event) 1084 if self.event_supported(event): 1085 self.handle_event(event) 1086 1087 def merge_and_process(self): 1088 """ 1089 Merges events from all registered parsers, sorts them by timestamp and processes them. 1090 """ 1091 all_events = [] 1092 for t in self.traces.values(): 1093 all_events.extend(t.events) 1094 all_events.sort(key=lambda x: x.ts) 1095 for event in all_events: 1096 self.on_new_event(event) 1097 1098 1099class SysViewMultiStreamTraceDataProcessor(SysViewTraceDataProcessor): 1100 """ 1101 SystemView trace data processor supporting multiple event streams. 1102 """ 1103 def __init__(self, traces, print_events=False, keep_all_events=False): 1104 """ 1105 see SysViewTraceDataProcessor.__init__() 1106 """ 1107 SysViewTraceDataProcessor.__init__(self, traces, print_events=print_events, keep_all_events=keep_all_events) 1108 self.stream_procs = {} 1109 1110 def add_stream_processor(self, stream_id, proc): 1111 """ 1112 Assigns processor for events stream. 1113 1114 Parameters 1115 ---------- 1116 stream_id : int 1117 stream ID. See SysViewTraceDataParser.STREAMID_xxx. 1118 Parsers for SysViewTraceDataParser.STREAMID_SYS are ignored. 1119 Top level parser is the default for SysViewTraceDataParser.STREAMID_SYS. 1120 proc : SysViewTraceDataProcessor 1121 processor object. 1122 """ 1123 if stream_id == SysViewTraceDataParser.STREAMID_SYS: 1124 return 1125 proc.root_proc = self # common processing data is kept by this processor 1126 self.stream_procs[stream_id] = proc 1127 1128 def get_trace_stream(self, core_id, stream_id): 1129 """ 1130 Retrieves parser for specified stream and core. 1131 1132 Parameters 1133 ---------- 1134 core_id : int 1135 Parser's core ID. 1136 stream_id : int 1137 Parser's stream ID. 1138 1139 Returns 1140 ------- 1141 SysViewTraceDataParser 1142 parser object for specified stream and core 1143 """ 1144 if core_id not in self.traces and 0 in self.traces and self.traces[0].esp_ext: 1145 # for Espressif extension there is one trace for all cores 1146 trace = self.traces[0] 1147 else: 1148 trace = self.traces[core_id] 1149 if stream_id == SysViewTraceDataParser.STREAMID_SYS: 1150 return trace 1151 if isinstance(trace, SysViewMultiTraceDataParser): 1152 return trace.stream_parsers[stream_id] 1153 return trace 1154 1155 def print_report(self): 1156 """ 1157 Iterates over registered stream processors and prints their reports. 1158 """ 1159 SysViewTraceDataProcessor.print_report(self) 1160 # need to sort stream procs by keys to print reports in the same order regardless of Python version 1161 stream_ids = list(self.stream_procs.keys()) 1162 stream_ids.sort() 1163 for stream_id in stream_ids: 1164 self.stream_procs[stream_id].print_report() 1165 1166 def cleanup(self): 1167 """ 1168 Iterates over registered stream processors and cleans them up. 1169 """ 1170 for stream_id in self.stream_procs: 1171 self.stream_procs[stream_id].cleanup() 1172 SysViewTraceDataProcessor.cleanup(self) 1173 1174 def on_new_event(self, event): 1175 """ 1176 Iterates over registered stream processors allowing them to do 1177 the processing of event. 1178 1179 Parameters 1180 ---------- 1181 event : SysViewEvent 1182 Event object. 1183 """ 1184 SysViewTraceDataProcessor.on_new_event(self, event) 1185 for stream_id in self.stream_procs: 1186 self.stream_procs[stream_id].on_new_event(event) 1187 1188 1189class SysViewTraceDataJsonEncoder(json.JSONEncoder): 1190 JSON_TRACE_VER = '1.0' 1191 1192 def default(self, obj): 1193 global _sysview_events_map 1194 global _os_events_map 1195 if isinstance(obj, SysViewMultiStreamTraceDataProcessor): 1196 json_event_ids = {'system': _sysview_events_map, 'os': {}} 1197 for eid in _os_events_map: 1198 ename = _os_events_map[eid][0] 1199 json_event_ids['os'][ename] = eid 1200 for stream in obj.stream_procs.values(): 1201 json_event_ids[stream.name] = stream.event_ids 1202 json_events = [] 1203 for e in obj.events: 1204 for stream in obj.stream_procs.values(): 1205 if stream.event_supported(e): 1206 json_events.append(e) 1207 break 1208 # include also OS and pre-defined events 1209 if isinstance(e, SysViewPredefinedEvent) or isinstance(e, SysViewOSEvent): 1210 json_events.append(e) 1211 return {'version': self.JSON_TRACE_VER, 'streams': json_event_ids, 'events': json_events} 1212 if isinstance(obj, SysViewHeapEvent): 1213 blk_size = 0 1214 if 'size' in obj.params: 1215 blk_size = obj.params['size'].value 1216 blk_addr = '0x{:x}'.format(obj.params['addr'].value) 1217 callers = [] 1218 for addr in obj.params['callers'].value: 1219 callers.append('0x{:x}'.format(addr)) 1220 return {'ctx_name': obj.ctx_name, 'in_irq': obj.in_irq, 'id': obj.id, 'core_id': obj.core_id, 1221 'ts': obj.ts, 'addr': blk_addr, 'size': blk_size, 'callers': callers} 1222 if isinstance(obj, SysViewPredefinedEvent) and obj.id == SYSVIEW_EVTID_PRINT_FORMATTED: 1223 return {'ctx_name': obj.ctx_name, 'in_irq': obj.in_irq, 'id': obj.id, 'core_id': obj.core_id, 1224 'ts': obj.ts, 'msg': obj.params['msg'].value, 'lvl': obj.params['lvl'].value} 1225 if isinstance(obj, SysViewEvent): 1226 jobj = obj.to_jsonable() 1227 # remove unused fields 1228 if 'name' in jobj: 1229 del jobj['name'] 1230 if 'plen' in jobj: 1231 del jobj['plen'] 1232 return jobj 1233 # Let the base class default method raise the TypeError 1234 return json.JSONEncoder.default(self, obj) 1235 1236 1237class SysViewHeapTraceDataParser(SysViewTraceDataExtEventParser): 1238 """ 1239 SystemView trace data parser supporting heap events. 1240 """ 1241 def __init__(self, print_events=False, core_id=0): 1242 """ 1243 SystemView trace data parser supporting multiple event streams. 1244 see SysViewTraceDataExtEventParser.__init__() 1245 """ 1246 SysViewTraceDataExtEventParser.__init__(self, events_num=len(SysViewHeapEvent.events_fmt.keys()), core_id=core_id, print_events=print_events) 1247 1248 def read_extension_event(self, evt_id, core_id, reader): 1249 """ 1250 Reads heap event. 1251 see SysViewTraceDataParser.read_extension_event() 1252 """ 1253 if (self.events_off >= SYSVIEW_MODULE_EVENT_OFFSET and evt_id >= self.events_off and 1254 evt_id < self.events_off + self.events_num): 1255 return SysViewHeapEvent(evt_id, core_id, self.events_off, reader) 1256 return SysViewTraceDataParser.read_extension_event(self, evt_id, core_id, reader) 1257 1258 def on_new_event(self, event): 1259 """ 1260 Keeps track of heap module descriptions. 1261 """ 1262 if self.root_proc == self: 1263 SysViewTraceDataParser.on_new_event(self, event) 1264 if event.id == SYSVIEW_EVTID_MODULEDESC and event.params['desc'].value == 'ESP32 SystemView Heap Tracing Module': 1265 self.events_off = event.params['evt_off'].value 1266 1267 1268class SysViewHeapTraceDataProcessor(SysViewTraceDataProcessor, apptrace.BaseHeapTraceDataProcessorImpl): 1269 """ 1270 SystemView trace data processor supporting heap events. 1271 """ 1272 def __init__(self, toolchain_pref, elf_path, root_proc=None, traces=[], print_events=False, print_heap_events=False): 1273 """ 1274 Constructor. 1275 see SysViewTraceDataProcessor.__init__() 1276 see apptrace.BaseHeapTraceDataProcessorImpl.__init__() 1277 """ 1278 SysViewTraceDataProcessor.__init__(self, traces, root_proc=root_proc, print_events=print_events) 1279 apptrace.BaseHeapTraceDataProcessorImpl.__init__(self, print_heap_events) 1280 self.toolchain = toolchain_pref 1281 self.elf_path = elf_path 1282 # self.no_ctx_events = [] 1283 self.name = 'heap' 1284 stream = self.root_proc.get_trace_stream(0, SysViewTraceDataParser.STREAMID_HEAP) 1285 self.event_ids = {'alloc': stream.events_off, 'free': stream.events_off + 1} 1286 1287 def event_supported(self, event): 1288 heap_stream = self.root_proc.get_trace_stream(event.core_id, SysViewTraceDataParser.STREAMID_HEAP) 1289 return heap_stream.event_supported(event) 1290 1291 def handle_event(self, event): 1292 heap_stream = self.root_proc.get_trace_stream(event.core_id, SysViewTraceDataParser.STREAMID_HEAP) 1293 if (event.id - heap_stream.events_off) == 0: 1294 heap_event = apptrace.HeapTraceEvent(event, True, toolchain=self.toolchain, 1295 elf_path=self.elf_path) 1296 else: 1297 heap_event = apptrace.HeapTraceEvent(event, False, toolchain=self.toolchain, 1298 elf_path=self.elf_path) 1299 apptrace.BaseHeapTraceDataProcessorImpl.on_new_event(self, heap_event) 1300 1301 def print_report(self): 1302 """ 1303 see apptrace.TraceDataProcessor.print_report() 1304 """ 1305 if self.root_proc == self: 1306 SysViewTraceDataProcessor.print_report(self) 1307 apptrace.BaseHeapTraceDataProcessorImpl.print_report(self) 1308 1309 1310class SysViewLogTraceEvent(apptrace.LogTraceEvent): 1311 """ 1312 SystemView log event. 1313 """ 1314 def __init__(self, ts, msg): 1315 """ 1316 Constructor. 1317 1318 Parameters 1319 ---------- 1320 msg : string 1321 Log message string. 1322 """ 1323 self.msg = msg 1324 self.ts = ts 1325 1326 def get_message(self, unused): 1327 """ 1328 Retrieves log message. 1329 1330 Returns 1331 ------- 1332 string 1333 formatted log message 1334 """ 1335 return '[{:.9f}] LOG: {}'.format(self.ts, self.msg) 1336 1337 1338class SysViewLogTraceDataParser(SysViewTraceDataParser): 1339 """ 1340 SystemView trace data parser supporting log events. 1341 """ 1342 def event_supported(self, event): 1343 return event.id == SYSVIEW_EVTID_PRINT_FORMATTED 1344 1345 def on_new_event(self, event): 1346 """ 1347 see SysViewTraceDataParser.on_new_event() 1348 """ 1349 if self.root_proc == self: 1350 SysViewTraceDataParser.on_new_event(self, event) 1351 1352 1353class SysViewLogTraceDataProcessor(SysViewTraceDataProcessor, apptrace.BaseLogTraceDataProcessorImpl): 1354 """ 1355 SystemView trace data processor supporting heap events. 1356 """ 1357 def __init__(self, traces=[], root_proc=None, print_events=False, print_log_events=False): 1358 """ 1359 Constructor. 1360 see SysViewTraceDataProcessor.__init__() 1361 see apptrace.BaseLogTraceDataProcessorImpl.__init__() 1362 """ 1363 SysViewTraceDataProcessor.__init__(self, traces, root_proc=root_proc, print_events=print_events) 1364 apptrace.BaseLogTraceDataProcessorImpl.__init__(self, print_log_events) 1365 self.name = 'log' 1366 self.event_ids = {'print': SYSVIEW_EVTID_PRINT_FORMATTED} 1367 1368 def event_supported(self, event): 1369 return event.id == SYSVIEW_EVTID_PRINT_FORMATTED 1370 1371 def on_new_event(self, event): 1372 """ 1373 Processes log events. 1374 """ 1375 if self.root_proc == self: 1376 SysViewTraceDataProcessor.on_new_event(self, event) 1377 if event.id == SYSVIEW_EVTID_PRINT_FORMATTED: 1378 log_evt = SysViewLogTraceEvent(event.ts, event.params['msg'].value) 1379 apptrace.BaseLogTraceDataProcessorImpl.on_new_event(self, log_evt) 1380 1381 def print_report(self): 1382 """ 1383 see apptrace.TraceDataProcessor.print_report() 1384 """ 1385 if self.root_proc == self: 1386 SysViewTraceDataProcessor.print_report(self) 1387 apptrace.BaseLogTraceDataProcessorImpl.print_report(self) 1388