DIRECTORY Atom USING [GetPropFromList, PropList], IO USING [int, PutF, rope], Rope USING [Cat, Concat, Equal, Fetch, FromRefText, Length, ROPE], ThymeGlobals USING[Aborted, argNames, branch, branchLink, branchLinkPtr, branchPtr, Canned, CapacitorBody, conLinkPtr, elements, Error, Error2, ErrorSignal, ErrorStrings, Eval, expressionPtr, FunctionBody, Handle, HashKey, hashModulus, InductorBody, instTreeNode, instTreePtr, ISourceBody, modBrPtr, ModelArgHash, ModelBody, modelBranch, modFuncBlk, modFuncPtr, namePtr, Next, node, nodePtr, nodePtrSeq, RealBranch, RealModel, RealNode, RealParm, realThingPtr, realThing, realThings, RefBranchRec, RefCircuitRec, RefCktInstRec, RefFunctionRec, RefModBody, RefModelRec, RefNodeRec, RefParmRec, refR, RefRealBranch, RefRealModel, RefRealNode, RefRealParm, RefUnReal, refUnReal, ValueSeq, VSourceBody], ThymeGlobalsExtras USING [CombineInstancesProc, IsUsefulProc]; ThymeBomb: CEDAR PROGRAM IMPORTS Atom, IO, Rope, ThymeGlobals EXPORTS ThymeGlobals = BEGIN OPEN ThymeGlobals; PushCopies: PROC[nameList: namePtr]= { FOR nl: namePtr _ nameList, nl.srchLink UNTIL nl = NIL DO nl.realCopy _ WITH nl.details SELECT FROM x: RefCircuitRec => NIL, x: RefCktInstRec => NIL, x: RefFunctionRec => NIL, p: RefParmRec => NEW[realThing _ [ nextThing: nl.realCopy, thing: IF p.default THEN NEW[RealParm_ [rp: p.dfltValue]] ELSE refUnReal] ], ENDCASE => NEW[realThing _ [ nextThing: nl.realCopy, thing: refUnReal] ]; ENDLOOP; }; -- PushCopies AdvanceLevel: PROC[nameList: namePtr]= { FOR nl: namePtr _ nameList, nl.srchLink UNTIL nl = NIL DO IF nl.realCopy # NIL THEN nl.realCopy.newLevel_ FALSE; ENDLOOP; }; -- AdvanceLevel PopCopies: PROC[handle: Handle, nameList: namePtr]= { FOR nl: namePtr _ nameList, nl.srchLink UNTIL nl = NIL DO WITH nl.details SELECT FROM x: RefCircuitRec => NULL; x: RefCktInstRec => NULL; x: RefFunctionRec => NULL; n: RefNodeRec => WITH nl.realCopy.thing SELECT FROM r: RefRealNode => { IF r.rn.branches # NIL THEN { handle.vars.nodeCount_ handle.vars.nodeCount + 1; r.rn.nextNode_ handle.vars.nodeList; handle.vars.nodeList_ r.rn; } ELSE { r.rn.nextNode_ handle.vars.unusedNodes; handle.vars.unusedNodes_ r.rn; }; nl.realCopy _ nl.realCopy.nextThing; }; ENDCASE => nl.realCopy _ nl.realCopy.nextThing; ENDCASE => nl.realCopy _ nl.realCopy.nextThing; ENDLOOP; }; -- PopCopies GetParmValue: PUBLIC PROC[handle: Handle, nPtr: namePtr] RETURNS[REAL]= { ENABLE ErrorSignal => ErrorSignal[331, s]; GetRealThing[handle, nPtr]; RETURN[IF handle.vars.n # NIL THEN LOOPHOLE[handle.vars.n] ELSE handle.vars.p] }; -- GetParmValue GetRealThing: PROC[handle: Handle, nPtr: namePtr]= { rCopy: realThingPtr; handle.vars.n _ NIL; handle.vars.b _ NIL; handle.vars.m _ NIL; handle.vars.p _ 0.0; IF nPtr=NIL THEN RETURN; rCopy _ nPtr.realCopy; IF rCopy # NIL THEN IF rCopy.newLevel THEN rCopy _ rCopy.nextThing; IF rCopy # NIL THEN WITH rCopy.thing SELECT FROM rt: RefRealNode => handle.vars.n _ rt.rn; rt: RefRealBranch => handle.vars.b _ rt.rb; rt: RefRealParm => handle.vars.p _ rt.rp; rt: RefRealModel => handle.vars.m _ rt.rm; rt: RefUnReal => ErrorSignal[330, nPtr.name]; ENDCASE ELSE WITH nPtr.details SELECT FROM pn: RefParmRec => IF pn.default THEN handle.vars.p _ pn.dfltValue ELSE ErrorSignal[331, nPtr.name]; ENDCASE => Error2[handle, 390, nPtr]; }; -- GetRealThing PutRealThing: PROC[handle: Handle, nPtr: namePtr, t: realThings]= { rCopy: realThingPtr_ nPtr.realCopy; IF rCopy # NIL THEN SELECT t FROM realNode => rCopy.thing _ NEW[RealNode_ [rn: handle.vars.n]]; realBranch => rCopy.thing _ NEW[RealBranch_ [rb: handle.vars.b]]; realParm => rCopy.thing _ NEW[RealParm_ [rp: handle.vars.p]]; realModel => rCopy.thing _ NEW[RealModel_ [rm: handle.vars.m]]; ENDCASE; }; -- PutRealThing PutParmValue: PUBLIC PROC[handle: Handle, nPtr: namePtr, val: REAL]= { handle.vars.p _ val; PutRealThing[handle, nPtr, realParm]; }; -- PutParmValue MakeConnections: PROC[handle: Handle, connections: conLinkPtr, fakes: namePtr]= { UNTIL fakes=NIL DO GetRealThing[handle, connections.namedNode]; PutRealThing[handle, fakes, realNode]; fakes _ fakes.nextName; connections _ connections.nextLink; ENDLOOP; }; -- MakeConnections Apply: PROC[handle: Handle, apList: expressionPtr]= { FOR ex: expressionPtr _ apList, ex.next UNTIL ex=NIL DO [] _ Eval[handle, ex]; ENDLOOP; }; -- Apply ExplodeInstance: PROC[handle: Handle, instNamePtr: namePtr] RETURNS[t: instTreePtr]= { inst: RefCktInstRec _ NARROW[instNamePtr.details]; ckt: namePtr _ NARROW[inst.of]; cktDetails: RefCircuitRec _ NARROW[ckt.details]; PushCopies[cktDetails.names]; MakeConnections[handle, inst.connections, cktDetails.fakeNodes]; Apply[handle, inst.actualParms]; AdvanceLevel[cktDetails.names]; t _ NEW[instTreeNode _ [instance: instNamePtr] ]; FOR exp: expressionPtr _ cktDetails.assertions, exp.next UNTIL exp=NIL DO IF Eval[handle, exp]=0.0 THEN Error2[handle, 341, instNamePtr]; ENDLOOP; Explode[handle, ckt, t]; PopCopies[handle, cktDetails.names]; }; -- ExplodeInstance ExplodeModelFunc: PROC[handle: Handle, mfNamePtr: namePtr, newFunc: modFuncPtr]= { index: NAT; arguments: argNames; parms: expressionPtr; data: REF ANY; WITH mfNamePtr.details SELECT FROM m: RefModelRec => { newFunc.argVector _ m.modelArgVec; arguments _ m.modelArgs; parms _ m.modelParms; data _ m.data; }; f: RefFunctionRec => { newFunc.argVector _ f.funcArgVec; arguments _ f.funcArgs; parms _ f.funcParms; data _ f.data; }; ENDCASE => Error2[handle, 399, mfNamePtr]; IF arguments # NIL THEN { newFunc.arguments_ NEW[nodePtrSeq[arguments.size]]; newFunc.arguments.visited _ FALSE; FOR index IN [0..arguments.size) DO IF arguments[index] # NIL THEN GetRealThing[handle, arguments[index]]; newFunc.arguments[index] _ handle.vars.n; ENDLOOP; }; index_ 0; FOR p: expressionPtr_ parms, p.next UNTIL p=NIL DO index_ index + 1; ENDLOOP; newFunc.parmVector_ NEW[ValueSeq[index]]; newFunc.parmVector.visited _ FALSE; newFunc.parmVector.handle _ handle; newFunc.parmVector.modFunc _ newFunc; UNTIL index=0 DO index_ index - 1; newFunc.parmVector[index] _ Eval[handle, parms]; parms_ parms.next; ENDLOOP; }; -- ExplodeModelFunc ExplodeController: PROC[handle: Handle, branchNamePtr: namePtr, newB: branchPtr]= { brDetails: RefBranchRec_ NARROW[branchNamePtr.details]; oldmf: namePtr_ brDetails.controller; newFunc: modFuncPtr; newModB: modBrPtr; WITH oldmf.details SELECT FROM fcn: RefFunctionRec => { handle.vars.funcCount _ handle.vars.funcCount + 1; newFunc_ NEW[modFuncBlk _ [ nextMFPtr: handle.vars.functionList, body: NEW[FunctionBody _ [functionProc: fcn.functionProc, branch: newB]] ]]; handle.vars.functionList _ newFunc; -- * ExplodeModelFunc[handle, oldmf, newFunc]; newB.controller _ newFunc; }; mod: RefModelRec => { mBody: RefModBody; GetRealThing[handle, oldmf]; mBody _ NARROW[handle.vars.m.body]; newModB _ NEW[modelBranch _ [nextBranch: mBody.modelBranches, b: newB]]; mBody.modelBranches _ newModB; newB.controller _ handle.vars.m; newB.modelIndex _ brDetails.modelIndex; }; ENDCASE => Error2[handle, 399, branchNamePtr]; }; -- ExplodeController ConnectBranch: PROC[n: nodePtr, b: branchPtr, pos: BOOL]= { IF n # NIL THEN { n.branches _ NEW[branchLink _ [nextLink: n.branches, branch: b, pos: pos]]; IF pos THEN b.posNode _ n ELSE b.negNode _ n; } ELSE ErrorSignal[242, b.branchName.name]; }; -- ConnectBranch ExplodeBranch: PROC[handle: Handle, branchNamePtr: namePtr] RETURNS[newB: branchPtr _ NIL]= { pNode, nNode: nodePtr; newC, newL, newV, newI: branchPtr; brDetails: RefBranchRec _ NARROW[branchNamePtr.details]; brValue: REAL _ 0.0; ParallelsExistingBranch: PROC [branchType: elements] RETURNS [BOOL] = { IF NOT (Rope.Fetch[branchNamePtr.name, 0] = '? -- anonymous AND brDetails.controller = NIL -- constant value ) THEN RETURN[FALSE]; -- can't add this one to any other IF brValue = 0 THEN RETURN[TRUE]; -- throw this one away FOR list: REF branchLink _ pNode.branches, list.nextLink WHILE list # NIL DO details: REF ANY; branchName: namePtr; otherBranch: branchPtr = list.branch; IF otherBranch.negNode = nNode -- same connections AND ISTYPE[(details _ (branchName _ otherBranch.branchName).details), RefBranchRec] AND NARROW[details, RefBranchRec].branchType = branchType -- same branch type AND Rope.Fetch[branchName.name, 0] = '? -- also anonymous AND otherBranch.controller = NIL -- constant value THEN { otherBranch.comVal _ otherBranch.comVal+Eval[handle, brDetails.valExpr]; RETURN[TRUE]; }; ENDLOOP; RETURN[FALSE]; }; handle.vars.branchCount _ handle.vars.branchCount + 1; GetRealThing[handle, brDetails.posNode]; pNode _ handle.vars.n; GetRealThing[handle, brDetails.negNode]; nNode _ handle.vars.n; SELECT TRUE FROM brDetails.controller = NIL => brValue _ Eval[handle, brDetails.valExpr]; ENDCASE => WITH brDetails.controller.details SELECT FROM mod: RefModelRec => { GetRealThing[handle, brDetails.controller]; IF handle.vars.m.body = $useless THEN RETURN; }; ENDCASE => NULL; IF pNode # nNode THEN { SELECT brDetails.branchType FROM resistor => newB_ NEW[branch_ [body: refR]]; capacitor=> { IF ParallelsExistingBranch[capacitor] THEN RETURN; newB_ newC_ NEW[branch_ [body: NEW[CapacitorBody_ [nextCapacitor: handle.vars.capacitorList]] ] ]; handle.vars.capacitorList_ newC; }; inductor => { newB_ newL_ NEW[branch_ [body: NEW[InductorBody_ [nextInductor: handle.vars.inductorList ]] ] ]; handle.vars.inductorList_ newL; }; vSource => { newB_ newV_ NEW[branch_ [body: NEW[VSourceBody_ [nextvSource: handle.vars.vSourceList ]] ] ]; handle.vars.vSourceList_ newV; }; iSource => { IF ParallelsExistingBranch[iSource] THEN RETURN; newB_ newI_ NEW[branch_ [body: NEW[ISourceBody_ [nextiSource: handle.vars.iSourceList ]] ] ]; handle.vars.iSourceList_ newI; }; ENDCASE => Error2[handle, 391, branchNamePtr]; handle.vars.b_ newB; PutRealThing[handle, branchNamePtr, realBranch]; newB.branchName_ branchNamePtr; newB.comVal_ brValue; newB.posNode _ pNode; newB.negNode _ nNode; IF brDetails.controller # NIL THEN ExplodeController[handle, branchNamePtr, newB]; ConnectBranch[pNode, newB, TRUE]; ConnectBranch[nNode, newB, FALSE]; }; }; -- ExplodeBranch Explode: PROC[handle: Handle, ckt: namePtr, tree: instTreePtr]= { curName: namePtr; newModel: modFuncPtr; newB: branchPtr; newTree: instTreePtr; cktDetails: RefCircuitRec _ NARROW[ckt.details]; IF Canned[handle] THEN SIGNAL Aborted; FOR curName _ cktDetails.names, curName.srchLink UNTIL curName=NIL DO WITH curName.details SELECT FROM x: RefNodeRec => { handle.vars.n _ tree.nodes _ NEW[node _ [ nodeName: curName, treeLevel: tree, brotherNodes: tree.nodes] ]; PutRealThing[handle, curName, realNode]; }; ENDCASE; ENDLOOP; FOR curName _ cktDetails.names, curName.srchLink UNTIL curName=NIL DO ENABLE ErrorSignal => { ErrorStrings[handle, error, TreeError[handle, tree, curName], s]; LOOP; }; WITH curName.details SELECT FROM rm: RefModelRec => { handle.vars.modelCount _ handle.vars.modelCount + 1; newModel_ NEW[modFuncBlk _ [ nextMFPtr: handle.vars.functionList, body: NEW[ModelBody _ [ modelProc: rm.modelProc, modelResults: rm.modelResults, modelName: curName, oldArgVector: rm.modelOldArgVec]] ]]; handle.vars.functionList _ newModel; ExplodeModelFunc[handle, curName, newModel]; IF ModelInstanceUseful[handle, rm, newModel] THEN { IF GetPropFromRef[rm.data, $CombineInstancesProc] # NIL THEN { -- register this instance for comparing with future ones key: HashKey = HashArgs[newModel]; IF handle.vars.modelArgs = NIL THEN handle.vars.modelArgs _ NEW[ModelArgHash _ ALL[NIL]]; handle.vars.modelArgs[key] _ CONS[newModel, handle.vars.modelArgs[key]]; }; } ELSE newModel.body _ $useless; handle.vars.m _ newModel; PutRealThing[handle, curName, realModel]; }; ENDCASE; ENDLOOP; FOR curName _ cktDetails.names, curName.srchLink UNTIL curName=NIL DO ENABLE ErrorSignal => { ErrorStrings[handle, error, TreeError[handle, tree, curName], s]; LOOP; }; WITH curName.details SELECT FROM x: RefBranchRec => { newB _ ExplodeBranch[handle, curName]; IF newB # NIL THEN { newB.brotherBranches_ tree.branches; newB.treeLevel_ tree; tree.branches_ newB; }; }; x: RefCktInstRec => { newTree _ ExplodeInstance[handle, curName]; newTree.father _ tree; newTree.brothers _ tree.sons; tree.sons _ newTree; }; ENDCASE; ENDLOOP; }; -- Explode ModelInstanceUseful: PROC [ handle: Handle, proto: RefModelRec, inst: modFuncPtr ] RETURNS [ useful: BOOL _ TRUE ] = { r: REF ANY; IF (r _ GetPropFromRef[proto.data, $IsUsefulProc]) # NIL THEN { isUsefulProc: ThymeGlobalsExtras.IsUsefulProc = NARROW[r, REF ThymeGlobalsExtras.IsUsefulProc]^; IF ~ isUsefulProc[inst.parmVector] THEN RETURN[FALSE]; }; IF (r _ GetPropFromRef[proto.data, $CombineInstancesProc]) # NIL THEN { combineInstancesProc: ThymeGlobalsExtras.CombineInstancesProc = NARROW[r, REF ThymeGlobalsExtras.CombineInstancesProc]^; match: modFuncPtr = FindMatchingModelInstance[handle, inst]; IF match # NIL AND combineInstancesProc[parmsA: match.parmVector, parmsB: inst.parmVector] THEN RETURN[FALSE]; }; }; GetPropFromRef: PROC [ propList, prop: REF ANY ] RETURNS [ val: REF ANY ] = { WITH propList SELECT FROM pl: Atom.PropList => val _ Atom.GetPropFromList[pl, prop]; ENDCASE => val _ NIL; }; HashArgs: PROC [ model: modFuncPtr ] RETURNS [ key: HashKey ] = { sum: INT _ 0; FOR i: NAT IN [0..model.arguments.size) DO TRUSTED {sum _ sum+LOOPHOLE[model.arguments[i], INT]}; ENDLOOP; IF sum < 0 THEN sum _ -sum; key _ sum MOD hashModulus; }; FindMatchingModelInstance: PROC [ handle: Handle, inst: modFuncPtr ] RETURNS [ match: modFuncPtr _ NIL ] = { key: HashKey = HashArgs[inst]; prevList: LIST OF REF ANY _ NIL; IF handle.vars.modelArgs = NIL THEN handle.vars.modelArgs _ NEW[ModelArgHash _ ALL[NIL]]; FOR list: LIST OF REF ANY _ handle.vars.modelArgs[key], list.rest WHILE list#NIL DO { WITH list.first SELECT FROM mf: modFuncPtr => { -- matches if arguments are the same and model name is the same. IF inst.arguments.size # mf.arguments.size THEN GOTO Mismatch; FOR i: NAT IN [0..inst.arguments.size) DO IF inst.arguments[i] # mf.arguments[i] THEN GOTO Mismatch; ENDLOOP; WITH mf.body SELECT FROM mb: RefModBody => WITH inst.body SELECT FROM nfb: RefModBody => IF mb.modelName # nfb.modelName THEN GOTO Mismatch; ENDCASE => GOTO Mismatch; ENDCASE => GOTO Mismatch; IF prevList # NIL THEN { -- there's a match, move it to the front prevList.rest _ list.rest; list.rest _ handle.vars.modelArgs[key]; handle.vars.modelArgs[key] _ list; }; RETURN[match: mf]; }; ENDCASE => NULL; EXITS Mismatch => NULL }; prevList _ list; ENDLOOP; }; -- end of FindMatchingModelInstance TreeError: PROC[handle: Handle, t: instTreePtr, n: namePtr] RETURNS[Rope.ROPE]= { RETURN[Rope.Concat[PrintTree[handle, t, TRUE], n.name]]; }; -- TreeError AlphaNumeric: PROC[name: Rope.ROPE] RETURNS[an: BOOL_ FALSE]= { tChar: CHAR _ Rope.Fetch[name, 0]; an _ tChar IN ['a..'z] OR tChar IN ['A..'Z]; -- first char should not be numeric IF an THEN FOR i: INT IN [1..Rope.Length[name]) DO tChar_ Rope.Fetch[name, i]; an_ tChar IN ['a..'z] OR tChar IN ['A..'Z] OR tChar IN ['0..'9]; IF ~an THEN RETURN; ENDLOOP; }; -- AlphaNumeric PrintTree: PROC[handle: Handle, t: instTreePtr, toRope: BOOL _ FALSE] RETURNS[r: Rope.ROPE _ NIL]= { IF t # NIL AND t # handle.vars.treeRoot THEN { tName: Rope.ROPE _ t.instance.name; r _ PrintTree[handle, t.father, toRope].Concat[IF AlphaNumeric[tName] THEN tName.Concat["/"] ELSE Rope.Cat["$", tName, "$/"] ]; }; IF toRope THEN RETURN ELSE { handle.msgStream.PutF["%g", IO.rope[r]]; r _ NIL; }; }; -- PrintTree PrintNode: PROC[handle: Handle, n: nodePtr, ok, toRope: BOOL _ FALSE] RETURNS[r: Rope.ROPE _ NIL]= { nName: Rope.ROPE _ n.nodeName.name; r _ PrintTree[handle, n.treeLevel, toRope].Concat[ IF ok OR AlphaNumeric[nName] THEN nName ELSE Rope.Cat["$", nName, "$"] ]; IF NOT toRope THEN { handle.msgStream.PutF["%g", IO.rope[r]]; r _ NIL; }; }; -- PrintNode PrintBranch: PROC[handle: Handle, b: branchPtr, ok, toRope: BOOL_ FALSE] RETURNS[r: Rope.ROPE_ NIL]= { bName: Rope.ROPE _ b.branchName.name; r _ PrintTree[handle, b.treeLevel, toRope].Concat[ IF ok OR AlphaNumeric[bName] THEN bName ELSE Rope.Cat["$", bName, "$"] ]; IF NOT toRope THEN { handle.msgStream.PutF["%g", IO.rope[r]]; r _ NIL; }; }; -- PrintBranch MakeStringNB: PUBLIC PROC[handle: Handle, n: nodePtr, b: branchPtr, ok: BOOL_ TRUE] RETURNS[Rope.ROPE]= { -- NB: Node/Branch; ok: non-alphanumeric chars allowed. RETURN[IF n # NIL THEN PrintNode[handle, n, ok, TRUE] ELSE PrintBranch[handle, b, ok, TRUE]]; }; -- MakeStringNB PrintTreeWithCktNames: PROC[handle: Handle, t: instTreePtr] = { IF t = NIL OR t = handle.vars.treeRoot THEN handle.msgStream.PutF["\t"] ELSE { tInstDetails: RefCktInstRec _ IF ISTYPE[t.instance.details, RefCktInstRec] THEN NARROW[t.instance.details] ELSE NIL; cktName: Rope.ROPE _ IF tInstDetails # NIL THEN tInstDetails.of.name ELSE NIL; PrintTreeWithCktNames[handle, t.father]; handle.msgStream.PutF["%g(%g)/", IO.rope[t.instance.name], IO.rope[cktName]]; }; }; -- PrintTreeWithCktNames PrintUnusedNodes: PROC[handle: Handle, n: nodePtr] = { FOR n: nodePtr _ handle.vars.unusedNodes, n.nextNode UNTIL n=NIL DO nName: Rope.ROPE _ n.nodeName.name; PrintTreeWithCktNames[handle, n.treeLevel]; handle.msgStream.PutF["%g", IO.rope[n.nodeName.name]]; handle.msgStream.PutF[IF n.nextNode = NIL THEN ".\n\n" ELSE ",\n"]; ENDLOOP; }; -- PrintUnusedNodes PrintHole: PUBLIC PROC[handle: Handle]= { handle.msgStream.PutF["\nNodes --\n"]; FOR n: nodePtr _ handle.vars.nodeList, n.nextNode UNTIL n=NIL DO [] _ PrintNode[handle, n, TRUE]; handle.msgStream.PutF[" _ {"]; FOR bLink: branchLinkPtr_ n.branches, bLink.nextLink UNTIL bLink=NIL DO [] _ PrintBranch[handle, bLink.branch, TRUE]; IF bLink.branch.posNode=n THEN handle.msgStream.PutF["+"] ELSE handle.msgStream.PutF["-"]; IF bLink.nextLink # NIL THEN handle.msgStream.PutF[", "]; ENDLOOP; handle.msgStream.PutF["}.\n"]; ENDLOOP; }; -- PrintHole FindNB: PROC[handle: Handle, tree: instTreePtr] RETURNS[n: nodePtr _ NIL, b: branchPtr _ NIL]= { IF handle.vars.item=name THEN { i: instTreePtr; FOR i_ tree.sons, i.brothers UNTIL i=NIL DO IF Rope.Equal[i.instance.name, Rope.FromRefText[handle.vars.newString]] THEN EXIT; ENDLOOP; IF i # NIL THEN { Next[handle]; IF handle.vars.item=slash THEN Next[handle] ELSE Error[handle, 300, FALSE]; [n, b] _ FindNB[handle, i]; } ELSE { FOR n_ tree.nodes, n.brotherNodes UNTIL n=NIL DO IF Rope.Equal[n.nodeName.name, Rope.FromRefText[handle.vars.newString]] THEN EXIT; ENDLOOP; IF n=NIL THEN FOR b_ tree.branches, b.brotherBranches UNTIL b=NIL DO IF Rope.Equal[b.branchName.name, Rope.FromRefText[handle.vars.newString]] THEN EXIT; ENDLOOP; Next[handle]; }; } ELSE Error[handle, 301, FALSE]; }; -- FindNB FindNodeOrBranch: PUBLIC PROC[handle: Handle] RETURNS[n: nodePtr, b: branchPtr]= { [n, b] _ FindNB[handle, handle.vars.treeRoot]; }; -- FindNodeOrBranch FillInBranchLinks: PROC[handle: Handle]= { FOR nodes: nodePtr_ handle.vars.nodeList, nodes.nextNode UNTIL nodes=NIL DO FOR links: branchLinkPtr_ nodes.branches, links.nextLink UNTIL links=NIL DO links.otherNode_ IF links.pos THEN links.branch.negNode ELSE links.branch.posNode; ENDLOOP; ENDLOOP; }; -- FillInBranchLinks Bomb: PUBLIC PROC[handle: Handle, cktRoot, gndNodeName: namePtr]= { cktRootDetails: RefCircuitRec_ NARROW[cktRoot.details]; handle.vars.treeRoot_ NEW[instTreeNode_ []]; PushCopies[cktRootDetails.names]; AdvanceLevel[cktRootDetails.names]; Explode[handle, cktRoot, handle.vars.treeRoot]; GetRealThing[handle, gndNodeName]; handle.vars.gndNode _ handle.vars.n; PopCopies[handle, cktRootDetails.names]; FillInBranchLinks[handle]; handle.msgStream.PutF[ "\n\nTotal %g nodes, %g models, %g functions, and %g branches.\n\n", IO.int[handle.vars.nodeCount], IO.int[handle.vars.modelCount], IO.int[handle.vars.funcCount], IO.int[handle.vars.branchCount]]; IF handle.vars.unusedNodes # NIL THEN { handle.msgStream.PutF["Unused nodes:\n"]; PrintUnusedNodes[handle, handle.vars.unusedNodes]; }; }; -- Bomb END. CHANGE LOG Wilhelm, March 16, 1982 9:41 AM Barth, 7-May-82 10:48:59 PDT Chen, February 12, 1984 7:50 PM, modified to support oldArgVector. Chen, June 10, 1984 9:47:59 pm PDT, cedarized. McCreight, April 2, 1985 3:41:00 pm PST. Chen, July 22, 1985 7:56:50 pm PDT, => Cedar6.0. Barth, November 12, 1986 3:33:56 pm PST, in ExplodeBranch initialize brValue 6ThymeBomb.mesa Copyright (C) 1985 by Xerox Corporation. All rights reserved. Last Edited by: Christian LeCocq February 4, 1987 6:10:36 pm PST Barth, November 12, 1986 3:35:20 pm PST Sweetsun Chen, July 22, 1985 8:04:35 pm PDT For each namePtr linked with the nameList, initialize its realCopy as follows: if the namePtr points to a circuit, a circuit instance, a model or a function, its realCopy is assigned nil; otherwise, allocate and initialize its realCopy as following: the "nextThing" of the new realCopy is the original realCopy, its "newLevel" is the default (TRUE), its "thing" is unReal, unless the namePtr is a parameter name pointer with default, in which case "thing" points to the default value. For each namePtr linked with the nameList do the following: If its details points to a circuit, a circuit instance, or a function, then do nothing; otherwise, pop up its realCopy.nextThing as its realCopy; If the original realCopy points to a nodePtr, then if it has nonNIL branches then pop the nodePtr on the handle.vars.nodeList, with original handle.vars.nodeList as its nextNode, and increment handle.vars.nodeCount; otherwise if its branches is nil then pop the nodePtr on top of handle.vars.unusedNodes with the original handle.vars.unusedNodes as its nextNode. * Reset n,b,m,and p; If nPtr and its realCopy is not NIL then depending on the type of its realCopy (or the non-nil nextThing of its realCopy, if its realCopy.newLevel is TRUE), set n,b,m, or p accordingly; but if its realCopy (or the nextThing, see above) is NIL and nPtr.details.default then set p with the default. Depending on the type of t, initialize nPtr.realCopy.thing to point to (the content of) n, b, p, or m. For each connection linked with connections, set n to its namedNode.realCopy.thing.rn; let fakes.realCopy.thing point to n, then proceed similarly (for connection.nextLink with fakes.nextName, and so on). .. so the model or function can know its environment in case of error initialize each parameter of newFunc See whether this model instance non-trivial and cannot be combined with another Κ – "cedar" style˜Icodešœ™Kšœ>™>šœ™K™0Kšœ$Οk™'Kšœ(™+—K™š ˜ Kšœœ˜'Kšœœ˜Kšœœ2œ˜BKšœ œ©˜»Kšœœ&˜>—K˜šΟn œœ˜š˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ —š˜Kšœ ˜ ——šœ˜Kšœ˜—K˜šž œœ˜&šΟtN™NKšŸl™lšŸ=™=KšŸ<œ™=KšŸΠktŸ™%KšŸ†™†——šœ%œœ˜9šœœ œ˜)Kšœœ˜Kšœœ˜Kšœœ˜šœœ˜"Kšœ˜Kš œœ œœœ ˜IKšœ˜—šœœ˜Kšœ˜Kšœ˜Kšœ˜——Kšœ˜—KšœΠct ˜—K˜šž œœ˜(šœ%œœ˜9Kšœœœœ˜6Kšœ˜—Kšœ‘˜—K˜šž œœ&˜5šŸ;™;KšŸWœ Ÿ.™‘šŸ2™2Kšœ Ÿ›™€Kšœ Ÿˆ™’——šœ%œœ˜9šœ œ˜Kšœœ˜Kšœœ˜Kšœœ˜šœ˜šœœ˜"šœ˜šœœœ˜Kšœ1˜1Kšœ$˜$Kšœ˜Kšœ˜—šœ˜Kšœ'˜'Kšœ˜Kšœ˜—Kšœ$˜$Kšœ˜—Kšœ(˜/——Kšœ(˜/—Kšœ˜—Kšœ‘ ˜—K˜š ž œœœ œœ˜IKšœ$˜*Kšœ˜Kš œœœœœœ˜NKšŸ™Kšœ‘˜—K˜šž œœ"˜4KšŸ3 Ÿs ŸU Ÿ6™»Kšœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœ˜Kšœœœœ˜Kšœ˜Kš œ œœœœ˜Cšœ œ˜šœ œ˜Kšœ)˜)Kšœ+˜+Kšœ)˜)Kšœ*˜*Kšœ-˜-Kš˜——š˜šœœ˜šœ˜Kšœ œœ˜Q—Kšœ˜%——Kšœ‘˜—K˜šž œœ1˜CKšŸf™fKšœ#˜#šœ œ˜šœ˜ Kšœœ ˜=Kšœœ"˜AKšœœ ˜=Kšœœ!˜?Kšœ˜——KšœŸ‘˜—K˜šž œœœ%œ˜FKšœ˜Kšœ%˜%KšœŸ‘˜—K˜šžœœ<˜QKšŸΝ™Νšœœ˜Kšœ,˜,Kšœ&˜&Kšœ˜Kšœ#˜#Kšœ˜—Kšœ‘˜—K˜šžœœ*˜5šœ%œœ˜7Kšœ˜Kšœ˜—KšœŸ‘˜ —K˜šžœœ'œ˜VKšœœ˜2Kšœœ ˜Kšœœ˜0Kšœ˜Kšœ@˜@Kšœ ˜ Kšœ˜Kšœœ*˜1šœ6œœ˜IKšœœ"˜?Kšœ˜—Kšœ˜Kšœ$˜$Kšœ‘˜K˜—K˜šžœœ<˜RKšœœ˜ Kšœ˜Kšœ˜Kšœœœ˜šœœ˜"šœ˜Kšœ"˜"Kšœ˜Kšœ˜Kšœ˜Kšœ˜—šœ˜Kšœ!˜!Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ#˜*—šœ œœ˜Kšœœ˜3Kšœœ˜$šœœ˜#Kšœœœ(˜FKšœ*˜*Kšœ˜—Kšœ˜—Kšœ ˜ Kš œ!œœœœ˜MKšœœ˜)Kšœœ˜#Kšœ#˜#šœ%˜%Kšœj™j—šœ ˜Kšœ˜Kšœ1˜1Kšœ˜Kšœ˜—Kšœ‘˜—K˜šžœœ<˜SKšœœ˜7Kšœ%˜%Kšœ˜Kšœ˜šœœ˜šœ˜Kšœ2˜2šœ œ˜Kšœ$˜$Kšœœ?˜HKšœ˜—Kšœ$Οc˜(Kšœ)˜)Kšœ˜Kšœ˜—šœ˜Kšœ˜Kšœ˜Kšœœ˜#Kšœ œ;˜HKšœ˜Kšœ ˜ Kšœ'˜'Kšœ˜—Kšœ'˜.—Kšœ‘˜—K˜šž œœ œ˜;šœœœ˜Kšœ œ;˜KKšœœœ˜-Kšœ˜—Kšœ%˜)KšœŸ‘˜—K˜šž œœ(˜;Kšœœ˜!Kšœ˜Kšœ"˜"Kšœœ˜8Kšœ œ˜šžœœœœ˜Gšœœ)’ ˜;Kšœœ’˜0Kšœœœœ’"˜8—Kš œ œœœ’˜8š œœ,œœ˜LKšœ œœ˜Kšœ˜Kšœ%˜%šœ’˜2KšœœM˜WKšœœ0’˜MKšœ%’˜9Kšœœ’˜2šœ˜KšœJ˜JKšœœ˜ Kšœ˜——Kšœ˜—Kšœœ˜Kšœ˜—Kšœ6˜6Kšœ(˜(Kšœ˜Kšœ(˜(Kšœ˜šœœ˜Kšœœ.˜Hšœ˜ šœœ˜-šœ˜Kšœ+˜+Kšœœœ˜-Kšœ˜—Kšœœ˜———šœœ˜šœ˜ Kšœœ˜,šœ ˜ Kšœ$œœ˜2šœ œ˜Kšœœ@˜J—Kšœ ˜ Kšœ˜—šœ ˜ šœ œ˜Kšœœ>˜H—Kšœ˜Kšœ˜—šœ ˜ šœ œ˜Kšœœ<˜F—Kšœ˜Kšœ˜—šœ ˜ Kšœ"œœ˜0šœ œ˜Kšœœ<˜F—Kšœ˜Kšœ˜—Kšœ'˜.—Kšœ˜Kšœ0˜0Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœœ0˜RKšœœ˜!Kšœœ˜"Kšœ˜—Kšœ‘˜—K˜šžœœ4˜AKšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœ˜0Kšœœœ ˜&šœ.œ œ˜Ešœœ˜ šœ˜šœœ ˜)Kšœ˜Kšœ˜Kšœ˜—Kšœ(˜(Kšœ˜—Kšœ˜—Kšœ˜—šœ.œ œ˜Ešœ˜KšœA˜AKšœ˜Kšœ˜—šœœ˜ šœ˜Kšœ4˜4šœ œ˜Kšœ$˜$šœœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ!˜!—Kšœ˜—Kšœ$˜$Kšœ,˜,šœ+œ˜3šœ2œœ’8˜wKšœ"˜"Kš œœœœœœ˜ZKšœœ'˜HK˜—K˜—Kšœ˜Kšœ˜Kšœ)˜)Kšœ˜—Kšœ˜—Kšœ˜—šœ.œ œ˜Ešœ˜KšœA˜AKšœ˜Kšœ˜—šœœ˜ šœ˜Kšœ&˜&šœœœ˜Kšœ$˜$Kšœ˜Kšœ˜Kšœ˜—Kšœ˜—šœ˜Kšœ+˜+Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜—Kšœ‘ ˜ —K˜š žœœ9œ œœ˜vKšœO™OKšœœœ˜ šœ3œœ˜?Kšœ/œœ#˜`Kšœ!œœœ˜6Kšœ˜—šœ;œœ˜GKšœ?œœ+˜xKšœ<˜šœœœ˜*Kšœ%œœ ˜:Kšœ˜—šœ œ˜šœ˜šœ œ˜Kšœœœœ ˜FKšœœ ˜——Kšœœ ˜—šœ œœ’(˜AK˜Kšœ'˜'Kšœ$˜$K˜—Kšœ ˜K˜—Kšœœ˜—Kšœ ˜Kšœ˜—Kšœ˜Kšœ˜—Kšœ’#˜&K˜—šž œœ-œœ˜QKšœ"œ ˜8Kšœ‘ ˜—K˜š ž œœ œœœœ˜?Kšœœ˜"Kšœ œ œœ ’#˜Pš œœœœ˜2Kšœ˜Kš œ œ œœ œœ ˜@Kšœœœ˜Kšœ˜—Kšœ‘˜—K˜šž œœ)œœœ œœ˜dšœœœœ˜.Kšœ œ˜#Kšœ/œœœ˜Kšœ˜—šœœœœ˜Kšœœ ˜(Kšœœ˜K˜—Kšœ‘ ˜—K˜šž œœ)œœœ œœ˜dKšœ œ˜#šœ2˜2Kšœœœœ˜FKšœ˜—šœœœ˜Kšœœ ˜(Kšœœ˜K˜—KšœŸ‘ ˜—K˜šž œœ+œœ˜HKšœ œœ˜Kšœ œ˜%šœ2˜2Kšœœœœ˜FKšœ˜—šœœœ˜Kšœœ ˜(Kšœœ˜K˜—Kšœ‘˜—K˜š ž œœœ/œœ˜SKšœœ’7˜MKš œœœœœœ˜]Kšœ‘˜—K˜šžœœ$˜?Kšœœœœ˜Gšœ˜Kš œœœ$œœœœ˜tKš œœœœœœœ˜NKšœ(˜(Kšœ!œœ˜MKšœ˜—Kšœ‘˜K˜—šžœœ ˜6šœ2œœ˜CKšœ œ˜#Kšœ+˜+Kšœœ˜6Kš œœœœ œ˜CKšœ˜—KšœŸ‘˜—K˜šž œœœ˜)Kšœ&˜&šœ/œœ˜@Kšœœ˜ Kšœ˜šœ2œœ˜GKšœ'œ˜-Kšœœ˜9Kšœ˜ Kšœœœ˜9Kšœ˜—Kšœ˜Kšœ˜—Kšœ‘ ˜—K˜š žœœ$œœœ˜`šœœ˜Kšœ˜šœœœ˜+KšœFœœ˜RKšœ˜—šœœœ˜Kšœ ˜ Kšœœ ˜+Kšœœ˜Kšœ˜Kšœ˜—šœ˜šœœœ˜0KšœFœœ˜RKšœ˜—š œœœœ%œœ˜DKšœHœœ˜TKšœ˜—Kšœ ˜ Kšœ˜—Kšœ˜—Kšœœ˜Kšœ‘ ˜ —K˜šžœœœœ˜RKšœ/˜/Kšœ’˜—K˜šžœœ˜*šœ6œœ˜Kšœ6œœ˜KKšœœ œœ˜RKšœ˜—Kšœ˜—Kšœ‘˜—K˜šžœœœ2˜CKšœœ˜7Kšœœ˜,Kšœ!˜!Kšœ#˜#Kšœ/˜/Kšœ"˜"Kšœ$˜$Kšœ(˜(Kšœ˜šœ˜KšœD˜DKšœ˜Kšœ˜Kšœ˜Kšœ˜!—šœœœ˜'Kšœ)˜)Kšœ2˜2K˜—Kšœ‘˜ —K˜Kšœ˜šœœ˜ Kšœ˜ Kšœ˜Kšœœ#˜CKšœœ ˜.Kšœ$œ˜(Kšœœ˜0Kšœ$œ%˜LK˜——…—O$qg