📄 epicanalysis.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: EpicAnalysis.java * * Copyright (c) 2005 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.geometry.GenMath;import com.sun.electric.database.text.TextUtils;import com.sun.electric.tool.simulation.AnalogAnalysis;import com.sun.electric.tool.simulation.AnalogSignal;import com.sun.electric.tool.simulation.Stimuli;import com.sun.electric.tool.simulation.Waveform;import com.sun.electric.tool.simulation.WaveformImpl;import com.sun.electric.tool.user.ActivityLogger;import java.awt.geom.Rectangle2D;import java.io.File;import java.io.FileNotFoundException;import java.io.IOException;import java.io.RandomAccessFile;import java.util.ArrayList;import java.util.Arrays;import java.util.BitSet;import java.util.Collections;import java.util.Comparator;import java.util.Enumeration;import java.util.HashMap;import java.util.List;import java.util.NoSuchElementException;import java.util.Vector;import javax.swing.tree.DefaultMutableTreeNode;import javax.swing.tree.TreeNode;import javax.swing.tree.TreePath;/** * Class to define a set of simulation data producet by Epic simulators. * This class differs from Anylisis base class by less memory consumption. * Waveforms are stored in a file in packed form. They are loaded to memory by * denand. Hierarchical structure is reconstructed from Epic flat names into Context objects. * EpicSignals don't store signalContex strings, EpicAnalysis don't have signalNames hash map. * Elements of Context are EpicTreeNodes. They partially implements interface javax.swing.tree.TreeNode . */public class EpicAnalysis extends AnalogAnalysis { /** Separator in Epic signal names. */ static final char separator = '.'; /** Type of voltage signal. */ static final byte VOLTAGE_TYPE = 1; /** Type of current signal. */ static final byte CURRENT_TYPE = 2; /** Fake context which denotes voltage signal. */ static final Context VOLTAGE_CONTEXT = new Context(VOLTAGE_TYPE); /** Fake context which denotes current signal. */ static final Context CURRENT_CONTEXT = new Context(CURRENT_TYPE); /** File name of File with waveforms. */ private File waveFileName; /** Opened file with waveforms. */ private RandomAccessFile waveFile; /** Offsets of packed waveforms in the file. */ int[] waveStarts; /** Time resolution of integer time unit. */ private double timeResolution; /** Voltage resolution of integer voltage unit. */ private double voltageResolution; /** Current resolution of integer current unit. */ private double currentResolution; /** Simulation time. */ private double maxTime; /** Unmodifieable view of signals list. */ private List<AnalogSignal> signalsUnmodifiable; /** a set of voltage signals. */ private BitSet voltageSignals = new BitSet(); /** Top-most context. */ private Context rootContext; /** Hash of all contexts. */ private Context[] contextHash = new Context[1]; /** Count of contexts in the hash. */ private int numContexts = 0; /** * Package-private constructor. * @param sd Stimuli. */ EpicAnalysis(Stimuli sd) { super(sd, AnalogAnalysis.ANALYSIS_TRANS, false); signalsUnmodifiable = Collections.unmodifiableList(super.getSignals()); } /** * Set time resolution of this EpicAnalysis. * @param timeResolution time resolution in nanoseconds. */ void setTimeResolution(double timeResolution) { this.timeResolution = timeResolution; } /** * Set voltage resolution of this EpicAnalysys. * @param voltageResolution voltage resolution in volts. */ void setVoltageResolution(double voltageResolution) { this.voltageResolution = voltageResolution; } /** * Set current resolution of this EpicAnalysys. * @param currentResolution in amperes ( milliamperes? ). */ void setCurrentResolution(double currentResolution) { this.currentResolution = currentResolution; } double getValueResolution(int signalIndex) { return voltageSignals.get(signalIndex) ? voltageResolution : currentResolution; } /** * Set simulation time of this EpicAnalysis. * @param maxTime simulation time in nanoseconds. */ void setMaxTime(double maxTime) { this.maxTime = maxTime; } /** * Set root context of this EpicAnalysys. * @param context root context. */ void setRootContext(Context context) { rootContext = context; } /** * Set waveform file of this EpicAnalysis. * @param waveFileName File object with name of waveform file. */ void setWaveFile(File waveFileName) throws FileNotFoundException { this.waveFileName = waveFileName; waveFileName.deleteOnExit(); waveFile = new RandomAccessFile(waveFileName, "r"); } /** * Free allocated resources before closing. */ @Override public void finished() { try { waveFile.close(); waveFileName.delete(); } catch (IOException e) { } } /** * Method to quickly return the signal that corresponds to a given Network name. * This method overrides the m,ethod from Analysis class. * It doesn't use signalNames hash map. * @param netName the Network name to find. * @return the Signal that corresponds with the Network. * Returns null if none can be found. */ @Override public AnalogSignal findSignalForNetworkQuickly(String netName) { AnalogSignal old = super.findSignalForNetworkQuickly(netName); String lookupName = TextUtils.canonicString(netName); int index = searchName(lookupName); if (index < 0) { assert old == null; return null; } AnalogSignal sig = signalsUnmodifiable.get(index); return sig; } /** * Public method to build tree of EpicTreeNodes. * Root of the tree us EpicRootTreeNode objects. * Deeper nodes are EpicTreeNode objects. * @param analysis name of root DefaultMutableTreeNode. * @return root EpicRootTreeNode of the tree. */ public DefaultMutableTreeNode getSignalsForExplorer(String analysis) { DefaultMutableTreeNode signalsExplorerTree = new EpicRootTreeNode(this, analysis); return signalsExplorerTree; } /** * Returns EpicSignal by its TreePath. * @param treePath specified TreePath. * @return EpicSignal or null. */ public static EpicSignal getSignal(TreePath treePath) { Object[] path = treePath.getPath(); int i = 0; while (i < path.length && !(path[i] instanceof EpicRootTreeNode)) i++; if (i >= path.length) return null; EpicAnalysis an = ((EpicRootTreeNode)path[i]).an; i++; int index = 0; for (; i < path.length; i++) { EpicTreeNode tn = (EpicTreeNode)path[i]; index += tn.nodeOffset; if (tn.isLeaf()) return (EpicSignal)an.signalsUnmodifiable.get(index); } return null; } /** * Method to get the list of signals in this Simulation Data object. * List is unmodifieable. * @return a List of signals. */ @Override public List<AnalogSignal> getSignals() { return signalsUnmodifiable; } /** * This methods overrides Analysis.nameSignal. * It doesn't use Analisys.signalNames to use less memory. */ @Override public void nameSignal(AnalogSignal ws, String sigName) {} /** * Finds signal index of AnalogSignal with given full name. * @param name full name. * @return signal index of AnalogSignal in unmodifiable list of signals or -1. */ int searchName(String name) { Context context = rootContext; for (int pos = 0, index = 0;;) { int indexOfSep = name.indexOf(separator, pos); if (indexOfSep < 0) { EpicTreeNode sig = context.sigs.get(name.substring(pos)); return sig != null ? index + sig.nodeOffset : -1; } EpicTreeNode sub = context.subs.get(name.substring(pos, indexOfSep)); if (sub == null) return -1; context = sub.context; pos = indexOfSep + 1; index += sub.nodeOffset; } } /** * Makes fullName or signalContext of signal with specified index. * @param index signal index. * @param full true to request full name. */ String makeName(int index, boolean full) { StringBuilder sb = new StringBuilder(); Context context = rootContext; if (context == null) return null; if (index < 0 || index >= context.treeSize) throw new IndexOutOfBoundsException(); for (;;) { int localIndex = context.localSearch(index); EpicTreeNode tn = context.nodes[localIndex]; Context subContext = tn.context; if (subContext.isLeaf()) { if (full) sb.append(tn.name); else if (sb.length() == 0) return null; else sb.setLength(sb.length() - 1); return sb.toString(); } sb.append(tn.name); sb.append(separator); index -= tn.nodeOffset; context = subContext; } } /** * Method to get Fake context of AnalogSignal. * @param byte physical type of AnalogSignal. * @return Fake context. */ static Context getContext(byte type) { switch (type) { case VOLTAGE_TYPE: return VOLTAGE_CONTEXT; case CURRENT_TYPE: return CURRENT_CONTEXT; } throw new IllegalArgumentException(); } /** * Method to get Context by list of names and list of contexts. * @param strings list of names. * @param contexts list of contexts. */ Context getContext(ArrayList<String> strings, ArrayList<Context> contexts) { assert strings.size() == contexts.size(); int hashCode = Context.hashValue(strings, contexts); int i = hashCode & 0x7FFFFFFF; i %= contextHash.length; for (int j = 1; contextHash[i] != null; j += 2) { Context c = contextHash[i]; if (c.hashCode == hashCode && c.equals(strings, contexts)) return c; i += j; if (i >= contextHash.length) i -= contextHash.length; } // Need to create new context. if (numContexts*2 <= contextHash.length - 3) { // create a new CellUsage, if enough space in the hash Context c = new Context(strings, contexts, hashCode); contextHash[i] = c; numContexts++; return c; } // enlarge hash if not rehash(); return getContext(strings, contexts); } /** * Rehash the context hash. * @throws IndexOutOfBoundsException on hash overflow. */ private void rehash() { int newSize = numContexts*2 + 3; if (newSize < 0) throw new IndexOutOfBoundsException(); Context[] newHash = new Context[GenMath.primeSince(newSize)]; for (int k = 0; k < contextHash.length; k++) { Context c = contextHash[k]; if (c == null) continue; int i = c.hashCode & 0x7FFFFFFF; i %= newHash.length; for (int j = 1; newHash[i] != null; j += 2) { i += j; if (i >= newHash.length) i -= newHash.length; } newHash[i] = c; } contextHash = newHash; } @Override protected Waveform[] loadWaveforms(AnalogSignal signal) { int index = signal.getIndexInAnalysis(); double valueResolution = getValueResolution(index); int start = waveStarts[index]; int len = waveStarts[index + 1] - start; byte[] packedWaveform = new byte[len]; try { waveFile.seek(start); waveFile.readFully(packedWaveform); } catch (IOException e) { ActivityLogger.logException(e); return new Waveform[] { new WaveformImpl(new double[0], new double[0]) }; } int count = 0; for (int i = 0; i < len; count++) { int l; int b = packedWaveform[i++] & 0xff; if (b < 0xC0) l = 0; else if (b < 0xFF) l = 1; else l = 4; i += l; b = packedWaveform[i++] & 0xff; if (b < 0xC0) l = 0; else if (b < 0xFF) l = 1; else l = 4; i += l; } double[] time = new double[count]; double[] value = new double[count]; count = 0; int t = 0; int v = 0; for (int i = 0; i < len; count++) { int l; int b = packedWaveform[i++] & 0xff; if (b < 0xC0) { l = 0; } else if (b < 0xFF) { l = 1; b -= 0xC0; } else { l = 4; } while (l > 0) { b = (b << 8) | packedWaveform[i++] & 0xff; l--; } t = t + b; time[count] = t * timeResolution; b = packedWaveform[i++] & 0xff; if (b < 0xC0) { l = 0; b -= 0x60; } else if (b < 0xFF) { l = 1; b -= 0xDF; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -