Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Stimuli.java
*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
*
* 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 com.sun.electric.database.geometry.btree.CachingPageStorage;
import com.sun.electric.database.geometry.btree.CachingPageStorageWrapper;
import com.sun.electric.database.geometry.btree.FilePageStorage;
import com.sun.electric.database.geometry.btree.MemoryPageStorage;
import com.sun.electric.database.geometry.btree.OverflowPageStorage;
import com.sun.electric.database.geometry.btree.PageStorage;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.tool.user.waveform.WaveformWindow;
import com.sun.electric.util.TextUtils;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* This class represents a set of simulation *inputs* -- that is,
* "force" and "release" events -- in contrast to Signal, which
* represents simulation *outputs*.
*/
public class Stimuli
{
// logic levels and signal strengths for digital signals
public static final int LOGIC = 03;
public static final int LOGIC_LOW = 0;
public static final int LOGIC_X = 1;
public static final int LOGIC_HIGH = 2;
public static final int LOGIC_Z = 3;
public static final int STRENGTH = 014;
public static final int OFF_STRENGTH = 0;
public static final int NODE_STRENGTH = 04;
public static final int GATE_STRENGTH = 010;
public static final int VDD_STRENGTH = 014;
/** the WaveformWindow associated with this Stimuli */ private WaveformWindow ww;
/** the simulation engine associated with this Stimuli */ private Engine engine;
/** the cell attached to this Stimuli information */ private Cell cell;
/** the disk file associated with this Stimuli */ private URL fileURL;
/** the separator character that breaks names */ private char separatorChar;
/** the SignalCollections in this Stimuli */ private Map scMap;
/** the list of SignalCollections in this Stimuli */ private List scList;
/** control points when signals are selected */ private Map,Double[]> controlPointMap;
/** Cached version of net delimiter */ private String delim;
/** for storing stimuli in a disk cache */ private CachingPageStorage ps;
/**
* Constructor to build a new Simulation Data object.
*/
public Stimuli()
{
separatorChar = '.';
scMap = new HashMap();
scList = new ArrayList();
controlPointMap = new HashMap,Double[]>();
delim = " ";
// build disk cache
try
{
long highWaterMarkInBytes = 50 * 1024 * 1024;
PageStorage fps = FilePageStorage.create();
PageStorage ops = new OverflowPageStorage(new MemoryPageStorage(fps.getPageSize()), fps, highWaterMarkInBytes);
ps = new CachingPageStorageWrapper(ops, 16 * 1024, false);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public CachingPageStorage getPageStorage() { return ps; }
/**
* Free allocated resources before closing.
*/
public void finished()
{
controlPointMap.clear();
scMap.clear();
scList.clear();
ps.close();
ps = null;
ww = null;
}
public void addSignalCollection(SignalCollection an)
{
scMap.put(an.getName(), an);
scList.add(an);
}
/**
* Method to find a SignalCollection with a given name.
* @param title the stimulus name being queried.
* @return the SignalCollection with that name (null if not found).
*/
public SignalCollection findSignalCollection(String title)
{
SignalCollection an = scMap.get(title);
return an;
}
public void setNetDelimiter(String d) { delim = d; }
public String getNetDelimiter() { return delim; }
public Iterator getSignalCollections() { return scList.iterator(); }
/**
* Method to set the Cell associated with this simulation data.
* The associated Cell is the top-level cell in the hierarchy,
* and is usually the Cell that was used to generate the simulation input deck.
* @param cell the Cell associated with this simulation data.
*/
public void setCell(Cell cell) { this.cell = cell; }
/**
* Method to return the Cell associated with this simulation data.
* The associated Cell is the top-level cell in the hierarchy,
* and is usually the Cell that was used to generate the simulation input deck.
* @return the Cell associated with this simulation data.
*/
public Cell getCell() { return cell; }
/**
* Method to set the simulation Engine associated with this simulation data.
* This is only for data associated with built-in simulators (ALS and IRSIM).
* @param engine the simulation Engine associated with this simulation data.
*/
public void setEngine(Engine engine) { this.engine = engine; }
/**
* Method to return the simulation Engine associated with this simulation data.
* This is only for data associated with built-in simulators (ALS and IRSIM).
* @return the simulation Engine associated with this simulation data.
*/
public Engine getEngine() { return engine; }
public void setWaveformWindow(WaveformWindow ww) { this.ww = ww; }
/**
* Method to return the separator character for names in this simulation.
* The separator character separates levels of hierarchy. It is usually a "."
* @return the separator character for names in this simulation.
*/
public char getSeparatorChar() { return separatorChar; }
/**
* Method to set the separator character for names in this simulation.
* The separator character separates levels of hierarchy. It is usually a "."
* @param sep the separator character for names in this simulation.
*/
public void setSeparatorChar(char sep) { separatorChar = sep; }
/**
* Method to set a URL to the file containing this simulation data.
* @param fileURL a URL to the file containing this simulation data.
*/
public void setFileURL(URL fileURL) { this.fileURL = fileURL; }
/**
* Method to return a URL to the file containing this simulation data.
* @return a URL to the file containing this simulation data.
*/
public URL getFileURL() { return fileURL; }
/**
* Method to return the WaveformWindow that displays this simulation data.
* @return the WaveformWindow that displays this simulation data.
*/
public WaveformWindow getWaveformWindow() { return ww; }
/**
* Method to return an array of control points associated with a signal.
* Control points are places where the user has added stimuli to the signal (set a level or strength).
* These points can be selected for change of the stimuli.
* @param sig the signal in question.
* @return an array of times where there are control points.
* Null if no control points are defined.
*/
public Double [] getControlPoints(Signal> sig) { return controlPointMap.get(sig); }
/**
* Method to clear the list of control points associated with a signal.
* Control points are places where the user has added stimuli to the signal (set a level or strength).
* These points can be selected for change of the stimuli.
* @param sig the signal to clear.
*/
public void clearControlPoints(Signal> sig) { controlPointMap.remove(sig); }
/**
* Method to add a new control point to the list on a signal.
* Control points are places where the user has added stimuli to the signal (set a level or strength).
* These points can be selected for change of the stimuli.
* @param sig the signal in question.
* @param time the time of the new control point.
*/
public void addControlPoint(Signal> sig, double time)
{
Double [] controlPoints = controlPointMap.get(sig);
if (controlPoints == null)
{
controlPoints = new Double[1];
controlPoints[0] = new Double(time);
controlPointMap.put(sig, controlPoints);
} else
{
// see if it is in the list already
for(int i=0; i sig, double time)
{
Double [] controlPoints = controlPointMap.get(sig);
if (controlPoints == null) return;
// see if it is in the list already
boolean found = false;
for(int i=0; i sig : sc.getSignals())
{
if (leftEdge == rightEdge)
{
leftEdge = sig.getMinTime();
rightEdge = sig.getMaxTime();
} else
{
if (leftEdge < rightEdge)
{
leftEdge = Math.min(leftEdge, sig.getMinTime());
rightEdge = Math.max(rightEdge, sig.getMaxTime());
} else
{
leftEdge = Math.max(leftEdge, sig.getMinTime());
rightEdge = Math.min(rightEdge, sig.getMaxTime());
}
}
}
}
return leftEdge;
}
/**
* Method to return the rightmost X coordinate of this Stimuli.
* This value may not be the same as the maximum-x of the bounds, because
* the data may not be monotonically increasing (may run backwards, for example).
* @return the rightmost X coordinate of this Stimuli.
*/
public double getMaxTime()
{
double leftEdge = 0, rightEdge = 0;
for(SignalCollection sc : scList)
{
for (Signal> sig : sc.getSignals())
{
if (leftEdge == rightEdge)
{
leftEdge = sig.getMinTime();
rightEdge = sig.getMaxTime();
} else
{
if (leftEdge < rightEdge)
{
leftEdge = Math.min(leftEdge, sig.getMinTime());
rightEdge = Math.max(rightEdge, sig.getMaxTime());
} else
{
leftEdge = Math.max(leftEdge, sig.getMinTime());
rightEdge = Math.min(rightEdge, sig.getMaxTime());
}
}
}
}
if (engine != null)
{
double minRange = engine.getMinTimeRange();
if (rightEdge - leftEdge < minRange) rightEdge = leftEdge + minRange;
}
return rightEdge;
}
/**
* Method to tell whether this simulation data is analog or digital.
* @return true if this simulation data is analog.
*/
public boolean isAnalog()
{
for(SignalCollection sc : scList)
{
for (Signal> sig : sc.getSignals())
{
if (!sig.isDigital()) return true;
}
}
return false;
}
/**
* Method to convert a strength to an index value.
* The strengths are OFF_STRENGTH, NODE_STRENGTH, GATE_STRENGTH, and VDD_STRENGTH.
* The indices are integers that can be saved to disk.
* @param strength strength level.
* @return the index for that strength (0-based).
*/
public static int strengthToIndex(int strength) { return strength / 4; }
/**
* Method to convert a strength index to a strength value.
* The strengths are OFF_STRENGTH, NODE_STRENGTH, GATE_STRENGTH, and VDD_STRENGTH.
* The indices of the strengths are integers that can be saved to disk.
* @param index a strength index (0-based).
* @return the equivalent strength.
*/
public static int indexToStrength(int index) { return index * 4; }
/**
* Method to describe the level in a given state.
* A 'state' is a combination of a level and a strength.
* The levels are LOGIC_LOW, LOGIC_HIGH, LOGIC_X, and LOGIC_Z.
* @param state the given state.
* @return a description of the logic level in that state.
*/
public static String describeLevel(int state)
{
switch (state&Stimuli.LOGIC)
{
case Stimuli.LOGIC_LOW: return "low";
case Stimuli.LOGIC_HIGH: return "high";
case Stimuli.LOGIC_X: return "undefined";
case Stimuli.LOGIC_Z: return "floating";
}
return "?";
}
/**
* Method to describe the level in a given state, with only 1 character.
* A 'state' is a combination of a level and a strength.
* The levels are LOGIC_LOW, LOGIC_HIGH, LOGIC_X, and LOGIC_Z.
* @param state the given state.
* @return a description of the logic level in that state.
*/
public static String describeLevelBriefly(int state)
{
switch (state&Stimuli.LOGIC)
{
case Stimuli.LOGIC_LOW: return "L";
case Stimuli.LOGIC_HIGH: return "H";
case Stimuli.LOGIC_X: return "X";
case Stimuli.LOGIC_Z: return "Z";
}
return "?";
}
/**
* Method to convert a state representation (L, H, X, Z) to a state
* @param s1 character string that contains state value.
* @return the state value.
*/
public static int parseLevel(String s1)
{
if (s1.length() > 0)
{
switch (s1.charAt(0))
{
case 'L': case 'l': return Stimuli.LOGIC_LOW;
case 'X': case 'x': return Stimuli.LOGIC_X;
case 'H': case 'h': return Stimuli.LOGIC_HIGH;
case 'Z': case 'z': return Stimuli.LOGIC_Z;
}
}
return Stimuli.LOGIC_X;
}
/**
* Method to describe the strength in a given state.
* A 'state' is a combination of a level and a strength.
* The strengths are OFF_STRENGTH, NODE_STRENGTH, GATE_STRENGTH, and VDD_STRENGTH.
* @param strength the given strength.
* @return a description of the strength in that state.
*/
public static String describeStrength(int strength)
{
switch (strength&Stimuli.STRENGTH)
{
case Stimuli.OFF_STRENGTH: return "off";
case Stimuli.NODE_STRENGTH: return "node";
case Stimuli.GATE_STRENGTH: return "gate";
case Stimuli.VDD_STRENGTH: return "power";
}
return "?";
}
public static SignalCollection newSignalCollection(Stimuli sd, final String title)
{
SignalCollection sc = new SignalCollection(title);
sd.addSignalCollection(sc);
return sc;
}
/**
* Method to find busses in a list of signals and create them.
* @param signalList the list of signals.
* @param sc the SignalCollection in which the signals reside.
*/
public void makeBusSignals(List> signalList, SignalCollection sc)
{
if (signalList == null) return;
Collections.sort(signalList, new WaveformWindow.SignalsByName());
List> busSoFar = new ArrayList>();
for(Signal> sig : signalList)
{
String curSignalName = sig.getSignalName();
int squarePos = curSignalName.indexOf('[');
if (squarePos < 0)
{
makeBus(busSoFar, sc);
continue;
}
boolean startNewBus = false;
if (busSoFar.size() > 0)
{
String curBusName = curSignalName.substring(0, squarePos);
int curIndex = TextUtils.atoi(curSignalName.substring(squarePos+1));
String curScope = sig.getSignalContext();
if (curScope == null) curScope = "";
Signal> lastSig = busSoFar.get(busSoFar.size()-1);
String lastSignalName = lastSig.getSignalName();
squarePos = lastSignalName.indexOf('[');
String lastBusName = lastSignalName.substring(0, squarePos);
int lastIndex = TextUtils.atoi(lastSignalName.substring(squarePos+1));
String lastScope = lastSig.getSignalContext();
if (lastScope == null) lastScope = "";
if (!lastBusName.equals(curBusName)) startNewBus = true; else
if (!lastScope.equals(curScope)) startNewBus = true; else
if (lastIndex+1 != curIndex) startNewBus = true;
}
if (startNewBus)
makeBus(busSoFar, sc);
busSoFar.add(sig);
}
makeBus(busSoFar, sc);
}
private void makeBus(List> busSoFar, SignalCollection sc)
{
if (busSoFar.size() == 0) return;
int width = busSoFar.size();
Signal[] subsigs = new Signal[width];
for(int i=0; i)busSoFar.get(i);
// get first index
String firstEntryName = subsigs[0].getSignalName();
int firstSquarePos = firstEntryName.indexOf('[');
int firstIndex = TextUtils.atoi(firstEntryName.substring(firstSquarePos+1));
// get last index
String lastEntryName = subsigs[width-1].getSignalName();
int lastSquarePos = lastEntryName.indexOf('[');
int lastIndex = TextUtils.atoi(lastEntryName.substring(lastSquarePos+1));
// make the bus
String busName = firstEntryName.substring(0, firstSquarePos) + "[" + firstIndex + ":" + lastIndex + "]";
String scope = subsigs[0].getSignalContext();
BusSample.createSignal(sc, this, busName, scope, true, subsigs);
// reset the list
busSoFar.clear();
}
}