├── ant.manifest ├── jsim.manifest ├── tmsim.manifest ├── batchsim.manifest ├── bsim.manifest ├── .gitignore ├── icons ├── ant.gif ├── brun.gif ├── bsim.gif ├── copy.gif ├── cut.gif ├── exit.gif ├── icon.gif ├── jade.gif ├── jsim.gif ├── line.gif ├── new.gif ├── open.gif ├── oval.gif ├── rect.gif ├── redo.gif ├── save.gif ├── stop.gif ├── text.gif ├── undo.gif ├── wire.gif ├── zoom.gif ├── a2file.gif ├── breset.gif ├── bstep.gif ├── bstop.gif ├── cache.gif ├── chan1.gif ├── chan16.gif ├── chan2.gif ├── chan4.gif ├── chan8.gif ├── close.gif ├── display.gif ├── fastsim.gif ├── flatten.gif ├── fliph.gif ├── flipv.gif ├── gatesim.gif ├── label.gif ├── paste.gif ├── print.gif ├── reload.gif ├── rotccw.gif ├── rotcw.gif ├── rrect.gif ├── saveall.gif ├── saveas.gif ├── select.gif ├── stamp.gif ├── submit.gif ├── window.gif ├── zoomin.gif ├── zoomout.gif ├── assemble.gif ├── simulate.gif ├── terminal.gif └── timinganalysis.gif ├── README.md ├── simulation ├── SpiceIndependentSource.java ├── TCDComparator.java ├── TPDComparator.java ├── SpiceNode.java ├── SpiceDependentSource.java ├── SpiceCell.java ├── SpiceVCCS.java ├── SpiceResistor.java ├── SpiceCCCS.java ├── SpiceVCVS.java ├── EmuDevice.java ├── EmuCapacitor.java ├── HistoryRequest.java ├── SpiceCCVS.java ├── SpiceInductor.java ├── EmuResistor.java ├── SpiceSFFMSource.java ├── SimEvent.java ├── SpiceIndependentCurrentSource.java ├── SpiceCapacitor.java ├── SpiceIndependentVoltageSource.java ├── SpiceAMSource.java ├── Node.java ├── SpiceSinSource.java ├── SpiceStateDevice.java ├── SimSource.java ├── EmuMeter.java ├── SpiceExpSource.java ├── SpiceMOSModel_L1.java ├── SpiceDevice.java ├── SpiceSource.java ├── TimingInfo.java ├── EmuMosfet.java ├── Event.java ├── SimDevice.java ├── SpiceModel.java ├── SpicePWLSource.java ├── SpiceMosfetDiode.java ├── EmuMOSModel.java ├── SimDReg.java ├── SimDLatch.java ├── SimLogicDevice.java ├── EmuRegion.java ├── SpicePulseSource.java ├── SimLookupTable.java └── EmuNode.java ├── gui ├── ProgressTracker.java ├── GuiObservable.java ├── EditPanel.java ├── UndoList.java ├── POSTStream.java ├── GuiDialog.java ├── EditCanvas.java └── EditFrame.java ├── netlist ├── DevicePrototype.java ├── SubcircuitObject.java ├── Node.java ├── Token.java ├── CapacitorPrototype.java ├── InductorPrototype.java ├── PlotRequest.java ├── ResistorPrototype.java ├── Model.java ├── Analysis.java ├── Parameter.java ├── DependentSourcePrototype.java ├── NetlistConsumer.java ├── Identifier.java ├── MosfetPrototype.java ├── SubcircuitCall.java ├── Number.java ├── IndependentSourcePrototype.java └── Subcircuit.java ├── plot ├── PlotCoordinate.java ├── AnalogPlotCoordinate.java ├── PlotData.java └── DigitalPlotCoordinate.java ├── tmsim ├── TMAction.java └── TMSim.java ├── ant5 ├── bsim ├── Symbol.java └── Macro.java ├── fsm ├── ElevatorDiagram.java ├── Elevator.java ├── Lemming.java └── FSM.java └── jsim ├── BatchSimNetlistConsumer.java └── BatchSim.java /ant.manifest: -------------------------------------------------------------------------------- 1 | Main-Class: fsm.Ant 2 | -------------------------------------------------------------------------------- /jsim.manifest: -------------------------------------------------------------------------------- 1 | Main-Class: jsim.JSim 2 | -------------------------------------------------------------------------------- /tmsim.manifest: -------------------------------------------------------------------------------- 1 | Main-Class: tmsim.TMSim 2 | -------------------------------------------------------------------------------- /batchsim.manifest: -------------------------------------------------------------------------------- 1 | Main-Class: jsim.BatchSim 2 | -------------------------------------------------------------------------------- /bsim.manifest: -------------------------------------------------------------------------------- 1 | Main-Class: bsim.BSim 2 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *~ 3 | 4 | # Package Files # 5 | *.jar 6 | *.war 7 | *.ear 8 | -------------------------------------------------------------------------------- /icons/ant.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/ant.gif -------------------------------------------------------------------------------- /icons/brun.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/brun.gif -------------------------------------------------------------------------------- /icons/bsim.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/bsim.gif -------------------------------------------------------------------------------- /icons/copy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/copy.gif -------------------------------------------------------------------------------- /icons/cut.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/cut.gif -------------------------------------------------------------------------------- /icons/exit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/exit.gif -------------------------------------------------------------------------------- /icons/icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/icon.gif -------------------------------------------------------------------------------- /icons/jade.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/jade.gif -------------------------------------------------------------------------------- /icons/jsim.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/jsim.gif -------------------------------------------------------------------------------- /icons/line.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/line.gif -------------------------------------------------------------------------------- /icons/new.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/new.gif -------------------------------------------------------------------------------- /icons/open.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/open.gif -------------------------------------------------------------------------------- /icons/oval.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/oval.gif -------------------------------------------------------------------------------- /icons/rect.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/rect.gif -------------------------------------------------------------------------------- /icons/redo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/redo.gif -------------------------------------------------------------------------------- /icons/save.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/save.gif -------------------------------------------------------------------------------- /icons/stop.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/stop.gif -------------------------------------------------------------------------------- /icons/text.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/text.gif -------------------------------------------------------------------------------- /icons/undo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/undo.gif -------------------------------------------------------------------------------- /icons/wire.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/wire.gif -------------------------------------------------------------------------------- /icons/zoom.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/zoom.gif -------------------------------------------------------------------------------- /icons/a2file.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/a2file.gif -------------------------------------------------------------------------------- /icons/breset.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/breset.gif -------------------------------------------------------------------------------- /icons/bstep.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/bstep.gif -------------------------------------------------------------------------------- /icons/bstop.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/bstop.gif -------------------------------------------------------------------------------- /icons/cache.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/cache.gif -------------------------------------------------------------------------------- /icons/chan1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/chan1.gif -------------------------------------------------------------------------------- /icons/chan16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/chan16.gif -------------------------------------------------------------------------------- /icons/chan2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/chan2.gif -------------------------------------------------------------------------------- /icons/chan4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/chan4.gif -------------------------------------------------------------------------------- /icons/chan8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/chan8.gif -------------------------------------------------------------------------------- /icons/close.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/close.gif -------------------------------------------------------------------------------- /icons/display.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/display.gif -------------------------------------------------------------------------------- /icons/fastsim.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/fastsim.gif -------------------------------------------------------------------------------- /icons/flatten.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/flatten.gif -------------------------------------------------------------------------------- /icons/fliph.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/fliph.gif -------------------------------------------------------------------------------- /icons/flipv.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/flipv.gif -------------------------------------------------------------------------------- /icons/gatesim.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/gatesim.gif -------------------------------------------------------------------------------- /icons/label.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/label.gif -------------------------------------------------------------------------------- /icons/paste.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/paste.gif -------------------------------------------------------------------------------- /icons/print.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/print.gif -------------------------------------------------------------------------------- /icons/reload.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/reload.gif -------------------------------------------------------------------------------- /icons/rotccw.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/rotccw.gif -------------------------------------------------------------------------------- /icons/rotcw.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/rotcw.gif -------------------------------------------------------------------------------- /icons/rrect.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/rrect.gif -------------------------------------------------------------------------------- /icons/saveall.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/saveall.gif -------------------------------------------------------------------------------- /icons/saveas.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/saveas.gif -------------------------------------------------------------------------------- /icons/select.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/select.gif -------------------------------------------------------------------------------- /icons/stamp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/stamp.gif -------------------------------------------------------------------------------- /icons/submit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/submit.gif -------------------------------------------------------------------------------- /icons/window.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/window.gif -------------------------------------------------------------------------------- /icons/zoomin.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/zoomin.gif -------------------------------------------------------------------------------- /icons/zoomout.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/zoomout.gif -------------------------------------------------------------------------------- /icons/assemble.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/assemble.gif -------------------------------------------------------------------------------- /icons/simulate.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/simulate.gif -------------------------------------------------------------------------------- /icons/terminal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/terminal.gif -------------------------------------------------------------------------------- /icons/timinganalysis.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terman/6.004_courseware/HEAD/icons/timinganalysis.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 6.004_courseware 2 | ================ 3 | 4 | Courseware used in the 6.004 Labs (jsim, tmsim, bsim) 5 | -------------------------------------------------------------------------------- /simulation/SpiceIndependentSource.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | abstract class SpiceIndependentSource extends SpiceDevice { 6 | SpiceSource source; // source function 7 | } 8 | -------------------------------------------------------------------------------- /gui/ProgressTracker.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package gui; 4 | 5 | public interface ProgressTracker { 6 | boolean ProgressStart(Object owner); 7 | void ProgressReport(Object owner,double progress); 8 | long ProgressStop(Object owner); 9 | } 10 | -------------------------------------------------------------------------------- /netlist/DevicePrototype.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | abstract class DevicePrototype extends SubcircuitObject { 6 | // "netlist" the device to make it part of new network 7 | abstract public boolean Netlist(Netlist network,NetlistConsumer n); 8 | } 9 | -------------------------------------------------------------------------------- /plot/PlotCoordinate.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package plot; 4 | 5 | abstract class PlotCoordinate { 6 | public String toString() { 7 | return "coord["+GetX()+","+GetY()+"]"; 8 | } 9 | 10 | public double GetX() { return Double.NaN; } 11 | public double GetY() { return Double.NaN; } 12 | } 13 | -------------------------------------------------------------------------------- /netlist/SubcircuitObject.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | // superclass for things defined in a subcircuit: nodes, devices, models, 6 | // other subcircuits... 7 | abstract class SubcircuitObject { 8 | Subcircuit parent; // what circuit we belong to 9 | Identifier id; // user's name for this object 10 | } 11 | 12 | -------------------------------------------------------------------------------- /simulation/TCDComparator.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2007 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | public class TCDComparator implements java.util.Comparator { 6 | // sort with min tCDsum first 7 | public int compare(Object o1,Object o2) { 8 | TimingInfo t1 = (TimingInfo)o1; 9 | TimingInfo t2 = (TimingInfo)o2; 10 | return Double.compare(t1.tCDsum,t2.tCDsum); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /simulation/TPDComparator.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2007 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | public class TPDComparator implements java.util.Comparator { 6 | // sort with max tPDsum first 7 | public int compare(Object o1,Object o2) { 8 | TimingInfo t1 = (TimingInfo)o1; 9 | TimingInfo t2 = (TimingInfo)o2; 10 | return -Double.compare(t1.tPDsum,t2.tPDsum); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /plot/AnalogPlotCoordinate.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package plot; 4 | 5 | public class AnalogPlotCoordinate extends PlotCoordinate { 6 | double x,y; // another point in the curve 7 | 8 | public double GetX() { return x; } 9 | public double GetY() { return y; } 10 | 11 | public AnalogPlotCoordinate(double nx,double ny) { 12 | x = nx; 13 | y = ny; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /simulation/SpiceNode.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | public class SpiceNode extends Node { 6 | public int index; // index into solution vector 7 | 8 | public SpiceNode(String name,int index) { 9 | super(name); 10 | this.index = index; 11 | } 12 | 13 | public double GetValue(Network network) { 14 | return ((SpiceNetwork)network).solution[index]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /simulation/SpiceDependentSource.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceDependentSource extends SpiceDevice { 6 | int j1,j2; // control terminals 7 | int k1,k2; // output terminals 8 | double gain; // multiplicative factor 9 | 10 | public SpiceDependentSource(int pos,int neg,int cpos,int cneg,double g) { 11 | j1 = cpos; 12 | j2 = cneg; 13 | k1 = pos; 14 | k2 = neg; 15 | gain = g; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tmsim/TMAction.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2003 Christopher J. Terman - All Rights Reserved. 2 | 3 | package tmsim; 4 | 5 | public class TMAction { 6 | public static int UP = -1; 7 | public static int DOWN = 1; 8 | 9 | public String nextState; 10 | public String writeSymbol; 11 | public int direction; 12 | public int lineNumber; 13 | 14 | public TMAction(String state,String symbol,int dir,int line) { 15 | nextState = state; 16 | writeSymbol = symbol; 17 | direction = dir; 18 | lineNumber = line; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /netlist/Node.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | class Node extends SubcircuitObject { 6 | Object netlisterNode; // used during netlisting 7 | boolean external; // true if node appears on .subckt arg list 8 | 9 | public Node(Subcircuit p,Identifier name) { 10 | // fill in our name, add ourselves to our parent 11 | parent = p; 12 | id = name; 13 | if (p != null) p.nodes.put(id.name,this); 14 | netlisterNode = null; 15 | external = false; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /netlist/Token.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | class Token { 6 | public Netlist netlist; // which netlist 7 | public int start; // index of first char 8 | public int end; // index of last char 9 | 10 | public Token(Netlist netlist,int start,int end) { 11 | this.netlist = netlist; 12 | this.start = start; 13 | this.end = end; 14 | } 15 | 16 | public String toString() { 17 | return ""; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ant5: -------------------------------------------------------------------------------- 1 | ; fsm from lecture 2 | 3 | ; | T T 4 | ;now L R S | next L R F M E 5 | ;------------+----------------- 6 | lost 0 0 - | lost 0 0 1 0 0 7 | lost 1 - - | rotccw 0 0 1 0 0 8 | lost 0 1 - | rotccw 0 0 1 0 0 9 | rotccw 0 0 - | wall1 1 0 0 0 0 10 | rotccw 1 - - | rotccw 1 0 0 0 0 11 | rotccw 0 1 - | rotccw 1 0 0 0 0 12 | wall1 - 0 - | corner 0 1 1 0 0 13 | wall1 - 1 - | wall2 0 1 1 0 0 14 | wall2 1 - - | rotccw 1 0 1 0 0 15 | wall2 0 1 - | wall2 1 0 1 0 0 16 | wall2 0 0 - | wall1 1 0 1 0 0 17 | corner - 0 - | corner 0 1 1 0 0 18 | corner - 1 - | wall2 0 1 1 0 0 19 | 20 | -------------------------------------------------------------------------------- /simulation/SpiceCell.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | // sparse matrix entry 6 | class SpiceCell { 7 | int row,column; 8 | SpiceCell nextRow; 9 | SpiceCell nextColumn; 10 | double gExp; // used to initialize gExp each iteration 11 | double luExp; // value for this iteration 12 | boolean nonzero; // true if this cell is known to be nonzero 13 | 14 | public SpiceCell(int c) { 15 | column = c; 16 | nextRow = null; 17 | nextColumn = null; 18 | gExp = 0.0; 19 | luExp = 0.0; 20 | nonzero = false; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /simulation/SpiceVCCS.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceVCCS extends SpiceDependentSource { 6 | public SpiceVCCS(SpiceNetwork network,int pos,int neg,int cpos,int cneg,double g) { 7 | super(pos,neg,cpos,cneg,g); 8 | 9 | // vccs can be handled completely by updating constants used 10 | // used to initialize admittance matrix on each iteration 11 | network.FindMatrixElement(k1,j1).gExp += g; 12 | network.FindMatrixElement(k1,j2).gExp -= g; 13 | network.FindMatrixElement(k2,j1).gExp += g; 14 | network.FindMatrixElement(k2,j2).gExp -= g; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /gui/GuiObservable.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package gui; 4 | 5 | import java.util.Observable; 6 | 7 | public class GuiObservable extends Observable { 8 | boolean notify = true; 9 | 10 | public GuiObservable() { 11 | super(); 12 | } 13 | 14 | public boolean setNotify(boolean which) { 15 | boolean old = notify; 16 | notify = which; 17 | return old; 18 | } 19 | 20 | public synchronized boolean hasChanged() { 21 | return notify; 22 | } 23 | 24 | public void notifyObservers(Object arg) { 25 | if (notify) { 26 | setChanged(); 27 | super.notifyObservers(arg); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /netlist/CapacitorPrototype.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | class CapacitorPrototype extends DevicePrototype { 6 | Node n1; // two terminal nodes 7 | Node n2; 8 | Number capacitance; 9 | 10 | public CapacitorPrototype(Identifier c_id,Node c_n1,Node c_n2,Number c) { 11 | id = c_id; 12 | n1 = c_n1; 13 | n2 = c_n2; 14 | capacitance = c; 15 | } 16 | 17 | // add device to netlist 18 | public boolean Netlist(Netlist network,NetlistConsumer n) { 19 | n.MakeCapacitor(network.prefix + id.name, 20 | n1.netlisterNode,n2.netlisterNode,capacitance.value); 21 | return true; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /netlist/InductorPrototype.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | class InductorPrototype extends DevicePrototype { 6 | Node n1; // two terminal nodes 7 | Node n2; 8 | Number inductance; 9 | 10 | public InductorPrototype(Identifier i_id,Node i_n1,Node i_n2,Number i) { 11 | id = i_id; 12 | n1 = i_n1; 13 | n2 = i_n2; 14 | inductance = i; 15 | } 16 | 17 | // add device to netlist 18 | public boolean Netlist(Netlist network,NetlistConsumer n) { 19 | n.MakeInductor(network.prefix + id.name, 20 | n1.netlisterNode,n2.netlisterNode,inductance.value); 21 | return true; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /netlist/PlotRequest.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | // plot requests are accumulated in a vector which in turn is added to 6 | // the plots vector of the appropriate Analysis 7 | public class PlotRequest { 8 | public Identifier property; // V, I, ... 9 | public Identifier element; // node or element name 10 | 11 | public PlotRequest(Identifier prop,Identifier elem) { 12 | property = prop; 13 | element = elem; 14 | } 15 | 16 | public String Property() { 17 | return property.name.toLowerCase(); 18 | } 19 | 20 | public String Element() { 21 | return element.name; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /netlist/ResistorPrototype.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | class ResistorPrototype extends DevicePrototype { 6 | Node n1; // two terminal nodes 7 | Node n2; 8 | Number resistance; 9 | 10 | public ResistorPrototype(Identifier r_id,Node r_n1,Node r_n2,Number r) { 11 | id = r_id; 12 | n1 = r_n1; 13 | n2 = r_n2; 14 | resistance = r; 15 | } 16 | 17 | // add device to netlist 18 | public boolean Netlist(Netlist network,NetlistConsumer n) { 19 | n.MakeResistor(network.prefix + id.name, 20 | n1.netlisterNode,n2.netlisterNode,resistance.value); 21 | return true; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /simulation/SpiceResistor.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceResistor extends SpiceDevice { 6 | int npos,nneg; // just in case we might need them 7 | double conductance; 8 | 9 | public SpiceResistor(SpiceNetwork network,int n1,int n2,double y) { 10 | npos = n1; 11 | nneg = n2; 12 | conductance = y; 13 | 14 | // resistor can be handled completely by updating constant used 15 | // used to initialize admittance matrix on each iteration 16 | network.FindMatrixElement(n1,n1).gExp += y; 17 | network.FindMatrixElement(n1,n2).gExp -= y; 18 | network.FindMatrixElement(n2,n1).gExp -= y; 19 | network.FindMatrixElement(n2,n2).gExp += y; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /simulation/SpiceCCCS.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceCCCS extends SpiceDependentSource { 6 | public SpiceCCCS(SpiceNetwork network,int pos,int neg,int cpos,int cneg,double g) { 7 | super(pos,neg,cpos,cneg,g); 8 | 9 | int branch = network.size++; 10 | 11 | // cccs can be handled completely by updating constants used 12 | // used to initialize admittance matrix on each iteration 13 | network.FindMatrixElement(j1,branch).gExp = 1; 14 | network.FindMatrixElement(j2,branch).gExp = -1; 15 | network.FindMatrixElement(branch,j1).gExp = 1; 16 | network.FindMatrixElement(branch,j2).gExp = -1; 17 | network.FindMatrixElement(k1,branch).gExp = g; 18 | network.FindMatrixElement(k2,branch).gExp = -g; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /simulation/SpiceVCVS.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceVCVS extends SpiceDependentSource { 6 | public SpiceVCVS(SpiceNetwork network,int pos,int neg,int cpos,int cneg,double g) { 7 | super(pos,neg,cpos,cneg,g); 8 | 9 | int branch = network.size++; 10 | 11 | // vcvs can be handled completely by updating constants used 12 | // used to initialize admittance matrix on each iteration 13 | network.FindMatrixElement(k1,branch).gExp = 1; 14 | network.FindMatrixElement(k2,branch).gExp = -1; 15 | network.FindMatrixElement(branch,k1).gExp = 1; 16 | network.FindMatrixElement(branch,k2).gExp = -1; 17 | network.FindMatrixElement(branch,j1).gExp = -g; 18 | network.FindMatrixElement(branch,j2).gExp = g; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /gui/EditPanel.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2002 Christopher J. Terman - All Rights Reserved. 2 | 3 | package gui; 4 | 5 | import java.awt.BorderLayout; 6 | import java.awt.event.ActionEvent; 7 | import java.awt.event.ActionListener; 8 | import java.util.Observer; 9 | import javax.swing.JPanel; 10 | 11 | public class EditPanel extends JPanel implements ActionListener { 12 | public GuiFrame parent; 13 | public GuiObservable observers; // who's watching us 14 | 15 | public EditPanel(GuiFrame parent) { 16 | super(); 17 | setLayout(new BorderLayout()); 18 | this.parent = parent; 19 | observers = new GuiObservable(); 20 | } 21 | 22 | public void actionPerformed(ActionEvent event) { 23 | } 24 | 25 | public void Kill() { 26 | } 27 | 28 | public void Message(String message) { 29 | parent.Message(message); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /simulation/EmuDevice.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | abstract class EmuDevice { 6 | EmuRegion region; // region we belong to 7 | EmuDevice regionLink; // next device in region's device list 8 | 9 | public EmuDevice() { 10 | region = null; 11 | } 12 | 13 | public void Print() { } 14 | public void Finalize() { } 15 | public void Reset() { } 16 | public double Incremental(EmuNode n,double timestep) { return 0; } 17 | public double Update(double time) { return EmuRegion.NO_EVENT; } 18 | public boolean Conducting() { return false; } 19 | public double PowerPaths() { return 0; } 20 | 21 | public void AddToRegion(EmuRegion r,EmuNode n) { 22 | if (region == null) { 23 | region = r; 24 | r.AddDevice(this,n); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /simulation/EmuCapacitor.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class EmuCapacitor extends EmuDevice { 6 | EmuNode n1; 7 | EmuNode n2; 8 | double capacitance; 9 | 10 | public EmuCapacitor(EmuNode n1,EmuNode n2,double capacitance) { 11 | super(); 12 | 13 | this.n1 = n1; 14 | this.n2 = n2; 15 | this.capacitance = capacitance; 16 | n1.AddDevice(this); 17 | n2.AddDevice(this); 18 | } 19 | 20 | public void RemoveDevice() { 21 | n1.RemoveDevice(this); 22 | n2.RemoveDevice(this); 23 | } 24 | 25 | public double Incremental(EmuNode n,double timestep) { 26 | if (timestep <= 0) return 0; 27 | else return (capacitance/timestep)*((n == n1) ? n2.deltaV : n1.deltaV); 28 | } 29 | 30 | public void AddToRegion(EmuRegion r,EmuNode n) { 31 | super.AddToRegion(r,(n == n1) ? n2 : n1); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /simulation/HistoryRequest.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class HistoryRequest { 6 | HistoryRequest next; 7 | int index; 8 | int bit; 9 | double tlast; 10 | double vlast; 11 | int lv1; 12 | int lv2; 13 | boolean firstTime; 14 | 15 | HistoryRequest(int bit,int index) { 16 | this.index = index; 17 | this.bit = bit; 18 | tlast = 0; 19 | vlast = 0; 20 | lv1 = 0; 21 | lv2 = 0; 22 | firstTime = true; 23 | } 24 | 25 | static HistoryRequest Insert(HistoryRequest list,HistoryRequest request) { 26 | HistoryRequest last = null; 27 | HistoryRequest r; 28 | for (r = list; r != null; last = r, r = r.next) 29 | if (request.index >= r.index) break; 30 | if (last == null) list = request; 31 | else last.next = request; 32 | request.next = r; 33 | return list; 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /simulation/SpiceCCVS.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceCCVS extends SpiceDependentSource { 6 | public SpiceCCVS(SpiceNetwork network,int pos,int neg,int cpos,int cneg,double g) { 7 | super(pos,neg,cpos,cneg,g); 8 | 9 | int b1 = network.size++; 10 | int b2 = network.size++; 11 | 12 | // ccvs can be handled completely by updating constants used 13 | // used to initialize admittance matrix on each iteration 14 | network.FindMatrixElement(j1,b1).gExp = 1; 15 | network.FindMatrixElement(j2,b1).gExp = -1; 16 | network.FindMatrixElement(b1,j1).gExp = 1; 17 | network.FindMatrixElement(b1,j2).gExp = -1; 18 | 19 | network.FindMatrixElement(k1,b2).gExp = 1; 20 | network.FindMatrixElement(k2,b2).gExp = -1; 21 | network.FindMatrixElement(b2,k1).gExp = 1; 22 | network.FindMatrixElement(b2,k2).gExp = -1; 23 | 24 | network.FindMatrixElement(b2,b1).gExp = -g; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /netlist/Model.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2001 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | import java.util.HashMap; 6 | 7 | class Model extends SubcircuitObject { 8 | public Object netlisterModel; // used during netlisting 9 | public int type; // what kind of model we are 10 | public HashMap options; // values for model options 11 | 12 | public Model(Subcircuit p,Identifier name,int t) { 13 | // fill in our name, add ourselves to our parent 14 | parent = p; 15 | id = name; 16 | if (p != null) p.models.put(id.name,this); 17 | type = t; 18 | options = new HashMap(); 19 | } 20 | 21 | public boolean Netlist(Netlist network,NetlistConsumer nc) { 22 | netlisterModel = nc.MakeModel(network.prefix+id.name,type,options); 23 | return true; 24 | } 25 | 26 | // convert string into appropriate model type 27 | static int ModelType(String name) { 28 | if (name.equalsIgnoreCase("nmos")) return NetlistConsumer.NMOS; 29 | else if (name.equalsIgnoreCase("pmos")) return NetlistConsumer.PMOS; 30 | else return 0; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /simulation/SpiceInductor.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceInductor extends SpiceStateDevice { 6 | int i,j; // two terminal nodes 7 | SpiceCell sourceCell; // our entry in the source vector 8 | int k; // matrix row for branch current 9 | SpiceCell kk; // where we'll put Req. 10 | 11 | public SpiceInductor(SpiceNetwork net,int n1,int n2,double l) { 12 | super(net,l,true); 13 | i = n1; 14 | j = n2; 15 | 16 | k = network.size++; 17 | network.FindMatrixElement(i,k).gExp = 1; 18 | network.FindMatrixElement(j,k).gExp = -1; 19 | network.FindMatrixElement(k,i).gExp = 1; 20 | network.FindMatrixElement(k,j).gExp = -1; 21 | sourceCell = network.FindSourceElement(k); 22 | kk = network.FindMatrixElement(k,k); 23 | } 24 | 25 | public boolean EachIteration(int mode,double time,double timestep) { 26 | x = value * network.solution[k]; // set flux 27 | 28 | if (mode == SpiceNetwork.TRANSIENT_ANALYSIS) { 29 | Integrate(); 30 | kk.luExp = -geq; 31 | sourceCell.luExp = xprimeEQ; 32 | } 33 | 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /simulation/EmuResistor.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class EmuResistor extends EmuDevice { 6 | EmuNode n1; 7 | EmuNode n2; 8 | double conductance; 9 | double previousI; 10 | 11 | public EmuResistor(EmuNode n1,EmuNode n2,double conductance) { 12 | super(); 13 | this.n1 = n1; 14 | this.n2 = n2; 15 | this.conductance = conductance; 16 | n1.AddDevice(this); 17 | n2.AddDevice(this); 18 | } 19 | 20 | public void Reset() { 21 | previousI = 0; 22 | } 23 | 24 | public double Incremental(EmuNode n,double timestep) { 25 | return conductance*((n == n1) ? n2.deltaV : n1.deltaV); 26 | } 27 | 28 | public double Update(double time) { 29 | double i = conductance*(n1.voltage - n2.voltage); 30 | double deltaI = i - previousI; 31 | previousI = i; 32 | n1.totalTransconductance += conductance; 33 | n2.totalTransconductance += conductance; 34 | n1.totalCurrent -= deltaI; 35 | n2.totalCurrent += deltaI; 36 | 37 | return EmuRegion.NO_EVENT; 38 | } 39 | 40 | public void AddToRegion(EmuRegion r,EmuNode n) { 41 | super.AddToRegion(r,(n == n1) ? n2 : n1); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /simulation/SpiceSFFMSource.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | // single-frequency FM source function 6 | class SpiceSFFMSource extends SpiceSource { 7 | double offset; // offset 8 | double amplitude; // amplitude 9 | double fcarrier; // carrier frequency 10 | double mindex; // modulation index 11 | double fsignal; // signal frequency 12 | 13 | public SpiceSFFMSource(double xdc,double xacmag,double xacphase,double params[],double vil,double vih) { 14 | super(xdc,xacmag,xacphase); 15 | 16 | offset = (params == null || params.length < 1) ? 0 : params[0]; 17 | amplitude = (params == null || params.length < 2) ? 0 : params[1]; 18 | fcarrier = (params == null || params.length < 3) ? 0 : params[2]; 19 | mindex = (params == null || params.length < 4) ? 0 : params[3]; 20 | fsignal = (params == null || params.length < 5) ? 0 : params[4]; 21 | 22 | fcarrier *= 2*Math.PI; 23 | fsignal *= 2*Math.PI; 24 | } 25 | 26 | public String SourceName() { return "SFFM"; } 27 | 28 | public double TransientValue(double time) { 29 | return offset + amplitude*Math.sin(fcarrier*time + mindex*Math.sin(fsignal*time)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /simulation/SimEvent.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | public class SimEvent extends Event { 6 | static public final int CONTAMINATION = 0; // contamination event 7 | static public final int PROPAGATION = 1; // propagation event 8 | 9 | int type; // type of event 10 | SimNode node; // node 11 | int v; // new value 12 | 13 | public SimEvent(int type,SimNode node,int v) { 14 | super(); 15 | Initialize(type,node,v); 16 | } 17 | 18 | public boolean Before(Event other) { 19 | // keep contamination events sorted before propagation events 20 | if (etime == other.etime) 21 | return type == CONTAMINATION && 22 | ((SimEvent)other).type != CONTAMINATION; 23 | else return etime < other.etime; 24 | } 25 | 26 | public String toString() { 27 | if (node == null) return "SimEvent["+hashCode()+"]"; 28 | else return ((type == CONTAMINATION) ? "Contam[" : "Prop[") + 29 | node.name + "->" + SimNode.VALUES.charAt(v) + 30 | "@" + etime + "]"; 31 | } 32 | 33 | public void Initialize(int type,SimNode node,int v) { 34 | etime = NO_EVENT; 35 | this.type = type; 36 | this.node = node; 37 | this.v = v; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /simulation/SpiceIndependentCurrentSource.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceIndependentCurrentSource extends SpiceIndependentSource { 6 | SpiceCell spos,sneg; // our entries in the source vector 7 | 8 | public SpiceIndependentCurrentSource(SpiceNetwork network,int npos,int nneg, 9 | double dc,double acmag,double acphase, 10 | int trantype,double params[], 11 | double vil,double vih) { 12 | spos = network.FindSourceElement(npos); 13 | sneg = network.FindSourceElement(nneg); 14 | source = SpiceSource.Allocate(dc,acmag,acphase,trantype,params,vil,vih); 15 | 16 | // we need to set up sourceCell each iteration 17 | iterationLink = network.eachIteration; 18 | network.eachIteration = this; 19 | } 20 | 21 | public void ComputeBreakpoints(SpiceNetwork network,double stopTime) { 22 | source.ComputeBreakpoints(network,stopTime); 23 | } 24 | 25 | public boolean EachIteration(int mode,double time,double timestep) { 26 | double i; 27 | 28 | if (mode == SpiceNetwork.OPERATING_POINT) i = source.dc; 29 | else i = source.TransientValue(time); 30 | spos.luExp -= i; 31 | sneg.luExp += i; 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /simulation/SpiceCapacitor.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceCapacitor extends SpiceStateDevice { 6 | int i,j; // two terminal nodes 7 | 8 | // capacitor is modelled as a current source in parallel with an resistor 9 | SpiceCell sourceI,sourceJ; // elements from source vector 10 | SpiceCell ii,ij,ji,jj; // elements from admittance matrix 11 | 12 | public SpiceCapacitor(SpiceNetwork net,int n1,int n2,double c) { 13 | super(net,c,true); 14 | i = n1; 15 | j = n2; 16 | 17 | sourceI = network.FindSourceElement(n1); 18 | sourceJ = network.FindSourceElement(n2); 19 | ii = network.FindMatrixElement(n1,n1); 20 | ij = network.FindMatrixElement(n1,n2); 21 | ji = network.FindMatrixElement(n2,n1); 22 | jj = network.FindMatrixElement(n2,n2); 23 | } 24 | 25 | public boolean EachIteration(int mode,double time,double timestep) { 26 | double vcap = ((i < 0) ? 0 : network.solution[i]) - 27 | ((j < 0) ? 0 : network.solution[j]); 28 | 29 | x = value * vcap; // set charge 30 | 31 | if (mode == SpiceNetwork.TRANSIENT_ANALYSIS) { 32 | Integrate(); 33 | 34 | sourceI.luExp -= xprimeEQ; 35 | sourceJ.luExp += xprimeEQ; 36 | ii.luExp += geq; 37 | ij.luExp -= geq; 38 | ji.luExp -= geq; 39 | jj.luExp += geq; 40 | } 41 | 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /simulation/SpiceIndependentVoltageSource.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceIndependentVoltageSource extends SpiceIndependentSource { 6 | SpiceCell sourceCell; // our entry in the source vector 7 | 8 | public SpiceIndependentVoltageSource(SpiceNetwork network,int npos,int nneg, 9 | double dc,double acmag,double acphase, 10 | int trantype,double params[], 11 | double vil,double vih) { 12 | int branch = network.size++; 13 | network.FindMatrixElement(npos,branch).gExp = 1; 14 | network.FindMatrixElement(nneg,branch).gExp = -1; 15 | network.FindMatrixElement(branch,npos).gExp = 1; 16 | network.FindMatrixElement(branch,nneg).gExp = -1; 17 | sourceCell = network.FindSourceElement(branch); 18 | source = SpiceSource.Allocate(dc,acmag,acphase,trantype,params,vil,vih); 19 | 20 | // we need to set up sourceCell each iteration 21 | iterationLink = network.eachIteration; 22 | network.eachIteration = this; 23 | } 24 | 25 | public void ComputeBreakpoints(SpiceNetwork network,double stopTime) { 26 | source.ComputeBreakpoints(network,stopTime); 27 | } 28 | 29 | public boolean EachIteration(int mode,double time,double timestep) { 30 | if (mode == SpiceNetwork.OPERATING_POINT) sourceCell.luExp = source.dc; 31 | else sourceCell.luExp = source.TransientValue(time); 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /gui/UndoList.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2002 Christopher J. Terman - All Rights Reserved. 2 | 3 | package gui; 4 | 5 | import java.util.Vector; 6 | 7 | public class UndoList { 8 | public String name; 9 | public Vector list; 10 | UndoList nextLink; 11 | UndoList prevLink; 12 | 13 | public UndoList(String name,Vector list,UndoList prev) { 14 | this.name = name; 15 | this.list = list; 16 | if (prev != null) { 17 | prevLink = prev; 18 | prev.nextLink = this; 19 | } 20 | } 21 | 22 | public final UndoList next() { 23 | return nextLink; 24 | } 25 | 26 | public final UndoList prev() { 27 | return prevLink; 28 | } 29 | 30 | public final void ignoreNext() { 31 | if (nextLink != null) 32 | nextLink = nextLink.next(); 33 | } 34 | 35 | public final void ignorePrev() { 36 | if (prevLink != null) 37 | prevLink = prevLink.prev(); 38 | } 39 | 40 | public final void unlink() { 41 | if (prevLink != null) 42 | prevLink.ignoreNext(); 43 | if (nextLink != null) 44 | nextLink.ignorePrev(); 45 | } 46 | 47 | public final void insertAfter(UndoList x) { 48 | x.unlink(); 49 | prevLink = this; 50 | x.nextLink = nextLink; 51 | if (nextLink!=null) 52 | nextLink.prevLink = x; 53 | nextLink = x; 54 | } 55 | 56 | public boolean CanUndoRedo(boolean redo) { 57 | UndoList u = (UndoList)(redo ? next() : prev()); 58 | return u != null; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /simulation/SpiceAMSource.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | // amplitude modulation source function 6 | class SpiceAMSource extends SpiceSource { 7 | double amplitude; // amplitude 8 | double fcarrier; // carrier frequency 9 | double fmodulation; // modulation frequency 10 | double offset; // offset constant 11 | double delay; // delay time before start of signal 12 | 13 | public SpiceAMSource(double xdc,double xacmag,double xacphase,double params[],double vil,double vih) { 14 | super(xdc,xacmag,xacphase); 15 | 16 | amplitude = (params == null || params.length < 1) ? 0 : params[0]; 17 | offset = (params == null || params.length < 2) ? 0 : params[1]; 18 | fmodulation = (params == null || params.length < 3) ? 0 : params[2]; 19 | fcarrier = (params == null || params.length < 4) ? 0 : params[3]; 20 | delay = (params == null || params.length < 5) ? 0 : params[4]; 21 | 22 | fcarrier *= 2*Math.PI; 23 | fmodulation *= 2*Math.PI; 24 | } 25 | 26 | public String SourceName() { return "AM"; } 27 | 28 | public double TransientValue(double time) { 29 | if (time <= delay) return 0; 30 | else return amplitude*(offset + Math.sin(fmodulation*(time-delay)))* 31 | Math.sin(fcarrier*(time-delay)); 32 | } 33 | 34 | public void ComputeBreakpoints(SpiceNetwork network,double stopTime) { 35 | network.AddBreakpoint(delay); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /simulation/Node.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | abstract public class Node { 6 | static public final int V0 = 0; // "0" logic low 7 | static public final int V1 = 1; // "1" logic high 8 | static public final int VX = 2; // "X" unknown 9 | static public final int VZ = 3; // "Z" high-impedence 10 | static public final String VALUES = "01XZ"; 11 | 12 | public String name; // name of this node 13 | public boolean history; // true if we're keeping a history 14 | public int hIndex; // index for most recent history record 15 | 16 | public Node(String name) { 17 | this.name = name; 18 | history = true; 19 | hIndex = -1; 20 | } 21 | 22 | abstract public double GetValue(Network network); 23 | 24 | public void setEnabled(boolean which) { 25 | history = which; 26 | } 27 | 28 | public void ResetHistory() { 29 | hIndex = -1; 30 | } 31 | 32 | public void RecordValue(Network network,double time,double v) { 33 | if (history) 34 | hIndex = network.WriteRecord(hIndex,time,(float)v); 35 | } 36 | 37 | public void RecordLogicValue(Network network,double time,int v) { 38 | if (history) { 39 | float value; 40 | if (v == V0) value = 0; 41 | else if (v == V1) value = 1; 42 | else if (v == VZ) value = Float.POSITIVE_INFINITY; 43 | else value = Float.NaN; 44 | hIndex = network.WriteRecord(hIndex,time,value); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /simulation/SpiceSinSource.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | // sin source function 6 | class SpiceSinSource extends SpiceSource { 7 | double offset; // offset 8 | double amplitude; // amplitude 9 | double frequency; // freq in Hz. 10 | double delay; // delay in seconds 11 | double theta; // damping factor in 1/seconds 12 | double phi; // phase delay in degrees 13 | 14 | public SpiceSinSource(double xdc,double xacmag,double xacphase,double params[],double vil,double vih) { 15 | super(xdc,xacmag,xacphase); 16 | 17 | offset = (params == null || params.length < 1) ? 0 : params[0]; 18 | amplitude = (params == null || params.length < 2) ? 0 : params[1]; 19 | frequency = (params == null || params.length < 3) ? 1e6 : params[2]; 20 | delay = (params == null || params.length < 4) ? 0 : params[3]; 21 | theta = (params == null || params.length < 5) ? 0 : params[4]; 22 | phi = (params == null || params.length < 6) ? 0 : Math.PI*params[5]/180.0; 23 | } 24 | 25 | public String SourceName() { return "SIN"; } 26 | 27 | public double TransientValue(double time) { 28 | if (time <= delay) return offset + amplitude*Math.sin(phi); 29 | else return offset + amplitude * Math.exp((delay-time)*theta) * 30 | Math.sin(phi + 2*Math.PI*frequency*(time-delay)); 31 | } 32 | 33 | public void ComputeBreakpoints(SpiceNetwork network,double stopTime) { 34 | network.AddBreakpoint(delay); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /simulation/SpiceStateDevice.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceStateDevice extends SpiceDevice { 6 | SpiceNetwork network; // we'll need some node voltages 7 | double value; // device value 8 | double x; // state variable (charge, flux) 9 | double xprime; // dstate/dt (current, voltage) 10 | double previousX; // x on last iteration 11 | double previousXprime; // xprime on last iteration 12 | double xprimeEQ; // equivalents for current timestep 13 | double geq; 14 | 15 | public SpiceStateDevice(SpiceNetwork net,double v,boolean eachIteration) { 16 | super(); 17 | network = net; 18 | value = v; 19 | x = 0; 20 | xprime = 0; 21 | previousX = 0; 22 | previousXprime = 0; 23 | 24 | // we need to set up source vector and admittance matrix each iteration 25 | if (eachIteration) { 26 | iterationLink = network.eachIteration; 27 | network.eachIteration = this; 28 | } 29 | 30 | // update history at end of timestep 31 | timestepLink = network.endOfTimestep; 32 | network.endOfTimestep = this; 33 | } 34 | 35 | // for backward Euler: coeff0 = 1/timestep, coeff1 = 0 36 | // for trapezoidal: coeff0 = 2/timestep, coeff1 = 1 37 | void Integrate() { 38 | xprime = network.coeff0*(x - previousX) - network.coeff1*previousXprime; 39 | xprimeEQ = xprime - network.coeff0*x; 40 | geq = network.coeff0*value; 41 | } 42 | 43 | public void EndOfTimestep(boolean breakpoint,double timestep) { 44 | previousX = x; 45 | previousXprime = xprime; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /simulation/SimSource.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2007 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | import java.util.ArrayList; 6 | 7 | class SimSource extends SimDevice { 8 | SpiceSource source; 9 | 10 | public SimSource(String name,ArrayList outputs,SpiceSource source) { 11 | super(name,1,1); 12 | this.source = source; 13 | 14 | // make output and input too, so each event triggers the 15 | // scheduling of the next 16 | nodes[0] = (SimNode)outputs.get(0); 17 | nodes[1] = nodes[0]; 18 | SetupNodes(); 19 | 20 | // add device to network 21 | nodes[0].network.AddDevice(this,0.0); 22 | } 23 | 24 | public void Reset() { 25 | EvaluateC(); 26 | int v = nodes[0].network.VtoL(source.TransientValue(0)); 27 | if (v != Node.VX) nodes[1].SchedulePEvent(0,v,0,false); 28 | else EvaluateP(); 29 | } 30 | 31 | public void EvaluateC() { 32 | SimNetwork network = nodes[1].network; 33 | double next = source.NextContaminationTime(network.time); 34 | //System.out.println("cnext="+next+" @ "+network.time); 35 | if (next >= 0) nodes[1].ScheduleCEvent(next - network.time); 36 | } 37 | 38 | public void EvaluateP() { 39 | SimNetwork network = nodes[1].network; 40 | double next = source.NextPropagationTime(network.time); 41 | //System.out.println(name+": pnext="+next+" v="+source.TransientValue(next)+" @ "+network.time); 42 | int v = network.VtoL(source.TransientValue(next)); 43 | if (next >= 0) nodes[1].SchedulePEvent(next - network.time,v,0,false); 44 | } 45 | 46 | // for timing analysis 47 | 48 | public boolean isSource() { return true; } 49 | } 50 | -------------------------------------------------------------------------------- /simulation/EmuMeter.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class EmuMeter { 6 | EmuMeter netLink; // next meter in the network 7 | EmuNode node; // node we're metering 8 | double totalTime; 9 | double vAverage; 10 | double vRMS; 11 | double vPeak; 12 | double vPeakTime; 13 | double iAverage; 14 | double iRMS; 15 | double iPeak; 16 | double iPeakTime; 17 | 18 | public EmuMeter() { 19 | } 20 | 21 | public void Reset() { 22 | totalTime = 0; 23 | vAverage = 0; 24 | vRMS = 0; 25 | vPeakTime = 0; 26 | iAverage = 0; 27 | iRMS = 0; 28 | iPeakTime = 0; 29 | } 30 | 31 | public void ResetState() { 32 | Reset(); 33 | node.Reset(); 34 | } 35 | 36 | static public void UpdateMeters(EmuMeter m,double time,double timestep) { 37 | while (m != null) { 38 | m.Update(time,timestep); 39 | m = m.netLink; 40 | } 41 | } 42 | 43 | public void Update(double time,double timestep) { 44 | double v; 45 | 46 | totalTime += timestep; 47 | 48 | // update average and RMS voltage accumulators 49 | v = node.voltage * timestep; 50 | vAverage += v; 51 | vRMS += node.voltage * v; 52 | 53 | // update peak voltage accumulator 54 | v = Math.abs(node.voltage); 55 | if (vPeakTime < 0 || vPeak < v) { 56 | vPeakTime = time; 57 | vPeak = v; 58 | } 59 | 60 | // update average and RMS current accumulators 61 | v = node.totalCurrent * timestep; 62 | iAverage += v; 63 | iRMS += node.totalCurrent * v; 64 | 65 | // update peak current accumulator 66 | v = Math.abs(node.totalCurrent); 67 | if (iPeakTime < 0 || iPeak < v) { 68 | iPeakTime = time; 69 | iPeak = v; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /netlist/Analysis.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2001 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | import java.util.ArrayList; 6 | 7 | // Each requested analysis is represented by an instance of this class 8 | // and added (in order) to the analyses vector of the current network 9 | public class Analysis { 10 | static public final int OperatingPoint = 1; 11 | static public final int DC = 2; 12 | static public final int Transient = 3; 13 | static public final int AC = 4; 14 | 15 | public int type; // type of analysis 16 | public Identifier command; // used for reporting errors 17 | public ArrayList params; // analysis parameters 18 | public ArrayList plots; // each element is a vector of PlotRequests 19 | 20 | public Analysis(Identifier cmd,int atype) { 21 | command = cmd; 22 | type = atype; 23 | params = new ArrayList(); 24 | plots = new ArrayList(); 25 | } 26 | 27 | // convert string into appropriate analysis type 28 | static int AnalysisType(String name) { 29 | if (name.equalsIgnoreCase("op")) return OperatingPoint; 30 | else if (name.equalsIgnoreCase("dc")) return DC; 31 | else if (name.equalsIgnoreCase("tran")) return Transient; 32 | else if (name.equalsIgnoreCase("ac")) return AC; 33 | else return 0; 34 | } 35 | 36 | // look for most recent analysis of a given type 37 | static Analysis FindAnalysis(Netlist network,String name) { 38 | int atype = AnalysisType(name); 39 | ArrayList analyses = network.analyses; 40 | 41 | // search backwards through analyses vector for type we want 42 | for (int i = analyses.size() - 1; i >= 0; i -= 1) { 43 | Analysis a = (Analysis)analyses.get(i); 44 | if (a.type == atype) return a; 45 | } 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /simulation/SpiceExpSource.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | // exponential source function 6 | class SpiceExpSource extends SpiceSource { 7 | double offset; // offset 8 | double amplitude; // amplitude 9 | double ramplitude; // amplitude at end of rise time 10 | double delay1; // rise delay in seconds 11 | double rtau; // rise time constant 12 | double delay2; // fall delay in seconds 13 | double ftau; // fall time constant 14 | 15 | public SpiceExpSource(double xdc,double xacmag,double xacphase,double params[],double vil,double vih) { 16 | super(xdc,xacmag,xacphase); 17 | 18 | offset = (params == null || params.length < 1) ? 0 : params[0]; 19 | amplitude = (params == null || params.length < 2) ? 0 : params[1]; 20 | delay1 = (params == null || params.length < 3) ? 0 : params[2]; 21 | rtau = (params == null || params.length < 4) ? 1e-9 : params[3]; 22 | delay2 = (params == null || params.length < 5) ? 1e-9 : params[4]; 23 | ftau = (params == null || params.length < 6) ? 1e-9 : params[5]; 24 | 25 | if (delay2 < delay1) delay2 = delay1; 26 | amplitude -= offset; 27 | ramplitude = amplitude * (1-Math.exp((delay1-delay2)/rtau)); 28 | } 29 | 30 | public String SourceName() { return "EXP"; } 31 | 32 | public double TransientValue(double time) { 33 | if (time <= delay1) return offset; 34 | else if (time <= delay2) 35 | return offset + amplitude*(1-Math.exp((delay1-time)/rtau)); 36 | else 37 | return offset + ramplitude*Math.exp((delay2-time)/ftau); 38 | } 39 | 40 | public void ComputeBreakpoints(SpiceNetwork network,double stopTime) { 41 | network.AddBreakpoint(delay1); 42 | network.AddBreakpoint(delay2); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /gui/POSTStream.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2001 Christopher J. Terman - All Rights Reserved. 2 | 3 | package gui; 4 | 5 | import java.io.FilterOutputStream; 6 | import java.io.IOException; 7 | import java.io.OutputStream; 8 | 9 | // recode stream using HTTP POST conventions 10 | public class POSTStream extends FilterOutputStream { 11 | boolean firstTag = true; 12 | 13 | public POSTStream(OutputStream out) { 14 | super(out); 15 | } 16 | 17 | private int HexDigit(int b) { 18 | b &= 0xF; 19 | return (b > 9) ? (b + 'A' - 10) : b + '0'; 20 | } 21 | 22 | public void write(int b) throws IOException { 23 | if (b == ' ') 24 | out.write('+'); 25 | else if ((b >= '0' && b <= '9') || 26 | (b >= 'A' && b <= 'Z') || 27 | (b >= 'a' && b <= 'z')) 28 | out.write(b); 29 | else { 30 | out.write('%'); 31 | out.write(HexDigit(b >> 4)); 32 | out.write(HexDigit(b)); 33 | } 34 | } 35 | 36 | public void write(byte[] buf,int off,int len) throws IOException { 37 | if (off + len > buf.length) len = buf.length - off; 38 | for (int i = 0; i < len; i += 1) write(buf[i + off]); 39 | } 40 | 41 | public void write(byte[] buf) throws IOException { 42 | write(buf,0,buf.length); 43 | } 44 | 45 | public void write(char[] buf) throws IOException { 46 | int l = buf.length; 47 | for (int i = 0; i < l; i += 1) 48 | write(buf[i]); 49 | } 50 | 51 | public void write(String s) throws IOException { 52 | int l = s.length(); 53 | for (int i = 0; i < l; i += 1) 54 | write(s.charAt(i)); 55 | } 56 | 57 | public void writeTag(String tag) throws IOException { 58 | if (firstTag) firstTag = false; 59 | else out.write('&'); 60 | for (int i = 0; i < tag.length(); i += 1) 61 | out.write(tag.charAt(i)); 62 | out.write('='); 63 | out.flush(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /simulation/SpiceMOSModel_L1.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2001 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | import java.util.HashMap; 6 | 7 | class SpiceMOSModel_L1 extends SpiceMOSModel { 8 | double m_lambda; // (1/V = 0.0) channel-length modulatio 9 | 10 | public SpiceMOSModel_L1(String n,int mtype,HashMap xoptions,double temp) { 11 | // process common model parameters 12 | super(n,mtype,1,xoptions,temp); 13 | 14 | // model parameters specific to Level 1 15 | m_lambda = GetOption("lambda",0.0); 16 | } 17 | 18 | public void Setup(SpiceMosfet m,double l,double w) { 19 | super.Setup(m,l,w); 20 | } 21 | 22 | // assumes vds >= 0 23 | public void ids_gds(SpiceMosfet m,double vds,double vgs,double vbs) { 24 | double vdsat,temp1; 25 | 26 | temp1 = (vbs > 0) ? Math.max(0,sqrt_phi - vbs*inv_2_sqrt_phi) : 27 | Math.sqrt(phi - vbs); 28 | // can we do vbi*mtype once during setup? 29 | m.vth = vbi*m_type + m_gamma*temp1; 30 | if (temp1 > 0) temp1 = m_gamma/(2*temp1); 31 | else temp1 = 0; 32 | 33 | vdsat = Math.max(0,vgs - m.vth); 34 | //if (m.debug) System.out.println("vbi="+vbi+" vth="+m.vth+" vdsat="+vdsat); 35 | 36 | if (vdsat > 0) { 37 | double betap = m.beta*(1 + m_lambda*vds); 38 | if (vdsat > vds) { // linear region 39 | double temp = vds*(vdsat - 0.5*vds); 40 | m.ids = betap*temp; 41 | m.gds = betap*(vdsat-vds) + m_lambda*m.beta*temp; 42 | m.gm = betap*vds; 43 | m.gmbs = m.gm*temp1; 44 | } else { // saturation region 45 | double temp = vdsat*vdsat*0.5; 46 | m.ids = betap*temp; 47 | m.gds = m_lambda*m.beta*temp; 48 | m.gm = betap*vdsat; 49 | m.gmbs = m.gm*temp1; 50 | } 51 | } else { // cut-off region 52 | m.ids = 0; 53 | m.gds = 0; 54 | m.gm = 0; 55 | m.gmbs = 0; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /simulation/SpiceDevice.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceDevice { 6 | SpiceDevice iterationLink; // link in eachIteration device list 7 | SpiceDevice timestepLink; // link in endOfTimestep device list 8 | 9 | public SpiceDevice() { 10 | iterationLink = null; 11 | timestepLink = null; 12 | } 13 | 14 | // add any necessary break points 15 | public void ComputeBreakpoints(SpiceNetwork network,double stopTime) { } 16 | 17 | // return true if device has converged, false otherwise 18 | // devices that need to load something new into the admittance 19 | // matrix before each solution should override this method and 20 | // add themselves to the eachIteration list of the network. 21 | // Since that list is used to determine which devices' EachIteration 22 | // method needs to be called this default method should never be 23 | // called. Devices whose contribution to the admittance matrix 24 | // doesn't change iteration-to-iteration just add their contributions 25 | // to the gExp slot of the apropriate cell. 26 | public boolean EachIteration(int mode,double time,double timestep) { 27 | return true; 28 | } 29 | 30 | // some devices need to reset their state if we redo the timestep 31 | public void RestoreState(double time) { } 32 | 33 | // devices that need to set up for the next timestep (eg, capacitors 34 | // and inductors) add themselves to the endOfTimestep list of the 35 | // network. Since that list is used to determine which devices' 36 | // EndOfTimestep method needs to be called this default method should 37 | // never be called. 38 | public void EndOfTimestep(boolean breakpoint,double timestep) { 39 | System.out.println("No one should get here!"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /bsim/Symbol.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package bsim; 4 | 5 | import java.util.Hashtable; 6 | import java.util.Vector; 7 | 8 | public class Symbol { 9 | public static final int UNDEF = 0; // symbol has no value 10 | public static final int ASSIGN = 1; // value established with "=" 11 | public static final int LABEL = 2; // value established with ":" 12 | 13 | public String name; // symbol's name 14 | public int value; // numeric value 15 | public int type; // tells how symbol got its value 16 | public Vector mdefs; // macro definitions with this name 17 | 18 | public Symbol(Hashtable symbols,String name,int value,int type) { 19 | this.name = name; 20 | this.value = value; 21 | this.type = type; 22 | mdefs = new Vector(); 23 | if (symbols != null) symbols.put(name,this); 24 | } 25 | 26 | public Symbol(Hashtable symbols,String name) { 27 | this(symbols,name,0,UNDEF); 28 | } 29 | 30 | public Symbol(Hashtable symbols,String name,int value) { 31 | this(symbols,name,value,ASSIGN); 32 | } 33 | 34 | public String toString() { 35 | return ""; 36 | } 37 | 38 | public Macro LookupMacro(int nparams) { 39 | for (int i = 0; i < mdefs.size(); i += 1) { 40 | Macro m = (Macro)mdefs.elementAt(i); 41 | if (m.NParams() == nparams) return m; 42 | } 43 | return null; 44 | } 45 | 46 | public void ClearMacroDefinitions() { 47 | mdefs.setSize(0); 48 | } 49 | 50 | public void AddMacroDefinition(Macro m) { 51 | mdefs.addElement(m); 52 | } 53 | 54 | public static Symbol Lookup(Hashtable symbols,String name,boolean create) { 55 | Symbol s = (Symbol)symbols.get(name); 56 | if (s == null && create) s = new Symbol(symbols,name,0,UNDEF); 57 | return s; 58 | } 59 | 60 | public static Symbol Lookup(Hashtable symbols,String name) { 61 | return Lookup(symbols,name,true); 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /simulation/SpiceSource.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | import netlist.NetlistConsumer; 6 | 7 | // simple DC source 8 | class SpiceSource { 9 | double dc; // dc value 10 | double acmag; // ac magnitude 11 | double acphase; // ac phase 12 | 13 | public SpiceSource(double xdc,double xacmag,double xacphase) { 14 | dc = xdc; 15 | acmag = xacmag; 16 | acphase = xacphase; 17 | } 18 | 19 | public double TransientValue(double time) { return dc; } 20 | 21 | public double NextBreakpoint(double time,double dv) { return -1; } 22 | 23 | public void ComputeBreakpoints(SpiceNetwork network,double stopTime) { }; 24 | 25 | public boolean SupportsGateLevelSimulation() { return false; } 26 | 27 | public double NextContaminationTime(double time) { return -1; } 28 | 29 | public double NextPropagationTime(double time) { return -1; } 30 | 31 | public String SourceName() { return "DC"; } 32 | 33 | public static SpiceSource Allocate(double dc,double acmag,double acphase, 34 | int trantype,double params[], 35 | double vil,double vih) { 36 | SpiceSource s; 37 | 38 | if (trantype == NetlistConsumer.PWL) 39 | s = new SpicePWLSource(dc,acmag,acphase,params,vil,vih); 40 | else if (trantype == NetlistConsumer.PULSE) 41 | s = new SpicePulseSource(dc,acmag,acphase,params,vil,vih); 42 | else if (trantype == NetlistConsumer.SIN) 43 | s = new SpiceSinSource(dc,acmag,acphase,params,vil,vih); 44 | else if (trantype == NetlistConsumer.EXP) 45 | s = new SpiceExpSource(dc,acmag,acphase,params,vil,vih); 46 | else if (trantype == NetlistConsumer.SFFM) 47 | s = new SpiceSFFMSource(dc,acmag,acphase,params,vil,vih); 48 | else if (trantype == NetlistConsumer.AM) 49 | s = new SpiceAMSource(dc,acmag,acphase,params,vil,vih); 50 | else 51 | s = new SpiceSource(dc,acmag,acphase); 52 | 53 | // if no DC value specified, use transient value at time 0 54 | if (s.dc == Double.NEGATIVE_INFINITY) s.dc = s.TransientValue(0); 55 | // if still no DC value, default to 0 56 | if (s.dc == Double.NEGATIVE_INFINITY) s.dc = 0; 57 | 58 | return s; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /netlist/Parameter.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | public class Parameter { 6 | public static final int NUMBER = 0; 7 | public static final int STRING = 1; 8 | public static final int VECTOR = 2; 9 | 10 | public Parameter next; // next parameter in list 11 | public int type; 12 | public String name; // identifier 13 | public boolean defined; // true if user specified value 14 | 15 | public double ndefaultValue; // value if not specified by user 16 | public double nvalue; // parameter's value 17 | 18 | public Object oDefaultValue; // value if not specified by user 19 | public Object ovalue; // parameter's value 20 | 21 | public Parameter(String n,double v,Parameter nxt) { 22 | next = nxt; 23 | name = n; 24 | defined = false; 25 | 26 | type = NUMBER; 27 | ndefaultValue = v; 28 | nvalue = v; 29 | } 30 | 31 | public Parameter(String n,String v,Parameter nxt) { 32 | next = nxt; 33 | name = n; 34 | defined = false; 35 | 36 | type = STRING; 37 | oDefaultValue = v; 38 | ovalue = v; 39 | } 40 | 41 | public Parameter(String n,double v[],Parameter nxt) { 42 | next = nxt; 43 | name = n; 44 | defined = false; 45 | 46 | type = VECTOR; 47 | oDefaultValue = v; 48 | ovalue = v; 49 | } 50 | 51 | public Parameter Find(String n) { 52 | Parameter search = this; 53 | 54 | while (search != null) { 55 | if (search.name.equalsIgnoreCase(n)) return search; 56 | search = search.next; 57 | } 58 | return null; 59 | } 60 | 61 | public void Initialize() { 62 | nvalue = ndefaultValue; 63 | ovalue = oDefaultValue; 64 | defined = false; 65 | } 66 | 67 | public double Value(String n,double vdefault) { 68 | Parameter p = Find(n); 69 | return (p == null || p.type != NUMBER) ? vdefault : p.nvalue; 70 | } 71 | 72 | public String SValue(String n,String vdefault) { 73 | Parameter p = Find(n); 74 | return (p == null || p.type != STRING) ? vdefault : (String)p.ovalue; 75 | } 76 | 77 | public double[] VValue(String n,double vdefault[]) { 78 | Parameter p = Find(n); 79 | return (p == null || p.type != VECTOR) ? vdefault : (double [])p.ovalue; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /netlist/DependentSourcePrototype.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | class DependentSourcePrototype extends DevicePrototype { 6 | static final int VCVS = 1; // voltage-controlled voltage source 7 | static final int VCCS = 2; // voltage-controlled current source 8 | static final int CCVS = 3; // current-controlled voltage source 9 | static final int CCCS = 4; // current-controlled current source 10 | 11 | int type; // type of source 12 | Node npos; // two output terminal nodes 13 | Node nneg; 14 | Node ncpos; // two control terminals 15 | Node ncneg; 16 | Number gain; // multiplicative factor 17 | 18 | public DependentSourcePrototype(Identifier s_id,Node s_pos,Node s_neg, 19 | Node s_cpos,Node s_cneg,Number s_gain) { 20 | id = s_id; 21 | npos = s_pos; 22 | nneg = s_neg; 23 | ncpos = s_cpos; 24 | ncneg = s_cneg; 25 | gain = s_gain; 26 | 27 | switch (Character.toLowerCase(id.name.charAt(0))) { 28 | case 'e': type = VCVS; break; 29 | case 'f': type = CCCS; break; 30 | case 'g': type = VCCS; break; 31 | case 'h': type = CCVS; break; 32 | } 33 | } 34 | 35 | // add device to netlist 36 | public boolean Netlist(Netlist network,NetlistConsumer n) { 37 | switch (type) { 38 | case VCVS: 39 | n.MakeVCVS(network.prefix + id.name, 40 | npos.netlisterNode,nneg.netlisterNode, 41 | ncpos.netlisterNode,ncneg.netlisterNode, 42 | gain==null ? 1 : gain.value); 43 | break; 44 | case VCCS: 45 | n.MakeVCCS(network.prefix + id.name, 46 | npos.netlisterNode,nneg.netlisterNode, 47 | ncpos.netlisterNode,ncneg.netlisterNode, 48 | gain==null ? 1 : gain.value); 49 | break; 50 | case CCVS: 51 | n.MakeCCVS(network.prefix + id.name, 52 | npos.netlisterNode,nneg.netlisterNode, 53 | ncpos.netlisterNode,ncneg.netlisterNode, 54 | gain==null ? 1 : gain.value); 55 | break; 56 | case CCCS: 57 | n.MakeCCCS(network.prefix + id.name, 58 | npos.netlisterNode,nneg.netlisterNode, 59 | ncpos.netlisterNode,ncneg.netlisterNode, 60 | gain==null ? 1 : gain.value); 61 | break; 62 | } 63 | return true; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /netlist/NetlistConsumer.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2001 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | 8 | public interface NetlistConsumer { 9 | String Problem(); 10 | 11 | // models 12 | static final int NMOS = 1; // model types 13 | static final int PMOS = 2; 14 | Object MakeModel(String name,int mtype,HashMap options); 15 | 16 | // nodes 17 | Object FindNode(String name,boolean create); 18 | Object MakeGndNode(String name); 19 | void NodeAlias(Object node,String alias); 20 | void ConnectNodes(Object n1,Object n2); 21 | 22 | // built-in gates 23 | boolean MakeGate(String id,String function,ArrayList nodes,Parameter params); 24 | 25 | // devices 26 | boolean MakeResistor(String id,Object n1,Object n2,double resistance); 27 | boolean MakeCapacitor(String id,Object n1,Object n2,double capacitance); 28 | boolean MakeInductor(String id,Object n1,Object n2,double Inductance); 29 | boolean MakeMosfet(String id,Object d,Object g,Object s,Object b, 30 | Object model,double l,double w,double sl,double sw, 31 | double ad,double pd,double nrd,double rdc, 32 | double as,double ps,double nrs,double rsc); 33 | 34 | // sources 35 | static final int PWL = 1; // transient source function types 36 | static final int PULSE = 2; 37 | static final int SIN = 3; 38 | static final int EXP = 4; 39 | static final int SFFM = 5; 40 | static final int AM = 6; 41 | 42 | boolean MakeIndependentVoltageSource(String id,Object npos,Object nneg, 43 | double dc,double acmag,double acphase, 44 | int trantype,double params[]); 45 | boolean MakeIndependentCurrentSource(String id,Object npos,Object nneg, 46 | double dc,double acmag,double acphase, 47 | int trantype,double params[]); 48 | boolean MakeVCVS(String id,Object npos,Object nneg, 49 | Object ncpos,Object ncneg,double gain); 50 | boolean MakeVCCS(String id,Object npos,Object nneg, 51 | Object ncpos,Object ncneg,double gain); 52 | boolean MakeCCVS(String id,Object npos,Object nneg, 53 | Object ncpos,Object ncneg,double gain); 54 | boolean MakeCCCS(String id,Object npos,Object nneg, 55 | Object ncpos,Object ncneg,double gain); 56 | } 57 | -------------------------------------------------------------------------------- /fsm/ElevatorDiagram.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2002 Christopher J. Terman - All Rights Reserved. 2 | 3 | package fsm; 4 | 5 | import java.awt.Color; 6 | import java.awt.Dimension; 7 | import java.awt.Graphics; 8 | import java.awt.Rectangle; 9 | import java.util.Random; 10 | import javax.swing.JPanel; 11 | 12 | import gui.GuiFrame; 13 | 14 | public class ElevatorDiagram extends JPanel { 15 | public boolean button[]; // request from floor N 16 | public boolean done; // all customers serviced? 17 | 18 | Lemming lemmings[]; 19 | GuiFrame parent; 20 | 21 | public ElevatorDiagram(GuiFrame parent,int nfloors) { 22 | super(); 23 | setBackground(Color.white); 24 | setOpaque(true); 25 | this.parent = parent; 26 | 27 | button = new boolean[nfloors]; 28 | 29 | lemmings = new Lemming[nfloors*3]; 30 | Reset(); 31 | } 32 | 33 | public boolean ClearAhead(Lemming l) { 34 | Rectangle r = l.bbox; 35 | if (r.x <= 40 || r.x+r.width >= 450) return false; 36 | for (int i = 0; i < lemmings.length; i += 1) { 37 | if (l == lemmings[i]) continue; 38 | if (r.intersects(lemmings[i].bbox)) return false; 39 | } 40 | return true; 41 | } 42 | 43 | // restore maze to its original condition 44 | public void Reset() { 45 | for (int i = 0; i < button.length; i += 1) 46 | button[i] = false; 47 | 48 | // kill off last batch 49 | for (int i = 0; i < lemmings.length; i += 1) 50 | if (lemmings[i] != null) 51 | lemmings[i].interrupt(); 52 | 53 | // create new lemmings 54 | Random pause = new Random(); 55 | for (int i = 0; i < lemmings.length; i += 1) { 56 | int wait = pause.nextInt(Lemming.QUANTUM*300); 57 | lemmings[i] = new Lemming(parent,this,wait); 58 | lemmings[i].Reset(408 - 34*(i%3),60*(i/3)+60); 59 | } 60 | 61 | // let 'em rip 62 | for (int i = 0; i < lemmings.length; i += 1) 63 | lemmings[i].start(); 64 | 65 | repaint(); 66 | } 67 | 68 | 69 | // simulate one step 70 | public void Update() { 71 | } 72 | 73 | // up one floor 74 | public void Up() { 75 | } 76 | 77 | // down one floor 78 | public void Down() { 79 | } 80 | 81 | // open door 82 | public void OpenDoor() { 83 | } 84 | 85 | // close door 86 | public void CloseDoor() { 87 | } 88 | 89 | public void paintComponent(Graphics g) { 90 | super.paintComponent(g); // paint background 91 | for (int i = 0; i < lemmings.length; i += 1) 92 | lemmings[i].Draw(g,Color.white); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /netlist/Identifier.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2001 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | import gui.UI; 6 | import java.util.ArrayList; 7 | 8 | class Identifier extends Token { 9 | public String name; // identifier 10 | 11 | static private StringBuffer scratch = new StringBuffer(); 12 | 13 | public Identifier(String n,Netlist netlist,int s,int e) { 14 | super(netlist,s,e); 15 | name = n.toLowerCase(); 16 | } 17 | 18 | public String toString() { 19 | return ""; 20 | } 21 | 22 | // some convenience functions 23 | public boolean equals(String s) { return name.equals(s); } 24 | public boolean equals(Identifier i) { return name.equals(i.name); } 25 | 26 | // expand any iterators and return vector of identifiers 27 | public ArrayList Expand() { 28 | ArrayList ids = UI.ExpandNodeName(name); 29 | 30 | // convert each string into an identifier. Look for special 31 | // case where no expansion happened so we can just use ourself 32 | int nids = ids.size(); 33 | if (nids == 1 && name.equals((String)ids.get(0))) 34 | ids.set(0,this); 35 | else for (int i = 0; i < nids; i += 1) 36 | ids.set(i,new Identifier((String)ids.get(i),netlist,start,end)); 37 | return ids; 38 | } 39 | 40 | // true if ch is a legal character in an identifier 41 | static public boolean IdChar(int ch) { 42 | if (ch >= '0' && ch <= '9') return true; 43 | else if (ch >= 'a' && ch <= 'z') return true; 44 | else if (ch >= 'A' && ch <= 'Z') return true; 45 | else switch (ch) { 46 | case '[': 47 | case ']': 48 | case '$': 49 | case '_': 50 | case '.': 51 | case ':': 52 | case '#': 53 | return true; 54 | default: 55 | return false; 56 | } 57 | } 58 | 59 | // see if we can interpret line[lineOffset...] as an identifier 60 | synchronized static public Identifier Parse(StringBuffer line,Netlist netlist,int lineOffset) { 61 | int lineLength = line.length(); 62 | int ch,start; 63 | 64 | scratch.setLength(0); 65 | 66 | // skip over blanks 67 | while (lineOffset < lineLength && line.charAt(lineOffset) <= ' ') 68 | lineOffset += 1; 69 | start = lineOffset; 70 | 71 | while (lineOffset < lineLength && IdChar(ch = line.charAt(lineOffset))) { 72 | scratch.append((char)ch); 73 | lineOffset += 1; 74 | } 75 | 76 | // see if we've found anything 77 | if (lineOffset == start) return null; 78 | return new Identifier(scratch.toString(),netlist,start,lineOffset); 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /bsim/Macro.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package bsim; 4 | 5 | import java.util.Hashtable; 6 | import java.util.Vector; 7 | 8 | public class Macro { 9 | Symbol name; // symbol which is name of this macro 10 | String body; // body is just a character string 11 | Vector params; // Symbol for each formal parameter 12 | boolean called; // used to catch recursive macro calls 13 | 14 | public Macro(Symbol name,String body,Vector params) { 15 | this.name = name; 16 | this.body = body; 17 | this.params = params; 18 | called = false; 19 | 20 | name.AddMacroDefinition(this); 21 | } 22 | 23 | public String toString() { 24 | String result = ""; 31 | return result; 32 | } 33 | 34 | // convenience functions for defining built-in macros 35 | 36 | // 0-argument macro 37 | public Macro(Hashtable symbols,String name,String body) { 38 | this(Symbol.Lookup(symbols,name),body,new Vector()); 39 | } 40 | 41 | // 1-argument macro 42 | public Macro(Hashtable symbols,String name,String p1,String body) { 43 | this(Symbol.Lookup(symbols,name),body,new Vector()); 44 | params.addElement(Symbol.Lookup(symbols,p1)); 45 | } 46 | 47 | // 2-argument macro 48 | public Macro(Hashtable symbols,String name,String p1,String p2,String body) { 49 | this(Symbol.Lookup(symbols,name),body,new Vector()); 50 | params.addElement(Symbol.Lookup(symbols,p1)); 51 | params.addElement(Symbol.Lookup(symbols,p2)); 52 | } 53 | 54 | // 3-argument macro 55 | public Macro(Hashtable symbols,String name,String p1,String p2,String p3,String body) { 56 | this(Symbol.Lookup(symbols,name),body,new Vector()); 57 | params.addElement(Symbol.Lookup(symbols,p1)); 58 | params.addElement(Symbol.Lookup(symbols,p2)); 59 | params.addElement(Symbol.Lookup(symbols,p3)); 60 | } 61 | 62 | // 4-argument macro 63 | public Macro(Hashtable symbols,String name,String p1,String p2,String p3,String p4,String body) { 64 | this(Symbol.Lookup(symbols,name),body,new Vector()); 65 | params.addElement(Symbol.Lookup(symbols,p1)); 66 | params.addElement(Symbol.Lookup(symbols,p2)); 67 | params.addElement(Symbol.Lookup(symbols,p3)); 68 | params.addElement(Symbol.Lookup(symbols,p4)); 69 | } 70 | 71 | public int NParams() { 72 | return params.size(); 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /netlist/MosfetPrototype.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | class MosfetPrototype extends DevicePrototype { 6 | Node d,g,s,b; // four terminal nodes 7 | Identifier model; // mosfet model 8 | double l; // length 9 | double w; // width 10 | double sl; // scaled length 11 | double sw; // scaled width 12 | double ad; // drain area 13 | double pd; // drain perimeter 14 | double nrd; // number of squares of drain diffusion 15 | double rdc; // additional drain resistance 16 | double as; // source area 17 | double ps; // source perimeter 18 | double nrs; // number of squares of source diffusion 19 | double rsc; // additional source resistance 20 | 21 | public static Parameter mparams = InitializeParameters(); 22 | 23 | public MosfetPrototype(Identifier m_id,Node m_d,Node m_g,Node m_s,Node m_b, 24 | Identifier m_model,double m_l,double m_w, 25 | double m_sl,double m_sw, 26 | double m_ad,double m_pd,double m_nrd,double m_rdc, 27 | double m_as,double m_ps,double m_nrs,double m_rsc) { 28 | id = m_id; 29 | d = m_d; 30 | g = m_g; 31 | s = m_s; 32 | b = m_b; 33 | model = m_model; 34 | l = m_l; 35 | w = m_w; 36 | sl = m_sl; 37 | sw = m_sw; 38 | ad = m_ad; 39 | pd = m_pd; 40 | nrd = m_nrd; 41 | rdc = m_rdc; 42 | as = m_as; 43 | ps = m_ps; 44 | nrs = m_nrs; 45 | rsc = m_rsc; 46 | } 47 | 48 | // add device to netlist 49 | public boolean Netlist(Netlist network,NetlistConsumer n) { 50 | Model m = network.currentSubcircuit.FindModel(model); 51 | 52 | if (m == null) { 53 | network.Error(model,"Can't find .model definition with this name"); 54 | return false; 55 | } 56 | 57 | n.MakeMosfet(network.prefix + id.name, 58 | d.netlisterNode,g.netlisterNode,s.netlisterNode,b.netlisterNode, 59 | m.netlisterModel,l,w,sl,sw,ad,pd,nrd,rdc,as,ps,nrs,rsc); 60 | return true; 61 | } 62 | 63 | // set up list of parameters and their default values 64 | static Parameter InitializeParameters() { 65 | Parameter p = null; 66 | 67 | p = new Parameter("l",0.0,p); 68 | p = new Parameter("w",0.0,p); 69 | p = new Parameter("sl",0.0,p); 70 | p = new Parameter("sw",0.0,p); 71 | p = new Parameter("ad",0.0,p); 72 | p = new Parameter("pd",0.0,p); 73 | p = new Parameter("nrd",0.0,p); 74 | p = new Parameter("rdc",0.0,p); 75 | p = new Parameter("as",0.0,p); 76 | p = new Parameter("ps",0.0,p); 77 | p = new Parameter("nrs",0.0,p); 78 | p = new Parameter("rsc",0.0,p); 79 | 80 | return p; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /plot/PlotData.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2001 Christopher J. Terman - All Rights Reserved. 2 | 3 | package plot; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class PlotData { 8 | public String name; // name of element 9 | public ArrayList coords; // [Analog|Digital]PlotCoordinates 10 | String haxis,vaxis; // what's being plotted on each axis 11 | double xmin,xmax; // bounds on values 12 | double ymin,ymax; // bounds on values 13 | public int width; // for digital data: width in bits 14 | 15 | public PlotData(String name,String haxis,String vaxis,int width) { 16 | this.name = name; 17 | this.haxis = haxis; 18 | this.vaxis = vaxis; 19 | this.width = width; 20 | coords = new ArrayList(); 21 | 22 | xmax = Double.NEGATIVE_INFINITY; 23 | xmin = Double.POSITIVE_INFINITY; 24 | ymax = Double.NEGATIVE_INFINITY; 25 | ymin = Double.POSITIVE_INFINITY; 26 | } 27 | 28 | public String toString() { 29 | return name+"[x="+xmin+","+xmax+" y="+ymin+","+ymax+"]"; 30 | } 31 | 32 | // add a new coordinate to the list 33 | public void AddPoint(PlotCoordinate c) { 34 | // find where it goes: list is sorted by increasing X 35 | int ncoords = coords.size(); 36 | boolean inserted = false; 37 | double x = c.GetX(); 38 | for (int i = 0; i < ncoords; i += 1) { 39 | PlotCoordinate cc = (PlotCoordinate)coords.get(i); 40 | if (x <= cc.GetX()) { 41 | coords.add(i,c); 42 | inserted = true; 43 | break; 44 | } 45 | } 46 | if (!inserted) coords.add(c); 47 | 48 | if (!Double.isNaN(x) && !Double.isInfinite(x)) { 49 | if (x < xmin) xmin = x; 50 | if (x > xmax) xmax = x; 51 | } 52 | double y = c.GetY(); 53 | if (!Double.isNaN(y) && !Double.isInfinite(y)) { 54 | if (y < ymin) ymin = y; 55 | if (y > ymax) ymax = y; 56 | } 57 | } 58 | 59 | // find first plot coordinate with X greater than specified value 60 | public PlotCoordinate FindCoordinate(double x) { 61 | int ncoords = coords.size(); 62 | for (int i = 0; i < ncoords; i += 1) { 63 | PlotCoordinate cc = (PlotCoordinate)coords.get(i); 64 | double xx = cc.GetX(); 65 | if (xx > x) return cc; 66 | } 67 | return null; 68 | } 69 | 70 | public String toBinaryString(long v) { 71 | return toBinaryString(v,0); 72 | } 73 | 74 | public String toBinaryString(long v1,long v2) { 75 | String result = ""; 76 | for (int i = 0; i < width; i += 1) { 77 | if ((v2 & 1) != 0) result = "X" + result; 78 | else if ((v1 & 1) != 0) result = "1" + result; 79 | else result = "0" + result; 80 | v1 >>= 1; 81 | v2 >>= 1; 82 | } 83 | return result; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /simulation/TimingInfo.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2007 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | public class TimingInfo { 6 | public SimNode node; // what node this info is associated with 7 | public SimDevice device; // what device determined this info 8 | public double tCDsum; // min cummulative tCD from inputs to here 9 | public TimingInfo tCDlink; // previous link in tCD path 10 | public double tPDsum; // max cummulative tPD from inputs to here 11 | public TimingInfo tPDlink; // previous link in tPD path 12 | 13 | public double tCD; // specs for driving gate 14 | public double tPD; // already accounts for node capacitance 15 | 16 | public TimingInfo(SimNode node,SimDevice device) { 17 | this.node = node; 18 | this.device = device; 19 | tCDsum = 0; 20 | tCDlink = null; 21 | tPDsum = 0; 22 | tPDlink = null; 23 | tCD = 0; 24 | tPD = 0; 25 | } 26 | 27 | public SimNode getTCDSource() { 28 | TimingInfo t = this; 29 | while (t.tCDlink != null) t = t.tCDlink; 30 | return t.node; 31 | } 32 | 33 | public SimNode getTPDSource() { 34 | TimingInfo t = this; 35 | while (t.tPDlink != null) t = t.tPDlink; 36 | return t.node; 37 | } 38 | 39 | public void setSpecs(double tCD,double tPD) { 40 | this.tCD = tCD; 41 | this.tPD = tPD; 42 | } 43 | 44 | // keep track of min tCD as we consider each path 45 | public void setDelays(TimingInfo link) { 46 | double t; 47 | 48 | // update min tCD 49 | t = link.tCDsum + tCD; 50 | if (tCDlink == null || t < tCDsum) { 51 | tCDlink = link; 52 | tCDsum = t; 53 | } 54 | 55 | // update max tPD 56 | t = link.tPDsum + tPD; 57 | if (tPDlink == null || t > tPDsum) { 58 | tPDlink = link; 59 | tPDsum = t; 60 | } 61 | } 62 | 63 | // recursively print out tPD path 64 | public void printTPD(java.io.PrintWriter out,int indent) { 65 | if (tPDlink != null) tPDlink.printTPD(out,indent); 66 | 67 | // skip internal nodes with tPD's of zero 68 | if (node.isInput() || tPD != 0) { 69 | String driverName = ""; 70 | if (device != null) driverName = " [" + device.name + "]"; 71 | 72 | for (int i = 0; i < indent; i +=1) out.print(' '); 73 | out.format("+ %1$5.3fns = %2$5.3fns %3$s%4$s\n",tPD*1e9,tPDsum*1e9,node.name,driverName); 74 | } 75 | } 76 | 77 | // recursively print out tCD path 78 | public void printTCD(java.io.PrintWriter out,int indent) { 79 | if (tCDlink != null) tCDlink.printTCD(out,indent); 80 | 81 | String driverName = ""; 82 | if (device != null) driverName = " [" + device.name + "]"; 83 | 84 | for (int i = 0; i < indent; i +=1) out.print(' '); 85 | out.format("%s %2$5.3fns = %3$5.3fns %4$s%5$s\n",tCD >= 0 ? "+":"-",Math.abs(tCD)*1e9,tCDsum*1e9,node.name,driverName); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /simulation/EmuMosfet.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class EmuMosfet extends EmuDevice { 6 | EmuNode d; 7 | EmuNode g; 8 | EmuNode s; 9 | EmuNode b; 10 | double w; 11 | double l; 12 | Object model; 13 | 14 | double vds; // vds at which ids and gds were computed 15 | double gds; 16 | double ids; 17 | 18 | public EmuMosfet(EmuNode d,EmuNode g,EmuNode s,EmuNode b, 19 | SpiceMOSModel m,double l,double w, 20 | double ad,double pd,double as,double ps) { 21 | this.d = d; 22 | this.g = g; 23 | this.s = s; 24 | this.b = b; 25 | this.w = w; 26 | this.l = l; 27 | model = m; 28 | 29 | // approximate diffusion widths if user hasn't supplied dimensions 30 | double diffWidth = Math.min(w,l); 31 | if (as==0 && ps==0) { as = w * diffWidth; ps = w + 2*diffWidth; } 32 | if (ad==0 && pd==0) { ad = w * diffWidth; pd = w + 2*diffWidth; } 33 | 34 | // add gate and diffusion capacitors 35 | g.capacitance += w*l*m.m_cox + w*(m.m_cgso + m.m_cgdo) + l*m.m_cgbo; 36 | d.capacitance += ad*m.cj + pd*m.cjsw; 37 | s.capacitance += as*m.cj + ps*m.cjsw; 38 | 39 | d.AddDevice(this); 40 | s.AddDevice(this); 41 | } 42 | 43 | public void AddToRegion(EmuRegion r,EmuNode n) { 44 | super.AddToRegion(r,(n == d) ? s : d); 45 | } 46 | 47 | public void Finalize() { 48 | // build table-driven model 49 | model = region.network.MakeEmuMOSModel((SpiceMOSModel)model,w,l); 50 | 51 | g.AddFanoutRegion(region); 52 | b.AddFanoutRegion(region); 53 | } 54 | 55 | public void Reset() { 56 | gds = 0; 57 | ids = 0; 58 | vds = 0; 59 | } 60 | 61 | void RecomputeIdsGds(double vg,double vd,double vs,double vb) { 62 | double previousI = ids; 63 | 64 | // compute ids, gds using model... 65 | ((EmuMOSModel)model).ids_gds(this,vg,vd,vs,vb); 66 | 67 | // update drain and source info on current flows 68 | double deltaI = ids - previousI; 69 | d.totalCurrent -= deltaI; 70 | s.totalCurrent += deltaI; 71 | d.totalTransconductance += gds; 72 | s.totalTransconductance += gds; 73 | 74 | vds = vd - vs; 75 | 76 | //System.out.println("vd="+vd+" vs="+vs+" vg="+vg+" vb="+vb+" ids="+ids+" gds="+gds); 77 | } 78 | 79 | public double Incremental(EmuNode n,double timestep) { 80 | double nvd = d.voltage + d.deltaV; 81 | double nvs = s.voltage + s.deltaV; 82 | // recompute ids and gds if voltages change a lot 83 | if (Math.abs((nvd - nvs) - vds) > .5) { 84 | d.totalTransconductance -= gds; 85 | s.totalTransconductance -= gds; 86 | RecomputeIdsGds(g.voltage,nvs,nvd,b.voltage); 87 | } 88 | 89 | return gds*((n == d) ? s.deltaV : d.deltaV); 90 | } 91 | 92 | public double Update(double time) { 93 | RecomputeIdsGds(g.voltage,s.voltage,d.voltage,b.voltage); 94 | return EmuRegion.NO_EVENT; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /plot/DigitalPlotCoordinate.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2001 Christopher J. Terman - All Rights Reserved. 2 | 3 | package plot; 4 | 5 | import gui.UI; 6 | 7 | public class DigitalPlotCoordinate extends PlotCoordinate { 8 | double x; // another point in the curve 9 | long v1; // 4-value logic, 64 bits 10 | long v2; 11 | long vmask; // which bits defined at this time 12 | 13 | public double GetX() { return x; } 14 | 15 | public DigitalPlotCoordinate(double nx) { 16 | x = nx; 17 | v1 = 0; 18 | v2 = 0; 19 | vmask = 0; 20 | } 21 | 22 | public void AddBit(int bit,int v1,int v2) { 23 | if (bit < 0 || bit > 63) return; 24 | long mask = ((long)1) << bit; 25 | this.v1 &= ~mask; 26 | if (v1 != 0) this.v1 |= mask; 27 | this.v2 &= ~mask; 28 | if (v2 != 0) this.v2 |= mask; 29 | vmask |= mask; 30 | } 31 | 32 | public boolean Merge(DigitalPlotCoordinate previous,long mask) { 33 | v1 |= ((previous == null) ? mask : previous.v1) & ~vmask; 34 | v2 |= ((previous == null) ? mask : previous.v2) & ~vmask; 35 | vmask = mask; 36 | return previous != null && previous.x == x; 37 | } 38 | 39 | public boolean Match(long v) { 40 | return ((v2 & vmask) == 0 && ((v1 ^ v) & vmask) == 0); 41 | } 42 | 43 | public String toString() { 44 | return "["+UI.EngineeringNotation(x,3)+"s: 0b"+toBinaryString()+"]"; 45 | } 46 | 47 | public String toBinaryString() { 48 | String result = ""; 49 | long tmask = vmask; 50 | long tv1 = v1; 51 | long tv2 = v2; 52 | for (int i = 0; i < 64; i += 1) { 53 | if (tmask == 0) break; 54 | if ((tv2 & 1) == 1) result = "X" + result; 55 | else if ((tv1 & 1) == 1) result = "1" + result; 56 | else result = "0" + result; 57 | tmask >>= 1; 58 | tv1 >>= 1; 59 | tv2 >>= 1; 60 | } 61 | return result; 62 | } 63 | 64 | public String toOctalString() { 65 | String result = ""; 66 | long tmask = vmask; 67 | long tv1 = v1; 68 | long tv2 = v2; 69 | for (int i = 0; i < 64; i += 3) { 70 | if (tmask == 0) break; 71 | if ((tv2 & 0x7) != 0) result = "X" + result; 72 | else { 73 | int v = (int)(tv1 & 0x7); 74 | result = (char)('0' + v) + result; 75 | } 76 | tmask >>= 3; 77 | tv1 >>= 3; 78 | tv2 >>= 3; 79 | } 80 | return result; 81 | } 82 | 83 | public String toHexString() { 84 | String result = ""; 85 | long tmask = vmask; 86 | long tv1 = v1; 87 | long tv2 = v2; 88 | for (int i = 0; i < 64; i += 4) { 89 | if (tmask == 0) break; 90 | if ((tv2 & 0xF) != 0) result = "X" + result; 91 | else { 92 | int v = (int)(tv1 & 0xF); 93 | if (v <= 9) result = (char)('0' + v) + result; 94 | else result = (char)('A' + v - 10) + result; 95 | } 96 | tmask >>= 4; 97 | tv1 >>= 4; 98 | tv2 >>= 4; 99 | } 100 | return result; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /netlist/SubcircuitCall.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2001 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | import java.util.ArrayList; 6 | 7 | class SubcircuitCall extends DevicePrototype { 8 | public Identifier subckt; // name of circuit we're an instance of 9 | public ArrayList args; // nodes to passed into subcircuit 10 | public Parameter params; // list of supplied parameters 11 | 12 | public SubcircuitCall(Identifier sc_id,Identifier sc_subckt,ArrayList sc_args,Parameter sc_params) { 13 | id = sc_id; 14 | subckt = sc_subckt; 15 | args = sc_args; 16 | params = sc_params; 17 | } 18 | 19 | // expand subcircuit call by expanding appropriate subckt definition 20 | public boolean Netlist(Netlist network,NetlistConsumer nc) { 21 | // built-in gates get special treatment 22 | if (subckt.name.charAt(0) == '$') { 23 | ArrayList nodes = (ArrayList)args.clone(); 24 | int nnodes = nodes.size(); 25 | for (int i = 0; i < nnodes; i += 1) 26 | nodes.set(i,((Node)nodes.get(i)).netlisterNode); 27 | if (!nc.MakeGate(network.prefix + id.name,subckt.name,nodes,params)) { 28 | network.Error(subckt,nc.Problem()); 29 | return false; 30 | } 31 | return true; 32 | } 33 | 34 | Subcircuit s = network.currentSubcircuit.FindSubcircuit(subckt,network.topLevel.stype); 35 | 36 | if (s == null) { 37 | network.Error(subckt,"Can't find .subckt definition for "+subckt.name); 38 | return false; 39 | } 40 | if (s.active) { 41 | network.Error(subckt,"Recursive call of .subckt "+subckt.name); 42 | return false; 43 | } 44 | 45 | int nexternals = s.externals.size(); 46 | int nargs = args.size(); 47 | int iterations = (nargs == 0 || nexternals == 0) ? 1 : nargs / nexternals; 48 | if (iterations * nexternals != nargs) { 49 | network.Error(subckt,"Number of arguments ("+nargs+") doesn't match .subckt definition for "+subckt.name+" (need multiple of "+nexternals+")"); 50 | return false; 51 | } 52 | 53 | // fix up prefix to reflect new layer of hierarchy 54 | String oldPrefix = network.prefix; 55 | 56 | for (int iter = 0; iter < iterations; iter += 1) { 57 | if (iterations == 1) 58 | network.prefix = oldPrefix + id.name + "." ; 59 | else 60 | network.prefix = oldPrefix + id.name + "#" + iter + "." ; 61 | 62 | // fill in netlister nodes for subcircuit's external nodes 63 | for (int i = 0; i < nexternals; i += 1) { 64 | Node arg = (Node)args.get(i*iterations + iter); 65 | Node ext = (Node)s.externals.get(i); 66 | ext.netlisterNode = arg.netlisterNode; 67 | 68 | if (network.localNames) { 69 | // allow user to refer to node by its "local" name too 70 | nc.NodeAlias(arg.netlisterNode,network.prefix+ext.id.name); 71 | } 72 | } 73 | 74 | // netlist all devices in the subcircuit definition 75 | if (!s.Netlist(network,nc)) { 76 | network.prefix = oldPrefix; 77 | return false; 78 | } 79 | } 80 | 81 | // restore old prefix 82 | network.prefix = oldPrefix; 83 | return true; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /simulation/Event.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class Event { 6 | static final double NO_EVENT = -1; 7 | 8 | double etime; // time of this queue entry 9 | Event parent; // leftist tree pointers 10 | Event left; 11 | Event right; 12 | int distance; // minimum distance to leaf 13 | 14 | public Event() { 15 | etime = NO_EVENT; 16 | parent = null; 17 | left = null; 18 | right = null; 19 | distance = 0; 20 | } 21 | 22 | // used to determine sorting order of events in queue. Override 23 | // if a more complicated predicate is needed for subclasses of Event. 24 | // It's better to return false if possible since that means less work... 25 | public boolean Before(Event other) { 26 | return etime < other.etime; 27 | } 28 | 29 | // adjust distance from leafs all the way up the tree, rearranging 30 | // children to keep the shortest path on the right branch 31 | static private void UpdateDistance(Event p) { 32 | while (p != null) { 33 | int ldist = (p.left == null) ? 0 : p.left.distance; 34 | int rdist = (p.right == null) ? 0 : p.right.distance; 35 | // maintain right child as having minimum distance 36 | if (ldist < rdist) { 37 | Event r = p.left; 38 | p.left = p.right; 39 | p.right = r; 40 | rdist = ldist; 41 | } 42 | p.distance = 1 + rdist; 43 | p = p.parent; 44 | } 45 | } 46 | 47 | static private Event MergeWithQueue(Event queue,Event q) { 48 | if (queue == null) { 49 | queue = q; 50 | q.parent = null; 51 | return queue; 52 | } 53 | 54 | Event p = queue; 55 | Event parent = null; 56 | 57 | // merge this Q into tree. If P has a later time 58 | // Q will take its place and we'll continue the merge with 59 | // this event. Otherwise just keep passing Q down the tree, 60 | // using the right branch since it's guaranteed to be the 61 | // shortest. 62 | while (true) { 63 | // Q is earlier, so swap places with current node 64 | if (q.Before(p)) { 65 | Event temp = p; 66 | p = q; 67 | q = temp; 68 | p.parent = parent; 69 | if (parent == null) queue = p; 70 | else parent.right = p; 71 | } 72 | // got to a leaf node so add Q as right child and 73 | // then update distances on the way back up 74 | if (p.right == null) { 75 | p.right = q; 76 | q.parent = p; 77 | UpdateDistance(p); 78 | return queue; 79 | } 80 | // keep descending 81 | parent = p; 82 | p = p.right; 83 | } 84 | } 85 | 86 | public Event RemoveFromQueue(Event queue) { 87 | etime = NO_EVENT; 88 | if (parent == null) queue = left; 89 | else { 90 | if (parent.left == this) parent.left = left; 91 | else parent.right = left; 92 | UpdateDistance(parent); 93 | } 94 | if (left != null) left.parent = parent; 95 | if (right != null) queue = MergeWithQueue(queue,right); 96 | return queue; 97 | } 98 | 99 | public Event AddToQueue(Event queue,double eventTime) { 100 | if (etime != NO_EVENT) queue = RemoveFromQueue(queue); 101 | etime = eventTime; 102 | left = null; 103 | right = null; 104 | distance = 1; 105 | return MergeWithQueue(queue,this); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /simulation/SimDevice.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2007 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | public class SimDevice { 6 | String name; // name of this device 7 | SimDevice link; // link in network's list of all devices 8 | SimDevice clink; // link in list of devices with incoming C events 9 | SimDevice plink; // link in list of devices with incoming P events 10 | int ninputs; // number of inputs for this device 11 | int noutputs; // number of outputs for this device 12 | SimNode nodes[]; // all the fanin and fanout nodes; 13 | 14 | public SimDevice(String name) { 15 | this.name = name; 16 | this.ninputs = 0; 17 | this.noutputs = 0; 18 | nodes = null; 19 | } 20 | 21 | public SimDevice(String name,int ninputs,int noutputs) { 22 | this.name = name; 23 | this.ninputs = ninputs; 24 | this.noutputs = noutputs; 25 | nodes = new SimNode[ninputs+noutputs]; 26 | } 27 | 28 | public String toString() { 29 | String result = name+"["; 30 | for (int i = 0; i < ninputs; i += 1) { 31 | if (i != 0) result += ","; 32 | result += nodes[i].name; 33 | } 34 | result += ";"; 35 | for (int i = 0; i < noutputs; i += 1) { 36 | if (i != 0) result += ","; 37 | result += nodes[ninputs+i].name; 38 | } 39 | return result + "]"; 40 | } 41 | 42 | // change all internal references to node n1 to node n2 43 | public void ChangeNode(SimNode n1,SimNode n2) { 44 | for (int i = ninputs + noutputs - 1; i >=0; i -= 1) 45 | if (nodes[i] == n1) nodes[i] = n2; 46 | } 47 | 48 | // change first instance of node n1 in output list to node n2 49 | public void ChangeOutputNode(SimNode n1,SimNode n2) { 50 | for (int i = 0; i < noutputs; i += 1) 51 | if (nodes[i + ninputs] == n1) { 52 | nodes[i + ninputs] = n2; 53 | return; 54 | } 55 | } 56 | 57 | // helper function which adds this device as a fanout of the 58 | // input nodes and a driver of the output nodes 59 | void SetupNodes() { 60 | for (int i = 0; i < ninputs; i += 1) 61 | nodes[i].AddFanout(this); 62 | for (int i = 0; i < noutputs; i += 1) 63 | nodes[i+ninputs].AddDriver(this); 64 | } 65 | 66 | // is specified node always driven to 0 by this device? 67 | public boolean isAlwaysZero(SimNode n) { return false; } 68 | 69 | // initialize state and constant nodes 70 | public void Reset() { } 71 | 72 | // report minimum observed setup time 73 | public double MinObservedSetup() { return Double.POSITIVE_INFINITY; } 74 | public double MinObservedSetupTime() { return -1; } 75 | 76 | // recompute values for outputs because inputs have changed 77 | public void EvaluateC() { } 78 | public void EvaluateP() { } 79 | 80 | // determine whether specified output can be tristated 81 | public boolean Tristate(SimNode n) { return false; } 82 | 83 | // capacitance of terminal(s) connected to this node 84 | public double Capacitance(SimNode n) { return 0; } 85 | 86 | // for timing analysis 87 | public boolean isSource() { return false; } 88 | public boolean isPowerSupply() { return false; } 89 | public TimingInfo getTimingInfo(SimNode node) throws Exception { 90 | return new TimingInfo(node,this); 91 | } 92 | public TimingInfo getClockInfo(SimNode node) throws Exception { 93 | return null; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /simulation/SpiceModel.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2001 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | import java.util.HashMap; 6 | 7 | class SpiceModel { 8 | static final double EPSOX = 3.45314379969e-11; // (F/m) permittivity of silicon dioxide 9 | static final double EPSSIL = 1.035943139907e-10; // (F/m) permittivity of silicon 10 | static final double BOLTZ = 1.3806226e-23; // (J/K) Boltzmann constant 11 | static final double Q = 1.6021918e-19; // (C) electron charge 12 | static final double EG = 1.16; // energy gap 13 | static final double NI = 1.45e16; // (1/(cm^3)) intrinsic carrier concentration 14 | static final double TNOM = 25.0; 15 | static final double MAX_EXP_ARG = 709.0; 16 | 17 | String name; 18 | HashMap options; // name to Double 19 | boolean limited; 20 | 21 | public SpiceModel(String n,HashMap xoptions) { 22 | name = n; 23 | options = xoptions; 24 | } 25 | 26 | public double GetOption(String name,double defaultv) { 27 | Double v = (Double)options.get(name); 28 | return ((v == null) ? defaultv : v.doubleValue()); 29 | } 30 | 31 | // compute vt for a given temperature 32 | public double vt(double temp) { 33 | return BOLTZ*temp/Q; 34 | } 35 | 36 | // compute vcrit 37 | public double vcrit(double vt,double isat_div_by_vt) { 38 | return vt * Math.log(1/(1.4142135 * isat_div_by_vt)); 39 | } 40 | 41 | // limit PN junction voltages 42 | public double pnjlim(double vt,double vnew,double vold,double vcrit) { 43 | limited = false; 44 | if (vnew <= vcrit) return vnew; 45 | double delv = vnew - vold; 46 | if (Math.abs(delv) <= vt+vt) return vnew; 47 | limited = true; 48 | if (vold > 0) { 49 | double arg = 1 + delv/vt; 50 | if (arg > 0) return vold + vt*Math.log(arg); 51 | else return vcrit; 52 | } else return vt * Math.log(vnew/vt); 53 | } 54 | 55 | // limit FET voltages 56 | static final double vdd = 3.3; 57 | static final double v40pct = 0.4 * vdd; 58 | static final double v70pct = 0.7 * vdd; 59 | static final double v80pct = 0.8 * vdd; 60 | 61 | public double fetlim(double vnew,double vold,double vtn) { 62 | double vtsthi = 2*Math.abs(vold - vtn) + v40pct; 63 | double vtstlo = vtsthi/2 + v40pct; 64 | double vtox = vtn + v70pct; 65 | double delv = vnew - vold; 66 | if (vold < vtn) { 67 | if (delv > 0) { 68 | double vtemp = vtn + 0.5; 69 | if (vnew > vtemp) return vtemp; 70 | else if (delv > vtstlo) return vold + vtstlo; 71 | else return vnew; 72 | } else if (-delv > vtsthi) return vold - vtsthi; 73 | else return vnew; 74 | } else if (vold < vtox) { 75 | if (delv > 0) return Math.min(vnew,vtn + v80pct); 76 | else return Math.max(vnew,vtn - 0.5); 77 | } else if (delv > 0) { 78 | if (delv < vtsthi) return vnew; 79 | else return vold + vtsthi; 80 | } else if (vnew < vtox) return Math.max(vnew,vtn + v40pct); 81 | else if (-delv > vtstlo) return vold - vtstlo; 82 | else return vnew; 83 | } 84 | 85 | // limit drain-source voltage 86 | public double limvds(double vnew,double vold) { 87 | if (vold < v70pct) { 88 | if (vnew > vold) return Math.min(vnew,v80pct); 89 | else return Math.max(vnew,-0.5); 90 | } else if (vnew > vold) return Math.min(vnew,3*vold+v40pct); 91 | else if (vnew < v70pct) return Math.max(vnew,v40pct); 92 | else return vnew; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /simulation/SpicePWLSource.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | // piecewise linear source function 6 | class SpicePWLSource extends SpiceSource { 7 | double tvpairs[]; // time,value pairs 8 | int npairs; // number of pairs 9 | double vih,vil; 10 | 11 | public SpicePWLSource(double xdc,double xacmag,double xacphase,double params[],double vil,double vih) { 12 | super(xdc,xacmag,xacphase); 13 | 14 | tvpairs = params; 15 | npairs = (tvpairs == null) ? 0 : tvpairs.length; 16 | this.vih = vih; 17 | this.vil = vil; 18 | } 19 | 20 | public String SourceName() { return "PWL"; } 21 | 22 | public boolean SupportsGateLevelSimulation() { return true; } 23 | 24 | public double NextContaminationTime(double time) { 25 | time += 1e-13; // get past current time by epsilon 26 | double tlast = 0; 27 | double vlast = 0; 28 | for (int i = 0; i < npairs; i += 2) { 29 | double t = tvpairs[i]; 30 | double v = tvpairs[i+1]; 31 | if (i > 0 && time <= t) { 32 | if (vlast >= vih && v < vih) { 33 | double et = tlast + (t - tlast)*(vih - vlast)/(v - vlast); 34 | if (et > time) return et; 35 | } 36 | else if (vlast <= vil && v > vil) { 37 | double et = tlast + (t - tlast)*(vil - vlast)/(v - vlast); 38 | if (et > time) return et; 39 | } 40 | } 41 | tlast = t; 42 | vlast = v; 43 | } 44 | return -1; 45 | } 46 | 47 | public double NextPropagationTime(double time) { 48 | time += 1e-13; // get past current time by epsilon 49 | double tlast = 0; 50 | double vlast = 0; 51 | for (int i = 0; i < npairs; i += 2) { 52 | double t = tvpairs[i]; 53 | double v = tvpairs[i+1]; 54 | if (i > 0 && time <= t) { 55 | if (vlast < vih && v >= vih) { 56 | double et = tlast + (t - tlast)*(vih - vlast)/(v - vlast); 57 | if (et > time) return et; 58 | } 59 | else if (vlast > vil && v <= vil) { 60 | double et = tlast + (t - tlast)*(vil - vlast)/(v - vlast); 61 | if (et > time) return et; 62 | } 63 | } 64 | tlast = t; 65 | vlast = v; 66 | } 67 | return -1; 68 | } 69 | 70 | public double TransientValue(double time) { 71 | double tlast = 0; 72 | double vlast = 0; 73 | for (int i = 0; i < npairs; i += 2) 74 | if (time <= tvpairs[i]) { 75 | if (i == 0) { 76 | //System.out.println("pwl: t="+time+" v="+tvpairs[1]); 77 | return tvpairs[1]; 78 | } else { 79 | //System.out.println("pwl: t="+time+" v="+(vlast+((time-tlast)/(tvpairs[i]-tlast))*(tvpairs[i+1]-vlast))); 80 | return vlast+((time-tlast)/(tvpairs[i]-tlast))*(tvpairs[i+1]-vlast); 81 | } 82 | } else { 83 | tlast = tvpairs[i]; 84 | vlast = tvpairs[i+1]; 85 | } 86 | //System.out.println("pwl: t="+time+" v="+vlast); 87 | return vlast; 88 | } 89 | 90 | // return time of next breakpoint or voltage change of dv volts, 91 | // whichever is sooner 92 | public double NextBreakpoint(double time,double dv) { 93 | double tlast = 0; 94 | double vlast = 0; 95 | for (int i = 0; i < npairs; i += 2) 96 | if (time < tvpairs[i]) { 97 | if (i == 0) return tvpairs[i]; 98 | else { 99 | double sec_per_v = Math.abs((tvpairs[i] - tlast)/(tvpairs[i+1] - vlast)); 100 | return Math.min(tvpairs[i],time + dv * sec_per_v); 101 | } 102 | } else { 103 | tlast = tvpairs[i]; 104 | vlast = tvpairs[i+1]; 105 | } 106 | return -1; 107 | } 108 | 109 | public void ComputeBreakpoints(SpiceNetwork network,double stopTime) { 110 | for (int i = 0; i < npairs; i += 2) 111 | network.AddBreakpoint(tvpairs[i]); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /simulation/SpiceMosfetDiode.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class SpiceMosfetDiode extends SpiceStateDevice { 6 | SpiceMosfet fet; // we'll need some node voltages 7 | int diff; // diffusion node 8 | int bulk; 9 | 10 | SpiceCell dd,db,bd,bb; 11 | SpiceCell s_d,s_b; // source vector entries 12 | double isat,isat_div_by_vt,vcrit,a_cj,p_cjsw; 13 | double coeffA,coeffB; 14 | 15 | public SpiceMosfetDiode(SpiceMosfet fet,int diff,int bulk, 16 | double rdiff,double area,double perimeter) { 17 | super(fet.network,area*fet.model.cj + perimeter*fet.model.cjsw,false); 18 | this.fet = fet; 19 | 20 | // see if we need to add diff resistor 21 | this.diff = diff; 22 | this.bulk = bulk; 23 | if (rdiff > 0) { 24 | int xdiff = diff; 25 | this.diff = diff = network.size++; 26 | network.nodes.put("diff("+xdiff+")",new Integer(diff)); 27 | double gdiff = 1/rdiff; 28 | network.FindMatrixElement(xdiff,xdiff).gExp += gdiff; 29 | network.FindMatrixElement(xdiff,diff).gExp -= gdiff; 30 | network.FindMatrixElement(diff,xdiff).gExp -= gdiff; 31 | network.FindMatrixElement(diff,diff).gExp += gdiff; 32 | } 33 | 34 | // get all the matrix cells we'll need 35 | dd = network.FindMatrixElement(diff,diff); 36 | db = network.FindMatrixElement(diff,bulk); 37 | bb = network.FindMatrixElement(bulk,bulk); 38 | bd = network.FindMatrixElement(bulk,diff); 39 | s_d = network.FindSourceElement(diff); 40 | s_b = network.FindSourceElement(bulk); 41 | 42 | // add minimum conductances for PN junction 43 | double gmin = network.gmin; 44 | dd.gExp += gmin; 45 | db.gExp -= gmin; 46 | bd.gExp -= gmin; 47 | bb.gExp += gmin; 48 | 49 | // precompute diode parameters 50 | SpiceMOSModel model = fet.model; 51 | isat = area*model.js + perimeter*model.jsw; 52 | if (isat <=0) isat = area*model.is; 53 | isat_div_by_vt = isat/model.vt_temp; 54 | vcrit = model.vcrit(model.vt_temp,isat_div_by_vt); 55 | a_cj = area*model.cj; 56 | p_cjsw = perimeter*model.cjsw; 57 | 58 | coeffA = (model.pb * a_cj)/(1 - model.m_mj); 59 | coeffB = (model.pb * p_cjsw)/(1 - model.m_mjsw); 60 | } 61 | 62 | public void DiodeCurrents(double vbdo,int mode) { 63 | if (isat != 0) { 64 | SpiceMOSModel model = fet.model; 65 | double gbd; 66 | if (vbdo > 0) { 67 | double evbd = Math.exp(Math.min(SpiceModel.MAX_EXP_ARG,vbdo/model.vt_temp)); 68 | gbd = isat_div_by_vt * evbd; 69 | double ieqbd = model.m_type*(isat*(evbd - 1) - gbd*vbdo); 70 | s_b.luExp -= ieqbd; 71 | s_d.luExp += ieqbd; 72 | double arg = vbdo/model.pb; 73 | value = a_cj*(1 + model.m_mj*arg) + p_cjsw*(1 + model.m_mjsw*arg); 74 | // this isn't right but the diffusion diodes 75 | // are rarely forward biased so this will do for now... 76 | x = value * vbdo; // set charge 77 | } else { 78 | gbd = isat_div_by_vt; 79 | double arg = 1 - vbdo/model.pb; 80 | double sarg = Math.pow(arg,-model.m_mj); 81 | double sargsw = Math.pow(arg,-model.m_mjsw); 82 | value = a_cj*sarg + p_cjsw*sargsw; 83 | x = value * vbdo; // set charge 84 | // doesn't converge: x = coeffA*(1 - arg*sarg) + coeffB*(1 - arg*sargsw)); 85 | } 86 | bb.luExp += gbd; 87 | dd.luExp += gbd; 88 | bd.luExp -= gbd; 89 | db.luExp -= gbd; 90 | 91 | // capacitance calculations 92 | if (mode == SpiceNetwork.TRANSIENT_ANALYSIS) { 93 | Integrate(); 94 | xprimeEQ *= model.m_type; 95 | s_b.luExp -= xprimeEQ; 96 | s_d.luExp += xprimeEQ; 97 | dd.luExp += geq; 98 | db.luExp -= geq; 99 | bd.luExp -= geq; 100 | bb.luExp += geq; 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /netlist/Number.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2011 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | class Number extends Token { 6 | public double value; // value 7 | 8 | public Number(double v,Netlist netlist,int s,int e) { 9 | super(netlist,s,e); 10 | value = v; 11 | } 12 | 13 | // see if we can interpret line[lineOffset...] as a number 14 | static public Number Parse(StringBuffer line,Netlist netlist,int lineOffset) { 15 | int lineLength = line.length(); 16 | double multiplier = 1; // multiply final number by this 17 | double value = 0; 18 | int ch; 19 | int start; 20 | 21 | // skip over blanks 22 | while (lineOffset < lineLength && line.charAt(lineOffset) <= ' ') 23 | lineOffset += 1; 24 | start = lineOffset; 25 | 26 | // see if we can parse a signed number 27 | if (lineOffset < lineLength) { 28 | if ((ch = line.charAt(lineOffset)) == '+') lineOffset += 1; 29 | else if (ch == '-') { multiplier = -1; lineOffset +=1; } 30 | } 31 | int radix = 10; 32 | if (lineOffset < lineLength && ((ch = line.charAt(lineOffset))=='0')) { 33 | lineOffset += 1; 34 | if (lineOffset < lineLength) { 35 | ch = line.charAt(lineOffset); 36 | if (ch == 'x') { lineOffset +=1; radix = 16; } 37 | else if (ch == 'b') { lineOffset +=1; radix = 2; } 38 | else radix = 8; 39 | } 40 | } 41 | while (lineOffset < lineLength) { 42 | ch = line.charAt(lineOffset); 43 | if (radix == 2 && ch == '_') { 44 | // skip over underscores in binary numbers 45 | lineOffset += 1; 46 | continue; 47 | } 48 | else if (radix <= 10) { 49 | ch -= '0'; 50 | if (ch < 0 || ch >= radix) break; 51 | } else { 52 | ch -= '0'; 53 | if (ch < 0) break; 54 | if (ch > 9) { 55 | ch -= 'A' - '0' - 10; 56 | if (ch < 10) break; 57 | if (ch >= radix) { 58 | ch -= 'a' - 'A'; 59 | if (ch < 10 || ch >= radix) break; 60 | } 61 | } 62 | } 63 | value = radix*value + ch; 64 | lineOffset += 1; 65 | } 66 | 67 | // fractional part? 68 | if (lineOffset < lineLength && line.charAt(lineOffset)=='.') { 69 | lineOffset += 1; 70 | while (lineOffset < lineLength && 71 | ((ch = line.charAt(lineOffset))>='0' && ch<='9')) { 72 | value = 10*value + (ch - '0'); 73 | multiplier /= 10; 74 | lineOffset += 1; 75 | } 76 | } 77 | 78 | // see if we've found anything 79 | if (lineOffset == start) return null; 80 | 81 | // now see if there's an exponent specified 82 | value *= multiplier; 83 | if (lineOffset < lineLength) { 84 | switch(Character.toLowerCase(line.charAt(lineOffset))) { 85 | case 'e': 86 | int exponent = 0; 87 | boolean expNegative = false; 88 | lineOffset += 1; 89 | if (lineOffset < lineLength) { 90 | if ((ch = line.charAt(lineOffset)) == '+') lineOffset += 1; 91 | else if (ch == '-') { expNegative = true; lineOffset +=1; } 92 | } 93 | while (lineOffset < lineLength && 94 | ((ch = line.charAt(lineOffset))>='0' && ch<='9')) { 95 | exponent = 10*exponent + (ch - '0'); 96 | lineOffset += 1; 97 | } 98 | while (exponent-- > 0) value *= (expNegative ? .1 : 10.0); 99 | break; 100 | case 't': value *= 1e12; break; 101 | case 'g': value *= 1e9; break; 102 | case 'k': value *= 1e3; break; 103 | case 'u': value *= 1e-6; break; 104 | case 'n': value *= 1e-9; break; 105 | case 'p': value *= 1e-12; break; 106 | case 'f': value *= 1e-15; break; 107 | case 'm': 108 | if (lineOffset+2 < lineLength) { 109 | if (Character.toLowerCase(line.charAt(lineOffset+1))=='e' && 110 | Character.toLowerCase(line.charAt(lineOffset+2))=='g') { 111 | value *= 1e6; 112 | break; 113 | } else if (Character.toLowerCase(line.charAt(lineOffset+1))=='i' && 114 | Character.toLowerCase(line.charAt(lineOffset+2))=='l') { 115 | value *= 25.4e-6; 116 | break; 117 | } 118 | } 119 | value *= 1e-3; 120 | break; 121 | } 122 | } 123 | 124 | // skip any remaining suffix 125 | while (lineOffset < lineLength && Identifier.IdChar(line.charAt(lineOffset))) 126 | lineOffset += 1; 127 | return new Number(value,netlist,start,lineOffset); 128 | } 129 | } 130 | 131 | -------------------------------------------------------------------------------- /jsim/BatchSimNetlistConsumer.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 Christopher J. Terman - All Rights Reserved. 2 | 3 | package jsim; 4 | 5 | import netlist.NetlistConsumer; 6 | import netlist.Parameter; 7 | import java.util.ArrayList; 8 | import java.util.Enumeration; 9 | import java.util.Hashtable; 10 | import java.util.HashMap; 11 | 12 | public class BatchSimNetlistConsumer implements NetlistConsumer { 13 | // keep track of device counts 14 | public Hashtable counts = new Hashtable(); 15 | 16 | public BatchSimNetlistConsumer() { 17 | } 18 | 19 | // return JSON summary of device counts 20 | public String Summary() { 21 | StringBuffer result = new StringBuffer(); 22 | result.append("{"); 23 | boolean first = true; 24 | 25 | for (Enumeration e = counts.keys(); e.hasMoreElements();) { 26 | String devtype = e.nextElement(); 27 | if (first) first = false; 28 | else result.append(","); 29 | result.append("\""+devtype+"\":"+counts.get(devtype)); 30 | } 31 | 32 | result.append("}"); 33 | return result.toString(); 34 | } 35 | 36 | public String Problem() { return null; } 37 | 38 | // models 39 | public Object MakeModel(String name,int mtype,HashMap options) { 40 | if (mtype == NetlistConsumer.NMOS) return "n"; 41 | else if (mtype == NetlistConsumer.PMOS) return "p"; 42 | else return "?"; 43 | } 44 | 45 | // nodes 46 | public Object FindNode(String name,boolean create) { 47 | return name; 48 | } 49 | 50 | public Object MakeGndNode(String name) { 51 | return "GND"; // canoncialize name of ground node 52 | } 53 | 54 | public void NodeAlias(Object node,String alias) {} 55 | public void ConnectNodes(Object n1,Object n2) {} 56 | 57 | // increment count for a particular device type 58 | public void Increment(String devtype) { 59 | Integer count = counts.get(devtype); 60 | if (count == null) count = new Integer(0); 61 | counts.put(devtype,new Integer(count.intValue() + 1)); 62 | } 63 | 64 | // built-in gates 65 | public boolean MakeGate(String id,String function,ArrayList nodes,Parameter params) { 66 | Increment(function); 67 | return true; 68 | } 69 | 70 | // devices 71 | public boolean MakeResistor(String id,Object n1,Object n2,double resistance) { 72 | Increment("resistor"); 73 | return true; 74 | } 75 | 76 | public boolean MakeCapacitor(String id,Object n1,Object n2,double capacitance) { 77 | Increment("capacitor"); 78 | return true; 79 | } 80 | 81 | public boolean MakeInductor(String id,Object n1,Object n2,double Inductance) { 82 | Increment("inductor"); 83 | return true; 84 | } 85 | 86 | public boolean MakeMosfet(String id,Object d,Object g,Object s,Object b, 87 | Object model,double l,double w,double sl,double sw, 88 | double ad,double pd,double nrd,double rdc, 89 | double as,double ps,double nrs,double rsc) { 90 | Increment((String)model + "fet"); 91 | return true; 92 | } 93 | 94 | public boolean MakeIndependentVoltageSource(String id,Object npos,Object nneg, 95 | double dc,double acmag,double acphase, 96 | int trantype,double params[]) { 97 | Increment("v"); 98 | return true; 99 | } 100 | 101 | public boolean MakeIndependentCurrentSource(String id,Object npos,Object nneg, 102 | double dc,double acmag,double acphase, 103 | int trantype,double params[]) { 104 | Increment("i"); 105 | return true; 106 | } 107 | 108 | public boolean MakeVCVS(String id,Object npos,Object nneg, 109 | Object ncpos,Object ncneg,double gain) { 110 | Increment("vcvs"); 111 | return true; 112 | } 113 | 114 | public boolean MakeVCCS(String id,Object npos,Object nneg, 115 | Object ncpos,Object ncneg,double gain) { 116 | Increment("vccs"); 117 | return true; 118 | } 119 | 120 | public boolean MakeCCVS(String id,Object npos,Object nneg, 121 | Object ncpos,Object ncneg,double gain) { 122 | Increment("ccvs"); 123 | return true; 124 | } 125 | 126 | public boolean MakeCCCS(String id,Object npos,Object nneg, 127 | Object ncpos,Object ncneg,double gain) { 128 | Increment("cccs"); 129 | return true; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /simulation/EmuMOSModel.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | class EmuMOSModel { 6 | static final int VSBSIZE = 100; 7 | static final int VSATSIZE = 20; 8 | static final int VSATMIN = -1; 9 | static final int VDSSIZE = 50; 10 | 11 | SpiceMOSModel model; // parameters for this model 12 | double width; 13 | double length; 14 | boolean nmos; 15 | 16 | // 1D table lookup for VSB -> VTH 17 | double vsbQuanta; 18 | double vthTable[]; 19 | 20 | // 2D table lookup for VSAT, VDS -> IDS, GDS, GM 21 | double vsatQuanta; 22 | double vdsQuanta; 23 | double idsTable[]; 24 | double gdsTable[]; 25 | double gmTable[]; 26 | 27 | public EmuMOSModel(SpiceMOSModel m,double w,double l,double vmax) { 28 | model = m; 29 | width = w; 30 | length = l; 31 | nmos = (m.m_type == 1); 32 | 33 | // we'll be using our Spice setup to build the tables 34 | SpiceMosfet fet = new SpiceMosfet(m,l,w); 35 | 36 | // set up VTH table 37 | vsbQuanta = vmax/VSBSIZE; 38 | vthTable = new double[VSBSIZE]; 39 | for (int i = 0; i < VSBSIZE; i += 1) { 40 | fet.QueryModel(0,0,-(i*vsbQuanta)); 41 | vthTable[i] = fet.vth; 42 | } 43 | 44 | // set up IDS, GDS and GM tables 45 | vsatQuanta = (vmax - VSATMIN)/VSATSIZE; 46 | vdsQuanta = vmax/VDSSIZE; 47 | idsTable = new double[VSATSIZE * VDSSIZE]; 48 | gdsTable = new double[VSATSIZE * VDSSIZE]; 49 | gmTable = new double[VSATSIZE * VDSSIZE]; 50 | for (int i = 0; i < VSATSIZE; i += 1) 51 | for (int j = 0; j < VDSSIZE; j += 1) { 52 | try { 53 | // vgs = vsat + vth 54 | double vgs = (i*vsatQuanta + VSATMIN) + vthTable[0]; 55 | fet.QueryModel(j*vdsQuanta,vgs,0); 56 | 57 | int index = i*VDSSIZE + j; 58 | idsTable[index] = fet.ids; 59 | 60 | if (j > 0) 61 | gdsTable[index-1] = (fet.ids - idsTable[index-1])/vdsQuanta; 62 | if (j == VDSSIZE - 1) 63 | gdsTable[index] = gdsTable[index-1]; 64 | 65 | int prevrow = index - VDSSIZE; 66 | if (i > 0) 67 | gmTable[prevrow] = (fet.ids - idsTable[prevrow])/vsatQuanta; 68 | if (i == VSATSIZE - 1) 69 | gmTable[index] = gmTable[prevrow]; 70 | } 71 | catch (Exception e) { 72 | System.out.println("i="+i+" j="+j+" e="+e); 73 | } 74 | } 75 | } 76 | 77 | public boolean Match(SpiceMOSModel m,double w,double l) { 78 | return m==model && w==width && l==length; 79 | } 80 | 81 | public void ids_gds(EmuMosfet fet,double vg,double vs,double vd,double vb) { 82 | double vds,vgs,vsb,sign; 83 | 84 | if (nmos) { 85 | if (vd > vs) { 86 | vds = vd - vs; 87 | vgs = vg - vs; 88 | vsb = vs - vb; 89 | sign = 1; 90 | } else { 91 | vds = vs - vd; 92 | vgs = vg - vd; 93 | vsb = vd - vb; 94 | sign = -1; 95 | } 96 | } else { 97 | if (vd > vs) { 98 | vds = vd - vs; 99 | vgs = vd - vg; 100 | vsb = vb - vd; 101 | sign = 1; 102 | } else { 103 | vds = vs - vd; 104 | vgs = vs - vg; 105 | vsb = vb - vs; 106 | sign = -1; 107 | } 108 | } 109 | 110 | int vsbIndex; 111 | if (vsb < 0) vsbIndex = 0; 112 | else { 113 | vsbIndex = (int)Math.floor(vsb/vsbQuanta); 114 | if (vsbIndex >= VSBSIZE) vsbIndex = VSBSIZE - 1; 115 | } 116 | double vsat = vgs - vthTable[vsbIndex]; 117 | //System.out.println("vsbIndex="+vsbIndex+" vsat="+vsat); 118 | 119 | // we assume that the device is off when vsat < VSATMIN, 120 | // and start our table at vsat = VSATMIN 121 | if (vsat < VSATMIN) { 122 | fet.ids = 0; 123 | fet.gds = 0; 124 | } else { 125 | vsat -= VSATMIN; 126 | int vsatIndex = (int)Math.floor(vsat/vsatQuanta); 127 | if (vsatIndex >= VSATSIZE) vsatIndex = VSATSIZE - 1; 128 | 129 | // we know vds >= 0 130 | int vdsIndex = (int)Math.floor(vds/vdsQuanta); 131 | if (vdsIndex >= VDSSIZE) vdsIndex = VDSSIZE - 1; 132 | 133 | int index = vsatIndex * VDSSIZE + vdsIndex; 134 | fet.gds = gdsTable[index]; 135 | // use GDS and GM to compensate for the fact that we 136 | // rounded off vsat and vds when we accessed the table 137 | fet.ids = sign*(idsTable[index] 138 | + fet.gds*(vds - vdsIndex*vdsQuanta) 139 | + gmTable[index]*(vsat - vsatIndex*vsatQuanta)); 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /simulation/SimDReg.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2007 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class SimDReg extends SimDevice { 8 | static final int D = 0; // node indicies 9 | static final int CLK = 1; 10 | static final int Q = 2; 11 | 12 | boolean lenient; // input change doesn't force contamination 13 | double tcd; // contamination delay from any input to output 14 | double tpdr; // rising propagation delay from any input to output 15 | double tr; // load dependent L->H delay (s/f) 16 | double tpdf; // falling propagation delay from any input to output 17 | double tf; // load dependent H->L delay (s/f) 18 | double ts; // setup time 19 | double th; // hold time 20 | double cin; // capacitance of inputs 21 | double cout; // capacitance of output 22 | 23 | int master; // value we're saving 24 | double minSetup; // minimum setup time we've seen 25 | double minSetupTime; // time we saw minSetup 26 | 27 | public SimDReg(String id,ArrayList inout,double tcd,double tpdr, 28 | double tr,double tpdf,double tf,double ts,double th, 29 | double cin,double cout,double dsize,boolean lenient) { 30 | super(id,2,1); 31 | 32 | this.tcd = tcd; 33 | this.tpdr = tpdr; 34 | this.tr = tr; 35 | this.tpdf = tpdf; 36 | this.tf = tf; 37 | this.ts = ts; 38 | this.th = th; 39 | this.cin = cin; 40 | this.cout = cout; 41 | this.lenient = lenient; 42 | 43 | // store input and output nodes, fix up fanout/driver lists 44 | nodes[D] = (SimNode)inout.get(D); 45 | nodes[CLK] = (SimNode)inout.get(CLK); 46 | nodes[Q] = (SimNode)inout.get(Q); 47 | SetupNodes(); 48 | nodes[D].network.AddDevice(this,dsize); 49 | 50 | nodes[CLK].setClock(); // special treatment during timing analysis 51 | } 52 | 53 | // initialize state 54 | public void Reset() { 55 | minSetup = Double.POSITIVE_INFINITY; 56 | minSetupTime = -1; 57 | master = Node.VX; 58 | } 59 | 60 | // report minimum observed setup time 61 | public double MinObservedSetup() { return minSetup; } 62 | public double MinObservedSetupTime() { return minSetupTime; } 63 | 64 | // change D regs to propagate C & D events only when clock 65 | // makes transition to "1". 66 | 67 | // recompute values for outputs because inputs have changed 68 | public void EvaluateP() { 69 | SimNode clk = nodes[CLK]; 70 | if (clk.v == Node.V0) master = nodes[D].v; 71 | else if (clk.Trigger()) { 72 | if (clk.v == Node.V1) { 73 | // track minimum setup time we see 74 | double now = clk.network.time; 75 | double tsetup = now - nodes[D].lastEvent; 76 | if (now > 0 && tsetup < minSetup) { 77 | minSetup = tsetup; 78 | minSetupTime = now; 79 | } 80 | // report setup time violations? 81 | 82 | if (!lenient || master != nodes[Q].v) 83 | // for lenient dreg's, q output is propagated only 84 | // when new output value differs from current one 85 | nodes[Q].ScheduleCEvent(tcd); 86 | nodes[Q].SchedulePEvent((master == Node.V0) ? tpdf : tpdr, 87 | master, 88 | (master == Node.V0) ? tf : tr, 89 | lenient); 90 | } else { 91 | // X on clock won't contaminate value in master if we're 92 | // a lenient register and master == D 93 | if (!lenient || master != nodes[D].v) 94 | master = Node.VX; 95 | // send along to Q if we're not lenient or if master != Q 96 | if (!lenient || master != nodes[Q].v) 97 | nodes[Q].SchedulePEvent(Math.min(tpdf,tpdr),Node.VX,0,lenient); 98 | } 99 | } 100 | } 101 | 102 | public TimingInfo getTimingInfo(SimNode output) throws Exception { 103 | TimingInfo result = super.getTimingInfo(output); 104 | 105 | // add delay info for this gate 106 | double t1 = tpdr + tr*output.capacitance; 107 | double t2 = tpdf + tf*output.capacitance; 108 | result.setSpecs(tcd,Math.max(t1,t2)); 109 | 110 | // timing is with respect to CLK input 111 | result.setDelays(nodes[CLK].getTimingInfo()); 112 | 113 | return result; 114 | } 115 | 116 | public TimingInfo getClockInfo(SimNode clk) throws Exception { 117 | if (nodes[CLK] != clk || nodes[D].isPowerSupply()) return null; 118 | 119 | TimingInfo result = new TimingInfo(clk,this); 120 | result.setSpecs(-th,ts); 121 | result.setDelays(nodes[D].getTimingInfo()); 122 | 123 | return result; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /netlist/IndependentSourcePrototype.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | import java.util.ArrayList; 6 | 7 | class IndependentSourcePrototype extends DevicePrototype { 8 | static final int VoltageSource = 1; 9 | static final int CurrentSource = 2; 10 | 11 | int type; // type of source 12 | Node npos; // two terminal nodes 13 | Node nneg; 14 | Number dc; // dc source value 15 | Number acmag; // ac source magnitude 16 | Number acphase; // ac source phase 17 | int tranfun; // transient source function 18 | ArrayList params; // parameters for transient source 19 | 20 | public IndependentSourcePrototype(Identifier s_id,int s_type,Node s_pos,Node s_neg, 21 | Number s_dc,Number s_acmag,Number s_acphase, 22 | int s_tranfun,ArrayList s_params) { 23 | id = s_id; 24 | type = s_type; 25 | npos = s_pos; 26 | nneg = s_neg; 27 | dc = s_dc; 28 | acmag = s_acmag; 29 | acphase = s_acphase; 30 | tranfun = s_tranfun; 31 | params = s_params; 32 | } 33 | 34 | // convert string into appropriate transient function type 35 | static int SourceFunctionType(String name) { 36 | if (name.equalsIgnoreCase("pwl")) return NetlistConsumer.PWL; 37 | else if (name.equalsIgnoreCase("pulse")) return NetlistConsumer.PULSE; 38 | else if (name.equalsIgnoreCase("sin")) return NetlistConsumer.SIN; 39 | else if (name.equalsIgnoreCase("exp")) return NetlistConsumer.EXP; 40 | else if (name.equalsIgnoreCase("sffm")) return NetlistConsumer.SFFM; 41 | else if (name.equalsIgnoreCase("am")) return NetlistConsumer.AM; 42 | else return 0; 43 | } 44 | 45 | // check parameters supplied for a transient source function 46 | static boolean CheckParams(Netlist v,int trantype,ArrayList p) { 47 | switch (trantype) { 48 | case NetlistConsumer.PWL: 49 | double last = 0; 50 | for (int i = 0; i < p.size(); i += 2) { 51 | Number n = (Number)p.get(i); 52 | if (i > 0 && n.value <= last) { 53 | v.Error(n,"PWL times not monotonically increasing"); 54 | return false; 55 | } 56 | last = n.value; 57 | if (i+1 == p.size()) { 58 | v.Error("Expected even number of parameters for PWL"); 59 | return false; 60 | } 61 | } 62 | return true; 63 | case NetlistConsumer.PULSE: 64 | if (p.size() < 6) { 65 | v.Error("Expected at least six parameters for PULSE"); 66 | return false; 67 | } 68 | Number n = (Number)p.get(2); 69 | if (n.value < 0) { 70 | v.Error(n,"PULSE delay parameter cannot be negative"); 71 | return false; 72 | } 73 | n = (Number)p.get(3); 74 | if (n.value <= 0) { 75 | v.Error(n,"PULSE rise time parameter must be greater than zero"); 76 | return false; 77 | } 78 | n = (Number)p.get(4); 79 | if (n.value <= 0) { 80 | v.Error(n,"PULSE fall time parameter must be greater than zero"); 81 | return false; 82 | } 83 | n = (Number)p.get(5); 84 | if (n.value < 0) { 85 | v.Error(n,"PULSE width parameter cannot be negative"); 86 | return false; 87 | } 88 | return true; 89 | case NetlistConsumer.SIN: 90 | return true; 91 | case NetlistConsumer.EXP: 92 | return true; 93 | case NetlistConsumer.SFFM: 94 | return true; 95 | case NetlistConsumer.AM: 96 | return true; 97 | } 98 | return false; 99 | } 100 | 101 | // add device to netlist 102 | public boolean Netlist(Netlist network,NetlistConsumer n) { 103 | int nparams = (params!=null) ? params.size() : 0; 104 | double p[] = null; 105 | 106 | if (nparams > 0) { 107 | p = new double[nparams]; 108 | for (int i = 0; i < nparams; i += 1) 109 | p[i] = ((Number)params.get(i)).value; 110 | } 111 | 112 | switch (type) { 113 | case VoltageSource: 114 | n.MakeIndependentVoltageSource(network.prefix + id.name, 115 | npos.netlisterNode,nneg.netlisterNode, 116 | dc==null ? Double.NEGATIVE_INFINITY : dc.value, 117 | acmag==null ? 0 : acmag.value, 118 | acphase==null ? 0 : acphase.value, 119 | tranfun,p); 120 | break; 121 | case CurrentSource: 122 | n.MakeIndependentCurrentSource(network.prefix + id.name, 123 | npos.netlisterNode,nneg.netlisterNode, 124 | dc==null ? Double.NEGATIVE_INFINITY : dc.value, 125 | acmag==null ? 0 : acmag.value, 126 | acphase==null ? 0 : acphase.value, 127 | tranfun,p); 128 | break; 129 | } 130 | return true; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /simulation/SimDLatch.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2007 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class SimDLatch extends SimDevice { 8 | static final int D = 0; // node indicies 9 | static final int G = 1; 10 | static final int Q = 2; 11 | 12 | boolean lenient; // input change doesn't force contamination 13 | double tcd; // contamination delay from any input to output 14 | double tpdr; // rising propagation delay from any input to output 15 | double tr; // load dependent L->H delay (s/f) 16 | double tpdf; // falling propagation delay from any input to output 17 | double tf; // load dependent H->L delay (s/f) 18 | double ts; // setup time 19 | double th; // hold time 20 | double cin; // capacitance of inputs 21 | double cout; // capacitance of output 22 | 23 | int master; // value we're saving 24 | double minSetup; // minimum setup time we've seen 25 | double minSetupTime; // time we saw minSetup 26 | 27 | public SimDLatch(String id,ArrayList inout,double tcd,double tpdr, 28 | double tr,double tpdf,double tf,double ts,double th, 29 | double cin,double cout,double dsize,boolean lenient) { 30 | super(id,2,1); 31 | 32 | this.tcd = tcd; 33 | this.tpdr = tpdr; 34 | this.tr = tr; 35 | this.tpdf = tpdf; 36 | this.tf = tf; 37 | this.ts = ts; 38 | this.th = th; 39 | this.cin = cin; 40 | this.cout = cout; 41 | this.lenient = lenient; 42 | 43 | // store input and output nodes, fix up fanout/driver lists 44 | nodes[D] = (SimNode)inout.get(D); 45 | nodes[G] = (SimNode)inout.get(G); 46 | nodes[Q] = (SimNode)inout.get(Q); 47 | SetupNodes(); 48 | nodes[D].network.AddDevice(this,dsize); 49 | } 50 | 51 | // initialize state 52 | public void Reset() { 53 | minSetup = Double.POSITIVE_INFINITY; 54 | minSetupTime = -1; 55 | master = Node.VX; 56 | } 57 | 58 | // report minimum observed setup time 59 | public double MinObservedSetup() { return minSetup; } 60 | public double MinObservedSetupTime() { return minSetupTime; } 61 | 62 | // override this method if table lookup doesn't do the job 63 | public int ComputeOutputValue() { 64 | int g = nodes[G].v; 65 | int d = nodes[D].v; 66 | if (g == Node.V0) return master; 67 | else if (g == Node.V1 || master == d) return d; 68 | else return Node.VX; 69 | } 70 | 71 | // some input node has just processed a contamination event 72 | public void EvaluateC() { 73 | SimNode onode = nodes[Q]; 74 | int v = ComputeOutputValue(); 75 | 76 | // master follows D when G = 1 77 | if (nodes[G].v == Node.V1) master = v; 78 | 79 | // a lenient gate won't contaminate the output under the 80 | // right circumstances 81 | if (lenient) { 82 | if (onode.pdEvent == null) { 83 | // no events pending and current value is same as new value 84 | if (onode.cdEvent == null && v == onode.v) return; 85 | } else { 86 | // node is destined to have the same value as new value 87 | if (v == onode.pdEvent.v) return; 88 | } 89 | } 90 | 91 | // schedule contamination event with specified delay 92 | onode.ScheduleCEvent(tcd); 93 | } 94 | 95 | // some input node has just processed a propagation event 96 | public void EvaluateP() { 97 | SimNode onode = nodes[ninputs]; 98 | int v = ComputeOutputValue(); 99 | 100 | // master follows D when G = 1 101 | if (nodes[G].v == Node.V1) master = v; 102 | 103 | if (!lenient || v != onode.v || onode.cdEvent != null || onode.pdEvent != null) { 104 | double drive,tpd; 105 | if (v == Node.V1) { tpd = tpdr; drive = tr; } 106 | else if (v == Node.V0) { tpd = tpdf; drive = tf; } 107 | else { tpd = Math.min(tpdr,tpdf); drive = 0; } 108 | onode.SchedulePEvent(tpd,v,drive,lenient); 109 | } 110 | } 111 | 112 | public TimingInfo getTimingInfo(SimNode output) throws Exception { 113 | TimingInfo result = super.getTimingInfo(output); 114 | 115 | // add delay info for this gate 116 | double t1 = tpdr + tr*output.capacitance; 117 | double t2 = tpdf + tf*output.capacitance; 118 | result.setSpecs(tcd,Math.max(t1,t2)); 119 | 120 | // loop through inputs looking for min/max paths. Treat latch 121 | // like an ordinary gate for timing purposes. 122 | for (int i = 0; i < 2; i += 1) { 123 | if (nodes[i].isPowerSupply()) continue; 124 | TimingInfo t = nodes[i].getTimingInfo(); 125 | result.setDelays(t); 126 | } 127 | 128 | return result; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /simulation/SimLogicDevice.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2007 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class SimLogicDevice extends SimDevice { 8 | boolean lenient; // input change doesn't force contamination 9 | boolean tristate; // output can be tristated 10 | double tcd; // contamination delay from any input to output 11 | double tpdr; // rising propagation delay from any input to output 12 | double tr; // load dependent L->H delay (s/f) 13 | double tpdf; // falling propagation delay from any input to output 14 | double tf; // load dependent H->L delay (s/f) 15 | double cin; // capacitance of inputs 16 | double cout; // capacitance of output 17 | SimLookupTable tbl; 18 | 19 | 20 | public SimLogicDevice(String name,ArrayList inout,double tcd,double tpdr,double tr,double tpdf,double tf,double cin,double cout,double size,boolean lenient,boolean tristate,SimLookupTable tbl) { 21 | super(name,inout.size()-1,1); 22 | 23 | // store input and output nodes, fix up fanout/driver lists 24 | for (int i = 0; i <= ninputs; i += 1) 25 | nodes[i] = (SimNode)inout.get(i); 26 | SetupNodes(); 27 | 28 | nodes[0].network.AddDevice(this,size); 29 | this.tcd = tcd; 30 | this.tpdr = tpdr; 31 | this.tr = tr; 32 | this.tpdf = tpdf; 33 | this.tf = tf; 34 | this.cin = cin; 35 | this.cout = cout; 36 | this.lenient = lenient; 37 | this.tristate = tristate; 38 | this.tbl = tbl; 39 | } 40 | 41 | // override this method if table lookup doesn't do the job 42 | public int ComputeOutputValue() { 43 | SimLookupTable t = tbl; 44 | if (t == null) return Node.VX; 45 | 46 | for (int i = 0; i < ninputs; i += 1) 47 | t = t.table[nodes[i].v]; 48 | return t.value; 49 | } 50 | 51 | // check for constant generators 52 | public void Reset() { 53 | int v = ComputeOutputValue(); 54 | if (v == Node.V0 || v == Node.V1) { 55 | nodes[ninputs].ScheduleCEvent(tcd); 56 | nodes[ninputs].SchedulePEvent((v == Node.V0) ? tpdf : tpdr, 57 | v, 58 | (v == Node.V0) ? tf : tr, 59 | false); 60 | } 61 | } 62 | 63 | // is specified node always driven to 0 by this device? 64 | public boolean isAlwaysZero(SimNode n) { 65 | return ninputs == 0 && tbl.value==Node.V0; 66 | } 67 | 68 | // some input node has just processed a contamination event 69 | public void EvaluateC() { 70 | SimNode onode = nodes[ninputs]; 71 | 72 | // a lenient gate won't contaminate the output under the 73 | // right circumstances 74 | if (lenient) { 75 | int v = ComputeOutputValue(); 76 | if (onode.pdEvent == null) { 77 | // no events pending and current value is same as new value 78 | if (onode.cdEvent == null && v == onode.v) return; 79 | } else { 80 | // node is destined to have the same value as new value 81 | if (v == onode.pdEvent.v) return; 82 | } 83 | } 84 | 85 | // schedule contamination event with specified delay 86 | onode.ScheduleCEvent(tcd); 87 | } 88 | 89 | // some input node has just processed a propagation event 90 | public void EvaluateP() { 91 | SimNode onode = nodes[ninputs]; 92 | int v = ComputeOutputValue(); 93 | if (!lenient || v != onode.v || onode.cdEvent != null || onode.pdEvent != null) { 94 | double drive,tpd; 95 | if (v == Node.V1) { tpd = tpdr; drive = tr; } 96 | else if (v == Node.V0) { tpd = tpdf; drive = tf; } 97 | else { tpd = Math.min(tpdr,tpdf); drive = 0; } 98 | onode.SchedulePEvent(tpd,v,drive,lenient); 99 | } 100 | } 101 | 102 | // determine whether specified output can be tristated 103 | public boolean Tristate(SimNode n) { return tristate; } 104 | 105 | // capacitance of terminal(s) connected to this node 106 | public double Capacitance(SimNode n) { 107 | double c = 0; 108 | for (int i = 0; i < ninputs; i += 1) 109 | if (nodes[i] == n) c += cin; 110 | if (nodes[ninputs] == n) c += cout; 111 | return c; 112 | } 113 | 114 | // for timing analysis 115 | public boolean isPowerSupply() { 116 | return name.endsWith("_power_supply"); 117 | } 118 | 119 | public TimingInfo getTimingInfo(SimNode output) throws Exception { 120 | TimingInfo result = super.getTimingInfo(output); 121 | 122 | // add delay info for this gate 123 | double t1 = tpdr + tr*output.capacitance; 124 | double t2 = tpdf + tf*output.capacitance; 125 | result.setSpecs(tcd,Math.max(t1,t2)); 126 | 127 | // loop through inputs looking for min/max paths 128 | for (int i = 0; i < ninputs; i += 1) { 129 | if (nodes[i].isPowerSupply()) continue; 130 | TimingInfo t = nodes[i].getTimingInfo(); 131 | result.setDelays(t); 132 | } 133 | 134 | return result; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /fsm/Elevator.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2002 Christopher J. Terman - All Rights Reserved. 2 | 3 | package fsm; 4 | 5 | import gui.EditBuffer; 6 | import gui.GuiFrame; 7 | import gui.POSTStream; 8 | import gui.UI; 9 | import java.awt.Component; 10 | import java.awt.GridBagConstraints; 11 | import java.awt.GridBagLayout; 12 | import java.awt.event.ActionEvent; 13 | import java.awt.event.ActionListener; 14 | import java.awt.event.WindowEvent; 15 | import java.awt.event.WindowListener; 16 | import java.io.File; 17 | import java.io.FileOutputStream; 18 | import java.io.IOException; 19 | import java.io.InputStream; 20 | import java.io.PrintWriter; 21 | import java.text.DateFormat; 22 | import java.util.Date; 23 | import javax.swing.JDialog; 24 | import javax.swing.JEditorPane; 25 | import javax.swing.JLabel; 26 | import javax.swing.JOptionPane; 27 | import javax.swing.JPanel; 28 | import javax.swing.JScrollPane; 29 | 30 | public class Elevator extends GuiFrame implements ActionListener, WindowListener { 31 | public static String version = "1.0.1"; 32 | public static String copyright = "Copyright (C) Christopher J. Terman 2002"; 33 | 34 | String cmdargs[] = null; // command line args 35 | 36 | String initialFSM = 37 | "; dumb elevator: just sits on first floor!\n"+ 38 | "\n"+ 39 | ";state F2 F3 F4 | next U D O C\n"+ 40 | ";----------------+---------------\n"+ 41 | "start - - - | start 0 0 1 0\n"; 42 | 43 | public Elevator(String args[]) { 44 | super(args,"Elevator "+version,true,false); 45 | setIconImage(GetImageResource("/icons/ant.gif")); 46 | 47 | // set up edit window 48 | AddToolButton("/icons/exit.gif",UI.EXIT,this); 49 | AddToolSeparator(); 50 | AddToolButton("/icons/new.gif",UI.NEW,this); 51 | AddToolButton("/icons/open.gif",UI.OPEN,this); 52 | AddToolButton("/icons/close.gif",UI.CLOSE,this); 53 | AddToolButton("/icons/reload.gif",UI.RELOAD,this); 54 | AddToolButton("/icons/save.gif",UI.SAVE,this); 55 | AddToolButton("/icons/saveas.gif",UI.SAVEAS,this); 56 | AddToolButton("/icons/saveall.gif",UI.SAVEALL,this); 57 | AddToolSeparator(); 58 | AddToolButton("/icons/submit.gif",UI.CHECKOFF,this); 59 | Message("Elevator "+version+", "+copyright); 60 | 61 | SetTab(ReadFiles()); 62 | 63 | // display our handiwork 64 | setVisible(true); 65 | } 66 | 67 | // used by stand-alone application 68 | public static void main(String args[]) { 69 | new Elevator(args); 70 | } 71 | 72 | public void actionPerformed(ActionEvent event) { 73 | eventThread = Thread.currentThread(); 74 | String what = event.getActionCommand(); 75 | try { 76 | if (what.equals(UI.CHECKOFF)) { 77 | Checkoff(); 78 | } else super.actionPerformed(event); 79 | } 80 | catch (Exception e) { 81 | Message("Internal error: "+e); 82 | 83 | String ename = GetParameter("reporterrors"); 84 | if (ename != null) { 85 | if (ename.equals("-reporterrors")) e.printStackTrace(System.out); 86 | else { 87 | try { 88 | PrintWriter out = new PrintWriter(new FileOutputStream(ename,true)); 89 | String time = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,DateFormat.SHORT).format(new Date()); 90 | String user = System.getProperty("user.name","???"); 91 | String host = System.getProperty("hostname","???"); 92 | out.println("version=\""+version+"\" time=\""+time+"\" user=\""+user+"@"+host+"\" action=\""+what+"\""); 93 | e.printStackTrace(out); 94 | 95 | // capture buffer contents 96 | int nviews = tabPane.getTabCount(); 97 | for (int i = 0; i < nviews; i += 1) { 98 | EditBuffer n = (EditBuffer)tabPane.getComponentAt(i); 99 | n.Capture(out); 100 | } 101 | out.close(); 102 | } 103 | catch (Exception ee) { 104 | } 105 | } 106 | } 107 | } 108 | } 109 | 110 | public void RemoveView(Component v) { 111 | RemoveTab(v); 112 | } 113 | 114 | public EditBuffer ReadFiles() { 115 | ElevatorPanel result = (ElevatorPanel)super.ReadFiles(); 116 | if (result.source == null) { 117 | result.setText(initialFSM); 118 | } 119 | return result; 120 | } 121 | 122 | public Component OpenFile(File file,boolean atEnd) { 123 | // set default directory for file chooser 124 | if (lastDirectory == null && file != null) 125 | lastDirectory = file.getParent(); 126 | 127 | ElevatorPanel n = new ElevatorPanel(this,file); 128 | AddTab(n.TabName(),n.ToolTip(),n,atEnd ? -1 : 0); 129 | 130 | return (Component)n; 131 | } 132 | 133 | public void Checkoff() { 134 | ElevatorPanel n = (ElevatorPanel)Selectee(); 135 | int result = n.Solved(); 136 | 137 | if (result != 1) { 138 | JOptionPane.showMessageDialog(this,"You must get all the lemmings to the ground floor before submitting your FSM.", 139 | "Checkoff failure...", 140 | JOptionPane.WARNING_MESSAGE); 141 | return; 142 | } 143 | 144 | DoCheckoff("6004.lcs.mit.edu/currentsemester/6004assignment.doit"); 145 | } 146 | 147 | public void GeneratePostData(POSTStream o) throws IOException { 148 | // indicate assignment 149 | o.writeTag("checkoff"); 150 | o.write("Lab #3"); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /simulation/EmuRegion.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | import netlist.PlotRequest; 6 | 7 | class EmuRegion extends Event { 8 | static final EmuRegion CONSTANT_REGION = new EmuRegion(null); 9 | static final EmuRegion LAST_REGION = new EmuRegion(null); 10 | 11 | EmuNetwork network; // network we belong to 12 | EmuRegion netLink; // next region in network 13 | EmuNode nodes; // DC-connected nodes 14 | EmuDevice devices; // device belonging to the region 15 | double lastUpdateTime; 16 | EmuRegion link; // next region in linked list 17 | 18 | public EmuRegion(EmuNetwork network) { 19 | super(); 20 | this.network = network; 21 | nodes = null; 22 | devices = null; 23 | link = null; 24 | } 25 | 26 | public EmuRegion(EmuNetwork network,EmuNode n) { 27 | this(network); 28 | AddNode(n); 29 | } 30 | 31 | public String toString() { 32 | String result = "EmuRegion["; 33 | int i = 0; 34 | for (EmuNode n = nodes; n != null; n = n.regionLink) { 35 | if (i != 0) result += ","; 36 | result += n.name + "=" + n.voltage; 37 | if (++i > 5) break; 38 | } 39 | return result+"]"; 40 | } 41 | 42 | public void AddNode(EmuNode n) { 43 | if (n.region == null) { 44 | n.regionLink = nodes; 45 | nodes = n; 46 | n.AddToRegion(this); 47 | } 48 | } 49 | 50 | public void AddDevice(EmuDevice d,EmuNode n) { 51 | d.regionLink = devices; 52 | devices = d; 53 | AddNode(n); 54 | } 55 | 56 | // finalize each device, set fanout links 57 | public void Finalize() { 58 | for (EmuDevice d = devices; d != null; d = d.regionLink) 59 | d.Finalize(); 60 | } 61 | 62 | public void ResetTime(double delta) { 63 | if (etime != 0) etime -= delta; 64 | lastUpdateTime = 0; 65 | } 66 | 67 | public void ResetState() { 68 | etime = NO_EVENT; 69 | lastUpdateTime = 0; 70 | for (EmuDevice d = devices; d != null; d = d.regionLink) d.Reset(); 71 | for (EmuNode n = nodes; n != null; n = n.regionLink) n.Reset(); 72 | } 73 | 74 | // compute what next voltage will be for all the nodes in 75 | // the region. If the new voltage would trigger an event 76 | // for a node, update all its fanout regions, and so on. 77 | public EmuRegion ComputeUpdate(double time,EmuRegion link) { 78 | // add region to linked list of visited regions. Filling in the 79 | // link marks this region as having already been processed... 80 | this.link = link; 81 | link = this; 82 | 83 | // if we're not up-to-date, iterate through each node in region 84 | // updating it's voltage and currents. Iteration stops when 85 | // values converge or if we exceed alloted number of iterations. 86 | double timestep = time - lastUpdateTime; 87 | if (timestep != 0) { 88 | if (network.debugLevel > 1) 89 | System.out.println("Update t="+time+", "+this); 90 | 91 | int iterations = network.maxIterations; 92 | boolean converged = false; 93 | while (!converged && iterations > 0) { 94 | converged = true; 95 | // update each node in the region 96 | for (EmuNode n = nodes; n != null; n = n.regionLink) 97 | if (!n.ComputeUpdate(timestep)) converged = false; 98 | iterations -= 1; 99 | } 100 | //if (!converged) System.out.println("No convergence at time "+time+" for "+this); 101 | } 102 | 103 | // remember that we did this update and check to see if any 104 | // fanout regions need updating too 105 | lastUpdateTime = time; 106 | for (EmuNode n = nodes; n != null; n = n.regionLink) 107 | link = n.CheckFanouts(time,link); 108 | 109 | return link; 110 | } 111 | 112 | public void Snapshot() { 113 | for (EmuNode n = nodes; n != null; n = n.regionLink) 114 | n.Snapshot(); 115 | } 116 | 117 | // update node voltages 118 | public void PerformUpdate() { 119 | for (EmuNode n = nodes; n != null; n = n.regionLink) 120 | n.PerformUpdate(); 121 | } 122 | 123 | public void ForcedUpdate(double t) { 124 | for (EmuNode n = nodes; n != null; n = n.regionLink) 125 | n.PerformUpdate(); 126 | for (EmuDevice d = devices; d != null; d = d.regionLink) 127 | d.Update(t); 128 | lastUpdateTime = t; 129 | link = null; 130 | } 131 | 132 | // determine when to schedule next event for this region 133 | public void ScheduleNextUpdate(double time) { 134 | double timestep = NO_EVENT; 135 | 136 | // update all devices and accumulate min timestep they require 137 | for (EmuDevice d = devices; d != null; d = d.regionLink) { 138 | double t = d.Update(time); 139 | if (t != NO_EVENT && (timestep == NO_EVENT || t < timestep)) 140 | timestep = t; 141 | } 142 | 143 | // predict appropriate timestep for each node in region 144 | for (EmuNode n = nodes; n != null; n = n.regionLink) { 145 | double t = n.PredictTimestep(); 146 | if (t != NO_EVENT && (timestep == NO_EVENT || t < timestep)) 147 | timestep = t; 148 | } 149 | 150 | if (timestep != NO_EVENT) network.AddEvent(this,time + timestep); 151 | else if (etime != NO_EVENT) network.DeleteEvent(this); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /simulation/SpicePulseSource.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | // pulsed source function 6 | class SpicePulseSource extends SpiceSource { 7 | double init; // initial value 8 | double pulsed; // pulsed value 9 | double delay; // initial delay 10 | double period; // how often it repeats 11 | double t2; // end time of onset ramp 12 | double t3; // start time of recovery ramp 13 | double t4; // end time of recovery ramp 14 | 15 | double tc1,tc2,tp1,tp2; // used during gate-level simulation 16 | 17 | public SpicePulseSource(double xdc,double xacmag,double xacphase,double params[],double vil,double vih) { 18 | super(xdc,xacmag,xacphase); 19 | 20 | init = (params == null || params.length < 1) ? 0 : params[0]; 21 | pulsed = (params == null || params.length < 2) ? 0 : params[1]; 22 | 23 | delay = (params == null || params.length < 3) ? 0 : params[2]; 24 | if (delay < 0) delay = 0; 25 | double tr = (params == null || params.length < 4) ? 1e-9 : params[3]; 26 | if (tr < 0) tr = 0; 27 | double tf = (params == null || params.length < 5) ? tr : params[4]; 28 | if (tf < 0) tf = 0; 29 | double pw = (params == null || params.length < 6) ? 0 : params[5]; 30 | if (pw < 0) pw = 0; 31 | 32 | t2 = tr; 33 | t3 = tr + pw; 34 | t4 = tr + pw + tf; 35 | 36 | period = (params == null || params.length < 7) ? t4 + pw : params[6]; 37 | if (period < t4) period = t4; 38 | 39 | tc1 = -1; 40 | tc2 = -1; 41 | if (init <= vil && pulsed > vil) 42 | tc1 = t2*(vil - init)/(pulsed - init); 43 | else if (init >= vih && pulsed < vih) 44 | tc1 = t2*(vih - init)/(pulsed - init); 45 | 46 | if (pulsed <= vil && init > vil) 47 | tc2 = t3 + (t4 - t3)*(vil - pulsed)/(init - pulsed); 48 | else if (pulsed >= vih && init < vih) 49 | tc2 = t3 + (t4 - t3)*(vih - pulsed)/(init - pulsed); 50 | 51 | tp1 = -1; 52 | tp2 = -1; 53 | if (init < vih && pulsed >= vih) 54 | tp1 = t2*(vih - init)/(pulsed - init); 55 | else if (init > vil && pulsed <= vil) 56 | tp1 = t2*(vil - init)/(pulsed - init); 57 | 58 | if (pulsed > vil && init <= vil) 59 | tp2 = t3 + (t4 - t3)*(vil - pulsed)/(init - pulsed); 60 | else if (pulsed < vih && init >= vih) 61 | tp2 = t3 + (t4 - t3)*(vih - pulsed)/(init - pulsed); 62 | } 63 | 64 | public String SourceName() { return "PULSE"; } 65 | 66 | public double TransientValue(double time) { 67 | if (time <= delay) return init; 68 | time -= delay; 69 | if (time > period) time -= Math.floor(time/period)*period; 70 | if (time < t2) return init + (pulsed - init) * (time/t2); 71 | else if (time <= t3) return pulsed; 72 | else if (time < t4) return pulsed + (init - pulsed) * ((time - t3)/(t4 - t3)); 73 | else return init; 74 | } 75 | 76 | public boolean SupportsGateLevelSimulation() { return true; } 77 | 78 | public double NextContaminationTime(double time) { 79 | double tbase = delay; 80 | double toffset = 0; 81 | if (time > delay) { 82 | tbase = Math.floor((time - delay)/period)*period + delay; 83 | toffset = time - tbase + 1e-13; 84 | } 85 | 86 | if (tc1 == -1) { 87 | if (tc2 == -1) return -1; 88 | return (toffset < tc2) ? tbase + tc2 : tbase + period + tc2; 89 | } else if (tc2 == -1) 90 | return (toffset < tc1) ? tbase + tc1 : tbase + period + tc1; 91 | else if (toffset < tc1) return tbase + tc1; 92 | else if (toffset < tc2) return tbase + tc2; 93 | else return tbase + period + tc1; 94 | } 95 | 96 | public double NextPropagationTime(double time) { 97 | double tbase = delay; 98 | double toffset = 0; 99 | if (time > delay) { 100 | tbase = Math.floor((time - delay)/period)*period + delay; 101 | toffset = time - tbase + 1e-13; 102 | } 103 | 104 | if (tp1 == -1) { 105 | if (tp2 == -1) return -1; 106 | return (toffset < tp2) ? tbase + tp2 : tbase + period + tp2; 107 | } else if (tp2 == -1) 108 | return (toffset < tp1) ? tbase + tp1 : tbase + period + tp1; 109 | else if (toffset < tp1) return tbase + tp1; 110 | else if (toffset < tp2) return tbase + tp2; 111 | else return tbase + period + tp1; 112 | } 113 | 114 | // return time of next breakpoint or voltage change of dv volts, 115 | // whichever is sooner 116 | public double NextBreakpoint(double time,double dv) { 117 | double tbase = delay; 118 | double toffset = 0; 119 | if (time > delay) { 120 | tbase = Math.floor((time - delay)/period)*period + delay; 121 | toffset = time - tbase; 122 | } 123 | 124 | if (toffset < t2) { 125 | double sec_per_v = Math.abs(t2/(pulsed - init)); 126 | return Math.min(tbase + t2,time + dv * sec_per_v); 127 | } else if (toffset < t3) return tbase + t3; 128 | else if (toffset < t4) { 129 | double sec_per_v = Math.abs((t4 - t3)/(init - pulsed)); 130 | return Math.min(tbase + t4,time + dv * sec_per_v); 131 | } else return tbase + period; 132 | } 133 | 134 | public void ComputeBreakpoints(SpiceNetwork network,double stopTime) { 135 | for (double base = delay; base < stopTime; base += period) { 136 | network.AddBreakpoint(base); 137 | if (t2 > 0) network.AddBreakpoint(base + t2); 138 | if (t3 > t2) network.AddBreakpoint(base + t3); 139 | if (t4 > t3) network.AddBreakpoint(base + t4); 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /netlist/Subcircuit.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2001 Christopher J. Terman - All Rights Reserved. 2 | 3 | package netlist; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.Iterator; 8 | 9 | public class Subcircuit extends SubcircuitObject { 10 | public static final int SUBCKT = 0; 11 | public static final int DSUBCKT = 1; 12 | public static final int GSUBCKT = 2; 13 | public static final String SNAMES[] = {".subckt", ".dsubckt", ".gsubckt"}; 14 | 15 | public HashMap nodes; // local nodes 16 | private HashMap subcircuits; // local subcircuits 17 | private HashMap dsubcircuits; // local device subcircuits 18 | private HashMap gsubcircuits; // local gate subcircuits 19 | public HashMap models; // local models 20 | public HashMap devices; // local devices 21 | public ArrayList externals; // vector of external nodes 22 | public ArrayList connectedNodes; // node pairs to be connected 23 | public boolean active; // are we current being netlisted? 24 | public int stype; // type of subcircuit 25 | 26 | public Subcircuit(Subcircuit p,Identifier name,int stype) { 27 | // fill in our name, add ourselves to our parent 28 | parent = p; 29 | id = name; 30 | this.stype = stype; 31 | if (p != null) p.AddSubcircuit(id.name,this,stype); 32 | 33 | // initialize hashtable for local definitions 34 | nodes = new HashMap(); 35 | subcircuits = new HashMap(); 36 | dsubcircuits = new HashMap(); 37 | gsubcircuits = new HashMap(); 38 | models = new HashMap(); 39 | devices = new HashMap(); 40 | externals = new ArrayList(); 41 | connectedNodes = new ArrayList(); 42 | active = false; 43 | } 44 | 45 | public void AddSubcircuit(String name,Subcircuit s,int stype) { 46 | if (stype == DSUBCKT) dsubcircuits.put(name,s); 47 | else if (stype == GSUBCKT) gsubcircuits.put(name,s); 48 | else subcircuits.put(name,s); 49 | } 50 | 51 | public Subcircuit GetSubcircuit(String name,int stype) { 52 | if (stype == DSUBCKT) return (Subcircuit)dsubcircuits.get(name); 53 | else if (stype == GSUBCKT) return (Subcircuit)gsubcircuits.get(name); 54 | else return (Subcircuit)subcircuits.get(name); 55 | } 56 | 57 | // add a device to this subcircuit 58 | public void AddDevice(Netlist network,DevicePrototype d) { 59 | if (devices.get(d.id.name) != null) { 60 | network.Error(d.id,"Duplicate device name"); 61 | return; 62 | } 63 | devices.put(d.id.name,d); 64 | } 65 | 66 | public void ConnectNodes(Netlist network,Identifier n1,Identifier n2) { 67 | connectedNodes.add(FindNode(network,n1)); 68 | connectedNodes.add(FindNode(network,n2)); 69 | } 70 | 71 | // locate node given its name 72 | public Node FindNode(Netlist network,Identifier name) { 73 | Node n; 74 | 75 | // first see if it's a global node 76 | if ((n = (Node)network.globalNodes.get(name.name)) != null) 77 | return(n); 78 | 79 | // if not, it must be a local node 80 | if ((n = (Node)nodes.get(name.name)) != null) return(n); 81 | 82 | return new Node(this,name); 83 | } 84 | 85 | // locate subcircuit definition given its name 86 | public Subcircuit FindSubcircuit(Identifier name,int stype) { 87 | Subcircuit search = this; 88 | 89 | // search up .subckt hierarchy until we find a winner 90 | while (search != null) { 91 | HashMap tbl = (stype == DSUBCKT) ? search.dsubcircuits : search.gsubcircuits; 92 | Subcircuit s = (Subcircuit)tbl.get(name.name); 93 | if (s == null) s = (Subcircuit)search.subcircuits.get(name.name); 94 | if (s != null) return s; 95 | search = search.parent; 96 | } 97 | return null; 98 | } 99 | 100 | // locate model definition given its name 101 | public Model FindModel(Identifier name) { 102 | Subcircuit search = this; 103 | 104 | // search up .subckt hierarchy until we find a winner 105 | while (search != null) { 106 | Model m = (Model)search.models.get(name.name); 107 | if (m != null) return m; 108 | search = search.parent; 109 | } 110 | return null; 111 | } 112 | 113 | // netlist each device in the subcircuit 114 | public boolean Netlist(Netlist network,NetlistConsumer nc) { 115 | String prefix = network.prefix; 116 | active = true; 117 | 118 | // get a netlister node for each non-external node in the subcircuit 119 | Iterator iter = nodes.values().iterator(); 120 | while (iter.hasNext()) { 121 | Node n = (Node)iter.next(); 122 | if (!n.external) 123 | n.netlisterNode = nc.FindNode(prefix + n.id.name,true); 124 | } 125 | 126 | // get a netlister model for each model in the subcircuit 127 | iter = models.values().iterator(); 128 | while (iter.hasNext()) { 129 | Model m = (Model)iter.next(); 130 | if (!m.Netlist(network,nc)) { active = false; return false; } 131 | } 132 | 133 | // connect node pairs as user requested 134 | int nconnects = connectedNodes.size(); 135 | for (int i = 0; i < nconnects; i += 2) { 136 | Node n1 = (Node)connectedNodes.get(i); 137 | Node n2 = (Node)connectedNodes.get(i+1); 138 | nc.ConnectNodes(n1.netlisterNode,n2.netlisterNode); 139 | } 140 | 141 | // netlist each device 142 | iter = devices.values().iterator(); 143 | while (iter.hasNext()) { 144 | DevicePrototype d = (DevicePrototype)iter.next(); 145 | if (!d.Netlist(network,nc)) { active = false; return false; } 146 | } 147 | active = false; 148 | return true; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /simulation/SimLookupTable.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2000 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | public class SimLookupTable { 6 | public SimLookupTable table[]; // indexed by 4-value logic 7 | public int value; // logic value for this table 8 | 9 | static public SimLookupTable LTable = InitializeTables(); 10 | static public SimLookupTable HTable; 11 | static public SimLookupTable XTable; 12 | static public SimLookupTable ZTable; 13 | static public SimLookupTable SelectTable; 14 | static public SimLookupTable SelectNextTable; 15 | static public SimLookupTable Ensure0Table; 16 | static public SimLookupTable Ensure1Table; 17 | static public SimLookupTable EqualTable; 18 | 19 | static public SimLookupTable BusTable; 20 | static public SimLookupTable Bus0Table; 21 | static public SimLookupTable Bus1Table; 22 | static public SimLookupTable TristateBufferTable; 23 | 24 | static public SimLookupTable AndXTable; 25 | static public SimLookupTable AndTable; 26 | static public SimLookupTable NandXTable; 27 | static public SimLookupTable NandTable; 28 | static public SimLookupTable OrXTable; 29 | static public SimLookupTable OrTable; 30 | static public SimLookupTable NorXTable; 31 | static public SimLookupTable NorTable; 32 | static public SimLookupTable XorTable; 33 | static public SimLookupTable Xor1Table; 34 | static public SimLookupTable Mux2Table; 35 | 36 | public SimLookupTable(int value) { 37 | table = new SimLookupTable[4]; 38 | this.value = value; 39 | } 40 | 41 | public void Setup(SimLookupTable t1,SimLookupTable t2,SimLookupTable t3,SimLookupTable t4) { 42 | table[0] = t1; 43 | table[1] = t2; 44 | table[2] = t3; 45 | table[3] = t4; 46 | } 47 | 48 | // set up some useful tables 49 | public static SimLookupTable InitializeTables() { 50 | if (LTable == null) { 51 | // always "0" 52 | LTable = new SimLookupTable(Node.V0); 53 | LTable.Setup(LTable,LTable,LTable,LTable); 54 | // always "1" 55 | HTable = new SimLookupTable(Node.V1); 56 | HTable.Setup(HTable,HTable,HTable,HTable); 57 | // always "X" 58 | XTable = new SimLookupTable(Node.VX); 59 | XTable.Setup(XTable,XTable,XTable,XTable); 60 | // always "Z" 61 | ZTable = new SimLookupTable(Node.VZ); 62 | ZTable.Setup(ZTable,ZTable,ZTable,ZTable); 63 | // select this 64 | SelectTable = new SimLookupTable(Node.VX); 65 | SelectTable.Setup(LTable,HTable,XTable,XTable); 66 | // select next 67 | SelectNextTable = new SimLookupTable(Node.VX); 68 | SelectNextTable.Setup(SelectTable,SelectTable,SelectTable,SelectTable); 69 | // must be 0 70 | Ensure0Table = new SimLookupTable(Node.VX); 71 | Ensure0Table.Setup(LTable,XTable,XTable,XTable); 72 | // must be 1 73 | Ensure1Table = new SimLookupTable(Node.VX); 74 | Ensure1Table.Setup(XTable,HTable,XTable,XTable); 75 | // this == next 76 | EqualTable = new SimLookupTable(Node.VX); 77 | EqualTable.Setup(Ensure0Table,Ensure1Table,XTable,XTable); 78 | 79 | // tristate bus resolution 80 | // produces "Z" if all inputs are "Z" 81 | // produces "1" if one input is "1" and other inputs are "1" or "Z" 82 | // produces "0" if one input is "0" and other inputs are "0" or "Z" 83 | // produces "X" otherwise 84 | BusTable = new SimLookupTable(Node.VZ); 85 | Bus0Table = new SimLookupTable(Node.V0); 86 | Bus1Table = new SimLookupTable(Node.V1); 87 | BusTable.Setup(Bus0Table,Bus1Table,XTable,BusTable); 88 | Bus0Table.Setup(Bus0Table,XTable,XTable,Bus0Table); 89 | Bus1Table.Setup(XTable,Bus1Table,XTable,Bus1Table); 90 | 91 | // tristate buffer (node order: enable,in) 92 | TristateBufferTable = new SimLookupTable(Node.VX); 93 | TristateBufferTable.Setup(ZTable,SelectTable,XTable,XTable); 94 | 95 | // and tables 96 | AndXTable = new SimLookupTable(Node.VX); 97 | AndXTable.Setup(LTable,AndXTable,AndXTable,AndXTable); 98 | AndTable = new SimLookupTable(Node.V1); 99 | AndTable.Setup(LTable,AndTable,AndXTable,AndXTable); 100 | 101 | // nand tables 102 | NandXTable = new SimLookupTable(Node.VX); 103 | NandXTable.Setup(HTable,NandXTable,NandXTable,NandXTable); 104 | NandTable = new SimLookupTable(Node.V0); 105 | NandTable.Setup(HTable,NandTable,NandXTable,NandXTable); 106 | 107 | // or tables 108 | OrXTable = new SimLookupTable(Node.VX); 109 | OrXTable.Setup(OrXTable,HTable,OrXTable,OrXTable); 110 | OrTable = new SimLookupTable(Node.V0); 111 | OrTable.Setup(OrTable,HTable,OrXTable,OrXTable); 112 | 113 | // nor tables 114 | NorXTable = new SimLookupTable(Node.VX); 115 | NorXTable.Setup(NorXTable,LTable,NorXTable,NorXTable); 116 | NorTable = new SimLookupTable(Node.V1); 117 | NorTable.Setup(NorTable,LTable,NorXTable,NorXTable); 118 | 119 | // xor tables 120 | XorTable = new SimLookupTable(Node.V0); 121 | Xor1Table = new SimLookupTable(Node.V1); 122 | XorTable.Setup(XorTable,Xor1Table,XTable,XTable); 123 | Xor1Table.Setup(Xor1Table,XorTable,XTable,XTable); 124 | 125 | // 2-input mux table (node order: sel,d0,d1) 126 | Mux2Table = new SimLookupTable(Node.VX); 127 | Mux2Table.Setup(SelectTable,SelectNextTable,EqualTable,EqualTable); 128 | } 129 | return LTable; 130 | } 131 | } 132 | 133 | -------------------------------------------------------------------------------- /fsm/Lemming.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2002 Christopher J. Terman - All Rights Reserved. 2 | 3 | package fsm; 4 | 5 | import java.awt.Color; 6 | import java.awt.Graphics; 7 | import java.awt.Image; 8 | import java.awt.MediaTracker; 9 | import java.awt.Rectangle; 10 | import java.net.URL; 11 | 12 | import javax.sound.midi.MidiSystem; 13 | import javax.sound.midi.Sequence; 14 | import javax.sound.midi.Sequencer; 15 | import javax.swing.JComponent; 16 | 17 | import gui.GuiFrame; 18 | 19 | public class Lemming extends Thread { 20 | public static final String LEFT = "left"; 21 | public static final String RIGHT = "right"; 22 | public static final int STEP = 2; 23 | public static final int QUANTUM = 50; 24 | 25 | public static Sequencer midi; 26 | 27 | public static final int INVISIBLE = 0; 28 | 29 | public static final int STANDING = 1; 30 | static final String STANDING_IMAGES[] = { 31 | "/fsm/Stander01.gif", 32 | "/fsm/Stander02.gif", 33 | "/fsm/Stander03.gif", 34 | "/fsm/Stander04.gif", 35 | "/fsm/Stander05.gif", 36 | "/fsm/Stander06.gif", 37 | "/fsm/Stander07.gif", 38 | "/fsm/Stander08.gif", 39 | "/fsm/Stander09.gif", 40 | "/fsm/Stander10.gif", 41 | "/fsm/Stander11.gif", 42 | "/fsm/Stander12.gif", 43 | "/fsm/Stander13.gif", 44 | "/fsm/Stander14.gif" 45 | }; 46 | static Image standingImages[]; 47 | 48 | public static final int WALKING = 2; 49 | public static final String WALKING_IMAGES[] = { 50 | "/fsm/Walker01.gif", 51 | "/fsm/Walker02.gif", 52 | "/fsm/Walker03.gif", 53 | "/fsm/Walker04.gif", 54 | "/fsm/Walker05.gif", 55 | "/fsm/Walker06.gif", 56 | "/fsm/Walker07.gif", 57 | "/fsm/Walker08.gif", 58 | "/fsm/Walker09.gif", 59 | "/fsm/Walker10.gif", 60 | "/fsm/Walker11.gif", 61 | "/fsm/Walker12.gif", 62 | "/fsm/Walker13.gif", 63 | "/fsm/Walker14.gif", 64 | }; 65 | static Image walkingImages[]; 66 | static int w,h; // image size 67 | 68 | public int x,y; // location 69 | public String facing; // which way we're facing 70 | public Rectangle bbox; // area we're headed into 71 | int pause; 72 | int quantum; 73 | 74 | public int nextState; // what we should be doing 75 | ElevatorDiagram parent; 76 | int currentState; // what we are doing 77 | int currentSubstate; // animation substate 78 | Image currentImages[]; 79 | 80 | public Lemming(GuiFrame gui,ElevatorDiagram parent,int pause) { 81 | this.parent = parent; 82 | this.pause = pause; 83 | bbox = new Rectangle(); 84 | 85 | if (midi == null) { 86 | try { 87 | midi = MidiSystem.getSequencer(); 88 | midi.open(); 89 | URL url = parent.getClass().getResource("/fsm/Lemmings.mid"); 90 | midi.setSequence(MidiSystem.getSequence(url)); 91 | midi.start(); 92 | } 93 | catch (Exception e) { 94 | System.out.println(e); 95 | } 96 | } 97 | 98 | // one-time initialization: read in images, wait till ready 99 | if (standingImages == null) { 100 | MediaTracker t = new MediaTracker(parent); 101 | int tindex = 0; 102 | int n = STANDING_IMAGES.length; 103 | 104 | standingImages = new Image[n]; 105 | for (int i = 0; i < n; i += 1) { 106 | standingImages[i] = gui.GetImageResource(STANDING_IMAGES[i]); 107 | t.addImage(standingImages[i],tindex++); 108 | } 109 | 110 | n = WALKING_IMAGES.length; 111 | walkingImages = new Image[n]; 112 | for (int i = 0; i < n; i += 1) { 113 | walkingImages[i] = gui.GetImageResource(WALKING_IMAGES[i]); 114 | t.addImage(walkingImages[i],tindex++); 115 | } 116 | 117 | try { 118 | t.waitForAll(); 119 | w = walkingImages[0].getWidth(null); 120 | h = walkingImages[0].getHeight(null); 121 | } 122 | catch (InterruptedException e) { } 123 | } 124 | } 125 | 126 | public void run() { 127 | while (!interrupted()) { 128 | try { 129 | sleep(quantum); 130 | quantum = QUANTUM; 131 | } 132 | catch (InterruptedException e) { } 133 | Step(); 134 | Repaint(); 135 | } 136 | } 137 | 138 | synchronized void Step() { 139 | if (currentSubstate == currentImages.length-1) { 140 | // use mutex to ensure two lemmings don't head for 141 | // the same open space 142 | synchronized (parent) { 143 | // see if we can start walking... 144 | int dx = STEP * (walkingImages.length - 1); 145 | if (facing == LEFT) bbox.setBounds(x-dx,y,dx+w,h); 146 | else bbox.setBounds(x,y,dx+w,h); 147 | if (parent.ClearAhead(this)) currentState = WALKING; 148 | else { 149 | bbox.setBounds(x,y,w,h); 150 | facing = (facing == LEFT) ? RIGHT : LEFT; 151 | currentState = STANDING; 152 | } 153 | } 154 | SetupImages(); 155 | } else { 156 | currentSubstate += 1; 157 | if (currentState == WALKING) 158 | x += (facing == LEFT) ? -STEP : STEP; 159 | } 160 | } 161 | 162 | synchronized public void Reset(int x,int y) { 163 | quantum = pause; 164 | currentState = STANDING; 165 | facing = LEFT; 166 | this.x = x; 167 | this.y = y; 168 | bbox.setBounds(x,y,w,h); 169 | SetupImages(); 170 | } 171 | 172 | public void SetupImages() { 173 | currentSubstate = 0; 174 | switch (currentState) { 175 | case STANDING: 176 | currentImages = standingImages; 177 | break; 178 | case WALKING: 179 | currentImages = walkingImages; 180 | break; 181 | } 182 | } 183 | 184 | public void Repaint() { 185 | parent.repaint(x-STEP,y-STEP,w+2*STEP,h+2*STEP); 186 | } 187 | 188 | synchronized public void Draw(Graphics g,Color bg) { 189 | if (currentState != INVISIBLE) { 190 | Image i = currentImages[currentSubstate]; 191 | if (facing == LEFT) 192 | g.drawImage(i,x,y,x+w,y+h,0,0,w,h,bg,null); 193 | else 194 | g.drawImage(i,x,y,x+w,y+h,w,0,0,h,bg,null); 195 | } 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /jsim/BatchSim.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2011 Christopher J. Terman - All Rights Reserved. 2 | 3 | // usage: java -jar batchsim.jar [options] [file or directory]... 4 | // options: -s device-level simulation 5 | // -f fast device-level simulation 6 | // -g gate-level simulation 7 | // generates a JSON file containing an array of objects, one object for each file processed. 8 | // each object has the following attributes: 9 | // "file": 10 | // "error": {"start": ,"end":,"message":} # error message from simulator 11 | // "size": {: ...} 12 | // "verify": [{"nodes": [, ...],"values":[{"t":,"v":}]}, ...] 13 | 14 | package jsim; 15 | 16 | import gui.GuiFrame; 17 | import java.io.File; 18 | import java.io.PrintStream; 19 | 20 | import netlist.Netlist; 21 | import netlist.NetlistConsumer; 22 | import netlist.Analysis; 23 | import netlist.Subcircuit; 24 | import netlist.VerifyData; 25 | 26 | import simulation.EmuNetwork; 27 | import simulation.Network; 28 | import simulation.SimNetwork; 29 | import simulation.SpiceNetwork; 30 | 31 | public class BatchSim extends GuiFrame { 32 | public int simulator = 0; // 0: Simulate, 1: FastSimulate, 2: GateSimulate 33 | public String msg; 34 | public int start = 0; 35 | public int end = 0; 36 | 37 | public BatchSim(String args[]) throws java.io.IOException { 38 | super(args,"BatchSim",true,true); 39 | 40 | // look for switches 41 | for (int i = 0; i < cmdargs.length; i += 1) { 42 | if (cmdargs[i].startsWith("-g")) simulator = 2; // gate simulate 43 | if (cmdargs[i].startsWith("-f")) simulator = 1; // fast simulate 44 | if (cmdargs[i].startsWith("-s")) simulator = 0; // simulate 45 | } 46 | 47 | // look through command args; anything that's not a switch 48 | // should be the name of a directory full of files to simulate 49 | for (int i = 0; i < cmdargs.length; i += 1) { 50 | if (cmdargs[i].startsWith("--")) i += 1; 51 | else if (!cmdargs[i].startsWith("-")) { 52 | PrintStream report = new PrintStream(cmdargs[i]+"_report.json"); 53 | report.println("["); 54 | File dir = new File(cmdargs[i]); 55 | if (dir.isDirectory()) { 56 | File[] files = dir.listFiles(); 57 | for (int j = 0; j < files.length; j += 1) { 58 | if (j != 0) report.println(","); 59 | ProcessFile(files[j],report,simulator); 60 | } 61 | } else ProcessFile(dir,report,simulator); 62 | report.println("]"); 63 | report.close(); 64 | } 65 | } 66 | } 67 | 68 | public void ProcessFile(File f,PrintStream report,int simulator) { 69 | report.println("{\"file\": \""+f.toString()+"\","); 70 | 71 | // read in the next netlist 72 | Netlist n = new Netlist(this,f); 73 | switch (simulator) { 74 | case 0: DoSimulate(n); break; 75 | case 1: DoFastSimulate(n); break; 76 | case 2: DoGateSimulate(n); break; 77 | } 78 | if (n.errors) { 79 | // report error 80 | report.println(" \"error\":{\"start\":"+n.error_start+",\"end\":"+n.error_end+",\"message\":\""+msg+"\"}\n}"); 81 | } else { 82 | // report device counts 83 | BatchSimNetlistConsumer nc = new BatchSimNetlistConsumer(); 84 | if (n.Netlist((NetlistConsumer)nc)) { 85 | report.println(" \"size\":"+nc.Summary()+","); 86 | } 87 | 88 | // do verification 89 | report.println(" \"verify\":["); 90 | int nverifications = n.verifications.size(); 91 | for (int k = 0; k < nverifications; k += 1) { 92 | if (k != 0) report.println(" ,"); 93 | VerifyData v = (VerifyData)n.verifications.get(k); 94 | report.println(v.GenerateCheckoff(n.currentNetwork)); 95 | } 96 | report.println(" ]\n}"); 97 | } 98 | n.CleanUp(); // done with this network 99 | } 100 | 101 | public void Simulate(Netlist n,Network s) { 102 | n.currentNetwork = s; 103 | 104 | // flatten our network 105 | if (n.Netlist((NetlistConsumer)s)) { 106 | if (!s.Finalize()) { 107 | n.Error(s.Problem()); 108 | } else { 109 | // perform first analysis 110 | if (n.analyses.size() > 0) { 111 | Analysis a = (Analysis)n.analyses.get(0); 112 | switch (a.type) { 113 | case Analysis.Transient: 114 | n.DoTransientAnalysis(s,a); 115 | break; 116 | case Analysis.DC: 117 | n.DoDCAnalysis(s,a); 118 | break; 119 | } 120 | } 121 | } 122 | } 123 | } 124 | 125 | public void DoSimulate(Netlist n) { 126 | n.ReadNetlist(n,false,Subcircuit.DSUBCKT); // parse netlist 127 | if (!n.errors) { 128 | Simulate(n,new SpiceNetwork(n.options,n.tempdir)); 129 | } 130 | } 131 | 132 | public void DoFastSimulate(Netlist n) { 133 | n.ReadNetlist(n,false,Subcircuit.DSUBCKT); // parse netlist 134 | if (!n.errors) { 135 | Simulate(n,new EmuNetwork(n.options,n.tempdir)); 136 | } 137 | } 138 | 139 | public void DoGateSimulate(Netlist n) { 140 | n.ReadNetlist(n,false,Subcircuit.GSUBCKT); // parse netlist 141 | if (!n.errors) { 142 | Simulate(n,new SimNetwork(n.options,n.tempdir)); 143 | } 144 | } 145 | 146 | 147 | public void Message(String msg,int start,int end) { 148 | this.msg = msg; 149 | this.start = start; 150 | this.end = end; 151 | } 152 | 153 | public void SetTab(java.awt.Component v) { } 154 | public void SetTab(int i) { } 155 | 156 | // used by stand-alone application 157 | public static void main(String args[]) { 158 | try { 159 | new BatchSim(args); 160 | } 161 | catch (Exception e) { 162 | System.out.println("Internal error: "+e); 163 | e.printStackTrace(System.out); 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /gui/GuiDialog.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1998-2002 Christopher J. Terman - All Rights Reserved. 2 | 3 | package gui; 4 | 5 | import java.awt.BorderLayout; 6 | import java.awt.Component; 7 | import java.awt.Container; 8 | import java.awt.Dimension; 9 | import java.awt.FlowLayout; 10 | import java.awt.Font; 11 | import java.awt.Frame; 12 | import java.awt.GridBagConstraints; 13 | import java.awt.GridBagLayout; 14 | import java.awt.Point; 15 | import java.awt.Toolkit; 16 | import java.awt.event.ActionEvent; 17 | import java.awt.event.ActionListener; 18 | import java.awt.event.WindowEvent; 19 | import java.awt.event.WindowListener; 20 | import javax.swing.JButton; 21 | import javax.swing.JDialog; 22 | import javax.swing.JLabel; 23 | import javax.swing.JPanel; 24 | import javax.swing.JTextField; 25 | 26 | // A standard dialog with an ok and cancel button at the bottom. 27 | public class GuiDialog extends JDialog implements ActionListener, WindowListener { 28 | boolean abort = false; 29 | JPanel buttons; 30 | public JButton exitButton; 31 | JButton okay; 32 | JButton cancel; 33 | 34 | JPanel centerPanel; 35 | GridBagLayout glayout; 36 | GridBagConstraints gc; 37 | 38 | public GuiDialog(Frame f,String title,boolean addButtons) { 39 | super(f,title,true); 40 | setResizable(false); 41 | 42 | Container contentPane = getContentPane(); 43 | contentPane.setLayout(new BorderLayout()); 44 | contentPane.setFont(new Font("SansSerif",Font.PLAIN,12)); 45 | 46 | // add standard buttons at the bottom 47 | buttons = new JPanel(); 48 | buttons.setLayout(new FlowLayout(FlowLayout.CENTER,15,5)); 49 | contentPane.add("South",buttons); 50 | if (addButtons) AddButtons(); 51 | 52 | addWindowListener(this); 53 | } 54 | 55 | public void AddButtons() { 56 | AddButton(okay = new JButton("Okay")); 57 | AddButton(cancel = new JButton("Cancel")); 58 | } 59 | 60 | public void AddButton(JButton b) { 61 | b.addActionListener(this); 62 | buttons.add(b); 63 | } 64 | 65 | public boolean ShowMessage(String msg) { 66 | SetupGridBag(); 67 | gc.gridwidth = GridBagConstraints.REMAINDER; 68 | 69 | int last = 0; 70 | int len = msg.length(); 71 | while (last < len) { 72 | int next = msg.indexOf('\n',last); 73 | if (next == -1) next = len; 74 | JLabel l = new JLabel(msg.substring(last,next)); 75 | glayout.setConstraints(l,gc); 76 | centerPanel.add(l); 77 | last = next + 1; 78 | } 79 | pack(); 80 | 81 | // finally show dialog and wait until user clicks okay 82 | // or closes window 83 | return Show(0,0); 84 | } 85 | 86 | public void ShowErrorMessage(String msg) { 87 | // remove cancel button 88 | buttons.remove(cancel); 89 | ShowMessage(msg); 90 | } 91 | 92 | public void SetupGridBag() { 93 | centerPanel = new JPanel(); 94 | getContentPane().add("Center",centerPanel); 95 | glayout = new GridBagLayout(); 96 | centerPanel.setLayout(glayout); 97 | 98 | gc = new GridBagConstraints(); 99 | gc.anchor = GridBagConstraints.WEST; 100 | } 101 | 102 | public void AddItem(String label,Component item) { 103 | if (centerPanel != null) { 104 | JLabel l = new JLabel(label+":"); 105 | gc.weightx = 0.0; 106 | gc.fill = GridBagConstraints.NONE; 107 | gc.gridwidth = 1; 108 | glayout.setConstraints(l,gc); 109 | centerPanel.add(l); 110 | 111 | gc.weightx = 1.0; 112 | gc.fill = GridBagConstraints.HORIZONTAL; 113 | gc.gridwidth = GridBagConstraints.REMAINDER; 114 | glayout.setConstraints(item,gc); 115 | centerPanel.add(item); 116 | } 117 | } 118 | 119 | public void AddItem(String description,String label,Component edit) { 120 | if (centerPanel != null) { 121 | JLabel desc = new JLabel(description); 122 | JLabel pname = new JLabel(label+"="); 123 | gc.anchor = GridBagConstraints.WEST; 124 | gc.gridwidth = 1; 125 | gc.fill = GridBagConstraints.NONE; 126 | gc.weightx = 0.0; 127 | glayout.setConstraints(desc,gc); 128 | centerPanel.add(desc); 129 | gc.anchor = GridBagConstraints.EAST; 130 | glayout.setConstraints(pname,gc); 131 | centerPanel.add(pname); 132 | gc.anchor = GridBagConstraints.WEST; 133 | gc.gridwidth = GridBagConstraints.REMAINDER; 134 | gc.fill = GridBagConstraints.HORIZONTAL; 135 | gc.weightx = 1.0; 136 | glayout.setConstraints(edit,gc); 137 | centerPanel.add(edit); 138 | } 139 | } 140 | 141 | public boolean Show(int x,int y) { 142 | abort = false; 143 | 144 | if (okay != null) { 145 | // position over "Okay" buttom 146 | Point blocn = buttons.getLocation(); 147 | Point oklocn = okay.getLocation(); 148 | Dimension oksize = okay.getSize(); 149 | x -= blocn.x + oklocn.x + oksize.width/2; 150 | y -= blocn.y + oklocn.y + oksize.height/2; 151 | } 152 | 153 | // don't position off screen! 154 | Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 155 | Dimension d = getSize(); 156 | x = Math.max(40,Math.min(x,screenSize.width-d.width)); 157 | y = Math.max(40,Math.min(y,screenSize.height-d.height)); 158 | 159 | setLocation(x,y); 160 | show(); 161 | return abort; 162 | } 163 | 164 | public boolean Show(int x,int y,JTextField focus) { 165 | if (focus != null) { 166 | focus.addActionListener(this); // typing RETURN terminates dialog 167 | focus.requestFocus(); // make it easy to type into field 168 | } 169 | boolean result = Show(x,y); 170 | if (focus != null) focus.removeActionListener(this); 171 | return result; 172 | } 173 | 174 | public void windowClosed(WindowEvent event) { } 175 | public void windowDeiconified(WindowEvent event) { } 176 | public void windowIconified(WindowEvent event) { } 177 | public void windowActivated(WindowEvent event) { } 178 | public void windowDeactivated(WindowEvent event) { } 179 | public void windowOpened(WindowEvent event) { } 180 | public void windowClosing(WindowEvent event) { 181 | dispose(); 182 | abort = true; 183 | } 184 | 185 | public void actionPerformed(ActionEvent event) { 186 | if (event.getSource() == cancel) abort = true; 187 | exitButton = (JButton)event.getSource(); 188 | dispose(); 189 | } 190 | } 191 | 192 | -------------------------------------------------------------------------------- /gui/EditCanvas.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2002 Christopher J. Terman - All Rights Reserved. 2 | 3 | package gui; 4 | 5 | import java.awt.Cursor; 6 | import java.awt.Dimension; 7 | import java.awt.Graphics; 8 | import java.awt.event.ComponentEvent; 9 | import java.awt.event.ComponentListener; 10 | import java.awt.Rectangle; 11 | import javax.swing.JPanel; 12 | 13 | public class EditCanvas extends JPanel implements ComponentListener { 14 | public EditFrame parent; 15 | public Transform viewTransform; 16 | public Rectangle tempRect; 17 | public int grid; 18 | int cursor; // cursor we should be using 19 | 20 | public EditCanvas(EditFrame e) { 21 | super(); 22 | setBackground(UI.EDITBGCOLOR); 23 | setOpaque(true); 24 | parent = e; 25 | 26 | tempRect = new Rectangle(); 27 | viewTransform = new Transform(0,0,Transform.NORTH,1.0); 28 | grid = 1; 29 | cursor = Cursor.DEFAULT_CURSOR; 30 | 31 | addMouseListener(e); 32 | addMouseMotionListener(e); 33 | addKeyListener(e); 34 | addComponentListener(this); 35 | } 36 | 37 | public void Repaint() { 38 | repaint(); 39 | } 40 | 41 | public void Repaint(Rectangle r) { 42 | viewTransform.TransformRectangle(r,tempRect); 43 | tempRect.width += 1; // avoid fractional pixel problems on repaint 44 | tempRect.height += 1; 45 | repaint(tempRect); 46 | } 47 | 48 | public void Repaint(int x,int y,int w,int h) { 49 | tempRect.setBounds(x,y,w,h); 50 | Repaint(tempRect); 51 | } 52 | 53 | public void Activate(boolean which) { 54 | setEnabled(which); 55 | if (which) { 56 | requestFocus(); 57 | setCursor(Cursor.getPredefinedCursor(cursor)); 58 | Repaint(); 59 | } else setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 60 | } 61 | 62 | public void SetCursor(int newcursor) { 63 | if (cursor != newcursor) { 64 | cursor = newcursor; 65 | if (isEnabled()) setCursor(Cursor.getPredefinedCursor(cursor)); 66 | } 67 | } 68 | 69 | public void DrawGrid(Graphics g, Rectangle clip) { 70 | // don't bother with grid when it gets small 71 | if ((grid * viewTransform.scale) >= 4) { 72 | int minx = OnGrid(clip.x); 73 | int maxx = OnGrid(clip.x + clip.width); 74 | int miny = OnGrid(clip.y); 75 | int maxy = OnGrid(clip.y + clip.height); 76 | g.setColor(UI.GRIDCOLOR); 77 | for (int i = minx; i <= maxx; i += grid) 78 | for (int j = miny; j <= maxy; j += grid) { 79 | boolean mod8 = grid == 1 && (i % 8)==0 && (j % 8)==0; 80 | viewTransform.DrawGridPoint(g,i,j,grid,mod8); 81 | } 82 | 83 | // draw origin 84 | viewTransform.DrawLine(g,-1,0,1,0); 85 | viewTransform.DrawLine(g,0,-1,0,1); 86 | } 87 | } 88 | 89 | public void paintComponent(Graphics g) { 90 | super.paintComponent(g); 91 | 92 | Rectangle repaintRect = g.getClipBounds(); 93 | tempRect.setBounds(X(repaintRect.x),Y(repaintRect.y), 94 | X(repaintRect.width+repaintRect.x)-X(repaintRect.x), 95 | Y(repaintRect.height+repaintRect.y)-Y(repaintRect.y)); 96 | DrawGrid(g,tempRect); 97 | parent.DrawContents(g,viewTransform,tempRect); 98 | } 99 | 100 | public void componentHidden(ComponentEvent e) { } 101 | public void componentMoved(ComponentEvent e) { } 102 | public void componentShown(ComponentEvent e) { } 103 | public void componentResized(ComponentEvent e) { 104 | parent.SetupScrollbars(); 105 | parent.Surround(); 106 | } 107 | 108 | // convert canvas coordinate to on-grid schematic coordinate 109 | public int X(int x) { 110 | if (viewTransform == null) return 0; 111 | return (int)Math.round((x - viewTransform.orgx)/viewTransform.scale); 112 | } 113 | 114 | // convert canvas coordinate to on-grid schematic coordinate 115 | public int Y(int y) { 116 | if (viewTransform == null) return 0; 117 | return (int)Math.round((y - viewTransform.orgy)/viewTransform.scale); 118 | } 119 | 120 | // determine nearest grid point 121 | public int OnGrid(int v) { 122 | if (v < 0) return ((-v+(grid>>1))/grid)*-grid; 123 | else return ((v+(grid>>1))/grid)*grid; 124 | } 125 | 126 | // set viewTransform so that entire plot is visible 127 | public void Surround(int x,int y,int width,int height) { 128 | Dimension d = getSize(); 129 | 130 | // choose scale so entire plot will fill about 90% of the view 131 | double scalex = (width==0) ? 4.0 : ((double)d.width)/width; 132 | double scaley = (height==0) ? 4.0 : ((double)d.height)/height; 133 | double scale = .9 * ((scalex < scaley) ? scalex : scaley); 134 | 135 | Recenter(x + (width >> 1),y + (height >> 1),scale); 136 | } 137 | 138 | // zoom display about (x,y) with specified scale 139 | public void Zoom(int mx,int my,int x,int y,double newscale) { 140 | viewTransform.orgx = mx - (int)(x * newscale); 141 | viewTransform.orgy = my - (int)(y * newscale); 142 | SetScale(newscale); 143 | } 144 | 145 | // recenter display about (x,y) with specified scale 146 | public void Recenter(int x,int y,double newscale) { 147 | Dimension d = getSize(); 148 | 149 | viewTransform.orgx = d.width/2 - (int)(x * newscale); 150 | viewTransform.orgy = d.height/2 - (int)(y * newscale); 151 | SetScale(newscale); 152 | } 153 | 154 | public void SetScale(double scale) { 155 | viewTransform.scale = scale; 156 | parent.SetupScrollbars(); 157 | Repaint(); 158 | } 159 | 160 | public void SetGrid(int newgrid) { 161 | if (newgrid > 0 && grid != newgrid) { 162 | grid = newgrid; 163 | Repaint(); 164 | } 165 | } 166 | 167 | public double GetScale() { 168 | return viewTransform.scale; 169 | } 170 | 171 | public int GetOriginX() { 172 | return (int)viewTransform.orgx; 173 | } 174 | 175 | public int GetOriginY() { 176 | return (int)viewTransform.orgy; 177 | } 178 | 179 | public void SetOriginX(int x) { 180 | viewTransform.orgx = x; 181 | Repaint(); 182 | } 183 | 184 | public void SetOriginY(int y) { 185 | viewTransform.orgy = y; 186 | Repaint(); 187 | } 188 | 189 | protected void RepaintRectangle(Rectangle rect) { 190 | viewTransform.TransformRectangle(rect,tempRect); 191 | Repaint(tempRect.x-2,tempRect.y-2, 192 | tempRect.width+4,tempRect.height+4); 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /fsm/FSM.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999 Christopher J. Terman - All Rights Reserved. 2 | 3 | package fsm; 4 | 5 | import gui.GuiFrame; 6 | import java.util.Vector; 7 | import javax.swing.JTextArea; 8 | 9 | public class FSM { 10 | int ninputs; 11 | int noutputs; 12 | 13 | // one line in truth table => one entry in each of the vectors 14 | Vector state; // name of state (String) 15 | Vector pattern; // input pattern (int[ninputs]) 16 | Vector next; // name of next state (String) 17 | Vector outputs; // outputs (int[noutputs]) 18 | Vector sol; // start of line (Integer) 19 | Vector eol; // end of line (Integer) 20 | 21 | public JTextArea source; 22 | GuiFrame message; 23 | int index; 24 | 25 | public FSM(JTextArea source,GuiFrame message,int ninputs,int noutputs) { 26 | this.source = source; 27 | this.message = message; 28 | this.ninputs = ninputs; 29 | this.noutputs = noutputs; 30 | 31 | state = new Vector(); 32 | pattern = new Vector(); 33 | next = new Vector(); 34 | outputs = new Vector(); 35 | sol = new Vector(); 36 | eol = new Vector(); 37 | } 38 | 39 | void Error(String msg) { 40 | source.setCaretPosition(index); 41 | if (message != null) 42 | message.Message(msg+" (caret marks location of error)"); 43 | } 44 | 45 | void SkipWhitespace(String spec,int end) { 46 | while (index < end && Character.isWhitespace(spec.charAt(index))) 47 | index += 1; 48 | } 49 | 50 | String ReadState(String spec,int end) { 51 | SkipWhitespace(spec,end); 52 | int start = index; 53 | while (index < end && Character.isLetterOrDigit(spec.charAt(index))) 54 | index += 1; 55 | if (start == index) { 56 | Error("expected state name"); 57 | return null; 58 | } 59 | return spec.substring(start,index); 60 | } 61 | 62 | int ReadInput(String spec,int end) { 63 | SkipWhitespace(spec,end); 64 | int ch = index < end ? spec.charAt(index) : 0; 65 | if (ch != '0' && ch != '1' && ch != '-') { 66 | Error("expected '0', '1' or '-'"); 67 | return -1; 68 | } 69 | index += 1; 70 | return ch; 71 | } 72 | 73 | int ReadOutput(String spec,int end) { 74 | SkipWhitespace(spec,end); 75 | int ch = index < end ? spec.charAt(index) : 0; 76 | if (ch != '0' && ch != '1') { 77 | Error("expected '0' or '1'"); 78 | return -1; 79 | } 80 | index += 1; 81 | return ch; 82 | } 83 | 84 | boolean ReadLine(String spec,int end) { 85 | int start = index; 86 | 87 | // skip over leading whitespace; ignore comments and empty lines 88 | SkipWhitespace(spec,end); 89 | if (index == end || spec.charAt(index) == ';') return false; 90 | 91 | // read input state and input values 92 | String istate = ReadState(spec,end); 93 | if (istate == null) return true; 94 | int ins[] = new int[ninputs]; 95 | for (int i = 0; i < ninputs; i += 1) { 96 | int in = ReadInput(spec,end); 97 | if (in == -1) return true; 98 | ins[i] = in; 99 | } 100 | 101 | // check for '|' separator 102 | SkipWhitespace(spec,end); 103 | if (index >= end || spec.charAt(index) != '|') { 104 | Error("expected '|'"); 105 | return true; 106 | } else index += 1; 107 | 108 | // read input state and input values 109 | String ostate = ReadState(spec,end); 110 | if (ostate == null) return true; 111 | int outs[] = new int[noutputs]; 112 | for (int i = 0; i < noutputs; i += 1) { 113 | int out = ReadOutput(spec,end); 114 | if (out == -1) return true; 115 | outs[i] = out; 116 | } 117 | 118 | SkipWhitespace(spec,end); 119 | if (index != end) { 120 | Error("expected end of line"); 121 | return true; 122 | } 123 | 124 | state.addElement(istate); 125 | pattern.addElement(ins); 126 | next.addElement(ostate); 127 | outputs.addElement(outs); 128 | sol.addElement(new Integer(start)); 129 | eol.addElement(new Integer(end)); 130 | return false; 131 | } 132 | 133 | // load fsm tables from spec. Each line should look like: 134 | // state in1 in2 ... inN : next out1 out2 outM 135 | public boolean Load() { 136 | String spec = source.getText(); 137 | int len = spec.length(); 138 | index = 0; 139 | 140 | state.setSize(0); 141 | pattern.setSize(0); 142 | next.setSize(0); 143 | outputs.setSize(0); 144 | sol.setSize(0); 145 | eol.setSize(0); 146 | 147 | while (index < len) { 148 | int eol = spec.indexOf('\n',index); 149 | if (eol == -1) eol = len; 150 | if (ReadLine(spec,eol)) return false; 151 | index = eol + 1; 152 | } 153 | return true; 154 | } 155 | 156 | public void DumpState(int i) { 157 | System.out.print("state="+(String)state.elementAt(i)); 158 | System.out.print(" inputs="); 159 | int p[] = (int[])pattern.elementAt(i); 160 | for (int j = 0; j < p.length; j += 1) 161 | System.out.print((char)p[j]); 162 | System.out.println(""); 163 | } 164 | 165 | // find which entry in tables that matches inputs 166 | public int Match(String s,int inputs[]) { 167 | int nlines = state.size(); 168 | int index = -1; 169 | 170 | for (int i = 0; i < nlines; i += 1) { 171 | //DumpState(i); 172 | if (s.equalsIgnoreCase((String)state.elementAt(i))) { 173 | int p[] = (int[])pattern.elementAt(i); 174 | boolean match = true; 175 | for (int n = 0; n < ninputs; n += 1) 176 | if (p[n]!='-' && p[n]!=inputs[n]) { 177 | match = false; 178 | break; 179 | } 180 | if (match) { 181 | if (index != -1 && message != null) { 182 | String error = "more than one match in FSM: s="+s; 183 | for (int n = 0; n < ninputs; n += 1) 184 | error += " "+((char)inputs[n]); 185 | message.Message(error); 186 | } else index = i; 187 | } 188 | } 189 | } 190 | 191 | if (index == -1 && message != null) { 192 | String error = "no match in FSM: s="+s; 193 | for (int n = 0; n < ninputs; n += 1) 194 | error += " "+((char)inputs[n]); 195 | message.Message(error); 196 | } 197 | 198 | return index; 199 | } 200 | 201 | public String NextState(int index) { 202 | if (index >= 0 && index < next.size()) 203 | return (String)next.elementAt(index); 204 | else return null; 205 | } 206 | 207 | public int[] Outputs(int index) { 208 | if (index >= 0 && index < next.size()) 209 | return (int [])outputs.elementAt(index); 210 | return null; 211 | } 212 | } 213 | 214 | -------------------------------------------------------------------------------- /gui/EditFrame.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2002 Christopher J. Terman - All Rights Reserved. 2 | 3 | package gui; 4 | 5 | import java.awt.BorderLayout; 6 | import java.awt.Dimension; 7 | import java.awt.Graphics; 8 | import java.awt.GridBagConstraints; 9 | import java.awt.GridBagLayout; 10 | import java.awt.Rectangle; 11 | import java.awt.event.ActionEvent; 12 | import java.awt.event.ActionListener; 13 | import java.awt.event.AdjustmentEvent; 14 | import java.awt.event.AdjustmentListener; 15 | import java.awt.event.KeyEvent; 16 | import java.awt.event.KeyListener; 17 | import java.awt.event.MouseEvent; 18 | import java.awt.event.MouseListener; 19 | import java.awt.event.MouseMotionListener; 20 | import javax.swing.BorderFactory; 21 | import javax.swing.JButton; 22 | import javax.swing.JPanel; 23 | import javax.swing.JScrollBar; 24 | import javax.swing.JToolBar; 25 | 26 | public class EditFrame extends EditPanel implements ActionListener, AdjustmentListener, MouseListener, MouseMotionListener, KeyListener { 27 | public EditCanvas canvas; 28 | public JToolBar bbar; 29 | JScrollBar vbar,hbar; 30 | JButton b1,b2,b3; 31 | public int mx,my; // mouse coords 32 | 33 | public static final double ZOOM_FACTOR = 1.5; 34 | 35 | public EditFrame(GuiFrame p) { 36 | super(p); 37 | mx = my = 0; 38 | 39 | // set up tool bar 40 | bbar = new JToolBar(); 41 | bbar.putClientProperty("JToolBar.isRollover",Boolean.TRUE); 42 | add("North",bbar); 43 | 44 | // use subsidiary panel for other elements so that 45 | // toolbar can be repositioned about edge... 46 | JPanel panel = new JPanel(); 47 | panel.setLayout(new BorderLayout()); 48 | add("Center",panel); 49 | 50 | canvas = new EditCanvas(this); 51 | canvas.setBorder(BorderFactory.createLoweredBevelBorder()); 52 | 53 | vbar = new JScrollBar(JScrollBar.VERTICAL); 54 | vbar.setBackground(UI.BGCOLOR); 55 | vbar.addAdjustmentListener(this); 56 | hbar = new JScrollBar(JScrollBar.HORIZONTAL); 57 | hbar.addAdjustmentListener(this); 58 | hbar.setBackground(UI.BGCOLOR); 59 | 60 | Dimension bdim = new Dimension(16,16); 61 | b1 = p.ImageButton("/icons/zoomin.gif"); 62 | b1.setToolTipText("Zoom in"); 63 | b1.addActionListener(this); 64 | b1.setPreferredSize(bdim); 65 | b2 = p.ImageButton("/icons/zoomout.gif"); 66 | b2.setToolTipText("Zoom out"); 67 | b2.addActionListener(this); 68 | b2.setPreferredSize(bdim); 69 | b3 = p.ImageButton("/icons/zoom.gif"); 70 | b3.setToolTipText("Surround"); 71 | b3.addActionListener(this); 72 | b3.setPreferredSize(bdim); 73 | 74 | panel.add("East",vbar); 75 | panel.add("Center",canvas); 76 | 77 | // use GridBag stuff to bottom row 78 | JPanel bottom = new JPanel(); 79 | panel.add("South",bottom); 80 | GridBagLayout glayout = new GridBagLayout(); 81 | bottom.setLayout(glayout); 82 | GridBagConstraints c = new GridBagConstraints(); 83 | 84 | // zoom buttons line up horizontally along bottom edge 85 | c.fill = GridBagConstraints.NONE; 86 | c.weightx = 0.0; 87 | c.weighty = 0.0; 88 | c.gridwidth = 1; 89 | glayout.setConstraints(b1,c); 90 | bottom.add(b1); 91 | glayout.setConstraints(b2,c); 92 | bottom.add(b2); 93 | glayout.setConstraints(b3,c); 94 | bottom.add(b3); 95 | 96 | // the horizonatal scrollbar fills out the bottom edge 97 | c.fill = GridBagConstraints.HORIZONTAL; 98 | c.weightx = 1.0; 99 | c.gridwidth = GridBagConstraints.REMAINDER; 100 | glayout.setConstraints(hbar,c); 101 | bottom.add(hbar); 102 | } 103 | 104 | public void DrawContents(Graphics g,Transform t,Rectangle bbox) { 105 | } 106 | 107 | public void MarkModified() { 108 | observers.notifyObservers(this); 109 | } 110 | 111 | public void Activate(boolean which) { 112 | canvas.Activate(which); 113 | hbar.setEnabled(which); 114 | vbar.setEnabled(which); 115 | b1.setEnabled(which); 116 | b2.setEnabled(which); 117 | b3.setEnabled(which); 118 | } 119 | 120 | // override 121 | public void Surround() { 122 | canvas.Surround(0,0,0,0); 123 | } 124 | 125 | // override 126 | public void SetupScrollbars() { 127 | SetupScrollbars(0,0,0,0); 128 | } 129 | 130 | // set scrollbar params to canonical values 131 | public void SetupScrollbars(int x,int y,int width,int height) { 132 | Dimension d = canvas.getSize(); 133 | Transform t = canvas.viewTransform; 134 | 135 | int extra = width >> 1; 136 | int vis = (int)(d.width/t.scale); 137 | int max = x + width + extra; 138 | hbar.setValues((int)(-t.orgx/t.scale),vis,x-extra,max); 139 | hbar.setBlockIncrement(vis); 140 | int temp = (canvas.grid < vis) ? canvas.grid : vis; 141 | hbar.setUnitIncrement(temp); 142 | 143 | extra = height >> 1; 144 | vis = (int)(d.height/t.scale); 145 | max = y + height + extra; 146 | vbar.setValues((int)(-t.orgy/t.scale),vis,y-extra,max); 147 | vbar.setBlockIncrement(vis); 148 | vbar.setUnitIncrement(temp); 149 | } 150 | 151 | // handle scrollbar events 152 | public void adjustmentValueChanged(AdjustmentEvent event) { 153 | JScrollBar source = (JScrollBar)event.getSource(); 154 | int max = source.getMaximum() - source.getVisibleAmount(); 155 | int org = (int)(-canvas.GetScale()*Math.min(max,event.getValue())); 156 | if (source == hbar) canvas.SetOriginX(org); 157 | else canvas.SetOriginY(org); 158 | canvas.repaint(); 159 | } 160 | 161 | // handle button/menu events 162 | public void actionPerformed(ActionEvent event) { 163 | Object s = event.getSource(); 164 | String a = event.getActionCommand(); 165 | 166 | if (b1 == s) canvas.SetScale(canvas.GetScale() * ZOOM_FACTOR); 167 | else if (b2 == s) canvas.SetScale(canvas.GetScale() / ZOOM_FACTOR); 168 | else if (b3 == s) Surround(); 169 | else super.actionPerformed(event); 170 | } 171 | 172 | public void mouseEntered(MouseEvent event) { 173 | canvas.requestFocus(); 174 | } 175 | 176 | public void mouseExited(MouseEvent event) { } 177 | public void mouseClicked(MouseEvent event) { } 178 | public void mouseMoved(MouseEvent event) { 179 | mx = event.getX(); 180 | my = event.getY(); 181 | } 182 | public void mousePressed(MouseEvent event) {} 183 | public void mouseReleased(MouseEvent event) {} 184 | public void mouseDragged(MouseEvent event) {} 185 | 186 | public void keyPressed(KeyEvent event) { 187 | int x = canvas.X(mx); 188 | int y = canvas.Y(my); 189 | 190 | switch (event.getKeyChar()) { 191 | case 'Z': 192 | canvas.Zoom(mx,my,x,y,canvas.GetScale()*ZOOM_FACTOR); 193 | break; 194 | case 'z': 195 | canvas.Zoom(mx,my,x,y,canvas.GetScale()/ZOOM_FACTOR); 196 | break; 197 | case 'c': 198 | canvas.Recenter(x,y,canvas.GetScale()); 199 | break; 200 | } 201 | } 202 | public void keyReleased(KeyEvent event) { } 203 | public void keyTyped(KeyEvent event) { } 204 | } 205 | -------------------------------------------------------------------------------- /simulation/EmuNode.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 1999-2001 Christopher J. Terman - All Rights Reserved. 2 | 3 | package simulation; 4 | 5 | import java.util.ArrayList; 6 | import netlist.PlotRequest; 7 | 8 | class EmuNode extends Node { 9 | EmuRegion region; // region we belong to 10 | EmuNode regionLink; // next node in region's node list 11 | ArrayList fanoutRegions; // regions we affect 12 | double lastFanoutVoltage; // last "event" voltage 13 | ArrayList devices; // devices we connect to 14 | double capacitance; 15 | double voltage; 16 | double deltaV; 17 | double lastDeltaV; 18 | double totalCurrent; 19 | double totalTransconductance; 20 | boolean powerSupply; 21 | SpiceSource source; 22 | PlotRequest plotRequest; 23 | 24 | public EmuNode(String name) { 25 | super(name); 26 | region = null; 27 | devices = new ArrayList(); 28 | fanoutRegions = new ArrayList(); 29 | voltage = 0.0; 30 | capacitance = 0.0; 31 | powerSupply = false; 32 | source = null; 33 | plotRequest = null; 34 | } 35 | 36 | // turn node into a power supply 37 | public void PowerSupply(double voltage) { 38 | powerSupply = true; 39 | this.voltage = voltage; 40 | deltaV = 0; 41 | lastFanoutVoltage = voltage; 42 | region = EmuRegion.CONSTANT_REGION; 43 | 44 | // remove any capacitors connected to this node from 45 | // the network -- they now behave as if they were 46 | // capacitors to gnd, ie, we account for the effect 47 | // in the nodal capacitance for each terminal. 48 | for (int i = devices.size() - 1; i >= 0; i -= 1) { 49 | EmuDevice d = (EmuDevice)devices.get(i); 50 | if (d instanceof EmuCapacitor) 51 | ((EmuCapacitor)d).RemoveDevice(); 52 | } 53 | } 54 | 55 | // turn node into an input 56 | public void VoltageSource(SpiceSource source) { 57 | this.source = source; 58 | } 59 | 60 | public double GetValue(Network network) { 61 | return voltage; 62 | } 63 | 64 | public void AddDevice(EmuDevice d) { 65 | if (!powerSupply) 66 | devices.add(d); 67 | } 68 | 69 | public void RemoveDevice(EmuDevice d) { 70 | devices.remove(d); 71 | } 72 | 73 | public void AddFanoutRegion(EmuRegion r) { 74 | if (!fanoutRegions.contains(r)) 75 | fanoutRegions.add(r); 76 | } 77 | 78 | public void AddToRegion(EmuRegion r) { 79 | EmuNetwork network = r.network; 80 | if (capacitance < network.minCapacitance) 81 | capacitance = network.minCapacitance; 82 | capacitance *= network.cAdjust; 83 | region = r; 84 | int ndevices = devices.size(); 85 | for (int i = 0; i < ndevices; i += 1) { 86 | EmuDevice d = (EmuDevice)devices.get(i); 87 | if (d.region == null) d.AddToRegion(r,this); 88 | } 89 | } 90 | 91 | public void Reset() { 92 | if (!powerSupply) { 93 | double v = (source == null) ? 0 : source.TransientValue(0); 94 | voltage = v; 95 | deltaV = 0; 96 | lastFanoutVoltage = v; 97 | lastDeltaV = 0; 98 | } 99 | totalCurrent = 0; 100 | totalTransconductance = 0; 101 | } 102 | 103 | // compute how much the voltage will change over specified timestep 104 | public boolean ComputeUpdate(double timestep) { 105 | boolean converged = true; 106 | 107 | // input nodes get special treatment 108 | if (source != null) { 109 | double v = source.TransientValue(region.network.time); 110 | deltaV = v - voltage; 111 | } else { 112 | // update current flowing into this node 113 | double i = totalCurrent; 114 | int ndevices = devices.size(); 115 | for (int j = 0; j < ndevices; j += 1) { 116 | EmuDevice d = (EmuDevice)devices.get(j); 117 | i += d.Incremental(this,timestep); 118 | } 119 | 120 | // no current => no voltage change 121 | if (i == 0) { 122 | deltaV = 0; 123 | lastDeltaV = 0; 124 | return true; 125 | } 126 | 127 | // timestep <= 0 indicates open capacitors 128 | if (timestep <= 0) 129 | deltaV = i/totalTransconductance; 130 | else 131 | deltaV = i/((capacitance/timestep) + totalTransconductance); 132 | 133 | // limit change in voltage at each iteration 134 | double dvLimit = region.network.dvLimit; 135 | double dv = deltaV - lastDeltaV; 136 | if (dv > dvLimit) { 137 | deltaV = lastDeltaV + dvLimit; 138 | converged = false; 139 | } else if (dv < -dvLimit) { 140 | deltaV = lastDeltaV - dvLimit; 141 | converged = false; 142 | } 143 | } 144 | 145 | // check for convergence 146 | if (Math.abs(deltaV) > region.network.absTol && 147 | Math.abs((deltaV - lastDeltaV)/deltaV) > region.network.relTol) 148 | converged = false; 149 | lastDeltaV = deltaV; 150 | 151 | return converged; 152 | } 153 | 154 | public void Snapshot() { 155 | EmuNetwork network = region.network; 156 | RecordValue(network,network.time,voltage); 157 | } 158 | 159 | // update voltage according to dictates of ComputeUpdate 160 | public void PerformUpdate() { 161 | voltage += deltaV; 162 | 163 | // gak! 164 | if (voltage > 6) { 165 | voltage = 6; 166 | //System.out.println(name+": cap="+capacitance+"deltaV="+deltaV+" totalCurrent="+totalCurrent+" totalG="+totalTransconductance); 167 | } else if (voltage < -1) voltage = -1; 168 | 169 | deltaV = 0; 170 | totalTransconductance = 0; 171 | 172 | EmuNetwork network = region.network; 173 | if (network.time > 0) RecordValue(network,network.time,voltage); 174 | } 175 | 176 | // predict when next event will happen based on node's capacitance, 177 | // how much delta V we're looking for and the total current flowing 178 | // in/out of the node 179 | public double PredictTimestep() { 180 | if (source != null) { 181 | double time = region.network.time; 182 | double bp = source.NextBreakpoint(time,region.network.eventThreshold); 183 | if (bp == -1) return EmuRegion.NO_EVENT; 184 | else return Math.max(region.network.minTimestep,bp - time); 185 | } else if (totalCurrent == 0) 186 | return EmuRegion.NO_EVENT; 187 | else { 188 | double t = (capacitance * region.network.eventThreshold) / 189 | Math.abs(totalCurrent); 190 | return Math.max(region.network.minTimestep,t); 191 | } 192 | } 193 | 194 | // if our new voltage has changed enough since the last time we 195 | // processed the fanout regions, we have to bring them up to date 196 | public EmuRegion CheckFanouts(double time,EmuRegion link) { 197 | if (fanoutRegions.size() > 0) { 198 | double newV = voltage + deltaV; 199 | if (Math.abs(newV - lastFanoutVoltage) >= region.network.eventThreshold) { 200 | lastFanoutVoltage = newV; 201 | int nfanouts = fanoutRegions.size(); 202 | for (int i = 0; i < nfanouts; i += 1) { 203 | EmuRegion r = (EmuRegion)fanoutRegions.get(i); 204 | // update region if it hasn't been processed yet 205 | if (r.link == null) link = r.ComputeUpdate(time,link); 206 | } 207 | } 208 | } 209 | 210 | return link; 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /tmsim/TMSim.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2003-2011 Christopher J. Terman - All Rights Reserved. 2 | 3 | package tmsim; 4 | 5 | import gui.EditBuffer; 6 | import gui.GuiFrame; 7 | import gui.POSTStream; 8 | import gui.UI; 9 | import java.awt.Component; 10 | import java.awt.GridBagConstraints; 11 | import java.awt.GridBagLayout; 12 | import java.awt.event.ActionEvent; 13 | import java.awt.event.ActionListener; 14 | import java.awt.event.WindowEvent; 15 | import java.awt.event.WindowListener; 16 | import java.io.File; 17 | import java.io.FileOutputStream; 18 | import java.io.IOException; 19 | import java.io.InputStream; 20 | import java.io.PrintWriter; 21 | import java.text.DateFormat; 22 | import java.util.Date; 23 | import javax.swing.JDialog; 24 | import javax.swing.JEditorPane; 25 | import javax.swing.JLabel; 26 | import javax.swing.JOptionPane; 27 | import javax.swing.JPanel; 28 | import javax.swing.JScrollPane; 29 | 30 | public class TMSim extends GuiFrame implements ActionListener, WindowListener { 31 | public static String version = "1.2.2"; 32 | public static String copyright = "Copyright (C) Christopher J. Terman 2003-2013"; 33 | 34 | public static String DUMMY_TM = 35 | "// 5-state busy beaver Turing Machine example\n\n"+ 36 | "// See how many 1's we can write on a blank tape using\n"+ 37 | "// only a five-state Turing Machine\n\n"+ 38 | "states A B C D E // list of state names, first is starting state\n"+ 39 | "symbols 1 // list of symbols (- is blank cell)\n"+ 40 | "tape test - // initial tape contents, blank in this case\n\n"+ 41 | "// Uhing's 5-state machine: writes 1915 1s in 2,133,492 steps before halting.\n"+ 42 | "// Note that the best known 5-state writes 4098 1s...\n"+ 43 | "// See http://grail.cba.csuohio.edu/~somos/busy.html\n\n"+ 44 | "// specify transistions: action state symbol state' write move\n"+ 45 | "// state = the current state of the FSM\n"+ 46 | "// symbol = the symbol read from the current cell\n"+ 47 | "// state' = state on the next cycle \n"+ 48 | "// write = symbol to be written into the current cell\n"+ 49 | "// move = tape movement (\"l\" = left, \"r\" = right, \"-\"=stay put)\n"+ 50 | "// old R new W M\n"+ 51 | "action A - B 1 r\n"+ 52 | "action A 1 C 1 l\n"+ 53 | "action B - A - l\n"+ 54 | "action B 1 D - l\n"+ 55 | "action C - A 1 l\n"+ 56 | "action C 1 *halt* 1 l\n"+ 57 | "action D - B 1 l\n"+ 58 | "action D 1 E 1 r\n"+ 59 | "action E - D - r\n"+ 60 | "action E 1 B - r\n"; 61 | 62 | String cmdargs[] = null; // command line args 63 | 64 | public TMSim(String args[]) { 65 | super(args,"TMSim "+version,true,false); 66 | //setIconImage(GetImageResource("/icons/ant.gif")); 67 | 68 | // set up edit window 69 | AddToolButton("/icons/exit.gif",UI.EXIT,this); 70 | AddToolSeparator(); 71 | AddToolButton("/icons/new.gif",UI.NEW,this); 72 | AddToolButton("/icons/open.gif",UI.OPEN,this); 73 | AddToolButton("/icons/close.gif",UI.CLOSE,this); 74 | AddToolButton("/icons/reload.gif",UI.RELOAD,this); 75 | AddToolButton("/icons/save.gif",UI.SAVE,this); 76 | AddToolButton("/icons/saveas.gif",UI.SAVEAS,this); 77 | AddToolButton("/icons/saveall.gif",UI.SAVEALL,this); 78 | AddToolSeparator(); 79 | AddToolButton("/icons/submit.gif",UI.CHECKOFF,this); 80 | Message("TMSim "+version+", "+copyright); 81 | 82 | SetTab(ReadFiles()); 83 | 84 | // display our handiwork 85 | setVisible(true); 86 | } 87 | 88 | // used by stand-alone application 89 | public static void main(String args[]) { 90 | new TMSim(args); 91 | } 92 | 93 | public void actionPerformed(ActionEvent event) { 94 | eventThread = Thread.currentThread(); 95 | String what = event.getActionCommand(); 96 | try { 97 | if (what.equals(UI.CHECKOFF)) { 98 | Checkoff(); 99 | } else super.actionPerformed(event); 100 | } 101 | catch (Exception e) { 102 | Message("Internal error: "+e); 103 | 104 | String ename = GetParameter("reporterrors"); 105 | if (ename != null) { 106 | if (ename.equals("-reporterrors")) e.printStackTrace(System.out); 107 | else { 108 | try { 109 | PrintWriter out = new PrintWriter(new FileOutputStream(ename,true)); 110 | String time = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,DateFormat.SHORT).format(new Date()); 111 | String user = System.getProperty("user.name","???"); 112 | String host = System.getProperty("hostname","???"); 113 | out.println("version=\""+version+"\" time=\""+time+"\" user=\""+user+"@"+host+"\" action=\""+what+"\""); 114 | e.printStackTrace(out); 115 | 116 | // capture buffer contents 117 | int nviews = tabPane.getTabCount(); 118 | for (int i = 0; i < nviews; i += 1) { 119 | EditBuffer n = (EditBuffer)tabPane.getComponentAt(i); 120 | n.Capture(out); 121 | } 122 | out.close(); 123 | } 124 | catch (Exception ee) { 125 | } 126 | } 127 | } 128 | } 129 | } 130 | 131 | public void RemoveView(Component v) { 132 | RemoveTab(v); 133 | } 134 | 135 | public EditBuffer ReadFiles() { 136 | TMPanel result = (TMPanel)super.ReadFiles(); 137 | if (result.source == null) { 138 | result.setText(DUMMY_TM); 139 | } 140 | result.Reset(); 141 | return result; 142 | } 143 | 144 | public Component OpenFile(File file,boolean atEnd) { 145 | // set default directory for file chooser 146 | if (lastDirectory == null && file != null) 147 | lastDirectory = file.getParent(); 148 | 149 | TMPanel n = new TMPanel(this,file); 150 | AddTab(n.TabName(),n.ToolTip(),n,atEnd ? -1 : 0); 151 | 152 | return (Component)n; 153 | } 154 | 155 | public void Checkoff() { 156 | TMPanel n = (TMPanel)Selectee(); 157 | 158 | if (n.checkoffChecksum == 123456) { 159 | System.out.println("checksum = "+n.tapeChecksum); 160 | return; 161 | } 162 | 163 | if (!n.Solved()) { 164 | JOptionPane.showMessageDialog(this,"Your TM must be run successfully on all the test tapes\nwithout changing your FSM in order to complete the checkoff.", 165 | "TMSim Checkoff", 166 | JOptionPane.WARNING_MESSAGE); 167 | return; 168 | } 169 | 170 | if (n.tapeChecksum != n.checkoffChecksum) { 171 | JOptionPane.showMessageDialog(this,"It appears that the checkoff information has been modified in some way. Please verify that you haven't modified any 'tape' or 'result' statements.", 172 | "TMSim Checkoff", 173 | JOptionPane.WARNING_MESSAGE); 174 | return; 175 | } 176 | 177 | DoCheckoff(n.checkoffServer); 178 | } 179 | 180 | public void GeneratePostData(POSTStream o) throws IOException { 181 | TMPanel n = (TMPanel)Selectee(); 182 | 183 | // indicate assignment 184 | o.writeTag("checkoff"); 185 | o.write(n.checkoffAssignment); 186 | 187 | // send number of states 188 | o.writeTag("size"); 189 | o.write(Integer.toString(n.getNStates())); 190 | 191 | // send checksum 192 | o.writeTag("checksum"); 193 | o.write(Integer.toString(n.checkoffChecksum)); 194 | 195 | // version 196 | o.writeTag("version"); 197 | o.write("TMSim"+version); 198 | } 199 | } 200 | --------------------------------------------------------------------------------