-- File: [Cherry]System>CSIM01>spAnalysis.mesa -- Last editted: -- Wilhelm February 24, 1982 3:08 PM, reformated by Barth and stored under -- [Cherry]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.