DIRECTORY Atom USING [GetPropFromList, PropList], IO USING [int, PutF, rope], Rope USING [Cat, Concat, Equal, Fetch, FromRefText, Length, ROPE], spGlobals 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], spGlobalsExtras USING [CombineInstancesProc, IsUsefulProc]; spBomb: CEDAR PROGRAM IMPORTS Atom, IO, Rope, spGlobals EXPORTS spGlobals= BEGIN OPEN spGlobals; 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; 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: spGlobalsExtras.IsUsefulProc = NARROW[r, REF spGlobalsExtras.IsUsefulProc]^; IF ~ isUsefulProc[inst.parmVector] THEN RETURN[FALSE]; }; IF (r _ GetPropFromRef[proto.data, $CombineInstancesProc]) # NIL THEN { combineInstancesProc: spGlobalsExtras.CombineInstancesProc = NARROW[r, REF spGlobalsExtras.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]= { cktRootDetails: RefCircuitRec_ NARROW[handle.vars.cktRoot.details]; handle.vars.treeRoot_ NEW[instTreeNode_ []]; pushCopies[cktRootDetails.names]; advanceLevel[cktRootDetails.names]; explode[handle, handle.vars.cktRoot, handle.vars.treeRoot]; getRealThing[handle, handle.vars.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. ήFile: spBomb.mesa Copyright (C) 1985 by Xerox Corporation. All rights reserved. Last Edited by: 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˜JšΟc™Jšœ>™>šœ™Icode™+—J™šΟk ˜ Jšœžœ˜'Jšžœžœ˜Jšœžœ2žœ˜BJšœ žœ©˜ΈJšœžœ&˜;—J˜šœžœž˜Jšžœžœ˜!Jšžœ ˜—J˜Jšžœžœ ˜J˜šœ žœ˜&šΠctN™NJšŸl™lšŸ=™=JšŸ<œ™=JšŸΠktŸ™%JšŸ†™†——J˜šžœ$žœžœž˜8šœ žœ žœž˜(Jšœžœ˜Jšœžœ˜Jšœžœ˜šœžœ ˜!Jšœ˜šœžœ žœžœ˜9Jšžœ˜——šžœžœ ˜Jšœ˜Jšœ˜——Jšžœ˜—JšœŸ ˜—J˜šœžœ˜(šžœ$žœžœž˜8Jšžœžœžœžœ˜6Jšžœ˜—JšœŸ˜—J˜šœ žœ&˜5šŸ;™;JšŸWœ Ÿ.™‘šŸ2™2Jšœ Ÿ›™€Jšœ Ÿˆ™’——šžœ$žœžœž˜8šžœ žœž˜Jšœžœ˜Jšœžœ˜Jšœžœ˜šœ˜šžœžœž˜"šœ˜šžœžœžœ˜Jšœ1˜1Jšœ$˜$Jšœ˜Jšœ˜—šžœ˜Jšœ'˜'Jšœ˜Jšœ˜—Jšœ#˜#Jšœ˜—Jšžœ'˜.——Jšžœ'˜.—Jšžœ˜—JšœŸ ˜—J˜š œžœžœ žœžœ˜IJšžœ$˜*Jšœ˜Jš žœžœžœžœžœžœ˜NJšŸ˜JšœŸ˜—J˜šœžœ"˜4JšŸ»™»J˜Jšœ˜J˜Jšœžœžœžœ˜OJšžœžœžœžœ˜Jšœ˜Jš žœ žœžœžœžœ˜Bšžœ žœž˜šžœ žœž˜Jšœ(˜(Jšœ*˜*Jšœ(˜(Jšœ)˜)Jšœ-˜-Jšž˜——šž˜šžœžœž˜šœ˜Jšžœ žœžœ˜P—Jšžœ˜%——JšœŸ˜—J˜šœžœ1˜CJšŸf™fJ˜Jšœ#˜#šžœ žœž˜šžœž˜ Jšœžœ ˜Jšžœ˜——JšœŸ˜—J˜šœžœžœ%žœ˜FJšœ˜Jšœ%˜%JšœŸ˜—J˜šœžœ<˜QJšŸΝ™Νšžœžœž˜Jšœ,˜,Jšœ&˜&Jšœ˜Jšœ"˜"Jšžœ˜—JšœŸ˜—J˜šœžœ*˜5šžœ%žœžœž˜7Jšœ˜Jšžœ˜—JšœŸ ˜ —J˜šœžœ'žœ˜VJšœžœ˜1Jšœžœ ˜Jšœžœ˜/J˜Jšœ˜Jšœ@˜@Jšœ ˜ Jšœ˜Jšœžœ)˜/šžœ6žœžœž˜IJšžœžœ"˜?Jšžœ˜—Jšœ˜Jšœ$˜$JšœŸ˜J˜—J˜šœžœ<˜RJšœžœ˜ Jšœ˜Jšœ˜Jšœžœžœ˜J˜šžœžœž˜"šœ˜Jšœ!˜!Jšœ˜Jšœ˜Jšœ˜Jšœ˜—šœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšžœ#˜*—J˜šžœ žœžœ˜Jšœžœ˜3Jšœžœ˜"šžœžœž˜#Jšžœžœžœ(˜FJšœ(˜(Jšžœ˜—Jšœ˜—J˜Jšœ ˜ Jš žœ!žœžœžœžœ˜MJšœžœ˜)Jšœžœ˜#Jšœ#˜#šœ%˜%JšœE™E—Jšœ$™$šžœ ž˜Jšœ˜Jšœ/˜/Jšœ˜Jšžœ˜—JšœŸ˜—J˜šœžœ<˜SJšœžœ˜7Jšœ%˜%Jšœ˜Jšœ˜J˜šžœžœž˜šœ˜Jšœ1˜1šœ žœ˜Jšœ$˜$Jšœžœ>˜GJšœ˜—Jšœ#˜'Jšœ)˜)Jšœ˜Jšœ˜—šœ˜Jšœ˜Jšœ˜Jšœžœ˜"Jšœ žœ:˜FJšœ˜Jšœ˜Jšœ&˜&Jšœ˜—Jšžœ'˜.—JšœŸ˜—J˜šœžœ žœ˜;šžœžœžœ˜Jšœ žœ:˜IJšžœžœžœ˜+Jšœ˜—Jšžœ%˜)JšœŸ˜—J˜šœžœ(˜;Jšžœžœ˜ Jšœ˜Jšœ"˜"Jšœžœ˜7Jšœ žœ˜J˜šΟnœžœžœžœ˜Gšžœžœ) ˜;Jšžœž˜0Jšœžœžœžœ"˜8—Jš žœ žœžœžœ˜8š žœžœ,žœžœž˜LJšœ žœžœ˜Jšœ˜Jšœ%˜%šžœ˜2JšžœžœI˜SJšžœžœ0˜MJšžœ%˜9Jšžœž˜2šžœ˜JšœH˜HJšžœžœ˜ Jšœ˜——Jšžœ˜—Jšžœžœ˜Jšœ˜J˜—Jšœ5˜5Jšœ(˜(Jšœ˜Jšœ(˜(Jšœ˜šžœžœž˜Jšœžœ/˜Išžœ˜ šžœžœž˜-šœ˜Jšœ+˜+Jšžœžœžœ˜-Jšœ˜—Jšžœžœ˜———J˜šžœžœ˜šžœž˜ Jšœžœ˜,šœ ˜ Jšžœ$žœžœ˜2šœ žœ˜Jšœžœ@˜J—Jšœ ˜ Jšœ˜—šœ ˜ šœ žœ˜Jšœžœ>˜H—Jšœ˜Jšœ˜—šœ ˜ šœ žœ˜Jšœžœ<˜F—Jšœ˜Jšœ˜—šœ ˜ Jšžœ"žœžœ˜0šœ žœ˜Jšœžœ<˜F—Jšœ˜Jšœ˜—Jšžœ'˜.—Jšœ˜Jšœ0˜0Jšœ˜Jšœ˜Jšœ˜Jšœ˜šžœžœž˜"Jšœ/˜/—Jšœžœ˜!Jšœžœ˜"Jšœ˜—JšœŸ˜—J˜šœ žœ4˜AJšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœžœ˜/J˜Jšžœžœžœ ˜&šžœ-žœ žœž˜Dšžœžœž˜ šœ˜šœžœ˜&Jšœ˜Jšœ˜Jšœ˜—Jšœ(˜(Jšœ˜—Jšžœ˜—Jšžœ˜—J˜šžœ-žœ žœž˜Dšžœ˜JšœA˜AJšžœ˜Jšœ˜—šžœžœž˜ šœ˜Jšœ3˜3šœ žœ˜Jšœ$˜$šœžœ ˜Jšœn˜n—Jšœ˜—Jšœ#˜#Jšœ,˜,šžœ+žœ˜3šžœ2žœžœ8˜wJšœ"˜"šžœžœž˜$Jšœžœžœžœ˜5—Jšœžœ'˜HJ˜—J˜—Jšžœ˜Jšœ˜Jšœ)˜)Jšœ˜—Jšžœ˜—Jšžœ˜J˜—šžœ-žœ žœž˜Dšžœ˜JšœA˜AJšžœ˜Jšœ˜—šžœžœž˜ šœ˜Jšœ%˜%šžœžœžœ˜Jšœ$˜$Jšœ˜Jšœ˜Jšœ˜—Jšœ˜—šœ˜Jšœ*˜*Jšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšžœ˜—Jšžœ˜—JšœŸ ˜ —J˜š‘œžœ9˜RJšžœ žœžœ˜#JšœO™OJšœžœžœ˜ šžœ3žœžœ˜?šœ,˜,Jšžœžœ ˜-—Jšžœ!žœžœžœ˜6Jšœ˜—šžœ;žœžœ˜Gšœ<˜šžœžœžœž˜*Jšžœ%žœžœ ˜:Jšžœ˜—šžœ žœž˜šœ˜šžœ žœž˜šœ˜Jšžœžœžœ ˜3—Jšžœžœ ˜——Jšžœžœ ˜J˜—šžœ žœžœ(˜AJ˜Jšœ'˜'Jšœ"˜"J˜—Jšžœ ˜J˜—Jšžœžœ˜—Jšžœ ž˜Jšœ˜—Jšœ˜Jšžœ˜—Jšœ#˜&J˜—šœ žœ-žœžœ˜QJšžœ"žœ ˜8JšœŸ ˜—J˜š ‘ œžœ žœžœžœžœ˜?Jšœžœ˜!Jšœ žœ žœžœ #˜Ošžœž˜ šžœžœžœž˜'Jšœ˜Jš œ žœ žœžœ žœžœ ˜@Jšžœžœžœ˜Jšžœ˜——JšœŸ˜—J˜šœ žœ)žœžœ˜EJšžœ žœžœ˜šžœžœžœžœ˜.Jšœ žœ˜#Jšœ0˜0Jšžœžœžœ˜PJšœ˜—šžœžœžœžœ˜Jšœžœ ˜(Jšœžœ˜J˜—JšœŸ ˜—J˜šœ žœ)žœžœ˜EJšžœ žœžœ˜Jšœ žœ˜#šœ1˜1Jšžœžœžœžœ˜FJšœ˜—šžœžœžœ˜Jšœžœ ˜(Jšœžœ˜J˜—JšœŸ ˜—J˜šœ žœ+žœžœ˜HJšžœ žœžœ˜Jšœ žœ˜%šœ1˜1Jšžœžœžœžœ˜FJšœ˜—šžœžœžœ˜Jšœžœ ˜(Jšœžœ˜J˜—JšœŸ˜—J˜š œžœžœ/žœžœ˜SJšžœžœ8˜Mšžœžœž˜Jšžœžœ˜#Jšžœžœ˜%Jšœ˜—JšœŸ˜—J˜šœžœ$˜?Jšžœžœžœžœ˜Gšžœ˜Jš œžœžœ$žœžœžœžœ˜tJš œžœžœžœžœžœžœ˜NJšœ(˜(Jšœ!žœžœ˜MJšœ˜—JšœŸ˜J˜—šœžœ ˜6šžœ2žœžœž˜CJšœ žœ˜#Jšœ+˜+Jšœžœ˜6Jš œžœžœžœ žœ˜CJšžœ˜—JšœŸ˜—J˜šœ žœžœ˜)Jšœ&˜&šžœ.žœžœž˜?Jšœžœ˜Jšœ˜šžœ2žœžœž˜GJšœ&žœ˜,Jšžœžœ˜9Jšžœ˜ Jšžœžœžœ˜9Jšžœ˜—Jšœ˜Jšžœ˜—JšœŸ ˜—J˜š œžœ$žœ žœžœ˜^šžœžœ˜Jšœ˜šžœžœžœž˜+JšžœFžœžœ˜RJšžœ˜—šžœžœžœ˜Jšœ ˜ Jšžœžœ ˜+Jšžœžœ˜Jšœ˜Jšœ˜—šžœ˜šžœžœžœž˜0JšžœFžœžœ˜RJšžœ˜—š žœžœžœžœ%žœžœž˜DJšžœHžœžœ˜TJšžœ˜—Jšœ ˜ Jšœ˜—Jšœ˜—Jšžœžœ˜JšœŸ ˜ —J˜šœžœžœžœ˜RJšœ-˜-Jšœ˜—J˜šœžœ˜*šžœ6žœžœž˜Kšžœ6žœžœž˜KJšœžœ žœžœ˜RJšžœ˜—Jšžœ˜—JšœŸ˜—J˜šœžœžœ˜$Jšœžœ˜CJšœžœ˜,Jšœ!˜!Jšœ#˜#Jšœ;˜;Jšœ.˜.Jšœ#˜#Jšœ(˜(Jšœ˜J˜šœ˜JšœD˜DJšžœ˜Jšžœ˜Jšžœ˜Jšžœ˜!—J˜šžœžœžœ˜'Jšœ)˜)Jšœ2˜2J˜—JšœŸ˜ —J˜Jšžœ˜šžœžœ˜ Jšœž˜ Jšœž˜Jšœžœ#˜CJšœžœ ˜.Jšœ$žœ˜(Jšœžœ˜0J˜——…—Nbp&