sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.irq/src/com/nokia/carbide/cpp/pi/irq/IrqTraceParser.java
author Toni Pulkkinen <ext-toni.p.pulkkinen@nokia.com>
Wed, 23 Jun 2010 15:05:09 +0300
changeset 12 ae255c9aa552
parent 5 844b047e260d
permissions -rw-r--r--
Performance Investigator Carbide extension 2.4.0

/*
 * 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.irq;

import java.io.*;
import java.util.*;

import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
import com.nokia.carbide.cpp.internal.pi.model.Parser;


/**
 * Class irq trace parser. 
 */
public class IrqTraceParser extends Parser
{
//  private String profilerVersion;
  private Vector completeIrqTrace;
  private int firstSample,lastSample;
  private long old1 = 0;
  private long old2 = 0;
  private long old3 = 0;
  private int sampleNum = 0;
  private int oldIrqLev1 = 0;
  private int oldIrqLev2 = 0;
    
  public IrqTraceParser(/*File irqFile, ProgressBar progressBar*/) throws Exception
  {
    this.completeIrqTrace = new Vector();
  }
  
  public ParsedTraceData parse(File f) throws Exception 
  {
    
    if(!f.exists()) //throw new IOException("GFC file does not exist");
	{
		setStateOk(false);
		return null;
	}
	else
    {
		/*if(progressBar != null) 
		{
			setProgressBarString("Analysing IRQ/SWI...");
		}*/
		
		FileInputStream fis = new FileInputStream(f);
		byte[] data = new byte[(int)f.length()];
		fis.read(data);
		//String version = getVersion(data);
		//System.out.println("IRQ trace version "+version);
		//profilerVersion = version;
		ByteArrayInputStream bais = new ByteArrayInputStream(data);
		DataInputStream dis = new DataInputStream(bais);
		
		this.traceVersion = this.getVersion(dis);
		if (this.traceVersion.indexOf("V1.20") != -1)
		{
			// start parsing
			try
			{
				int total = 0;
				while(true)
				{
					total += readEntries(dis);
					this.sampleNum++;
					//System.out.println("Sample #"+sampleNum+" "+this.completeIrqTrace.size());
					//System.out.println("******* Total now "+total+" "+Integer.toHexString(total));
			  	  	//System.in.read();
			  	  	//System.in.read();
				}
			}
			catch (EOFException eof)
			{
				//eof.printStackTrace();
			    ParsedTraceData ptd = new ParsedTraceData();
				ptd.staticData = null;
				ptd.traceData = this.getTrace();
				return ptd;
			}
			catch (Exception e)
			{
				System.out.println("Error in reading IRQ trace file");
				throw e;				
			}
	    }
		else
		{
			System.out.println("Unsupported IRQ version: "+this.traceVersion);
		    return null;
		}
    }
  	
  }
  
  public String getProfilerVersion()
  {
      return this.traceVersion;
  }
  
  private String getVersion(DataInputStream dis) throws IOException
  {
  	int length = dis.readUnsignedByte();
  	byte[] verArray = new byte[length];
  	dis.read(verArray);

  	String verString = new String(verArray);
//  	System.out.println("Version string: "+verString);
	if(verString.indexOf("Bappea") != -1)
		if(verString.indexOf("IRQ") != -1)
		{
  			int index = verString.indexOf("_");
  			String ver = verString.substring(index,length);
  			return ver;
  		}
	return("Unidentified");
  }
  
