sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.perfcounters/src/com/nokia/carbide/cpp/pi/internal/perfcounters/PecTraceParser.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.perfcounters/src/com/nokia/carbide/cpp/pi/internal/perfcounters/PecTraceParser.java	Wed Apr 21 15:14:16 2010 +0300
@@ -0,0 +1,290 @@
+/*
+ * 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.perfcounters;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.Parser;
+import com.nokia.carbide.cpp.pi.internal.perfcounters.ui.ProcessorSpeedInputDialog;
+
+
+/**
+ * Parser for performance counter event traces in binary format.
+ * Converts parsed content into PecSamples.
+ */
+public class PecTraceParser extends Parser {
+	private static final int INSTRUCTIONS_EXECUTED = 0x7;
+	private static final int CPU_CLOCK_TICK_DIV64 = 0xFFFF;
+	private static final int DUMMY_MIPS_ID = -1;
+	
+	
+	private boolean debug = false;
+	
+	private long time = 0;
+	
+	/** true if dialogs etc is allowed here, false for quiet mode */
+	private boolean allowUserInteraction;
+	
+	/** produce MIPS graph data */
+	protected boolean mipsEnabled;
+	/** the processor speed to use for MIPS graph calculations */
+	protected int processorSpeed;
+	
+	/**
+	 * Constructor
+	 * @param allowUserInteraction true, if user interactions such as dialogs are allowed
+	 */
+	public PecTraceParser(boolean allowUserInteraction) {
+		super();
+		this.allowUserInteraction = allowUserInteraction;
+	}
+
+	private static final Map<Integer, String> eventTypeTable = new HashMap<Integer, String>();
+	static {
+		eventTypeTable.put(0x0,Messages.PecTraceParser_0);
+		eventTypeTable.put(0x1,Messages.PecTraceParser_1);
+		eventTypeTable.put(0x2,Messages.PecTraceParser_2);
+		eventTypeTable.put(0x3,Messages.PecTraceParser_3);
+		eventTypeTable.put(0x4, Messages.PecTraceParser_4);
+		eventTypeTable.put(0x5, Messages.PecTraceParser_5);
+		eventTypeTable.put(0x6, Messages.PecTraceParser_6);
+		eventTypeTable.put(INSTRUCTIONS_EXECUTED, Messages.PecTraceParser_7);
+		eventTypeTable.put(0x9, Messages.PecTraceParser_8);
+		eventTypeTable.put(0xA, Messages.PecTraceParser_9);
+		eventTypeTable.put(0xB, Messages.PecTraceParser_10);
+		eventTypeTable.put(0xC, Messages.PecTraceParser_11);
+		eventTypeTable.put(0xD, Messages.PecTraceParser_12);
+		eventTypeTable.put(0xF, Messages.PecTraceParser_13);
+		eventTypeTable.put(0x10, Messages.PecTraceParser_14);
+		eventTypeTable.put(0x11, Messages.PecTraceParser_15);
+		eventTypeTable.put(0x12, Messages.PecTraceParser_16);
+		eventTypeTable.put(0x20, Messages.PecTraceParser_17);
+		eventTypeTable.put(0x21, Messages.PecTraceParser_18);
+		eventTypeTable.put(0x22, Messages.PecTraceParser_19);
+		eventTypeTable.put(0xFF, Messages.PecTraceParser_20);
+		eventTypeTable.put(CPU_CLOCK_TICK_DIV64, Messages.PecTraceParser_21);
+		eventTypeTable.put(DUMMY_MIPS_ID, PecTrace.MIPS_NAME);
+	}
+				
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.model.Parser#parse(java.io.File)
+	 */
+	@Override
+	public ParsedTraceData parse(File file) throws FileNotFoundException 
+	{
+		ParsedTraceData ptd = new ParsedTraceData();
+		ptd.functionResolvers = null;
+		ptd.staticData = null;
+		PecTrace pecTrace = new PecTrace();
+		ptd.traceData = pecTrace;
+		doParsing(file, pecTrace);
+		time = 0;
+		
+		return ptd;
+	}
+	
+	private void doParsing(File f, PecTrace 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("PEC trace version:"+this.traceVersion); //$NON-NLS-1$
+			
+			int firstData = dis.readUnsignedByte();
+			int secondData = dis.readUnsignedByte();
+			int thirdData = CPU_CLOCK_TICK_DIV64;
+			
+			if (allowUserInteraction && (firstData == INSTRUCTIONS_EXECUTED || secondData == INSTRUCTIONS_EXECUTED)){
+				Display.getDefault().syncExec( new Runnable() {
+
+					public void run () {
+						// in future, if we don't want to have a dialog in the core parser class
+						// we could call into an interface which ProcessorSpeedInputDialog would have to implement
+						ProcessorSpeedInputDialog dialog = new ProcessorSpeedInputDialog(
+								PlatformUI.getWorkbench()
+										.getActiveWorkbenchWindow().getShell());
+						if (dialog.open() == Window.OK){
+							processorSpeed = dialog.getIntValue();
+							mipsEnabled = true;
+						}
+					}
+				});
+				
+				
+			}
+
+			Integer[] valueTypeVector = new Integer[mipsEnabled ? 4 : 3];
+			valueTypeVector[0] = Integer.valueOf(firstData);
+			valueTypeVector[1] = Integer.valueOf(secondData);
+			// this type is always the cpu clock tick div 64
+			valueTypeVector[2] = Integer.valueOf(thirdData);
+			
+			if (mipsEnabled){
+				valueTypeVector[3] = DUMMY_MIPS_ID;
+			}
+			
+			trace.setValueTypes(this.parseValueTypes(valueTypeVector));
+			
+			PecSample s = null;			
+			while(true)
+			{
+				s = readSample(dis,s);
+				trace.addSample(s);
+			}
+		}
+		catch (IOException ioe)
+		{
+			//TODO: should we log this or handle it?
+			//my guess is this signifies the end of file
+		}
+	}
+
+	private PecSample readSample(DataInputStream dis,PecSample prevSample) throws IOException
+	{
+		int headerByte = (dis.readByte() << 24) >>> 24;
+		int neg0 = 0;
+		int neg1 = 0;
+		int neg2 = 0;
+		
+		int prev0 = 0;
+		int prev1 = 0;
+		int prev2 = 0;
+		
+		if(prevSample != null)
+		{
+			prev0 = prevSample.values[0];
+			prev1 = prevSample.values[1];
+			prev2 = prevSample.values[2]/64;
+		}
+		if(debug) if(this.time > 7820 && this.time < 7830) System.out.println("header: "+Long.toHexString(headerByte)+" = "+Integer.toBinaryString(headerByte));  //$NON-NLS-1$//$NON-NLS-2$
+		
+		if( ((headerByte >>> 7)&1) != 0)
+		{
+			neg0 = 1;
+		}
+		
+		if( ((headerByte >>> 6)&1) != 0)
+		{
+			neg1 = 1;
+		}
+		
+		if( ((headerByte >>> 5)&1) != 0)
+		{
+			neg2 = 1;
+		}
+		
+		int len0 = (((headerByte >> 3) << 30) >>> 30)+1;
+		int len1 = (((headerByte >> 1) << 30) >>> 30)+1;
+		int len2 = ((((headerByte) << 31) >>> 31)+1)*2;
+		
+		if(debug) if(this.time > 7820 && this.time < 7830) System.out.println("T:"+this.time+" len0:"+len0+" len1:"+len1+" len2:"+len2); //$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:"+neg0+" N1:"+neg1+" N2:"+neg2);   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
+		
+		long val0 = readVal(neg0,len0,dis);
+		long val1 = readVal(neg1,len1,dis);
+		long val2 = readVal(neg2,len2,dis);
+		
+		if(debug) if(this.time > 7820 && this.time < 7900) System.out.println("READ T:"+this.time+"   V0:"+Long.toHexString(val0)+" V1:"+Long.toHexString(val1)+" V2:"+Long.toHexString(val2));   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
+		val0 = prev0-val0;
+		val1 = prev1-val1;
+		val2 = prev2-val2;
+		
+		int[] values;
+		if (mipsEnabled){
+			values = new int[]{(int)val0,(int)val1,((int)val2)*64, (int)(processorSpeed * val1 / (val2*64))};
+		} else {
+			values = new int[]{(int)val0,(int)val1,((int)val2)*64};			
+		}
+		
+		PecSample ps = new PecSample(values, this.time);		
+		
+		if(debug) if(this.time > 7820 && this.time < 7900) System.out.println("T:"+this.time+"   V0:"+Long.toHexString(val0)+" V1:"+Long.toHexString(val1)+" V2:"+Long.toHexString(val2));  //$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+" "+val0+" "+val1+" "+val2);   //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$//$NON-NLS-4$
+		this.time++;
+		
+		return ps;
+	}
+
+	private long readVal(int neg,int len,DataInputStream dis) throws IOException
+	{
+		byte[] array = new byte[len];
+		dis.read(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 total;
+	}
+		
+	/**
+	 * Converts the given event type identifiers into the appropriate event type strings.
+	 * @param valueTypeIntegers list of event type identifiers
+	 * @return String[] of event type strings
+	 */
+	private String[] parseValueTypes(Integer[] valueTypeIntegers){
+		String[] s = new String[valueTypeIntegers.length];
+		for (int i = 0; i < valueTypeIntegers.length; i++) {
+			s[i] = convertValueType(valueTypeIntegers[i]);
+		}
+		
+		return s;
+	}
+	
+	private String convertValueType(int value) {
+		String s = eventTypeTable.get(Integer.valueOf(value));
+		if (s == null){
+			s = String.format(
+					Messages.PecTraceParser_22,
+					value);			
+		}
+		return s;
+
+	}
+
+}