-- File: [Cherry]<Thyme>System>CSIM01>spAnalysis.mesa -- Last editted: -- Wilhelm February 24, 1982 3:08 PM, reformated by Barth and stored under -- [Cherry]<Barth>Thyme>1.97> . DIRECTORY spGlobals; spAnalysis: PROGRAM IMPORTS spGlobals EXPORTS spGlobals = BEGIN OPEN spGlobals; checkNode: PROCEDURE[n: nodePtr] = BEGIN IF n↑.integrate OR n = gndNode OR n↑.curPtr # NIL THEN RETURN ELSE BEGIN n↑.integrate ← TRUE; n↑.nextIntNode ← intNodeList; intNodeList ← n END END; assignIntNodes: PROCEDURE = BEGIN caps: capacitorPtr ← capacitorList; UNTIL caps = NIL DO checkNode[caps↑.posNode]; checkNode[caps↑.negNode]; caps ← caps↑.nextCapacitor ENDLOOP END; allocateCurrent: PROCEDURE[v: vSourcePtr] = BEGIN pCount, nCount: CARDINAL ← 0; pAvail, nAvail: BOOLEAN ← FALSE; pNode: nodePtr ← v↑.posNode; nNode: nodePtr ← v↑.negNode; blP: branchLinkPtr; IF pNode = gndNode THEN IF nNode↑.curPtr # v THEN ErrorAtNB[490, NIL, v] ELSE NULL ELSE IF nNode = gndNode THEN IF pNode↑.curPtr # v THEN ErrorAtNB[490, NIL, v] ELSE NULL ELSE BEGIN pAvail ← pNode↑.curPtr = NIL; nAvail ← nNode↑.curPtr = NIL; IF ~pAvail AND ~nAvail THEN ErrorAtNB[490, NIL, v] ELSE IF pAvail AND ~nAvail THEN pNode↑.curPtr ← v ELSE IF ~pAvail AND nAvail THEN nNode↑.curPtr ← v ELSE BEGIN blP ← pNode↑.branches; UNTIL blP = NIL DO IF blP↑.branch↑.eType = vSource THEN pCount ← pCount + 1; blP ← blP↑.nextLink ENDLOOP; blP ← nNode↑.branches; UNTIL blP = NIL DO IF blP↑.branch↑.eType = vSource THEN nCount ← nCount + 1; blP ← blP↑.nextLink ENDLOOP; IF pCount < nCount THEN pNode↑.curPtr ← v ELSE nNode↑.curPtr ← v END END END; assignCurrents: PROCEDURE = BEGIN branchP: branchPtr; blP: branchLinkPtr; vP: vSourcePtr; -- Check connections to ground node first. blP ← gndNode↑.branches; UNTIL blP = NIL DO branchP ← blP↑.branch; WITH v: branchP↑ SELECT FROM vSource => IF v.posNode # gndNode THEN v.posNode↑.curPtr ← @v ELSE v.negNode↑.curPtr ← @v ENDCASE; blP ← blP↑.nextLink ENDLOOP; -- Do remaining branches. vP ← vSourceList; UNTIL vP = NIL DO allocateCurrent[vP]; vP ← vP↑.nextvSource ENDLOOP; END; dcPath: PROCEDURE[n: nodePtr] = BEGIN bLink: branchLinkPtr; b: branchPtr; IF ~n↑.marked THEN BEGIN n↑.marked ← TRUE; bLink ← n↑.branches; UNTIL bLink = NIL DO b ← bLink↑.branch; -- IF b↑.eType # capacitor AND b↑.eType # iSource THEN IF b↑.eType # capacitor THEN IF b↑.posNode = n THEN dcPath[b↑.negNode] ELSE dcPath[b↑.posNode]; bLink ← bLink↑.nextLink ENDLOOP END END; forceDcPaths: PROCEDURE = BEGIN n: nodePtr; dcPath[gndNode]; n ← nodeList; UNTIL n = NIL DO IF ~n↑.marked THEN ErrorAtNB[401, n, NIL]; n ← n↑.nextNode ENDLOOP END; vsXPath: PROCEDURE[n: nodePtr, skip: branchPtr, type: elements] = BEGIN bLink: branchLinkPtr; b: branchPtr; IF ~n↑.marked THEN BEGIN n↑.marked ← TRUE; bLink ← n↑.branches; UNTIL bLink = NIL DO b ← bLink↑.branch; IF b # skip THEN IF b↑.eType = vSource OR b↑.eType = type THEN IF b↑.posNode = n THEN vsXPath[b↑.negNode, NIL, type] ELSE vsXPath[b↑.posNode, NIL, type]; bLink ← bLink↑.nextLink ENDLOOP END END; vsIndLoops: PROCEDURE = BEGIN n: nodePtr; v: vSourcePtr; v ← vSourceList; UNTIL v = NIL DO n ← nodeList; UNTIL n = NIL DO n↑.marked ← FALSE; n ← n↑.nextNode ENDLOOP; vsXPath[v↑.posNode, v, inductor]; IF v↑.negNode↑.marked THEN ErrorAtNB[402, NIL, v]; v ← v↑.nextvSource ENDLOOP END; indNodes: PROCEDURE = BEGIN bLink: branchLinkPtr; i: inductorPtr; posOk, negOk: BOOLEAN; i ← inductorList; UNTIL i = NIL DO bLink ← i↑.posNode↑.branches; posOk ← FALSE; UNTIL bLink = NIL DO posOk ← posOk OR bLink↑.branch↑.eType # inductor; bLink ← bLink↑.nextLink ENDLOOP; bLink ← i↑.negNode↑.branches; negOk ← FALSE; UNTIL bLink = NIL DO negOk ← negOk OR bLink↑.branch↑.eType # inductor; bLink ← bLink↑.nextLink ENDLOOP; IF ~posOk OR ~negOk THEN ErrorAtNB[403, NIL, i]; i ← i↑.nextInductor ENDLOOP END; separateFunctions: PROCEDURE = BEGIN nodes: nodePtr ← nodeList; state: REAL = 1.0; other: REAL = 0.0; mf: modFuncPtr; nonState: BOOLEAN; UNTIL nodes = NIL DO OPEN nodes↑; nHist.y ← IF integrate OR nodes = gndNode THEN state ELSE IF curPtr # NIL THEN IF curPtr↑.controller = NIL THEN IF curPtr↑.posNode=gndNode OR curPtr↑.negNode=gndNode THEN state ELSE other ELSE IF LENGTH[curPtr↑.controller↑.argVector] = 0 THEN IF curPtr↑.posNode=gndNode OR curPtr↑.negNode=gndNode THEN state ELSE other ELSE other ELSE other; nHist.f0 ← other; nodes ← nextNode ENDLOOP; UNTIL functionList = NIL DO nonState ← FALSE; FOR i: CARDINAL IN [0..LENGTH[functionList↑.arguments]) DO nonState ← functionList↑.arguments[i]↑.nHist.y = other; IF nonState THEN EXIT ENDLOOP; mf ← functionList↑.nextFunction; IF nonState THEN BEGIN functionList↑.nextFunction ← otherModFunc; otherModFunc ← functionList END ELSE BEGIN functionList↑.nextFunction ← intNodeModFunc; intNodeModFunc ← functionList END; functionList ← mf ENDLOOP END; topoAnalysis: PUBLIC PROCEDURE = BEGIN forceDcPaths[]; vsIndLoops[]; indNodes[]; assignCurrents[]; assignIntNodes[]; separateFunctions[]; IF otherModFunc # NIL THEN printSysWindow["Non-state controlled functions."] END; END.