  private int readEntries(DataInputStream dis) throws Exception
  {
	int b0=0,b1=0,b2=0,b3=0;
	boolean swi = false;
  	int read = 0;
  	//System.out.println("-------------");
  	b0 = dis.readUnsignedByte();read++;
  	int length = b0; 
  	if(length == 0xff)
  	{
  		// length encoded in 3 bytes
  		b1 = dis.readUnsignedByte();read++;
  		b2 = dis.readUnsignedByte();read++;
  		b3 = dis.readUnsignedByte();read++;
  		length = b1;
  		length |= b2<<8;
  		length |= b3<<16;
  		//System.out.println("LONG length "+length);
  	}
//  	
//	System.out.println("SWI len "+Integer.toHexString(b0)+
//				 " "+Integer.toHexString(b1)+
//				 " "+Integer.toHexString(b2)+
//				 " "+Integer.toHexString(b3)+" "+length+" = 0x"+Integer.toHexString(length));
  	
  	while(length > 0)
  	{
  		int read_val = dis.readUnsignedByte();read++;length--;
		
  		//System.out.println("Length "+length);
  		
  		int repeat_val = 0;
  		int header = (read_val & (int)0xff);
  		int repeat = header>>>6;
  		
  		//System.out.println("Header "+Long.toHexString(header)+" "+Long.toBinaryString(header)+" repeat "+repeat);
  		
  		if(repeat == 0)
  		{
  			repeat_val = 0;
  			//System.out.println("no repeat "+Long.toHexString(repeat_val));
  		}
  		else if(repeat == 1)
  		{
  			repeat_val = (header & ((int)0x3F));
  			
  			//System.out.println("short repeat "+Long.toHexString(repeat_val));
  		}
  		else if(repeat == 2)
  		{
  			repeat_val = ((header & ((int)0x3F))<<8) | 
			(dis.readUnsignedByte());length--;read++;
  			
  			//System.out.println("medium repeat"+Long.toHexString(repeat_val));  		
  		}
  		else if(repeat == 3)
  		{
  			repeat_val = ((header & ((int)0x3F))<<24) | 
			(dis.readUnsignedByte() << 16) |
			(dis.readUnsignedByte() << 8) |
			(dis.readUnsignedByte() );length-=3;read+=3;
			/*
			for(int x=0;x<10;x++)
			{
				for(int y=0;y<8;y++)
				{
					System.out.println(Integer.toHexString(dis.readUnsignedByte()));
				}
				System.out.print("\n");
			}
			
			System.in.read();
			System.in.read();
			*/
  		}
  		
  		if(repeat_val > 0) 
  		{
  			addSwiRepeat(repeat_val);
  		}
  		else
  		{
  			int bytes_1 = (header & ((int)0x30))>>>4;
  			int bytes_2 = (header & ((int)0x0C))>>>2;
  			int bytes_3 = (header & ((int)0x03));
  			if(bytes_1 == 3) bytes_1 = 4;
  			if(bytes_2 == 3) bytes_2 = 4;
  			if(bytes_3 == 3) bytes_3 = 4;
  			
  			readSwiEntry(dis,bytes_1,bytes_2,bytes_3);
  			length-=(bytes_1+bytes_2+bytes_3);
  			read+=(bytes_1+bytes_2+bytes_3);		
  		}
  	}
  	
  	if(length == 0)
  	{
  		//Sytem.out.println("End of SWI, reading IRQ");
  	  	b0 = dis.readUnsignedByte();read++;
  	  	length = b0; 
  	  	if(length == 0xff)
  	  	{
  	  		// length encoded in 3 bytes
  	  		b1 = dis.readUnsignedByte();read++;
  	  		b2 = dis.readUnsignedByte();read++;
  	  		b3 = dis.readUnsignedByte();read++;
  	  		length = b1;
  	  		length |= b2<<8;
  	  		length |= b3<<16;
  	  		//System.out.println("LONG length "+length);
  	  	}
//  		System.out.println("IRQ len "+Integer.toHexString(b0)+
//				 " "+Integer.toHexString(b1)+
//				 " "+Integer.toHexString(b2)+
//				 " "+Integer.toHexString(b3)+" "+length+" = 0x"+Integer.toHexString(length));
  	  	
  	  	swi = true;
  	  	while(length > 0)
  	  	{
  	  		//System.out.println("Length "+length);
  	  		int firstByte = dis.readUnsignedByte();length--;read++;
  	  		
  	  		if(firstByte == 0xff)
  	  		{
  	  			// this is a repeat of the previous sample
  	  			int repeat = 	dis.readUnsignedByte() |
								(dis.readUnsignedByte()<<8) |
								(dis.readUnsignedByte()<<16);
  	  			//if(sampleNum == 5918 || sampleNum == 6137 || sampleNum == 7958)
  	  			//System.out.println(this.sampleNum+" IRQ Repeat of "+repeat+" L1:"+this.old_irq_lev1+" L2:"+this.old_irq_lev2);
  	  			this.addIrqRepeat(repeat);
  	  			
  	  			length-=3;read+=3;
  	  			
  	  			if(length > 0)
  	  			{
  	  				this.oldIrqLev1 = dis.readUnsignedByte();
  	  				this.oldIrqLev2 = dis.readUnsignedByte();
  	  				length-=2; read-=2;

  	  				this.addIrqSample();
  	  			}
  	  		}
  	  		else
  	  		{
  	  			this.oldIrqLev1 = firstByte;
  	  			this.oldIrqLev2 = dis.readUnsignedByte();
  	  			length--;read++;

  	  			this.addIrqSample();
  	  		}
  	  		
  			//System.out.println(this.sampleNum+" IRQ L1:"+this.old_irq_lev1+" L2:"+this.old_irq_lev2);
  	  	}
  	}
  	else
  	{
//  		System.out.println("Parse error "+Integer.toHexString(b0)+
//  										 " "+Integer.toHexString(b1)+
//  										 " "+Integer.toHexString(b2)+
//  										 " "+Integer.toHexString(b3)+" "+swi+" "+read);
  		
  		throw new Exception("Parse error "+Integer.toHexString(b0)+
  										 " "+Integer.toHexString(b1)+
  										 " "+Integer.toHexString(b2)+
  										 " "+Integer.toHexString(b3));
  	}

  	if(length == 0)
  	{
  		return read;
  	}
  	else
  	{
  		throw new Exception("Parse error");
  	}
  	
  }
     
