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

/*
 * Copyright (c) 2009 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.power;

import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;

import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
import com.nokia.carbide.cpp.pi.editors.PIPageEditor;


public class PwrTrace extends GenericSampledTrace
{
	private static final long serialVersionUID = -2398791759386296139L;
	
	transient private PowerTraceGraph[] graphs = null;
	transient private boolean complete = false;
	transient private ArrayList<PwrSample> powerChangePoints;	// times when power samples change
	transient private long maxEndTime;
	transient private TreeMap<Long, Integer> backlightChangePoints;
	
    private float voltage = 3.7f;
	
    // used when manually positioning the trace
    public int offset = 0; 
	
    public float batterySize = 1500f;
    
    private double scale = 0.0;
	private double min = 0.0;
	private double max = 0.0;
	private double synchValue = 0.0;
	private boolean backlightEnabled;	 
	 
	transient private int[] sampleTimes;
    transient private int[] ampValues;
    transient private int[] voltValues;
    transient private int[] capaValues;
    transient private double maxAmps = Double.MIN_VALUE;
	transient private double minAmps = Double.MAX_VALUE;
	transient private double maxPower = 0.0;
	

    public GenericTraceGraph getTraceGraph(int graphIndex, int uid)
	{		
		return getPowerGraph(graphIndex, uid);
	}
	
	public PowerTraceGraph getPowerGraph(int graphIndex, int uid)
	{
		if (graphs == null) {
			graphs = new PowerTraceGraph[3];
			maxEndTime = (long) ((PIPageEditor.currentPageEditor().getMaxEndTime() + .0005) * 1000); 
		}

		// note that graphIndex needs not match the index sent to GppTraceGraph
		if (   (graphIndex == PIPageEditor.THREADS_PAGE)
			|| (graphIndex == PIPageEditor.BINARIES_PAGE)
			|| (graphIndex == PIPageEditor.FUNCTIONS_PAGE)) {
			if (graphs[graphIndex] == null)
				graphs[graphIndex] = new PowerTraceGraph(graphIndex, uid, this);
			return graphs[graphIndex];
		}
	
		return null;
	}

    public float getBatterySize() 
	{
        return batterySize;
    }

    public void setBatterySize(float newVal) 
	{
        batterySize = newVal;
    }

    public int getOffset() 
	{
        return offset;
    }

    public float getVoltage()
    {
    	return voltage;
    }

	public int[] getSampleTimes()
    {
    	return sampleTimes;
    }

	public int[] getAmpValues()
    {
    	return ampValues;
    }

    public int[] getVoltValues()
    {
    	return voltValues;
    }

    public int[] getCapaValues()
    {
    	return capaValues;
    }

    public double getMaxAmps()
    {
    	return maxAmps;
    }

    public double getMinAmps()
    {
    	return minAmps;
    }

	public double getMaxPower()
    {
    	return maxPower;
    }

	public void setVoltage(float voltage)
    {
    	this.voltage = voltage;
    }
    
    public void setOffset( int newOffset ) 
	{
		int mySize = getSampleAmount();
		
		if( newOffset > mySize )
			offset = mySize;
		else if( (newOffset * -1) > mySize )
			offset = (-1)*mySize;
		else
			offset = newOffset;
    }
    
	public double getScale()
	{
		return scale;
	}
	
	public double getMin()
	{
		return min;
	}
	
	public double getMax()
	{
		return max;
	}
	
	public long getMaxEndTime()
	{
		return maxEndTime;
	}
	
	public double getSynchValue()
	{
		return synchValue;
	}
	
	public void setSynchValue(double aSynchValue)
	{
		synchValue = aSynchValue;
	}
	
	public void addSample(PwrSample sample)
	{
		this.samples.add(sample);
	}

	public PwrSample getPwrSample(int number)
	{
		return (PwrSample)this.samples.elementAt(number);
	}

	// compensate for different sampling speeds. 
	// the software traces are done at 1KHz and the 
	// power traces are typically done at 250Khz.
	//
	public void initData()
	{
		ArrayList<PwrSample> powerChangePoints = new ArrayList<PwrSample>();
		if(backlightEnabled){
			backlightChangePoints = new TreeMap<Long, Integer>();
		}
		PwrSample sample = (PwrSample) this.samples.get(0);
			
		long   currentTime     = sample.sampleSynchTime;
		double currentCurrent  = sample.current;
		double currentVoltage  = sample.voltage;
		double currentCapacity = sample.capacity;
		int currentBacklight = sample.backlight;
		if(backlightEnabled){
			backlightChangePoints.put(currentTime, currentBacklight);
		}
				
		for (int i = 1; i < this.samples.size(); i++) {
			sample = (PwrSample) this.samples.get(i);
			if (   sample.current  != currentCurrent
				|| sample.voltage  != currentVoltage
				|| sample.capacity != currentCapacity) {
				PwrSample addSample = new PwrSample(currentTime, currentCurrent, currentVoltage, currentCapacity);
				powerChangePoints.add(addSample);
				currentTime     = sample.sampleSynchTime;
				currentCurrent  = sample.current;
				currentVoltage  = sample.voltage;
				currentCapacity = sample.capacity;
			}
			if(backlightEnabled){
				if(sample.backlight != currentBacklight){
					backlightChangePoints.put(sample.sampleSynchTime, sample.backlight);
					currentBacklight = sample.backlight;
				}
			}
		
		}
		
		if(powerChangePoints.size() > 0){
			sample = powerChangePoints.get(powerChangePoints.size() - 1);
			if (   sample.current  != currentCurrent
				|| sample.voltage  != currentVoltage
				|| sample.capacity != currentCapacity) {
				powerChangePoints.add(new PwrSample(currentTime, currentCurrent, currentVoltage, currentCapacity));
			}	
		}

		this.powerChangePoints = powerChangePoints;
		
		sampleTimes = new int[this.powerChangePoints.size()];
        ampValues   = new int[this.powerChangePoints.size()];
        voltValues  = new int[this.powerChangePoints.size()];
        capaValues  = new int[this.powerChangePoints.size()];

		int localMaxAmps = Integer.MIN_VALUE;
		int localMinAmps = Integer.MAX_VALUE;

		for (int i = 0; i < this.powerChangePoints.size(); i++)
	    {
			PwrSample tmp = this.powerChangePoints.get(i);
			sampleTimes[i] = (int)Math.abs(tmp.sampleSynchTime);		
			ampValues[i]   = (int)Math.abs(tmp.current);	// in milliamps
			voltValues[i]  = (int)Math.abs(tmp.voltage);	// in millivolts
			capaValues[i]  = (int)Math.abs(tmp.capacity);

			if (ampValues[i] > localMaxAmps)
			{
				localMaxAmps = ampValues[i];
			}
			else if (ampValues[i] < minAmps )
			{
				localMinAmps = ampValues[i];
			}
		}
	    
	    maxAmps = localMaxAmps;
	    minAmps = localMinAmps;

	    scaleMaxPower();
	}
	
	public ArrayList<PwrSample> getPowerChangePoints()
	{
		return this.powerChangePoints;
	}
	
	public void scaleMaxPower()
	{
		maxPower = maxAmps * this.voltage;

		if (maxPower < 10)
	    	maxPower =     10;
		else if (maxPower <     20)
	    	maxPower =     20;
	    else if (maxPower <     50)
	    	maxPower =     50;
	    else if (maxPower <    100)
	    	maxPower =    100;
	    else if (maxPower <    200)
	    	maxPower =    200;
	    else if (maxPower <    500)
	    	maxPower =    500;
	    else if (maxPower <   1000)
	    	maxPower =   1000;
	    else if (maxPower <   2000)
	    	maxPower =   2000;
	    else if (maxPower <   5000)
	    	maxPower =   5000;
	    else if (maxPower <  10000)
	    	maxPower =  10000;
	    else if (maxPower <  20000)
	    	maxPower =  20000;
	    else if (maxPower <  50000)
	    	maxPower =  50000;
	    else if (maxPower < 100000)
	    	maxPower = 100000;
	}

  	/*
  	 * Check if the power trace is complete (first sample is at time 1, sample N is at time N)
  	 */
  	public void setComplete()
  	{
		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
  		int size;
  		
  		this.complete = true;
  		
   		size = this.samples.size();
  		for (int i = 0; i < size; i++) {
  			PwrSample element = (PwrSample)this.samples.get(i);
  			if (element.sampleSynchTime != i*samplingInterval) {
  				this.complete = false;
  				break;
  			}
  		}
  	}
  	
  	public boolean isComplete() {
  		return this.complete;
  	}
  	
  	public boolean isBacklightEnabled(){
  		//TODO remove this for enabling backlight visualization
  		return false;
  		//return backlightEnabled;
  	}
  	
	public void setBacklightEnabled(boolean backlightEnabled){
  		this.backlightEnabled = backlightEnabled;
  	}
	
	public Map<Long, Integer> getBacklightChangePoints(){
		return backlightChangePoints;
	}
}