sysview.py 50 KB

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