/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: AnalogAnalysis.java
*
* Copyright (c) 2007 Sun Microsystems and Static Free Software
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.simulation;
import java.util.*;
import com.sun.electric.tool.io.input.*;
import com.sun.electric.database.geometry.btree.*;
import java.io.*;
/**
* Analysis which contains analog signals
*/
public class AnalogAnalysis extends Analysis<AnalogSignal> {
/** all sweeps in this Analysis */ private List<Object> sweeps;
/** the common time array (if there is common time) */ private double [] commonTime;
/** the common time array (if there is common time) */ private HashMap<AnalogSignal,Waveform[]> waveformCache = new HashMap<AnalogSignal,Waveform[]>();
/**
* Constructor for a collection of analog simulation data.
* @param sd Stimuli that this analysis is part of.
* @param type the type of this analysis.
* @param extrapolateToRight true to draw the last value to the right
* (useful for IRSIM and other digital simulations).
* False to stop drawing signals after their last value
* (useful for Spice and other analog simulations).
*/
public AnalogAnalysis(Stimuli sd, AnalysisType type, boolean extrapolateToRight)
{
super(sd, type, extrapolateToRight);
if (type != ANALYSIS_MEAS)
sweeps = new ArrayList<Object>();
}
/**
* Free allocated resources before closing.
*/
@Override
public void finished()
{
super.finished();
if (sweeps != null) sweeps.clear();
}
@Override
public boolean isAnalog() { return true; }
/**
* Method to add information about another sweep in this simulation data.
* @param obj sweep information (typically a Double).
*/
public void addSweep(Object obj)
{
sweeps.add(obj);
setBoundsDirty();
}
/**
* Method to return the number of sweep objects in this simulation data.
* @return number of sweep objects in this simulation data.
* If there is no sweep information, the list is empty.
*/
public int getNumSweeps() { return (sweeps != null) ? Math.max(sweeps.size(), 1) : 1; }
/**
* Method to return sweep object in a given position.
* @param i the position to get.
* @return the sweep object for that position.
*/
public Object getSweep(int i)
{
if (sweeps == null || sweeps.size() == 0) return null;
return sweeps.get(i);
}
/**
* Method to construct an array of time values that are common to all signals.
* Some simulation data has all of its stimuli at the same time interval for every signal.
* To save space, such data can use a common time array, kept in the Simulation Data.
* If a signal wants to use its own time values, that can be done by placing the time
* array in the signal.
* @param numEvents the number of time events in the common time array.
*/
public void buildCommonTime(int numEvents)
{
commonTime = new double[numEvents];
}
/**
* Method to load an entry in the common time array.
* @param index the entry number.
* @param time the time value at
*/
public void setCommonTime(int index, double time)
{
commonTime[index] = time;
setBoundsDirty();
}
/**
* Method to get the array of time entries for this signal.
* @return the array of time entries for this signal.
*/
public double [] getCommonTimeArray() { return commonTime; }
/**
* Create new AnalogSignal with specified name.
* Signal obtains waveform constructed from common time and specified values.
* @param signalName signal name.
* @param signalContext a common prefix for the signal name.
* @param values specified values
* @return new AnalogSignal of this AnalogAnalysis
*/
public AnalogSignal addSignal(String signalName, String signalContext, double[] values)
{
AnalogSignal as = addEmptySignal(signalName, signalContext);
if (!isUseLegacySimulationCode()) {
BTree<Double,Double,Serializable> tree = NewEpicAnalysis.getTree();
int evmax = 0;
int evmin = 0;
double valmax = Double.MIN_VALUE;
double valmin = Double.MAX_VALUE;
for(int i=0; i<commonTime.length; i++) {
tree.insert(new Double(commonTime[i]), new Double(values[i]));
if (values[i] > valmax) { evmax = i; valmax = values[i]; }
if (values[i] < valmin) { evmin = i; valmin = values[i]; }
}
Waveform[] waveforms = { new BTreeNewSignal(evmin, evmax, tree) };
waveformCache.put(as, waveforms);
// System.err.println("put a btree");
} else {
Waveform[] waveforms = { new WaveformImpl(getCommonTimeArray(), values) };
waveformCache.put(as, waveforms);
}
return as;
}
/**
* Create new AnalogSignal with specified name.
* Signal obtains range constructed from common time range and specified value bounds.
* @param signalName signal name.
* @param signalContext a common prefix for the signal name.
* @param minValue the minimum value.
* @param maxValue the maximum value.
* @return new AnalogSignal of this AnalogAnalysis
*/
public AnalogSignal addSignal(String signalName, String signalContext, double minTime, double maxTime,
double minValue, double maxValue)
{
AnalogSignal as = addEmptySignal(signalName, signalContext);
return as;
}
/**
* Create new AnalogSignal with specified name.
* @param signalName signal name.
* @param signalContext a common prefix for the signal name.
* @return new AnalogSignal of this AnalogAnalysis
*/
private AnalogSignal addEmptySignal(String signalName, String signalContext)
{
AnalogSignal as = new AnalogSignal(this);
as.setSignalName(signalName, signalContext);
return as;
}
/**
* Method to return the waveform of specified signal in specified sweep.
* @param signal specified signal
* @param sweep sweep index
* @return the waveform of this signal in specified sweep.
*/
public Waveform getWaveform(AnalogSignal signal, int sweep)
{
Waveform[] waveforms = waveformCache.get(signal);
if (waveforms == null)
{
if (signal.getAnalysis() != this)
throw new IllegalArgumentException();
waveforms = loadWaveforms(signal);
assert waveforms.length == getNumSweeps();
waveformCache.put(signal, waveforms);
}
return waveforms[sweep];
}
protected Waveform[] loadWaveforms(AnalogSignal signal)
{
throw new UnsupportedOperationException();
}
}