sysview.py 50 KB

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