/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: RawSpiceOut.java
* Input/output tool: reader for Raw Spice output (.raw)
* Written by Steven M. Rubin, Sun Microsystems.
*
* Copyright (c) 2004 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.io.input;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.text.TextUtils;
import com.sun.electric.tool.simulation.AnalogAnalysis;
import com.sun.electric.tool.simulation.Stimuli;
import java.io.IOException;
import java.net.URL;
/**
* Class for reading and displaying waveforms from Raw Spice output.
* These are contained in .raw files.
*/
public class RawSpiceOut extends Simulate
{
RawSpiceOut() {}
/**
* Method to read an Raw Spice output file.
*/
protected void readSimulationOutput(Stimuli sd, URL fileURL, Cell cell)
throws IOException
{
// open the file
if (openTextInput(fileURL)) return;
// show progress reading .raw file
startProgressDialog("Raw Spice output", fileURL.getFile());
// read the actual signal data from the .raw file
readRawFile(cell, sd);
// stop progress dialog, close the file
stopProgressDialog();
closeInput();
}
private void readRawFile(Cell cell, Stimuli sd)
throws IOException
{
// once per deck
boolean first = true;
sd.setCell(cell);
// once per analysis in the deck
AnalogAnalysis an = null; // new AnalogAnalysis(sd, AnalogAnalysis.ANALYSIS_SIGNALS);
int numSignals = -1;
int eventCount = -1;
String[] signalNames = null;
double[][] values = null;
for(;;)
{
String line = getLineFromSimulator();
if (line == null) break;
// make sure this isn't an HSPICE deck (check first line)
if (first)
{
first = false;
if (line.length() >= 20)
{
String hsFormat = line.substring(16, 20);
if (hsFormat.equals("9007") || hsFormat.equals("9601"))
{
System.out.println("This is an HSPICE file, not a RAWFILE file");
System.out.println("Change the SPICE format (in Preferences) and reread");
return;
}
}
}
// find the ":" separator
int colonPos = line.indexOf(":");
if (colonPos < 0) continue;
String preColon = line.substring(0, colonPos);
String postColon = line.substring(colonPos+1).trim();
if (preColon.equals("Plotname"))
{
// terminate any previous analysis
if (an != null)
{
numSignals = -1;
eventCount = -1;
signalNames = null;
values = null;
}
// start reading a new analysis
if (postColon.startsWith("Transient Analysis"))
{
an = new AnalogAnalysis(sd, AnalogAnalysis.ANALYSIS_TRANS, false);
} else if (postColon.startsWith("DC Analysis"))
{
an = new AnalogAnalysis(sd, AnalogAnalysis.ANALYSIS_DC, false);
} else if (postColon.startsWith("AC Analysis"))
{
an = new AnalogAnalysis(sd, AnalogAnalysis.ANALYSIS_AC, false);
} else
{
System.out.println("ERROR: Unknown analysis: " + postColon);
return;
}
continue;
}
if (preColon.equals("No. Variables"))
{
numSignals = TextUtils.atoi(postColon) - 1;
continue;
}
if (preColon.equals("No. Points"))
{
eventCount = TextUtils.atoi(postColon);
an.buildCommonTime(eventCount);
continue;
}
if (preColon.equals("Variables"))
{
if (numSignals < 0)
{
System.out.println("Missing variable count in file");
return;
}
signalNames = new String[numSignals];
values = new double[numSignals][eventCount];
for(int i=0; i<=numSignals; i++)
{
if (postColon.length() > 0)
{
line = postColon;
postColon = "";
} else
{
line = getLineFromSimulator();
if (line == null)
{
System.out.println("Error: end of file during signal names");
return;
}
}
line = line.trim();
int numberOnLine = TextUtils.atoi(line);
if (numberOnLine != i)
System.out.println("Warning: Variable " + i + " has number " + numberOnLine);
int spacePos = line.indexOf(" "); if (spacePos < 0) spacePos = line.length();
int tabPos = line.indexOf("\t"); if (tabPos < 0) tabPos = line.length();
int pos = Math.min(spacePos, tabPos);
String name = line.substring(pos).trim();
spacePos = name.indexOf(" "); if (spacePos < 0) spacePos = name.length();
tabPos = name.indexOf("\t"); if (tabPos < 0) tabPos = name.length();
pos = Math.min(spacePos, tabPos);
name = name.substring(0, pos);
if (i == 0)
{
if (!name.equals("time") && an.getAnalysisType() == AnalogAnalysis.ANALYSIS_TRANS)
System.out.println("Warning: the first variable should be time, is '" + name + "'");
} else
{
signalNames[i-1] = name;
}
}
continue;
}
if (preColon.equals("Values"))
{
if (numSignals < 0)
{
System.out.println("Missing variable count in file");
return;
}
if (eventCount < 0)
{
System.out.println("Missing point count in file");
return;
}
for(int j=0; j<eventCount; j++)
{
for(int i = -1; i <= numSignals; )
{
line = getLineFromSimulator();
if (line == null)
{
System.out.println("Error: end of file during data points (read " + j + " out of " + eventCount);
return;
}
line = line.trim();
if (line.length() == 0) continue;
int charPos = 0;
while (charPos <= line.length())
{
int tabPos = line.indexOf("\t", charPos);
if (tabPos < 0) tabPos = line.length();
String field = line.substring(charPos, tabPos);
charPos = tabPos+1;
while (charPos < line.length() && line.charAt(charPos) == '\t') charPos++;
if (i < 0)
{
int lineNumber = TextUtils.atoi(field);
if (lineNumber != j)
System.out.println("Warning: event " + j + " has wrong event number: " + lineNumber);
} else
{
double val = TextUtils.atof(field);
if (i == 0) an.setCommonTime(j, val); else
values[i-1][j] = val;
}
i++;
if (i > numSignals) break;
}
}
}
for (int i = 0; i < numSignals; i++)
an.addSignal(signalNames[i], null, values[i]);
continue;
}
if (preColon.equals("Binary"))
{
if (numSignals < 0)
{
System.out.println("Missing variable count in file");
return;
}
if (eventCount < 0)
{
System.out.println("Missing point count in file");
return;
}
// read the data
for(int j=0; j<eventCount; j++)
{
an.setCommonTime(j, dataInputStream.readDouble());
for(int i=0; i<numSignals; i++)
values[i][j] = dataInputStream.readDouble();
}
continue;
}
}
}
}