#!/usr/bin/python

#
# Copyright (c) 2016 Intel Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import sys,re,os

class monitorEvent():
	def __init__(self, time, data1, data2, ptr):
		self.time = time
		self.data1 = data1
		self.data2 = data2
		self.ptr = ptr

class Params():
	# Quark X1000
	TICKS_PER_MSEC = 14318.1

def getData(monitorFile):

	eventList = []

	with open(monitorFile, 'rb') as f:
		for chunk in iter(lambda: f.read(16), ''):
			time = int(chunk[0:4][::-1].encode('hex'), 16)
			data1 = int(chunk[4:8][::-1].encode('hex'), 16)
			data2 = int(chunk[8:12][::-1].encode('hex'), 16)
			ptr = int(chunk[12:16][::-1].encode('hex'), 16)

			if ((time == 0) and (data1 == 0) and (data2 == 0)):
				break
			eventList.append(monitorEvent(time, data1, data2, ptr))
	return eventList

def formatTime(val):
	ticks_per_ms = Params.TICKS_PER_MSEC
	val_ms = val / ticks_per_ms
	return "{:15.3f}".format(val_ms)

def getTask(val):
	global symbols

	if val == 0:
		return "Idle"
	else:
		return symbols[val].replace('_k_task_obj_', '')

def formatEvent(time, data1, data2, ptr):
	global symbols
	global prevTaskName
	global prevTaskId

	mo_stbit0 = 0x20000000
	mo_stbit1 = 0x30000000
	mo_event = 0x40000000
	mo_lcomm = 0x50000000
	evt_type = data2 & 0xF0000000
	mask = 0xFFFFFFF
	evt_mask = 0xFFFFFFC

	if (evt_type == mo_stbit0):
		event = [ "State clear", decodeStateBits(data2 & mask), getTask(data1) ]
	elif (evt_type == mo_stbit1):
		event = [ "State set", decodeStateBits(data2 & mask), getTask(data1) ]
	elif (evt_type == mo_event):
		event = [ "Server event",
			  symbols[data2 & evt_mask].replace('_k_event_obj_',''),
			  "" ]
	elif (evt_type == mo_lcomm):
		event = [ "Server cmd", symbols[ptr], getTask(data1) ]
	elif (evt_type == 0):
		event = [ "Task switch to", "", getTask(data1) ]
		if (ftrace_format):
			ret = ""
			if (prevTaskId >= 0):
				ret = " {:>16}-{:<8} [000] .... {:12}: sched_switch: prev_comm={}" \
					" prev_pid={} prev_prio=0 prev_state=S ==> next_comm={}"   \
					" next_pid={} next_prio=0".format(prevTaskName,
									  prevTaskId,
									  formatTime(time),
									  prevTaskName,
									  prevTaskId,
									  getTask(data1),
									  data1)
			prevTaskName = getTask(data1)
			prevTaskId = data1
			return ret
	else:
		event = [ "UNDEFINED",
			  "data1={:08x}".format(data1),
			  "data2={:08x}".format(data2),
			  "ptr={:08x}".format(ptr) ]

	if (ftrace_format):
		return ""
	else:
		return "{} ms: {:15} {:13} {}".format(formatTime(time),
						      event[0],
						      event[2],
						      event[1])

def decode(eventList):
	for evt in eventList:
		s = formatEvent(evt.time, evt.data1, evt.data2, evt.ptr)
		if len(s) > 0:
			print s

def decodeStateBits(flags):
	bitValue = [ "STOP", "TERM", "SUSP", "BLCK", "GDBSTOP", "PRIO" , "NA" , "NA", "NA", "NA",
		     "NA", "TIME", "DRIV", "RESV", "EVNT", "ENQU", "DEQU", "SEND", "RECV", "SEMA",
		     "LIST", "LOCK", "ALLOC", "GTBL", "RESV", "RESV", "RECVDATA", "SENDDATA" ]
	s = ''

	for x in range(0, len(bitValue) - 1):
		if (flags & (1 << x)):
			s += bitValue[x] + " "

	return s

def loadSymbols(elfFile):
	os.system('readelf -s ' + elfFile + ' > symbols.txt')

	prog = re.compile("\s+\S+:\s+([a-fA-F0-9]+)\s+\d+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\S+)")
	objList = {}

	with open('symbols.txt', 'r') as f:
		for line in f:
			match = prog.match(line)
			if match:
				idx = int(match.group(1), 16)
				if not objList.has_key(idx):
					objList[idx] = match.group(2)
				else:
					s = match.group(2)
					# Prioritize tasks / event symbols when multiple symbols
					# on same address
					if "_k_task_obj" in s or "_k_event_obj" in s:
						objList[idx] = s


	os.system('rm -rf symbols.txt')

	return objList

symbols = {}
prevTaskName = ""
prevTaskId = -1
ftrace_format=0

def Main(argv):
	global symbols

	dumpFile = ""
	elfFile = ""

	sys.argv.pop(0)

	for arg in sys.argv:
		if arg == "--qemu":
			Params.TICKS_PER_MSEC=100000.0
		else:
			if not dumpFile:
				dumpFile = arg
			elif not elfFile:
				elfFile = arg

	if not elfFile:
		print "profile.py [DUMP FILE] [ELF FILE]"
		sys.exit(0)

	eventList = getData(dumpFile)
	symbols = loadSymbols(elfFile)
	decode(eventList)

if __name__ == "__main__":
	Main(sys.argv[1:])
