1# 2# Copyright (c) 2010-2024 Antmicro 3# 4# This file is licensed under the MIT License. 5# Full license text is available in 'licenses/MIT.txt'. 6# 7 8from struct import * 9 10 11class BaseEntry(Struct): 12 def __init__(self, format): 13 super(BaseEntry, self).__init__(format) 14 self.realTime = 0 15 self.virtualTime = 0 16 self.entryType = -1 17 18class MetricsParser: 19 def __init__(self, filePath): 20 self.filePath = filePath 21 22 def get_instructions_entries(self): 23 with open(self.filePath, "rb") as f: 24 cpus, _ = self._parseHeader(f) 25 return cpus, self._parse(f, b'\x00', '<iQ') 26 27 def get_memory_entries(self): 28 with open(self.filePath, "rb") as f: 29 _, _ = self._parseHeader(f) 30 return self._parse(f, b'\x01', 'c') 31 32 def get_peripheral_entries(self): 33 with open(self.filePath, "rb") as f: 34 _, peripherals = self._parseHeader(f) 35 return peripherals, self._parse(f, b'\x02', '<cQ') 36 37 def get_exceptions_entries(self): 38 with open(self.filePath, "rb") as f: 39 _, _ = self._parseHeader(f) 40 return self._parse(f, b'\x03', 'Q') 41 42 def _parse(self, f, entryType, format): 43 startTime = 0 44 entries = [] 45 entry = BaseEntry('<qdc') 46 while True: 47 entryHeader = f.read(entry.size) 48 if not entryHeader: 49 break 50 realTime, entry.virtualTime, entry.entryType = entry.unpack(entryHeader) 51 if startTime == 0: 52 startTime = realTime 53 entry.realTime = (realTime - startTime) / 10000 54 if entry.entryType == entryType: 55 result = [entry.realTime, entry.virtualTime] 56 for data in self._read(format, f): 57 result.append(data) 58 entries.append(result) 59 else: 60 self._ignore(entry.entryType, f) 61 return entries 62 63 def _parseHeader(self, f): 64 cpus = {} 65 peripherals = {} 66 numberOfCpus = self._read('i', f)[0] 67 for x in range(numberOfCpus): 68 cpuId = self._read('i', f)[0] 69 cpuNameLength = self._read('i', f)[0] 70 cpus[cpuId] = self._read('{}s'.format(cpuNameLength), f)[0].decode() 71 numberOfPeripherals = self._read('i', f)[0] 72 for x in range(numberOfPeripherals): 73 peripheralNameLength = self._read('i', f)[0] 74 peripheralName = self._read('{}s'.format(peripheralNameLength), f)[0].decode() 75 peripheralStartAddress, peripheralEndAddress = self._read('2Q', f) 76 peripherals[peripheralName] = [peripheralStartAddress, peripheralEndAddress] 77 return cpus, peripherals 78 79 def _ignore(self, entryType, f): 80 if entryType == b'\x00': 81 self._read('<iQ', f) 82 if entryType == b'\x01': 83 self._read('c', f) 84 if entryType == b'\x02': 85 self._read('<cQ', f) 86 if entryType == b'\x03': 87 self._read('<Q', f) 88 89 def _read(self, format, file): 90 return unpack(format, file.read(calcsize(format))) 91