<Cedar5.1>System>spAnalysis.mesa>> <> DIRECTORY spGlobals USING[ branchLinkPtr, branchPtr, elements, ErrorAtNB, Handle, modFuncPtr, nodePtr, RefC, RefI, RefL, RefR, RefV]; spAnalysis: CEDAR PROGRAM IMPORTS 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; << Check connections to ground node first.>> 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; << Do remaining branches.>> 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]= { 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^.eType # capacitor AND b^.eType # iSource THEN WITH b.body SELECT FROM x: spGlobals.RefC => NULL; ENDCASE => IF b.posNode=n THEN dcPath[b.negNode] ELSE dcPath[b.posNode]; bLink_ bLink.nextLink ENDLOOP; }; }; -- dcPath forceDcPaths: PROC[handle: Handle]= { n: spGlobals.nodePtr; dcPath[handle.vars.gndNode]; n_ handle.vars.nodeList; UNTIL n=NIL DO IF ~n.marked THEN spGlobals.ErrorAtNB[handle, 401, n, NIL]; n_ n.nextNode; ENDLOOP; }; -- 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]; -- IF handle.vars.otherModFunc # NIL THEN -- spGlobals.PutMsgLine[handle, "Non-state controlled functions."]; -- Commented the above until a better algorithm to check non-state controlled functions is employed. With the current algorithm, otherModFunc may be non-nil for the following example: -- ! ThymeBasics.thy -- Vdd, fooNode: node; -- ?: voltage[Vdd, Gnd] = 5.0; -- ?: voltage[fooNode, Vdd] = 0.0; -- ?: Diffusion[fooNode, Vdd]; }; -- topoAnalysis END. <> <<>> <> <> <>