-- File: [Cherry]<Thyme>System>C03>spBomb.mesa
-- Last editted:
-- SChen, February 12, 1984 7:50 PM
-- Wilhelm March 16, 1982 9:41 AM, reformated by Barth and stored under
-- [Cherry]<Barth>Thyme>1.97> .
DIRECTORY spGlobals, AltoDefs, Real, CWF;
spBomb: PROGRAM
IMPORTS spGlobals, CWF
EXPORTS spGlobals =
BEGIN
OPEN spGlobals;
treeRoot: instTreePtr;
unusedNodes: nodePtr ← NIL;
nodeCount: CARDINAL ← 0;
branchCount: CARDINAL ← 0;
modelCount: CARDINAL ← 0;
funcCount: CARDINAL ← 0;
printString: STRING = [256];
n: nodePtr; -- Real ones!!!
b: branchPtr;
p: REAL;
m: modelPtr;
gndNode: PUBLIC nodePtr;
nodeList: PUBLIC nodePtr ← NIL;
capacitorList: PUBLIC capacitorPtr ← NIL;
inductorList: PUBLIC inductorPtr ← NIL;
vSourceList: PUBLIC vSourcePtr ← NIL;
iSourceList: PUBLIC iSourcePtr ← NIL;
functionList: PUBLIC modFuncPtr ← NIL;
pushCopies: PROCEDURE[nameList: namePtr] =
BEGIN
r: realThingPtr;
WHILE nameList # NIL DO
WITH n: nameList↑ SELECT FROM
nodeName, branchName, conName, modelName =>
r ← makeRealThing[n.realCopy];
parmName =>
BEGIN
r ← makeRealThing[n.realCopy];
IF n.default THEN r.thing ← realParm[n.dfltValue]
END
ENDCASE => r ← NIL;
nameList↑.realCopy ← r;
nameList ← nameList↑.srchLink;
ENDLOOP
END;
advanceLevel: PROCEDURE[nameList: namePtr] =
BEGIN
UNTIL nameList = NIL DO
IF nameList↑.realCopy # NIL THEN
nameList↑.realCopy↑.newLevel ← FALSE;
nameList ← nameList↑.srchLink
ENDLOOP
END;
popCopies: PROCEDURE[nameList: namePtr] =
BEGIN
WHILE nameList # NIL DO
WITH n: nameList↑ SELECT FROM
parmName, branchName, conName, modelName =>
n.realCopy ← n.realCopy↑.nextThing;
nodeName =>
WITH r: n.realCopy↑ SELECT FROM
realNode =>
BEGIN
IF r.rn↑.branches # NIL THEN
BEGIN
nodeCount ← nodeCount + 1;
r.rn↑.nextNode ← nodeList;
nodeList ← r.rn
END
ELSE
BEGIN
r.rn↑.nextNode ← unusedNodes;
unusedNodes ← r.rn
END;
n.realCopy ← r.nextThing
END
ENDCASE => n.realCopy ← n.realCopy↑.nextThing
ENDCASE;
nameList ← nameList↑.srchLink;
ENDLOOP
END;
getParmValue: PUBLIC PROCEDURE[name: namePtr] RETURNS[REAL] =
BEGIN
ENABLE ErrorSignal => ErrorSignal[331, s];
getRealThing[name];
IF n # NIL THEN RETURN[LOOPHOLE[n]] ELSE RETURN[p]
END;
getRealThing: PROCEDURE[name: namePtr] =
BEGIN
thing: realThingPtr;
n ← NIL; b ← NIL; m ← NIL; p ← 0.0;
IF name = NIL THEN RETURN;
thing ← name↑.realCopy;
IF thing # NIL AND thing↑.newLevel THEN thing ← thing↑.nextThing;
IF thing # NIL THEN
WITH rt: thing↑ SELECT FROM
realNode => n ← rt.rn;
realBranch => b ← rt.rb;
realParm => p ← rt.rp;
realModel => m ← rt.rm;
unReal => ErrorSignal[330, name↑.name]
ENDCASE
ELSE
WITH pn: name↑ SELECT FROM
parmName =>
IF pn.default THEN p ← pn.dfltValue
ELSE ErrorSignal[331, name↑.name]
ENDCASE => error2[390, name]
END;
makeConnections: PROCEDURE[connections: conLinkPtr, fakes: namePtr] =
BEGIN
UNTIL fakes = NIL DO
getRealThing[connections↑.namedNode];
putRealThing[fakes, realNode];
fakes ← fakes↑.nextName;
connections ← connections↑.nextLink
ENDLOOP
END;
apply: PROCEDURE[apList: expressionPtr] =
BEGIN
UNTIL apList = NIL DO
[] ← eval[apList];
apList ← apList↑.nextExpression
ENDLOOP;
END;
putParmValue: PUBLIC PROCEDURE[name: namePtr, val: REAL] =
BEGIN
p ← val;
putRealThing[name, realParm]
END;
putRealThing: PROCEDURE[name: namePtr, t: realThings] =
BEGIN
IF name↑.realCopy # NIL THEN
SELECT t FROM
realNode => name↑.realCopy↑.thing ← realNode[n];
realBranch => name↑.realCopy↑.thing ← realBranch[b];
realParm => name↑.realCopy↑.thing ← realParm[p];
realModel => name↑.realCopy↑.thing ← realModel[m]
ENDCASE
END;
explodeInstance: PROCEDURE[inst: cktInstNamePtr]
RETURNS[t: instTreePtr] =
BEGIN
exp: expressionPtr;
pushCopies[inst↑.of↑.names];
makeConnections[inst↑.connections, inst↑.of↑.fakeNodes];
apply[inst↑.actualParms];
advanceLevel[inst↑.of↑.names];
t ← makeTreeNode[inst];
exp ← inst↑.of↑.assertions;
UNTIL exp = NIL DO
IF eval[exp] = 0.0 THEN error2[341, inst];
exp ← exp↑.nextExpression
ENDLOOP;
explode[inst↑.of, t];
popCopies[inst↑.of↑.names]
END;
explodeModelFunc: PROCEDURE[mfName: namePtr, newFunc: modFuncPtr] =
BEGIN
index: CARDINAL;
arguments: argNames;
parms, p: expressionPtr;
WITH mf: mfName↑ SELECT FROM
modelName =>
BEGIN
newFunc↑.argVector ← mf.modelArgVec;
arguments ← mf.modelArgs;
parms ← mf.modelParms
END;
functionName =>
BEGIN
newFunc↑.argVector ← mf.funcArgVec;
arguments ← mf.funcArgs;
parms ← mf.funcParms
END
ENDCASE => error2[399, mfName];
newFunc↑.arguments ← makeArgSource[LENGTH[arguments]];
FOR index IN [0..LENGTH[arguments]) DO
IF arguments[index] # NIL THEN
getRealThing[arguments[index]];
newFunc↑.arguments[index] ← n
ENDLOOP;
index ← 0;
FOR p ← parms, p↑.nextExpression UNTIL p = NIL DO
index ← index + 1
ENDLOOP;
newFunc↑.parmVector ← makeArgList[index];
UNTIL index = 0 DO
index ← index - 1;
newFunc↑.parmVector[index] ← eval[parms];
parms ← parms↑.nextExpression
ENDLOOP
END;
explodeController: PROCEDURE[bn: branchNamePtr, newB: branchPtr] =
BEGIN
oldmf: namePtr ← bn↑.controller;
newFunc: functionPtr;
newModB: modBrPtr;
WITH mf: oldmf↑ SELECT FROM
functionName =>
BEGIN
funcCount ← funcCount + 1;
newFunc ← makeFunction[];
newFunc↑.nextFunction ← functionList;
functionList ← newFunc;
newFunc↑.branch ← newB;
newFunc↑.functionProc ← mf.functionProc;
explodeModelFunc[oldmf, newFunc];
newB↑.controller ← newFunc
END;
modelName =>
BEGIN
getRealThing[@mf];
newModB ← makeModBranch[m↑.modelBranches, newB];
m↑.modelBranches ← newModB;
newB↑.controller ← m;
newB↑.modelIndex ← bn↑.modelIndex
END
ENDCASE => error2[399, bn]
END;
connectBranch: PROCEDURE[n: nodePtr, b: branchPtr,
pos: BOOLEAN] =
BEGIN
newLink: branchLinkPtr;
IF n # NIL THEN
BEGIN
newLink ← makeBranchLink[n↑.branches, b, pos];
n↑.branches ← newLink;
IF pos THEN b↑.posNode ← n ELSE b↑.negNode ← n
END
ELSE ErrorSignal[242, b↑.branchName↑.name]
END;
explodeBranch: PROCEDURE[bn: branchNamePtr]
RETURNS[newB: branchPtr ← NIL] =
BEGIN
pNode, nNode: nodePtr;
newC: capacitorPtr;
newL: inductorPtr;
newV: vSourcePtr;
newI: iSourcePtr;
branchCount ← branchCount + 1;
getRealThing[bn↑.posNode];
pNode ← n;
getRealThing[bn↑.negNode];
nNode ← n;
IF pNode # nNode THEN
BEGIN
SELECT bn↑.branchType FROM
resistor =>
newB ← makeResistor[];
capacitor =>
BEGIN
newB ← newC ← makeCapacitor[];
newC.nextCapacitor ← capacitorList;
capacitorList ← newC
END;
inductor =>
BEGIN
newB ← newL ← makeInductor[];
newL.nextInductor ← inductorList;
inductorList ← newL
END;
vSource =>
BEGIN
newB ← newV ← makeVoltage[];
newV.nextvSource ← vSourceList;
vSourceList ← newV
END;
iSource =>
BEGIN
newB ← newI ← makeCurrent[];
newI.nextiSource ← iSourceList;
iSourceList ← newI
END
ENDCASE => error2[391, bn];
b ← newB;
putRealThing[bn, realBranch];
newB↑.branchName ← bn;
connectBranch[pNode, newB, TRUE];
connectBranch[nNode, newB, FALSE];
IF bn↑.controller # NIL THEN
explodeController[bn, newB]
ELSE newB↑.comVal ← eval[bn↑.valExpr];
END
END;
explode: PROCEDURE[ckt: circuitNamePtr, tree: instTreePtr] =
BEGIN
curName: namePtr;
newNode: nodePtr ← NIL;
newModel: modelPtr;
newB: branchPtr;
newTree: instTreePtr;
curName ← ckt↑.names;
UNTIL curName = NIL DO
WITH cn: curName↑ SELECT FROM
nodeName =>
BEGIN
newNode ← makeNode[];
newNode↑.nodeName ← curName;
newNode↑.treeLevel ← tree;
newNode↑.brotherNodes ← tree↑.nodes;
tree↑.nodes ← newNode;
n ← newNode;
putRealThing[curName, realNode]
END
ENDCASE;
curName ← curName↑.srchLink
ENDLOOP;
curName ← ckt↑.names;
UNTIL curName = NIL DO
ENABLE
ErrorSignal =>
BEGIN
ErrorStrings[error, treeError[tree, curName], s];
curName ← curName↑.srchLink;
LOOP
END;
WITH cn: curName↑ SELECT FROM
modelName =>
BEGIN
modelCount ← modelCount + 1;
newModel ← makeModel[];
newModel↑.modelProc ← cn.modelProc;
newModel↑.modelName ← @cn;
newModel↑.modelResults ← cn.modelResults;
newModel↑.oldArgVector ← cn.modelOldArgVec;
newModel↑.modelBranches ← NIL;
newModel↑.nextFunction ← functionList;
functionList ← newModel;
explodeModelFunc[@cn, newModel];
m ← newModel;
putRealThing[curName, realModel]
END
ENDCASE;
curName ← curName↑.srchLink
ENDLOOP;
curName ← ckt↑.names;
UNTIL curName = NIL DO
ENABLE
ErrorSignal =>
BEGIN
ErrorStrings[error, treeError[tree, curName], s];
curName ← curName↑.srchLink;
LOOP
END;
IF curName↑.expExpr = NIL OR eval[curName↑.expExpr] # 0.0 THEN
WITH cn: curName↑ SELECT FROM
branchName =>
BEGIN
newB ← explodeBranch[@cn];
IF newB # NIL THEN
BEGIN
newB↑.brotherBranches ← tree↑.branches;
newB↑.treeLevel ← tree;
tree↑.branches ← newB
END
END;
cktInstance =>
BEGIN
newTree ← explodeInstance[@cn];
newTree↑.father ← tree;
newTree↑.brothers ← tree↑.sons;
tree↑.sons ← newTree
END
ENDCASE;
curName ← curName↑.srchLink
ENDLOOP
END;
treeError: PROCEDURE[t: instTreePtr, n: namePtr] RETURNS[STRING] =
BEGIN
oldProc: PROCEDURE[CHARACTER];
printString.length ← 0;
oldProc ← CWF.WriteToString[printString];
printTree[t];
CWF.WF1["%s", n↑.name];
[] ← CWF.SetWriteProcedure[oldProc];
RETURN[printString]
END;
funnyCharsInName: PROCEDURE[name: LONG STRING]
RETURNS[f: BOOLEAN ← FALSE] =
BEGIN
f ← name[0] ~IN ['A..'Z] AND name[0] ~IN ['a..'z];
IF f THEN RETURN;
FOR i: CARDINAL IN [1..name.length) DO
f ← name[i] ~IN ['A..'Z] AND name[i] ~IN ['a..'z] AND
name[i] ~IN ['0..'9];
IF f THEN EXIT
ENDLOOP
END;
printTree: PROCEDURE[t: instTreePtr] =
BEGIN
IF t # NIL AND t # treeRoot THEN
BEGIN
printTree[t↑.father];
IF ~funnyCharsInName[t↑.instance↑.name] THEN
CWF.WF1["%s/", t↑.instance↑.name]
ELSE CWF.WF1["$%s$/", t↑.instance↑.name]
END;
END;
printNode: PUBLIC PROCEDURE[n: nodePtr, ok: BOOLEAN] =
BEGIN
printTree[n↑.treeLevel];
IF ok OR ~funnyCharsInName[n↑.nodeName↑.name] THEN
CWF.WF1["%s", n↑.nodeName↑.name]
ELSE CWF.WF1["$%s$", n↑.nodeName↑.name]
END;
printBranch: PUBLIC PROCEDURE[b: branchPtr, ok: BOOLEAN] =
BEGIN
printTree[b↑.treeLevel];
IF ok OR ~funnyCharsInName[b↑.branchName↑.name] THEN
CWF.WF1["%s", b↑.branchName↑.name]
ELSE CWF.WF1["$%s$", b↑.branchName↑.name]
END;
makeStringNB: PUBLIC PROCEDURE[n: nodePtr, b: branchPtr,
ok: BOOLEAN ← TRUE]
RETURNS[STRING] =
BEGIN
oldProc: PROCEDURE[CHARACTER];
printString.length ← 0;
oldProc ← CWF.WriteToString[printString];
IF n # NIL THEN printNode[n, ok] ELSE printBranch[b, ok];
[] ← CWF.SetWriteProcedure[oldProc];
RETURN[printString]
END;
printHole: PUBLIC PROCEDURE =
BEGIN
n: nodePtr;
bLink: branchLinkPtr;
CWF.WF0["*nNodes --*n"];
n ← nodeList;
UNTIL n = NIL DO
printNode[n, TRUE];
CWF.WF0[" ← {"];
bLink ← n↑.branches;
UNTIL bLink = NIL DO
printBranch[bLink↑.branch, TRUE];
IF bLink↑.branch↑.posNode = n THEN CWF.WFC['+]
ELSE CWF.WFC['-];
bLink ← bLink↑.nextLink;
IF bLink # NIL THEN CWF.WF0[", "]
ENDLOOP;
CWF.WF0["}.*n"];
n ← n↑.nextNode
ENDLOOP
END;
findNB: PROCEDURE[tree: instTreePtr]
RETURNS[n: nodePtr ← NIL, b: branchPtr ← NIL] =
BEGIN
i: instTreePtr;
IF item = name THEN
BEGIN
i ← tree↑.sons;
UNTIL i = NIL DO
IF LongEqualStrings[i↑.instance↑.name,newString] THEN EXIT;
i ← i↑.brothers
ENDLOOP;
IF i # NIL THEN
BEGIN
next[];
IF item = slash THEN next[] ELSE error[300, FALSE];
[n, b] ← findNB[i]
END
ELSE
BEGIN
n ← tree↑.nodes;
UNTIL n = NIL DO
IF LongEqualStrings[newString,n↑.nodeName↑.name]
THEN EXIT;
n ← n↑.brotherNodes
ENDLOOP;
IF n = NIL THEN
BEGIN
b ← tree↑.branches;
UNTIL b = NIL DO
IF LongEqualStrings[newString,
b↑.branchName↑.name]
THEN EXIT;
b ← b↑.brotherBranches
ENDLOOP
END;
next[]
END
END
ELSE error[301, FALSE]
END;
findNodeOrBranch: PUBLIC PROCEDURE RETURNS[n: nodePtr, b: branchPtr] =
BEGIN
[n, b] ← findNB[treeRoot]
END;
fillInBranchLinks: PROCEDURE =
BEGIN
nodes: nodePtr ← nodeList;
links: branchLinkPtr;
UNTIL nodes = NIL DO
links ← nodes↑.branches;
UNTIL links = NIL DO
links↑.otherNode ← IF links↑.pos THEN links↑.branch↑.negNode
ELSE links↑.branch↑.posNode;
links ← links↑.nextLink
ENDLOOP;
nodes ← nodes↑.nextNode
ENDLOOP
END;
bomb: PUBLIC PROCEDURE =
BEGIN
treeRoot ← makeTreeNode[NIL];
pushCopies[cktRoot↑.names];
advanceLevel[cktRoot↑.names];
explode[cktRoot, treeRoot];
getRealThing[gndNodeName];
gndNode ← n;
popCopies[cktRoot↑.names];
fillInBranchLinks[];
CWF.SWF4[printString,
"%u nodes %u models %u functions %u branches",
@nodeCount, @modelCount, @funcCount, @branchCount];
printSysWindow[printString];
IF unusedNodes # NIL THEN printSysWindow["Unused nodes --"];
UNTIL unusedNodes = NIL DO
printSysWindow[makeStringNB[unusedNodes, NIL]];
unusedNodes ← unusedNodes↑.nextNode
ENDLOOP
END;
END.
2/12/84:-
original: [Cherry]<Thyme>System>CSIM02>spBomb.mesa
modified to support oldArgVector.