-- File: [Thyme]<Thyme>System>CSIM01>spOutput.mesa -- Last editted: -- Wilhelm April 6, 1982 11:36 AM, reformated by Barth and stored under -- [Cherry]<Barth>Thyme>1.97> . DIRECTORY spGlobals, AltoDefs, CWF, Real, RealFns, plotDefs, DisplayDefs, StreamDefs, TimeDefs, StringDefs, AbsAllocDefs; spOutput: PROGRAM IMPORTS spGlobals, CWF, P: plotDefs, DisplayDefs, Str: StreamDefs, TD: TimeDefs, StringDefs, AbsAllocDefs EXPORTS spGlobals = BEGIN OPEN spGlobals; t0: REAL; argumentPtr: TYPE = LONG POINTER TO argument; argument: TYPE = RECORD[node: nodePtr, branch: branchPtr, getComVal: BOOLEAN, dvdt: BOOLEAN, current: BOOLEAN]; printBlkPtr: TYPE = LONG POINTER TO printBlk; printBlk: TYPE = RECORD[nextBlk: printBlkPtr, relativeTo: REAL, arg: argument]; plotBlkPtr: TYPE = LONG POINTER TO plotBlk; plotBlk: TYPE = RECORD[nextBlk: plotBlkPtr, graph: P.GraphHandle, relativeTo: REAL, arg: argument]; maxPrints: CARDINAL = 10; numPrints: CARDINAL ← 0; prints: ARRAY [0..maxPrints) OF RECORD[printList: printBlkPtr, printTimeRelTo: REAL, printStream: Str.StreamHandle]; maxPlots: CARDINAL = 10; numPlots: CARDINAL ← 0; plots: ARRAY [0..maxPlots) OF RECORD[plotList: plotBlkPtr, title: LONG STRING, plotTimeRelTo: REAL, yMin, yMax: REAL, plotCount: CARDINAL]; displayBlanked: BOOLEAN; systemWindow: P.TWHandle ← NIL; thymeLog: Str.StreamHandle ← NIL; time: STRING = [40]; bwDisplay: BOOLEAN ← FALSE; makePrintBlk: PROCEDURE RETURNS[pb: printBlkPtr] = BEGIN pb ← AbsAllocDefs.Allocate[SIZE[printBlk]]; pb↑ ← [NIL, 1.0, [NIL, NIL, FALSE, FALSE, FALSE]] END; makePlotBlk: PROCEDURE RETURNS[pb: plotBlkPtr] = BEGIN pb ← AbsAllocDefs.Allocate[SIZE[plotBlk]]; pb↑ ← [NIL, NIL, 1.0, [NIL, NIL, FALSE, FALSE, FALSE]] END; restoreDisplay: PUBLIC PROCEDURE = BEGIN IF displayBlanked THEN DisplayDefs.DisplayOn[] END; killPlot: PUBLIC PROCEDURE = BEGIN i: CARDINAL; time: STRING = [40]; time.length ← 0; TD.AppendDayTime[time, TD.UnpackDT[TD.CurrentDayTime[]]]; CWF.FWF1[thymeLog, "*n*n%s", time]; CWF.WF1["*n*n%s", time]; IF thymeLog # NIL THEN thymeLog.destroy[thymeLog]; FOR i IN [0..numPrints) DO prints[i].printStream.destroy[prints[i].printStream] ENDLOOP; P.CloseWindow[] END; openSysWindow: PUBLIC PROCEDURE[herald: STRING] = BEGIN logName: STRING = [40]; CWF.SWF1[logName, "%s.log", inputFileName]; thymeLog ← Str.NewByteStream[logName, Str.WriteAppend]; thymeLog.reset[thymeLog]; time.length ← 0; TD.AppendDayTime[time, TD.UnpackDT[TD.CurrentDayTime[]]]; CWF.FWF2[thymeLog, "%s*n*n%s*n*n", herald, time]; CWF.WF2["%s*n*n%s*n*n", herald, time] END; printSysWindow: PUBLIC PROCEDURE[s: STRING] = BEGIN IF systemWindow # NIL THEN P.WriteLine[s, systemWindow]; CWF.FWF1[thymeLog, "%s*n", s] END; initPlot: PUBLIC PROCEDURE[tMin, tMax: REAL, blank: BOOLEAN] = BEGIN window: P.WindowHandle; plotWindow: P.PWHandle; plotColor: P.ColorHandle; i, color: CARDINAL; pl: plotBlkPtr; cy, cyTitle, h, w: INTEGER; w2, wTitle: P.TWHandle; s: STRING = [20]; displayBlanked ← blank AND ~bwDisplay; IF displayBlanked THEN DisplayDefs.DisplayOff[white]; t0 ← tMin; P.SetTempFileName[inputFileName]; FOR i IN [0..numPlots) DO window ← P.OpenWindow[NIL, TRUE, ~bwDisplay, FALSE]; [w, h] ← P.GetWindowSize[window]; cy ← P.HeightOfLines[MAX[plots[i].plotCount, 6]]; cyTitle ← P.HeightOfLines[3]; w2 ← P.GetTextWindow[1500, h - cy, w/2, h - 15,,,window]; wTitle ← P.GetTextWindow[w/2, h - cyTitle, w, h - 15,,,window]; P.WriteString[inputFileName, wTitle]; P.WriteString[" ", wTitle]; P.WriteLine[time, wTitle]; IF plots[i].title # NIL THEN P.WriteLine[plots[i].title, wTitle]; plotWindow ← P.GetPlotWindow[0, 0, w, h - cy - 50, tMin/plots[i].plotTimeRelTo, tMax/plots[i].plotTimeRelTo, plots[i].yMin, plots[i].yMax, , window]; IF i = 0 THEN systemWindow ← P.GetTextWindow[w/2, h - cy, w, h - cyTitle,, FALSE]; color ← 0; pl ← plots[i].plotList; UNTIL pl = NIL DO plotColor ← P.GetStandardColor[color]; P.SetWindowColor[plotColor, w2]; pl↑.graph ← SELECT color/8 FROM 0 => P.GetGraphHandle[plotWindow, plotColor], 1 => P.GetGraphHandle[plotWindow, plotColor,,, dashed], ENDCASE => P.GetGraphHandle[plotWindow, plotColor,,, dotted]; color ← color + 1; IF pl↑.arg.getComVal THEN P.WriteString["Value of ", w2] ELSE IF pl↑.arg.current THEN P.WriteString["Current through ", w2] ELSE IF pl↑.arg.dvdt THEN P.WriteString["Derivative at ", w2] ELSE P.WriteString["Voltage at ", w2]; P.WriteString[makeStringNB[pl↑.arg.node, pl↑.arg.branch], w2]; IF pl↑.relativeTo # 1.0 THEN BEGIN CWF.SWF1[s, "/%-9.2f", @pl↑.relativeTo]; P.WriteString[s, w2] END; P.WriteLine["", w2]; pl ← pl↑.nextBlk ENDLOOP ENDLOOP END; evaluateArgument: PROCEDURE[a: argumentPtr] RETURNS[iv: REAL] = BEGIN b: branchPtr; IF a↑.getComVal THEN RETURN[a↑.branch↑.comVal]; IF a↑.node # NIL THEN IF a↑.dvdt THEN iv ← a↑.node↑.nHist.f0 ELSE iv ← a↑.node↑.nHist.y ELSE BEGIN b ← a.branch; IF a↑.current THEN WITH b↑ SELECT FROM resistor => iv ← (posNode↑.nHist.y - negNode↑.nHist.y)/comVal; capacitor => iv ← (posNode↑.nHist.f0 - negNode↑.nHist.f0)*comVal; inductor => iv ← iHist.y/comVal; vSource => iv ← vsCurrent; iSource => iv ← comVal ENDCASE ELSE iv ← b↑.posNode↑.nHist.y - b↑.negNode↑.nHist.y END END; plotFromList: PUBLIC PROCEDURE[t: REAL] = BEGIN i: CARDINAL; p: plotBlkPtr; r: REAL; FOR i IN [0..numPlots) DO p ← plots[i].plotList; UNTIL p = NIL DO r ← evaluateArgument[@p↑.arg]/p↑.relativeTo; IF t > t0 THEN P.DrawGraph[p↑.graph, t/plots[i].plotTimeRelTo, r] ELSE P.PositionPen[p↑.graph, t0/plots[i].plotTimeRelTo, r]; p ← p↑.nextBlk ENDLOOP ENDLOOP END; printFromList: PUBLIC PROCEDURE[ni: CARDINAL, t: REAL, printStep: BOOLEAN] = BEGIN i: CARDINAL; p: printBlkPtr; r, trel: REAL; FOR i IN [0..numPrints) DO p ← prints[i].printList; trel ← t/prints[i].printTimeRelTo; CWF.FWF1[prints[i].printStream, "%9.3f", @trel]; IF printStep THEN CWF.FWF1[prints[i].printStream, "(%2d)", @ni]; UNTIL p = NIL DO r ← evaluateArgument[@p↑.arg]/p↑.relativeTo; CWF.FWF1[prints[i].printStream, " %9.3f", @r]; p ← p↑.nextBlk ENDLOOP; CWF.FWFCR[prints[i].printStream] ENDLOOP END; scale: PROCEDURE RETURNS[s: REAL ← 1.0] = BEGIN IF item = colon THEN BEGIN next[]; s ← getSignedNumber[] END END; makePrintList: PUBLIC PROCEDURE = BEGIN I, D, cv: BOOLEAN; pb, pb2, pb3: printBlkPtr; n: nodePtr; b: branchPtr; name: STRING = [40]; IF numPrints >= maxPrints THEN BEGIN error[631]; numPrints ← numPrints - 1 END; IF item = leftB THEN next[] ELSE error[600]; IF item = colon THEN BEGIN prints[numPrints].printTimeRelTo ← scale[]; IF item = comma THEN next[] ELSE error[603,, FALSE] END ELSE prints[numPrints].printTimeRelTo ← 1.0; prints[numPrints].printList ← NIL; UNTIL item # name DO [n, b] ← findNodeOrBranch[]; IF n = NIL AND b = NIL THEN error[620] ELSE BEGIN I ← b # NIL AND item = upArrow; D ← n # NIL AND item = quote; cv ← b # NIL AND item = atSign; IF I OR D OR cv THEN next[]; pb ← makePrintBlk[]; pb↑ ← [prints[numPrints].printList, scale[], [n, b, cv, D, I]]; prints[numPrints].printList ← pb END; IF item = comma THEN next[] ELSE EXIT ENDLOOP; pb ← NIL; pb3 ← prints[numPrints].printList; UNTIL pb3 = NIL DO pb2 ← pb3; pb3 ← pb3↑.nextBlk; pb2↑.nextBlk ← pb; pb ← pb2 ENDLOOP; prints[numPrints].printList ← pb; CWF.SWF2[name, "%s.out%d", inputFileName, @numPrints]; prints[numPrints].printStream ← Str.NewByteStream[name, Str.WriteAppend]; prints[numPrints].printStream.reset[prints[numPrints].printStream]; numPrints ← numPrints + 1; IF item = rightB THEN next[] ELSE error[601, TRUE] END; getPlotNum: PROCEDURE RETURNS[r: REAL ← 1.0] = BEGIN r ← getSignedNumber[]; IF item = comma THEN next[] ELSE error[603,, FALSE] END; makePlotList: PUBLIC PROCEDURE[bw: BOOLEAN] = BEGIN I, D, cv: BOOLEAN; pb: plotBlkPtr; n: nodePtr; b: branchPtr; bwDisplay ← bw; IF numPlots >= maxPlots THEN BEGIN error[632, FALSE]; numPlots ← numPlots - 1 END; IF item = leftB THEN next[] ELSE error[600]; IF item = string THEN BEGIN plots[numPlots].title ← newString; next[]; IF item = comma THEN next[] ELSE error[603,, FALSE] END ELSE plots[numPlots].title ← NIL; IF item = colon THEN BEGIN plots[numPlots].plotTimeRelTo ← scale[]; IF item = comma THEN next[] ELSE error[603,, FALSE] END ELSE plots[numPlots].plotTimeRelTo ← 1.0; plots[numPlots].yMin ← getPlotNum[]; plots[numPlots].yMax ← getPlotNum[]; IF plots[numPlots].yMin >= plots[numPlots].yMax THEN error[630, FALSE]; plots[numPlots].plotList ← NIL; plots[numPlots].plotCount ← 0; UNTIL item # name DO plots[numPlots].plotCount ← plots[numPlots].plotCount + 1; [n, b] ← findNodeOrBranch[]; IF n = NIL AND b = NIL THEN error[620] ELSE BEGIN I ← b # NIL AND item = upArrow; D ← n # NIL AND item = quote; cv ← b # NIL AND item = atSign; IF I OR D OR cv THEN next[]; pb ← makePlotBlk[]; pb↑ ← [plots[numPlots].plotList, NIL, scale[], [n, b, cv, D, I]]; plots[numPlots].plotList ← pb END; IF item = comma THEN next[] ELSE EXIT ENDLOOP; IF item = rightB THEN next[] ELSE error[601, TRUE]; numPlots ← numPlots + 1 END; dumpAll: PUBLIC PROCEDURE[t: REAL] = BEGIN dump: Str.StreamHandle; dname: STRING = [40]; nodes: nodePtr ← nodeList; inds: inductorPtr ← inductorList; dname.length ← 0; StringDefs.AppendString[dname, "Dumped "]; TD.AppendDayTime[dname, TD.UnpackDT[TD.CurrentDayTime[]]]; printSysWindow[dname]; CWF.SWF1[dname, "%s.dump", inputFileName]; dump ← Str.NewByteStream[dname, Str.WriteAppend]; dump.reset[dump]; CWF.FWF1[dump, "ic[%f,*n", @t]; UNTIL nodes = NIL DO CWF.FWF2[dump, "%s←%f", makeStringNB[nodes, NIL, FALSE], @nodes↑.nHist.y]; nodes ← nodes↑.nextNode; IF nodes # NIL THEN CWF.FWF[dump, ",*n"] ELSE CWF.FWFCR[dump] ENDLOOP; UNTIL inds = NIL DO CWF.FWF2[dump, "%s←%f", makeStringNB[NIL, inds, FALSE], @inds↑.iHist.y]; inds ← inds↑.nextInductor; IF inds # NIL THEN CWF.FWF[dump, ",*n"] ELSE CWF.FWFCR[dump] ENDLOOP; CWF.FWF[dump, "];*n"]; dump.destroy[dump] END; END.