  private void readSwiEntry(DataInputStream dis,int b1,int b2,int b3) throws Exception
  {
  	//System.out.println("b1: "+b1+" b2:"+b2+" b3:"+b3);
  
  	int value = 0;
  	int fValue = 0;
  	boolean neg = false;
	for(int i=0;i<4;i++) 
	{
		if(i<b1)
		{
			value = dis.readUnsignedByte();
			if((value & 0x80) > 0) neg = true;
			else neg = false;
			value = (value<<(8*i));
			fValue |= value;
			//System.out.println("v"+i+":"+Integer.toHexString(value));
		}
		else
		{
			if(neg == true) value = 0xff;
			else value = 0x00;
			value = (value<<(8*i));
			fValue |= value;
			//System.out.println("v"+i+":"+Integer.toHexString(value));
		}
	}
	//if(fValue == -1) System.out.println("1:"+fValue); 	
	this.old1 += fValue;

	value = 0;
	fValue = 0;
	neg = false;
	for(int i=0;i<4;i++)
	{
		if(i<b2)
		{
			value = dis.readUnsignedByte();
			if((value & 0x80) > 0) neg = true;
			else neg = false;
			value = (value<<(8*i));
			fValue |= value;
			//System.out.println("v"+i+":"+Integer.toHexString(value));
		}
		else
		{
			if(neg == true) value = 0xff;
			else value = 0x00;
			value = (value<<(8*i));
			fValue |= value;
			//System.out.println("v"+i+":"+Integer.toHexString(value));
		}
	}
	//if(fValue == -1) System.out.println("2:"+fValue); 	
	this.old2 += fValue;
	
	value = 0;
	fValue = 0;
	neg = false;
	for(int i=0;i<4;i++) 
	{
		if(i<b3)
		{
			value = dis.readUnsignedByte();
			if((value & 0x80) > 0) neg = true;
			else neg = false;
			value = (value<<(8*i));
			fValue |= value;
			//System.out.println("v"+i+":"+Integer.toHexString(value));
		}
		else
		{
			if(neg == true) value = 0xff;
			else value = 0x00;
			value = (value<<(8*i));
			fValue |= value;
			//System.out.println("v"+i+":"+Integer.toHexString(value));
		}
	}
	//if(fValue == -1) System.out.println("3:"+fValue); 	
	this.old3 += fValue;
	
	this.addSwiSample();
	/*
	System.out.println( "#"+this.sampleNum+" "+Integer.toHexString((int)old_1)+
						" "+Integer.toHexString((int)old_2)+
						" "+Integer.toHexString((int)old_3)+" "+sfp.getFunctionNameForAddress(((old_3<<32)>>>32)));
	*/
 	return;
  }
  
