/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: Simulate.java * Input/output tool: superclass for simulation-output formats that display their results in a waveform window. * Written by Steven M. Rubin, Sun Microsystems. * * Copyright (c) 2003 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.Main; import com.sun.electric.database.Environment; import com.sun.electric.database.hierarchy.Cell; import com.sun.electric.database.hierarchy.Library; import com.sun.electric.database.text.TextUtils; import com.sun.electric.database.variable.UserInterface; import com.sun.electric.tool.Job; import com.sun.electric.tool.UserInterfaceExec; import com.sun.electric.tool.io.FileType; import com.sun.electric.tool.io.input.verilog.VerilogOut; import com.sun.electric.tool.simulation.Simulation; import com.sun.electric.tool.simulation.Stimuli; import com.sun.electric.tool.user.dialogs.CellBrowser; import com.sun.electric.tool.user.dialogs.OpenFile; import com.sun.electric.tool.user.waveform.WaveformWindow; import java.io.File; import java.io.IOException; import java.net.URL; import javax.swing.SwingUtilities; /** * This class reads simulation output files and plots them. */ public abstract class Simulate extends Input { public Simulate() {} /** * Method called from the pulldown menus to read Spice output and plot it. */ public static void plotSpiceResults() { String format = Simulation.getSpiceOutputFormat(); Simulation.SpiceEngine engine = Simulation.getSpiceEngine(); FileType type = getSpiceOutputType(format, engine); if (type == null) return; plotSimulationResults(type, null, null, null); } /** * Method called from the pulldown menus to read Spice output for the current cell. */ public static void plotSpiceResultsThisCell() { UserInterface ui = Job.getUserInterface(); Cell cell = ui.needCurrentCell(); if (cell == null) return; String format = Simulation.getSpiceOutputFormat(); Simulation.SpiceEngine engine = Simulation.getSpiceEngine(); FileType type = getSpiceOutputType(format, engine); if (type == null) return; plotSimulationResults(type, cell, null, null); } /** * Method called from the pulldown menus to read Verilog output and plot it. */ public static void plotVerilogResults() { plotSimulationResults(FileType.VERILOGOUT, null, null, null); } /** * Method called from the pulldown menus to read Verilog output for the current cell. */ public static void plotVerilogResultsThisCell() { UserInterface ui = Job.getUserInterface(); Cell cell = ui.needCurrentCell(); if (cell == null) return; plotSimulationResults(FileType.VERILOGOUT, cell, null, null); } private static Simulate getSimulate(FileType type) { Simulate is = null; if (type == FileType.HSPICEOUT) { is = new HSpiceOut(); } else if (type == FileType.PSPICEOUT) { is = new PSpiceOut(); } else if (type == FileType.RAWSPICEOUT) { is = new RawSpiceOut(); } else if (type == FileType.RAWLTSPICEOUT) { is = new LTSpiceOut(); } else if (type == FileType.RAWSSPICEOUT) { is = new SmartSpiceOut(); } else if (type == FileType.SPICEOUT) { is = new SpiceOut(); } else if (type == FileType.EPIC) { // if (Simulation.isSpiceEpicReaderProcess()) if (!Simulation.isUseLegacySimulationCode()) { is = new NewEpicOutProcess(); } else { is = new EpicOutProcess(); } // else // is = new EpicOut(); } else if (type == FileType.VERILOGOUT) { is = new VerilogOut(); } return is; } /** * Method to read simulation output of a given type. */ public static void plotSimulationResults(FileType type, Cell cell, URL fileURL, WaveformWindow ww) { Simulate is = getSimulate(type); if (is == null) { System.out.println("Cannot handle " + type.getName() + " files yet"); return; } if (cell == null) { if (fileURL == null) { String fileName = OpenFile.chooseInputFile(type, null); if (fileName == null) return; fileURL = TextUtils.makeURLToFile(fileName); } String cellName = TextUtils.getFileNameWithoutExtension(fileURL); Library curLib = Library.getCurrent(); cell = curLib.findNodeProto(cellName); if (cell == null) { CellBrowser dialog = new CellBrowser(Main.getCurrentJFrame(), true, CellBrowser.DoAction.selectCellToAssoc); dialog.setVisible(true); cell = dialog.getSelectedCell(); if (cell == null) return; } } else { if (fileURL == null) { // String [] extensions = type.getFirstExtension(); String fileName = cell.getName() + "." + type.getFirstExtension(); // look for file in library path String filePath = TextUtils.getFilePath(cell.getLibrary().getLibFile()); File file = new File(filePath, fileName); if (!file.exists()) { // look for file in spice working directory String dir = type.getGroupPath(); file = new File(dir, fileName); } fileURL = TextUtils.makeURLToFile(file.getPath()); } } (new ReadSimulationOutput(type, is, fileURL, cell, ww)).start(); } public static Stimuli readSimulationResults(FileType type, Cell cell, URL fileURL) { Simulate is = getSimulate(type); if (is == null) { System.out.println("Cannot handle " + type.getName() + " files yet"); return null; } if (cell == null) { System.out.println("Error reading simulation results; specified Cell is null"); return null; } if (fileURL == null) { System.out.println("Error reading simulation results; specified file is null"); return null; } ReadSimulationOutput job = new ReadSimulationOutput(type, is, fileURL, cell, null); job.run(); return job.sd; } /** * Class to read simulation output in a new thread. */ private static class ReadSimulationOutput extends Thread { private FileType type; private Simulate is; private URL fileURL; private Cell cell; private WaveformWindow ww; private Stimuli sd; private final Environment launcherEnvironment; private final UserInterfaceExec userInterface; private ReadSimulationOutput(FileType type, Simulate is, URL fileURL, Cell cell, WaveformWindow ww) { this.type = type; this.is = is; this.fileURL = fileURL; this.cell = cell; this.ww = ww; sd = new Stimuli(); launcherEnvironment = Environment.getThreadEnvironment(); userInterface = new UserInterfaceExec(); } public void run() { if (Thread.currentThread() == this) { Environment.setThreadEnvironment(launcherEnvironment); Job.setUserInterface(userInterface); } try { is.readSimulationOutput(sd, fileURL, cell); if (sd != null) { sd.setDataType(type); sd.setFileURL(fileURL); final Stimuli sdx = sd; final WaveformWindow wwx = ww; SwingUtilities.invokeLater(new Runnable() { public void run() { Simulation.showSimulationData(sdx, wwx); }}); } } catch (IOException e) { System.out.println("End of file reached while reading " + fileURL); } } } /** * Method that is overridden by subclasses to actually do the work. */ protected abstract void readSimulationOutput(Stimuli sd, URL fileURL, Cell cell) throws IOException; public static FileType getSpiceOutputType(String format, Simulation.SpiceEngine engine) { if (format.equalsIgnoreCase("Standard")) { if (engine == Simulation.SpiceEngine.SPICE_ENGINE_H) return FileType.HSPICEOUT; if (engine == Simulation.SpiceEngine.SPICE_ENGINE_3 || engine == Simulation.SpiceEngine.SPICE_ENGINE_P) return FileType.PSPICEOUT; return FileType.SPICEOUT; } if (format.equalsIgnoreCase("Raw")) { return FileType.RAWSPICEOUT; } if (format.equalsIgnoreCase("RawSmart")) { return FileType.RAWSSPICEOUT; } if (format.equalsIgnoreCase("RawLT")) { return FileType.RAWLTSPICEOUT; } if (format.equalsIgnoreCase("Epic")) { return FileType.EPIC; } return null; } /** * Method to get the next line of text from the simulator. * Returns null at end of file. */ protected String getLineFromSimulator() throws IOException { StringBuffer sb = new StringBuffer(); int bytesRead = 0; for(;;) { int ch = lineReader.read(); if (ch == -1) return null; bytesRead++; if (ch == '\n' || ch == '\r') break; sb.append((char)ch); } updateProgressDialog(bytesRead); return sb.toString(); } /** * Method to remove the leading "x" character in each dotted part of a string. * HSpice decides to add "x" in front of every cell name, so the path "me.you" * appears as "xme.xyou". * @param name the string from HSpice. * @return the string without leading "X"s. */ static String removeLeadingX(String name) { // remove all of the "x" characters at the start of every instance name int dotPos = -1; while (name.indexOf('.', dotPos+1) >= 0) { int xPos = dotPos + 1; if (name.length() > xPos && name.charAt(xPos) == 'x') { name = name.substring(0, xPos) + name.substring(xPos+1); } dotPos = name.indexOf('.', xPos); if (dotPos < 0) break; } return name; } }