SpiceOutputViewImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Christian LeCocq March 25, 1987 10:01:45 am PST
Christian Le Cocq April 4, 1988 5:52:53 pm PDT
Description of what this module does.
DIRECTORY
Core,
CoreFlat,
CoreOps,
IO,
PlotGraph,
RefText,
Rope,
SpiceOps,
SymTab;
SpiceOutputViewImpl: CEDAR PROGRAM
IMPORTS CoreFlat, CoreOps, IO, PlotGraph, RefText, Rope, SymTab
EXPORTS SpiceOps
~ BEGIN
ConvData: TYPE ~ SpiceOps.ConvData;
ROPE: TYPE ~ Rope.ROPE;
VEC: TYPE ~ PlotGraph.VEC;
VecList: TYPE ~ LIST OF VEC;
DisplayList: TYPE = LIST OF DisplayListRec;
DisplayListRec: TYPE = RECORD [
graph: PlotGraph.Graph,
list: VecList
];
matchingPattern: ROPE = "0**** ";
analysisRope: ROPE = "ANALYSIS";
patternLength: INT = Rope.Length[matchingPattern];
leftPar: ROPE = "(";
rigthPar: ROPE = ")";
window: PlotGraph.Rectangle ← [0.0, 0.0, 100.0, 5.0];
Public
DisplaySpiceListing: PUBLIC PROC [convData: ConvData] ~ {
plot: PlotGraph.Plot;
stream: IO.STREAM ← convData.inS;
IF stream=NIL THEN RETURN;
SearchListingFile[stream, analysisRope];
plot ← PlotGraph.CreatePlot[CoreOps.GetCellTypeName[convData.rootCell]];
ReadFirstLine[stream, plot];
ChangeNames[plot, convData.rootCell, convData.invTable];
FillPlot[stream, plot];
PlotGraph.RefreshPlot[plot: plot, within: window, eraseFirst: TRUE]
};
ChangeNames: PROC [plot: PlotGraph.Plot, cellType: Core.CellType, nameTable: SymTab.Ref] ~ {
FOR iAxis: PlotGraph.AxisList ← plot.axis, iAxis.rest UNTIL iAxis=NIL DO
wire: CoreFlat.FlatWire ← NARROW[SymTab.Fetch[nameTable, iAxis.first.name].val];
IF wire#NIL THEN iAxis.first.name ← CoreFlat.WirePathRope[cellType, wire^];
ENDLOOP;
};
I/Os
MyGetLineRope: PROC [stream: IO.STREAM] RETURNS [line: ROPENIL] ~ {
bufMax: NAT = 256;
buffer: REF TEXT = RefText.ObtainScratch[bufMax];
bLen: NAT ← 0;
chars: INT ← 0;
{ ENABLE UNWIND => RefText.ReleaseScratch[buffer];
DO
char: CHAR
IO.GetChar[stream
! IO.EndOfStream => IF chars > 0 THEN EXIT ELSE REJECT];
IF char = '\n OR char = '\l THEN EXIT;
chars ← chars + 1;
IF bLen = bufMax THEN {
buffer.length ← bLen;
line ← Rope.Concat[line, Rope.FromRefText[buffer]];
bLen ← 0;
};
buffer[bLen] ← char;
bLen ← bLen+1;
ENDLOOP;
};
buffer.length ← bLen;
IF bLen # 0 THEN line ← Rope.Concat[line, Rope.FromRefText[buffer]];
RefText.ReleaseScratch[buffer];
RETURN [line];
};
SearchListingFile: PUBLIC PROC [stream: IO.STREAM, partName: ROPE] ~ {
Description of the procedure.
DO
l: ROPE ← MyGetLineRope[stream];
IF Rope.Equal[Rope.Substr[l, 0, patternLength], matchingPattern] THEN
IF Rope.Find[l, partName]> 0 THEN EXIT;
ENDLOOP;
[] ← MyGetLineRope[stream]; -- blank line
[] ← MyGetLineRope[stream]; -- *****... line
[] ← MyGetLineRope[stream]; -- blank line
[] ← MyGetLineRope[stream]; -- blank line
[] ← MyGetLineRope[stream]; -- blank line
for transient analysis the next line is : "
TIME V(1) V(2)"...
which is where the data begins.
};
SpaceInsideLine: IO.BreakProc ~ {
PROC [char: CHAR] RETURNS [CharClass]
RETURN[SELECT char FROM
IO.TAB, IO.SP => sepr,
IO.CR, IO.LF, '(, ') => break,
ENDCASE   => other]
};
ReadFirstLine: PUBLIC PROC [stream: IO.STREAM, plot: PlotGraph.Plot] ~ {
Description of the procedure.
displayList: DisplayList;
nLines: INT ← 0;
base, height: REAL;
token: ROPEIO.GetTokenRope[stream, SpaceInsideLine].token; -- gets "TIME"
token ← IO.GetTokenRope[stream, SpaceInsideLine].token; -- 1st output
UNTIL IsEOL[token] DO
name: ROPE;
graph: PlotGraph.Graph ← NEW[PlotGraph.GraphRec ← [class: gClass]];
SELECT TRUE FROM
Rope.Equal[token, "V"] => {base ← 0.0; height ← 5.0};
Rope.Equal[token, "I"] => {base ← 0.005; height ← 0.01; name ← "Current in "};
ENDCASE => ERROR;
IF ~Rope.Equal[IO.GetTokenRope[stream, SpaceInsideLine].token, leftPar] THEN ERROR;
name ← Rope.Cat[name, IO.GetTokenRope[stream, SpaceInsideLine].token, " "];
the extra space is needed in order to recognize the wire name - see SpiceInputGenImpl.NextInstanceId which generates rope numbers.
IF ~Rope.Equal[IO.GetTokenRope[stream, SpaceInsideLine].token, rigthPar] THEN ERROR;
nLines ← nLines+1;
plot.axis ← CONS[NEW[PlotGraph.AxisRec ← [
graphs: LIST[graph],
bounds: [0.0, base, 100.0, height],
name: name,
style: analog,
axisData: [axisData, axisData]
]], plot.axis];
displayList ← CONS[[graph: graph], displayList];
token ← IO.GetTokenRope[stream, SpaceInsideLine].token;
ENDLOOP;
plot.data ← displayList;
};
MyGetReal: PROC [stream: IO.STREAM] RETURNS [r: REAL] ~ {
Tries to cope with 0 being written as 0. e+00, which is 2 tokens for IO.
r ← IO.GetReal[stream];
IF IO.PeekChar[stream]#'. THEN RETURN;
[] ← IO.GetTokenRope[stream, SpaceInsideLine];
IF r=0.0 THEN IF ~Rope.Equal[IO.GetTokenRope[stream, SpaceInsideLine].token, "e+00"] THEN ERROR;
};
IsEOL: PROC [token: ROPE] RETURNS [isEol: BOOLEAN] ~ {
RETURN[SELECT Rope.Fetch[token, 0] FROM
IO.LF, IO.CR => TRUE,
ENDCASE => FALSE]
};
ReadValues: PUBLIC PROC [stream: IO.STREAM, nVal: INT] RETURNS [vecList: VecList] ~ {
Description of the procedure.
eolRope: ROPE;
time: REAL ← MyGetReal[stream]*1.e9;
THROUGH [1..nVal] DO
vecList ← CONS[[time, MyGetReal[stream]], vecList];
ENDLOOP;
eolRope ← IO.GetTokenRope[stream, SpaceInsideLine].token;
IF ~IsEOL[eolRope] THEN ERROR;
};
FillPlot: PROC [stream: IO.STREAM, plot: PlotGraph.Plot] ~ {
nVal: INT ← 0;
displayList: DisplayList ← NARROW[plot.data];
[] ← IO.GetTokenRope[stream, SpaceInsideLine];
[] ← IO.GetTokenRope[stream, SpaceInsideLine]; -- skip 2 lines
plot.lowerBounds ← [1.0e24, 1.0e24];
plot.upperBounds ← [-1.0e24, -1.0e24];
FOR iAxis: PlotGraph.AxisList ← plot.axis, iAxis.rest UNTIL iAxis=NIL DO
nVal ← nVal+1;
ENDLOOP;
DO
vecList: VecList;
IF IO.PeekChar[stream]#IO.SP THEN RETURN;
vecList ← ReadValues[stream, nVal];
FOR iDisplayList: DisplayList ← displayList, iDisplayList.rest UNTIL iDisplayList=NIL DO
plot.lowerBounds.x ← MIN[plot.lowerBounds.x, vecList.first.x];
plot.lowerBounds.y ← MIN[plot.lowerBounds.y, vecList.first.y];
plot.upperBounds.x ← MAX[plot.upperBounds.x, vecList.first.x];
plot.upperBounds.y ← MAX[plot.upperBounds.y, vecList.first.y];
iDisplayList.first.list ← CONS[vecList.first, iDisplayList.first.list];
vecList ← vecList.rest;
ENDLOOP;
ENDLOOP;
};
Display
Enum: PlotGraph.GraphEnumerateProc ~ {
PROC [plot: PlotGraph.Plot, graph: PlotGraph.Graph, bounds: PlotGraph.Rectangle, eachPoint: PlotGraph.PointProc] RETURNS [invalidEnumeration: BOOLFALSE] ~ {
quit: BOOLEANFALSE;
displayList: DisplayList ← NARROW[plot.data];
FOR iDisplayList: DisplayList ← displayList, iDisplayList.rest UNTIL iDisplayList=NIL OR quit DO
IF iDisplayList.first.graph=graph THEN
FOR iVecList: VecList ← iDisplayList.first.list, iVecList.rest UNTIL iVecList=NIL DO
IF eachPoint[iVecList.first.x, iVecList.first.y] THEN RETURN [TRUE];
ENDLOOP;
ENDLOOP;
};
gClass: PlotGraph.GraphClass ← NEW[PlotGraph.GraphClassRec ← [
insert: NIL,
delete: NIL,
enumerate: Enum
]];
axisData: PlotGraph.AxisData ← [1.0, TRUE];
Commander.Register[key: "SpiceOps", proc: SpiceDisplayCmd, doc: "Display files sent by Spice"];
END.