<> <> <> <> DIRECTORY IO, spGlobals USING[ branchLinkPtr, branchPtr, elements, ErrorAtNB, Handle, makeStringNB, modFuncPtr, nodePtr, RefC, RefI, RefL, RefR, RefV]; spAnalysis: CEDAR PROGRAM IMPORTS IO, spGlobals EXPORTS spGlobals= BEGIN Handle: TYPE= spGlobals.Handle; checkNode: PROC[handle: Handle, n: spGlobals.nodePtr]= { IF n.integrate OR n=handle.vars.gndNode OR n.curPtr # NIL THEN RETURN ELSE { n.integrate_ TRUE; n.nextIntNode_ handle.vars.intNodeList; handle.vars.intNodeList_ n; }; }; -- checkNode assignIntNodes: PROC[handle: Handle]= { caps: spGlobals.branchPtr; capsBody: spGlobals.RefC; caps_ handle.vars.capacitorList; UNTIL caps=NIL DO checkNode[handle, caps.posNode]; checkNode[handle, caps.negNode]; capsBody_ NARROW[caps.body]; caps_ capsBody.nextCapacitor ENDLOOP; }; -- assignIntNodes allocateCurrent: PROC[handle: Handle, v: spGlobals.branchPtr]= { pCount, nCount: LONG CARDINAL_ 0; pAvail, nAvail: BOOL_ FALSE; pNode: spGlobals.nodePtr_ v.posNode; nNode: spGlobals.nodePtr_ v.negNode; blP: spGlobals.branchLinkPtr; IF pNode=handle.vars.gndNode THEN {IF nNode.curPtr # v THEN spGlobals.ErrorAtNB[handle, 490, NIL, v]} ELSE IF nNode=handle.vars.gndNode THEN {IF pNode.curPtr # v THEN spGlobals.ErrorAtNB[handle, 490, NIL, v]} ELSE { pAvail_ pNode.curPtr=NIL; nAvail_ nNode.curPtr=NIL; IF ~pAvail AND ~nAvail THEN spGlobals.ErrorAtNB[handle, 490, NIL, v] ELSE IF pAvail AND ~nAvail THEN pNode.curPtr_ v ELSE IF ~pAvail AND nAvail THEN nNode.curPtr_ v ELSE { blP_ pNode.branches; UNTIL blP=NIL DO WITH blP.branch.body SELECT FROM x: spGlobals.RefV => pCount_ pCount + 1; ENDCASE; blP_ blP.nextLink; ENDLOOP; blP_ nNode.branches; UNTIL blP=NIL DO WITH blP.branch.body SELECT FROM x: spGlobals.RefV => nCount_ nCount + 1; ENDCASE; blP_ blP.nextLink; ENDLOOP; IF pCount < nCount THEN pNode.curPtr_ v ELSE nNode.curPtr_ v; }; }; }; -- allocateCurrent assignCurrents: PROC[handle: Handle]= { branchP: spGlobals.branchPtr; blP: spGlobals.branchLinkPtr; vP: spGlobals.branchPtr; <> <<>> blP_ handle.vars.gndNode.branches; UNTIL blP=NIL DO branchP_ blP.branch; WITH branchP.body SELECT FROM x: spGlobals.RefV => { IF branchP.posNode # handle.vars.gndNode THEN branchP.posNode.curPtr_ branchP ELSE branchP.negNode.curPtr_ branchP; }; ENDCASE; blP_ blP.nextLink; ENDLOOP; <> vP_ handle.vars.vSourceList; UNTIL vP=NIL DO vPBody: spGlobals.RefV_ NARROW[vP.body]; allocateCurrent[handle, vP]; vP_ vPBody.nextvSource; ENDLOOP; }; -- assignCurrents dcPath: PROC[n: spGlobals.nodePtr]= { IF ~n.marked THEN { n.marked_ TRUE; FOR bLink: spGlobals.branchLinkPtr_ n.branches, bLink.nextLink UNTIL bLink=NIL DO b: spGlobals.branchPtr = bLink.branch; <> WITH b.body SELECT FROM x: spGlobals.RefC => NULL; ENDCASE => dcPath[(IF b.posNode=n THEN b.negNode ELSE b.posNode)]; ENDLOOP; }; }; -- dcPath forceDcPaths: PROC[handle: Handle]= { problemNode: spGlobals.nodePtr _ NIL; problemCount: INT _ 0; dcPath[handle.vars.gndNode]; FOR n: spGlobals.nodePtr _ handle.vars.nodeList, n.nextNode UNTIL n=NIL DO IF ~n.marked THEN { FOR bLink: spGlobals.branchLinkPtr_ n.branches, bLink.nextLink UNTIL bLink=NIL DO <> IF bLink.branch.negNode # handle.vars.gndNode AND bLink.branch.posNode # handle.vars.gndNode THEN { spGlobals.ErrorAtNB[handle, 401, n, NIL]; -- doesn't go to Gnd EXIT; }; ENDLOOP; problemNode _ n; problemCount _ problemCount+1; }; ENDLOOP; IF problemCount>0 THEN { handle.msgStream.PutF[ "\nThe branches to %d nodes, for example %g, are only capacitors to Gnd\n", IO.int[problemCount], IO.rope[spGlobals.makeStringNB[handle, problemNode, NIL, FALSE]]]; }; }; -- forceDcPaths vsXPath: PROC[n: spGlobals.nodePtr, skip: spGlobals.branchPtr, type: spGlobals.elements]= { bLink: spGlobals.branchLinkPtr; b: spGlobals.branchPtr; IF ~n.marked THEN { n.marked_ TRUE; bLink_ n.branches; UNTIL bLink=NIL DO b_ bLink.branch; IF b # skip THEN { WITH b.body SELECT FROM x: spGlobals.RefR => IF type=resistor THEN GOTO common; x: spGlobals.RefC => IF type=capacitor THEN GOTO common; x: spGlobals.RefL => IF type=inductor THEN GOTO common; x: spGlobals.RefV => GOTO common; x: spGlobals.RefI => IF type=iSource THEN GOTO common; ENDCASE; EXITS common => IF b.posNode=n THEN vsXPath[b.negNode, NIL, type] ELSE vsXPath[b.posNode, NIL, type]; }; bLink_ bLink.nextLink; ENDLOOP; }; }; -- vsXPath vsIndLoops: PROC[handle: Handle]= { n: spGlobals.nodePtr; v: spGlobals.branchPtr_ handle.vars.vSourceList; vBody: spGlobals.RefV; UNTIL v=NIL DO n_ handle.vars.nodeList; UNTIL n=NIL DO n.marked_ FALSE; n_ n.nextNode; ENDLOOP; vsXPath[v.posNode, v, inductor]; IF v.negNode.marked THEN spGlobals.ErrorAtNB[handle, 402, NIL, v]; vBody_ NARROW[v.body]; v_ vBody.nextvSource; ENDLOOP; }; -- vsIndLoops indNodes: PROC[handle: Handle]= { bLink: spGlobals.branchLinkPtr; i: spGlobals.branchPtr; iBody: spGlobals.RefL; posOk, negOk: BOOL; i_ handle.vars.inductorList; UNTIL i=NIL DO bLink_ i.posNode.branches; posOk_ FALSE; UNTIL bLink=NIL DO -- if anyone is not an inductor then posOk_ TURE WITH bLink.branch.body SELECT FROM x: spGlobals.RefL => NULL; -- leave it as it is ENDCASE => posOk_ TRUE; bLink_ bLink.nextLink; ENDLOOP; bLink_ i.negNode.branches; negOk_ FALSE; UNTIL bLink=NIL DO -- if anyone is not an inductor then negOk_ TURE WITH bLink.branch.body SELECT FROM x: spGlobals.RefL => NULL; -- leave it as it is ENDCASE => negOk_ TRUE; bLink_ bLink.nextLink; ENDLOOP; IF ~(posOk AND negOk) THEN spGlobals.ErrorAtNB[handle, 403, NIL, i]; iBody_ NARROW[i.body]; i_ iBody.nextInductor; ENDLOOP; }; -- indNodes separateFunctions: PROC[handle: Handle]= { nodes: spGlobals.nodePtr_ handle.vars.nodeList; state: REAL= 1.0; other: REAL= 0.0; gnd: spGlobals.nodePtr= handle.vars.gndNode; mf: spGlobals.modFuncPtr; nonState: BOOL; UNTIL nodes=NIL DO OPEN nodes; nHist.y_ IF integrate OR nodes=gnd THEN state ELSE IF curPtr # NIL THEN IF curPtr.controller=NIL THEN IF curPtr.posNode=gnd OR curPtr.negNode=gnd THEN state ELSE other ELSE IF curPtr.controller.argVector=NIL THEN IF curPtr.posNode=gnd OR curPtr.negNode=gnd THEN state ELSE other ELSE IF curPtr.controller.argVector.size=0 THEN IF curPtr.posNode=gnd OR curPtr.negNode=gnd THEN state ELSE other ELSE other ELSE other; nHist.f0_ other; nodes_ nextNode; ENDLOOP; UNTIL handle.vars.functionList=NIL DO OPEN handle.vars; nonState_ FALSE; IF functionList.arguments # NIL THEN FOR i: NAT IN [0..functionList.arguments.size) DO nonState_ functionList.arguments[i].nHist.y=other; IF nonState THEN EXIT; ENDLOOP; mf_ functionList.nextMFPtr; IF nonState THEN { functionList.nextMFPtr_ otherModFunc; otherModFunc_ functionList; } ELSE { functionList.nextMFPtr_ intNodeModFunc; intNodeModFunc_ functionList; }; functionList_ mf; ENDLOOP; }; -- separateFunctions topoAnalysis: PUBLIC PROC[handle: Handle]= { forceDcPaths[handle]; vsIndLoops[handle]; indNodes[handle]; assignCurrents[handle]; assignIntNodes[handle]; separateFunctions[handle]; <<>> <> <> <> <> <> <> <> <> }; -- topoAnalysis END. CHANGE LOG. Wilhelm, February 24, 1982 3:08 PM Barth, 7-May-82 10:46:50 PDT Chen, June 10, 1984 5:29:02 pm PDT, cedarized McCreight, April 3, 1985 12:12:06 pm PST, added codes in "forceDcPaths" to provide more information for user. Chen, July 22, 1985 7:55:49 pm PDT => Cedar6.0.