sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ipc/src/com/nokia/carbide/cpp/pi/internal/ipc/IpcTraceParser.java
changeset 5 844b047e260d
child 12 ae255c9aa552
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ipc/src/com/nokia/carbide/cpp/pi/internal/ipc/IpcTraceParser.java	Wed Apr 21 15:14:16 2010 +0300
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description: 
+ *
+ */
+
+package com.nokia.carbide.cpp.pi.internal.ipc;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.Parser;
+
+
+/**
+ * Parser for performance counter event traces in binary format.
+ * Converts parsed content into IpcSamples.
+ */
+public class IpcTraceParser extends Parser {
+	private static final String IPC_EVENT_NOT_RECOGNISED = Messages.IpcTraceParser_0;
+	private static final int MAX_IPC_EVENTS_TRACED = 14; //2 IPC events * 5 possible values + 4 optional L2 counter values
+	private static final int MAX_IPC_NO_L2_EVENTS_TRACED = 10; //2 IPC events * 5 possible values
+	
+	
+	//private static int CPU_CLOCK_TICK_DIV64 = 0xFFFF;
+	private boolean debug = false; //CH: this could be replaced with Eclipse-style logging
+	private boolean l2Enabled = false;
+	
+	long time = 0;
+	
+	private static final Map<Integer, String> eventTypeTable = new HashMap<Integer, String>();
+	static {
+		eventTypeTable.put(0x0,Messages.IpcTraceParser_1);
+		eventTypeTable.put(0x1,Messages.IpcTraceParser_2);
+		eventTypeTable.put(0x2,Messages.IpcTraceParser_3);
+		eventTypeTable.put(0x3,Messages.IpcTraceParser_4);
+		eventTypeTable.put(0x4,Messages.IpcTraceParser_5);
+	}
+	private static final Map<Integer, String> counterTypeTable = new HashMap<Integer, String>();
+	static {
+		counterTypeTable.put(0x0,Messages.IpcTraceParser_6);
+		counterTypeTable.put(0x1,Messages.IpcTraceParser_7);
+		counterTypeTable.put(0x2,Messages.IpcTraceParser_8);
+		counterTypeTable.put(0x3,Messages.IpcTraceParser_9);
+		counterTypeTable.put(0x4,Messages.IpcTraceParser_10);
+		counterTypeTable.put(0x5,Messages.IpcTraceParser_11);
+	}	
+	private static final Map<Integer, String> l2EventTypeTable = new HashMap<Integer, String>();
+	static {
+		l2EventTypeTable.put(0x3,Messages.IpcTraceParser_12);
+		l2EventTypeTable.put(0x4,Messages.IpcTraceParser_13);
+		l2EventTypeTable.put(0x5,Messages.IpcTraceParser_14);
+		l2EventTypeTable.put(0x6,Messages.IpcTraceParser_15);
+		l2EventTypeTable.put(0x7,Messages.IpcTraceParser_16);
+		l2EventTypeTable.put(0xC,Messages.IpcTraceParser_17);
+		l2EventTypeTable.put(0xD,Messages.IpcTraceParser_18);
+	}			
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.model.Parser#parse(java.io.File)
+	 */
+	@Override
+	public ParsedTraceData parse(File file) throws Exception 
+	{
+		ParsedTraceData ptd = new ParsedTraceData();
+		ptd.functionResolvers = null;
+		ptd.staticData = null;
+		ptd.traceData = new IpcTrace();
+		doParsing(file,(IpcTrace)ptd.traceData);
+		time = 0;
+		
+		return ptd;
+	}
+	
+	private void doParsing(File f, IpcTrace trace) throws FileNotFoundException
+ {
+		DataInputStream dis = new DataInputStream(new FileInputStream(f));
+		try {
+			int len = dis.readByte();
+			byte[] versionString = new byte[len];
+			dis.read(versionString);
+			this.traceVersion = new String(versionString);
+			if (debug){
+				System.out.println("IPC trace version:" + this.traceVersion); //$NON-NLS-1$				
+			}
+
+			List<Integer> counterTypes = new ArrayList<Integer>();
+			List<Integer> counterL2Types = new ArrayList<Integer>();
+
+			// IPC counters
+			int firstCounter = dis.readUnsignedByte();
+			counterTypes.add(firstCounter);
+			int secondCounter = dis.readUnsignedByte();
+			counterTypes.add(secondCounter);
+
+			// this type is always the cpu clock tick div 64
+			// int thirdData = CPU_CLOCK_TICK_DIV64;
+			// valueTypeVector.add(new Integer(thirdData));
+
+			if (dis.readUnsignedByte() != 0) {
+				// L2 counters, add if available
+				int thirdCounter = dis.readUnsignedByte();
+				counterL2Types.add(thirdCounter);
+				int fourthCounter = dis.readUnsignedByte();
+				counterL2Types.add(fourthCounter);
+				int fifthCounter = dis.readUnsignedByte();
+				counterL2Types.add(fifthCounter);
+				int sixthCounter = dis.readUnsignedByte();
+				counterL2Types.add(sixthCounter);
+
+				trace.setValueTypes(this.parseValueTypes(counterTypes, counterL2Types));
+			} else {
+				trace.setValueTypes(this.parseValueTypes(counterTypes, null));
+			}
+
+			// System.out.println("IPC first "+firstCounter+" second "+secondCounter);
+
+			IpcSample s = null;
+			while (true) {
+				s = readSample(dis, s);
+				// System.out.println(this.time+" "+Long.toHexString(s.values[0])+" "+Long.toHexString(s.values[1])+" "+Long.toHexString(s.values[2]));
+				trace.addSample(s);
+			}
+		} catch (IOException ioe) {
+			// CH: is this just caught for end-of-file condition?
+		}
+	}
+
+	private IpcSample readSample(DataInputStream dis, IpcSample prevSample)
+			throws IOException {
+		// int headerByte = (dis.readInt()); // << 24) >>> 24;
+		int headerByte1 = (dis.readByte() << 24) >>> 24;
+		int headerByte2 = (dis.readByte() << 24) >>> 24;
+		int headerByte3 = (dis.readByte() << 24) >>> 24;
+		int headerByte4 = (dis.readByte() << 24) >>> 24;
+		int headerByte = ((((headerByte1) | (headerByte2) << 8) | (headerByte3) << 16) | headerByte4 << 24);
+
+		int headerByte11 = 0;
+		int headerByte12 = 0;
+		int headerByteL2 = 0;
+		// int j = ((headerByte >>> 30)&1);
+		if (((headerByte >>> 30) & 1) != 0 || l2Enabled) // flag bit in trace =>
+															// L2 trace included
+		{
+			l2Enabled = true;
+			headerByte11 = (dis.readByte() << 24) >>> 24;
+			headerByte12 = (dis.readByte() << 24) >>> 24; // overflow bits
+			headerByteL2 = ((headerByte11) | ((headerByte12) << 8));
+		}
+
+		int eventNumber = l2Enabled ? MAX_IPC_EVENTS_TRACED
+				: MAX_IPC_NO_L2_EVENTS_TRACED;
+
+		int[] neg = new int[eventNumber];
+		int[] prev = new int[eventNumber];
+
+		if (prevSample != null) {
+			prev[0] = prevSample.values[0];
+			prev[1] = prevSample.values[1];
+			prev[2] = prevSample.values[2];
+			prev[3] = prevSample.values[3];
+			prev[4] = prevSample.values[4];
+			prev[5] = prevSample.values[5];
+			prev[6] = prevSample.values[6];
+			prev[7] = prevSample.values[7];
+			prev[8] = prevSample.values[8];
+			prev[9] = prevSample.values[9];
+			if (l2Enabled) {
+				prev[10] = prevSample.values[10];
+				prev[11] = prevSample.values[11];
+				prev[12] = prevSample.values[12];
+				prev[13] = prevSample.values[13];
+			}
+		}
+		// /*if(debug) if(this.time > 7820 && this.time < 7830)*/
+		// System.out.println("header: "+Long.toHexString(headerByte)+" = "+Integer.toBinaryString(headerByte));
+
+		if (((headerByte >>> 29) & 1) != 0) {
+			neg[0] = 1;
+		}
+
+		if (((headerByte >>> 28) & 1) != 0) {
+			neg[1] = 1;
+		}
+
+		if (((headerByte >>> 27) & 1) != 0) {
+			neg[2] = 1;
+		}
+		if (((headerByte >>> 26) & 1) != 0) {
+			neg[3] = 1;
+		}
+
+		if (((headerByte >>> 25) & 1) != 0) {
+			neg[4] = 1;
+		}
+
+		if (((headerByte >>> 24) & 1) != 0) {
+			neg[5] = 1;
+		}
+		if (((headerByte >>> 23) & 1) != 0) {
+			neg[6] = 1;
+		}
+
+		if (((headerByte >>> 22) & 1) != 0) {
+			neg[7] = 1;
+		}
+
+		if (((headerByte >>> 21) & 1) != 0) {
+			neg[8] = 1;
+		}
+		if (((headerByte >>> 20) & 1) != 0) {
+			neg[9] = 1;
+		}
+
+		// check overflows of L2 counters
+		if (l2Enabled) {
+			if (((headerByteL2 >>> 11) & 1) != 0) {
+				neg[10] = 1;
+			}
+
+			if (((headerByteL2 >>> 10) & 1) != 0) {
+				neg[11] = 1;
+			}
+
+			if (((headerByteL2 >>> 9) & 1) != 0) {
+				neg[12] = 1;
+			}
+			if (((headerByteL2 >>> 8) & 1) != 0) {
+				neg[13] = 1;
+			}
+
+		}
+
+		int[] len = new int[eventNumber];
+		len[0] = (((headerByte >> 18) << 30) >>> 30) + 1;
+		len[1] = (((headerByte >> 16) << 30) >>> 30) + 1;
+		len[2] = (((headerByte >> 14) << 30) >>> 30) + 1;
+		len[3] = (((headerByte >> 12) << 30) >>> 30) + 1;
+		len[4] = (((headerByte >> 10) << 30) >>> 30) + 1;
+		len[5] = (((headerByte >> 8) << 30) >>> 30) + 1;
+		len[6] = (((headerByte >> 6) << 30) >>> 30) + 1;
+		len[7] = (((headerByte >> 4) << 30) >>> 30) + 1;
+		len[8] = (((headerByte >> 2) << 30) >>> 30) + 1;
+		len[9] = (((headerByte) << 30) >>> 30) + 1;
+
+		if (l2Enabled) {
+			len[10] = (((headerByteL2 >> 6) << 30) >>> 30) + 1;
+			len[11] = (((headerByteL2 >> 4) << 30) >>> 30) + 1;
+			len[12] = (((headerByteL2 >> 2) << 30) >>> 30) + 1;
+			len[13] = ((headerByteL2 << 30) >>> 30) + 1;
+		}
+		if (debug)
+			if (this.time > 7820 && this.time < 7830)
+				System.out.println("T:" + this.time + " len0:" + len[0] + " len1:" + len[1] + " len2:" + len[2]); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+		if (debug)
+			if (this.time > 7900 && this.time < 7900)
+				System.out.println("H: " + Integer.toBinaryString(headerByte) + " N0:" + neg[0] + " N1:" + neg[1] + " N2:" + neg[2]); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
+
+		int[] val = new int[eventNumber];
+		val[0] = readVal(neg[0], len[0], dis);
+		val[1] = readVal(neg[1], len[1], dis);
+		val[2] = readVal(neg[2], len[2], dis);
+		val[3] = readVal(neg[3], len[3], dis);
+		val[4] = readVal(neg[4], len[4], dis);
+		val[5] = readVal(neg[5], len[5], dis);
+		val[6] = readVal(neg[6], len[6], dis);
+		val[7] = readVal(neg[7], len[7], dis);
+		val[8] = readVal(neg[8], len[8], dis);
+		val[9] = readVal(neg[9], len[9], dis);
+
+		if (l2Enabled) {
+			val[10] = readVal(neg[10], len[10], dis);
+			val[11] = readVal(neg[11], len[11], dis);
+			val[12] = readVal(neg[12], len[12], dis);
+			val[13] = readVal(neg[13], len[13], dis);
+		}
+
+		if (debug)
+			if (this.time > 7820 && this.time < 7900)
+				System.out.println("READ T:" + this.time + "   V0:" + Integer.toHexString(val[0]) + " V1:" + Long.toHexString(val[1]) + " V2:" + Long.toHexString(val[2])); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+		for (int i = 0; i < eventNumber; i++) {
+			val[i] = prev[i] - val[i];
+		}
+
+		IpcSample ps = new IpcSample(val, this.time);
+
+		if (debug)
+			if (this.time > 7820 && this.time < 7900)
+				System.out.println("T:" + this.time + "   V0:" + Long.toHexString(val[0]) + " V1:" + Long.toHexString(val[1]) + " V2:" + Long.toHexString(val[2])); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
+		if (debug)
+			if (this.time > 7820 && this.time < 7900)
+				System.out.println("T:" + this.time + " " + val[0] + " " + val[1] + " " + val[2]); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
+		this.time++;
+		/*
+		 * dis.readByte(); dis.readByte(); dis.readByte(); dis.readByte();
+		 */
+		return ps;
+	}
+
+	private int readVal(int neg,int len,DataInputStream dis) throws IOException
+	{
+		byte[] array = new byte[len];
+		dis.read(array);
+		
+		//System.out.println("array: "+array);
+		
+		if(debug)
+			for(int k=0;k<array.length;k++)
+			{
+				if(this.time > 7820 && this.time < 7900) System.out.println(" "+Integer.toHexString(array[k])); //$NON-NLS-1$
+			}
+		
+		long total = 0;
+		for(int i=0;i<len;i++)
+		{
+			int value = ((array[i] << 24) >>> 24) << (i*8);			
+			total |= value;
+		}
+		
+		if(debug) if(this.time > 7820 && this.time < 7900) System.out.println("\n"+Long.toHexString(total)); //$NON-NLS-1$
+
+		if(debug) if(this.time > 7820 && this.time < 7900) System.out.println("T:"+this.time+" "+Long.toHexString(total));  //$NON-NLS-1$//$NON-NLS-2$
+		
+		if(neg != 0) total = ~total;
+		
+		return (int)total;
+	}
+		
+	private String[] parseValueTypes(List<Integer> counterTypes, List<Integer> counterL2Types){
+		String[] s = new String[counterTypes.size() * eventTypeTable.size() + (counterL2Types == null ? 0 : counterL2Types.size())];
+		int k = 0;
+		for (int i = 0; i < eventTypeTable.size(); i++) {
+			String eventType =  eventTypeTable.get(i);
+			for (Integer counterType : counterTypes) {
+				s[k] = String.format(Messages.IpcTraceParser_20, eventType, convertCounterType(counterType));
+				k++;
+			}
+		}
+		
+		if (counterL2Types != null){
+			for (Integer l2Type : counterL2Types) {
+				s[k] = convertL2EventType(l2Type);
+				k++;				
+			}
+		}
+		return s;
+	}
+	
+	private String convertL2EventType(Integer value) {
+		String s = IpcTraceParser.l2EventTypeTable.get(value);
+		if (s == null) {
+			s = String.format(IPC_EVENT_NOT_RECOGNISED, value);
+		}
+		return s;
+	}
+	
+	private String convertCounterType(Integer value) {
+		String s = IpcTraceParser.counterTypeTable.get(value);
+		if (s == null) {
+			s = String.format(IPC_EVENT_NOT_RECOGNISED, value);
+		}
+		return s;
+	}
+}