DIRECTORY IO, ThymeGlobals USING[branchLinkPtr, branchPtr, elements, ErrorAtNB, Handle, MakeStringNB, modFuncPtr, nodePtr, RefC, RefI, RefL, RefR, RefV]; ThymeAnalysis: CEDAR PROGRAM IMPORTS IO, ThymeGlobals EXPORTS ThymeGlobals = BEGIN Handle: TYPE= ThymeGlobals.Handle; CheckNode: PROC[handle: Handle, n: ThymeGlobals.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: ThymeGlobals.branchPtr; capsBody: ThymeGlobals.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: ThymeGlobals.branchPtr]= { pCount, nCount: LONG CARDINAL _ 0; pAvail, nAvail: BOOL _ FALSE; pNode: ThymeGlobals.nodePtr _ v.posNode; nNode: ThymeGlobals.nodePtr _ v.negNode; blP: ThymeGlobals.branchLinkPtr; IF pNode=handle.vars.gndNode THEN {IF nNode.curPtr # v THEN ThymeGlobals.ErrorAtNB[handle, 490, NIL, v]} ELSE IF nNode=handle.vars.gndNode THEN {IF pNode.curPtr # v THEN ThymeGlobals.ErrorAtNB[handle, 490, NIL, v]} ELSE { pAvail _ pNode.curPtr=NIL; nAvail _ nNode.curPtr=NIL; IF ~pAvail AND ~nAvail THEN ThymeGlobals.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: ThymeGlobals.RefV => pCount _ pCount + 1; ENDCASE; blP_ blP.nextLink; ENDLOOP; blP _ nNode.branches; UNTIL blP=NIL DO WITH blP.branch.body SELECT FROM x: ThymeGlobals.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: ThymeGlobals.branchPtr; blP: ThymeGlobals.branchLinkPtr; vP: ThymeGlobals.branchPtr; blP _ handle.vars.gndNode.branches; UNTIL blP=NIL DO branchP _ blP.branch; WITH branchP.body SELECT FROM x: ThymeGlobals.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: ThymeGlobals.RefV _ NARROW[vP.body]; AllocateCurrent[handle, vP]; vP_ vPBody.nextvSource; ENDLOOP; }; -- AssignCurrents DCPath: PROC[n: ThymeGlobals.nodePtr]= { IF ~n.marked THEN { n.marked _ TRUE; FOR bLink: ThymeGlobals.branchLinkPtr_ n.branches, bLink.nextLink UNTIL bLink=NIL DO b: ThymeGlobals.branchPtr = bLink.branch; WITH b.body SELECT FROM x: ThymeGlobals.RefC => NULL; ENDCASE => DCPath[(IF b.posNode=n THEN b.negNode ELSE b.posNode)]; ENDLOOP; }; }; -- DCPath ForceDCPaths: PROC[handle: Handle]= { problemNode: ThymeGlobals.nodePtr _ NIL; problemCount: INT _ 0; DCPath[handle.vars.gndNode]; FOR n: ThymeGlobals.nodePtr _ handle.vars.nodeList, n.nextNode UNTIL n=NIL DO IF ~n.marked THEN { FOR bLink: ThymeGlobals.branchLinkPtr_ n.branches, bLink.nextLink UNTIL bLink=NIL DO IF bLink.branch.negNode # handle.vars.gndNode AND bLink.branch.posNode # handle.vars.gndNode THEN { ThymeGlobals.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[ThymeGlobals.MakeStringNB[handle, problemNode, NIL, FALSE]]]; }; }; -- ForceDCPaths VsXPath: PROC[n: ThymeGlobals.nodePtr, skip: ThymeGlobals.branchPtr, type: ThymeGlobals.elements]= { bLink: ThymeGlobals.branchLinkPtr; b: ThymeGlobals.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: ThymeGlobals.RefR => IF type=resistor THEN GOTO common; x: ThymeGlobals.RefC => IF type=capacitor THEN GOTO common; x: ThymeGlobals.RefL => IF type=inductor THEN GOTO common; x: ThymeGlobals.RefV => GOTO common; x: ThymeGlobals.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: ThymeGlobals.nodePtr; v: ThymeGlobals.branchPtr_ handle.vars.vSourceList; vBody: ThymeGlobals.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 ThymeGlobals.ErrorAtNB[handle, 402, NIL, v]; vBody _ NARROW[v.body]; v _ vBody.nextvSource; ENDLOOP; }; -- VsIndLoops IndNodes: PROC[handle: Handle]= { bLink: ThymeGlobals.branchLinkPtr; i: ThymeGlobals.branchPtr; iBody: ThymeGlobals.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: ThymeGlobals.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: ThymeGlobals.RefL => NULL; -- leave it as it is ENDCASE => negOk_ TRUE; bLink _ bLink.nextLink; ENDLOOP; IF ~(posOk AND negOk) THEN ThymeGlobals.ErrorAtNB[handle, 403, NIL, i]; iBody_ NARROW[i.body]; i _ iBody.nextInductor; ENDLOOP; }; -- IndNodes SeparateFunctions: PROC[handle: Handle]= { nodes: ThymeGlobals.nodePtr_ handle.vars.nodeList; state: REAL= 1.0; other: REAL= 0.0; gnd: ThymeGlobals.nodePtr= handle.vars.gndNode; mf: ThymeGlobals.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. ^ThymeAnalysis.mesa Copyright (C) 1985 by Xerox Corporation. All rights reserved. Last Edited by: Christian LeCocq January 23, 1987 1:53:44 pm PST Sweetsun Chen, July 22, 1985 7:57:56 pm PDT Check connections to ground node first. Do remaining branches. IF b^.eType # capacitor AND b^.eType # iSource THEN We know this branch is a capacitor IF handle.vars.otherModFunc # NIL THEN ThymeGlobals.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]; Christian LeCocq January 23, 1987 9:48:10 am PST capitalized procs, change spMumble into ThymeMumble Κ ˜Icode™Kšœ>™>šœ™K™0Kšœ(Οk™+—K˜š ˜ Kšœ˜Kšœ œy˜‹K˜—šΟn œœ˜š˜Kšœ˜Kšœ ˜ —š˜Kšœ ˜ ——Kšœ˜K˜Kšœœ˜"K˜šž œœ,˜;Kš œ œœ œœ˜Ešœ˜Kšœ œ˜K˜'K˜K˜—KšœΟc ˜K˜—šžœœ˜'Kšœ˜Kšœ˜K˜!šœœ˜Kšœ ˜ Kšœ ˜ Kšœ œ ˜K˜Kšœ˜—KšœŸ˜K˜—šžœœ.˜CKšœœœ˜"Kšœœœ˜Kšœ(˜(Kšœ(˜(Kšœ ˜ šœ˜!Kšœœœ%œ˜F—š˜šœ˜!Kšœœœ%œ˜F—šœ˜Kšœœ˜Kšœœ˜Kšœ œ œ%œ˜Gš˜Kšœœ œ˜+š˜Kšœ œœ˜+šœ˜K˜šœœ˜šœœ˜ Kšœ,˜,Kšœ˜—K˜Kšœ˜—K˜šœœ˜šœœ˜ Kšœ,˜,Kšœ˜—K˜Kšœ˜—Kšœœ˜(Kšœ˜K˜———K˜——KšœŸ˜K˜—šžœœ˜'Kšœ ˜ Kšœ ˜ Kšœ˜KšΟt'™'K˜#šœœ˜K˜šœœ˜šœ˜Kšœ'œ!˜NKšœ"˜&K˜—Kšœ˜—K˜Kšœ˜—Kš ™K˜šœœ˜Kšœœ ˜,Kšœ˜K˜Kšœ˜—KšœŸ˜K˜—šžœœ˜(šœ œ˜Kšœ œ˜šœ?œœ˜TKšœ)˜)Kšœœ™3šœœ˜Kšœœ˜Kšœ œ œ œ ˜B—Kšœ˜—K˜—KšœŸ ˜ K˜—šž œœ˜%Kšœ$œ˜(Kšœœ˜Kšœ˜šœ<œœ˜Mšœ œ˜šœ?œœ˜TKšœ"™"šœ+˜-šœ,œ˜5Kšœ'œŸ˜AKšœ˜K˜——Kšœ˜—Kšœ˜K˜K˜—Kšœ˜—šœœ˜šœ˜KšœK˜KKšœ˜Kšœ5œœ˜E—K–"mycedar" style˜—KšœŸ˜K˜—šžœœ8˜EKšœ˜Kšœ"˜"Kšœ˜šœ œ˜Kšœ œ˜K˜šœœ˜K˜šœ œ˜šœœ˜Kšœœœœ˜:Kšœœœœ˜;Kšœœœœ˜:Kšœœ˜$Kšœœœœ˜9Kšœ˜—š˜šœ œ œœ˜;Kšœœ˜#——K˜—K˜Kšœ˜—K˜—KšœŸ ˜ K˜—šž œœ˜#Kšœ˜Kšœ3˜3Kšœ˜šœœ˜K˜šœœ˜Kšœ œ˜K˜Kšœ˜—Kšœ ˜ Kšœœ%œ˜EKšœœ ˜K˜Kšœ˜—KšœŸ ˜K˜—šžœœ˜!Kšœ"˜"Kšœ˜Kšœ˜Kšœœ˜K˜šœœ˜K˜Kšœœ˜šœœœŸ1˜Dšœœ˜"KšœœŸ˜2Kšœ œ˜—K˜Kšœ˜—K˜Kšœœ˜šœœœŸ0˜Cšœœ˜"KšœœŸ˜2Kšœ œ˜—K˜Kšœ˜—Kšœ œœ%œ˜GKšœœ ˜K˜Kšœ˜—KšœŸ ˜K˜—šžœœ˜*Kšœ2˜2Kšœœ˜Kšœœ˜Kšœ/˜/Kšœ˜Kšœ œ˜šœœ˜Kšœ˜ šœ œ œ œ˜-š˜šœ œ˜šœœ˜Kšœœœ˜6Kšœ˜ —š˜šœœ˜'Kšœœœ˜6Kšœ˜ —š˜šœ$˜*Kšœœœ˜6Kšœ˜ —Kšœ˜ ———Kšœ˜ ——K˜K˜Kšœ˜—šœœ˜%Kšœ ˜Kšœ œ˜šœœ˜$šœœœ"˜1K˜2Kšœ œœ˜Kšœ˜——K˜K˜šœ œ˜K˜%K˜—šœ˜K˜'K˜K˜—K˜Kšœ˜—KšœŸ˜K˜—šž œœœ˜,Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜šœœ™&KšœC™C—Kšœ΄™΄Kšœ™Kšœ™šœ™Kšœ™Kšœ™—KšœŸ˜K˜—Kšœ˜K˜Kšœœ˜ ˜Kšœ!˜#Kšœ˜Kšœœ ˜-Kšœ%œE˜mKšœœ ˜/—™0K™3——…—Ύ+-