  private void addSwiSample()
  {
	  long temp_1 = ((this.old1 << 32) >>> 32);
	  long temp_2 = ((this.old2 << 32) >>> 32);
	  long temp_3 = ((this.old3 << 32) >>> 32)-4;
	  
	  IrqSample sample = new IrqSample(this.sampleNum, temp_1, temp_2, temp_3);
	  /*
	  String n1 = sfp.getFunctionNameForAddress(temp_3);
	  
	  if(n1.indexOf("WaitForAnyRequest") != -1)
	  {
		  for(int i=-256;i<256;i++)
		  {
			  String n2 = sfp.getFunctionNameForAddress(temp_1+i);
			  if(n2.indexOf("WaitForAnyRequest") != -1)
			  {
				  System.out.print("\n"+i);
				  
				  System.out.println("EXEC CALL : "+sfp.getFunctionNameForAddress(temp_3));
				  System.out.println("Made in : "+sfp.getFunctionNameForAddress(temp_1+i));
				  break;
			  }
		  }
	  } 
	  */
	  this.completeIrqTrace.add(sample);
  }
  
  private void addSwiRepeat(int amount)
  {
	  long temp_1 = ((this.old1 << 32) >>> 32);
	  long temp_2 = ((this.old2 << 32) >>> 32);
	  long temp_3 = ((this.old3 << 32) >>> 32)-4;
	  
	  /*
	  String n1 = sfp.getFunctionNameForAddress(temp_3);
	  
	  if(n1.indexOf("WaitForAnyRequest") != -1)
	  {
		  for(int i=-256;i<256;i++)
		  {
			  String n2 = sfp.getFunctionNameForAddress(temp_1+i);
			  if(n2.indexOf("WaitForAnyRequest") != -1)
			  {
				  System.out.print("\n"+i);
				  
				  System.out.println("EXEC CALL : "+sfp.getFunctionNameForAddress(temp_3));
				  System.out.println("Made in : "+sfp.getFunctionNameForAddress(temp_1+i));
				  break;
			  }
		  }
	  } 
	  */
	  
	  IrqSample sample = new IrqSample(this.sampleNum,temp_1,temp_2,temp_3);
	  sample.repeatCount = amount;
	  this.completeIrqTrace.add(sample);
  }

  private void addIrqSample()
  {
  	IrqSample sample = new IrqSample(this.sampleNum,this.oldIrqLev1,this.oldIrqLev2);
  	this.completeIrqTrace.add(sample);
  }
  
  private void addIrqRepeat(int amount)
  {
  	  	IrqSample sample = new IrqSample(this.sampleNum,this.oldIrqLev1,this.oldIrqLev2);
  	  	sample.repeatCount = amount; 
 	  	this.completeIrqTrace.add(sample);
  }
  
  private GenericTrace getTrace()
  {
  	Enumeration completeEnum = this.completeIrqTrace.elements();
  	IrqTrace trace = new IrqTrace();
  	
  	while(completeEnum.hasMoreElements())
  	{
  		IrqSample sample = (IrqSample)completeEnum.nextElement();
  		trace.addSample(sample);
  	}
  	return trace;
  }
}