-- File: [Cherry]<Thyme>System>CSIM01>spBomb.mesa -- Last editted: -- 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↑.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.