<System>Cedar5.1>spBomb.mesa>> <> <<>> DIRECTORY IO USING [int, PutF, rope], Rope USING [Cat, Concat, Equal, Fetch, Length, ROPE], RopeFrom USING [String], spGlobals USING[Aborted, argNames, branch, branchLink, branchLinkPtr, branchPtr, Canned, CapacitorBody, conLinkPtr, error, error2, ErrorSignal, ErrorStrings, eval, expressionPtr, FunctionBody, Handle, InductorBody, instTreeNode, instTreePtr, ISourceBody, modBrPtr, 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]; spBomb: CEDAR PROGRAM IMPORTS IO, Rope, RopeFrom, spGlobals EXPORTS spGlobals= BEGIN OPEN spGlobals; pushCopies: PROC[nameList: namePtr]= { <> <> r: realThingPtr; WHILE nameList # NIL DO WITH nameList.details SELECT FROM x: RefCircuitRec => r_ NIL; x: RefCktInstRec => r_ NIL; x: RefFunctionRec => r_ NIL; p: RefParmRec => r_ NEW[realThing_ [ nextThing: nameList.realCopy, thing: IF p.default THEN NEW[RealParm_ [rp: p.dfltValue]] ELSE refUnReal] ]; ENDCASE => r_ NEW[realThing_ [nextThing: nameList.realCopy, thing: refUnReal] ]; nameList.realCopy_ r; nameList_ nameList.srchLink; ENDLOOP; }; -- pushCopies advanceLevel: PROC[nameList: namePtr]= { <> UNTIL nameList=NIL DO IF nameList.realCopy # NIL THEN nameList.realCopy.newLevel_ FALSE; nameList_ nameList.srchLink; ENDLOOP; }; -- advanceLevel popCopies: PROC[handle: Handle, nameList: namePtr]= { <> WHILE nameList # NIL DO WITH nameList.details SELECT FROM x: RefCircuitRec => NULL; x: RefCktInstRec => NULL; x: RefFunctionRec => NULL; n: RefNodeRec => WITH nameList.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; }; nameList.realCopy_ nameList.realCopy.nextThing; }; ENDCASE => nameList.realCopy_ nameList.realCopy.nextThing; ENDCASE => nameList.realCopy_ nameList.realCopy.nextThing; nameList_ nameList.srchLink; ENDLOOP; }; -- popCopies getParmValue: PUBLIC PROC[handle: Handle, nPtr: namePtr] RETURNS[REAL]= { ENABLE ErrorSignal => ErrorSignal[331, s]; getRealThing[handle, nPtr]; IF handle.vars.n # NIL THEN RETURN[LOOPHOLE[handle.vars.n]] ELSE RETURN[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 AND 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 nPtr.realCopy # NIL THEN SELECT t FROM realNode => rCopy.thing_ NEW[RealNode_ [handle.vars.n]]; realBranch => rCopy.thing_ NEW[RealBranch_ [handle.vars.b]]; realParm => rCopy.thing_ NEW[RealParm_ [handle.vars.p]]; realModel => rCopy.thing_ NEW[RealModel_ [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]= { UNTIL apList=NIL DO []_ eval[handle, apList]; apList_ apList.next; ENDLOOP; }; -- apply explodeInstance: PROC[handle: Handle, instNamePtr: namePtr] RETURNS[t: instTreePtr]= { exp: expressionPtr; 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] ]; exp_ cktDetails.assertions; UNTIL exp=NIL DO IF eval[handle, exp]=0.0 THEN error2[handle, 341, instNamePtr]; exp_ exp.next; ENDLOOP; explode[handle, ckt, t]; popCopies[handle, cktDetails.names]; }; -- explodeInstance explodeModelFunc: PROC[handle: Handle, mfNamePtr: namePtr, newFunc: modFuncPtr]= { index: NAT; arguments: argNames; parms, p: expressionPtr; WITH mfNamePtr.details SELECT FROM m: RefModelRec => { newFunc.argVector_ m.modelArgVec; arguments_ m.modelArgs; parms_ m.modelParms; }; f: RefFunctionRec => { newFunc.argVector_ f.funcArgVec; arguments_ f.funcArgs; parms_ f.funcParms; }; ENDCASE => error2[handle, 399, mfNamePtr]; IF arguments # NIL THEN { newFunc.arguments_ NEW[nodePtrSeq[arguments.size]]; -- initialize each argument 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_ parms, p.next UNTIL p=NIL DO index_ index + 1; ENDLOOP; newFunc.parmVector_ NEW[ValueSeq[index]]; -- initialize each parameter of 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]= { newLink: branchLinkPtr; IF n # NIL THEN { newLink_ NEW[branchLink_ [nextLink: n.branches, branch: b, pos: pos]]; n.branches_ newLink; 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]; handle.vars.branchCount_ handle.vars.branchCount + 1; getRealThing[handle, brDetails.posNode]; pNode_ handle.vars.n; getRealThing[handle, brDetails.negNode]; nNode_ handle.vars.n; IF pNode # nNode THEN { SELECT brDetails.branchType FROM resistor => newB_ NEW[branch_ [body: refR]]; capacitor=> { 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 => { 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; connectBranch[pNode, newB, TRUE]; connectBranch[nNode, newB, FALSE]; IF brDetails.controller # NIL THEN explodeController[handle, branchNamePtr, newB] ELSE newB.comVal_ eval[handle, brDetails.valExpr]; }; }; -- explodeBranch explode: PROC[handle: Handle, ckt: namePtr, tree: instTreePtr]= { curName: namePtr; newNode: nodePtr_ NIL; newModel: modFuncPtr; newB: branchPtr; newTree: instTreePtr; cktDetails: RefCircuitRec_ NARROW[ckt.details]; IF Canned[handle] THEN SIGNAL Aborted; curName_ cktDetails.names; UNTIL curName=NIL DO WITH curName.details SELECT FROM cn: RefNodeRec => { newNode_ NEW[node_ [ nodeName: curName, treeLevel: tree, brotherNodes: tree.nodes] ]; tree.nodes_ newNode; handle.vars.n_ newNode; putRealThing[handle, curName, realNode]; }; ENDCASE; curName_ curName.srchLink; ENDLOOP; curName_ cktDetails.names; UNTIL curName=NIL DO ENABLE ErrorSignal => { ErrorStrings[handle, error, treeError[handle, tree, curName], s]; curName_ curName.srchLink; LOOP; }; WITH curName.details SELECT FROM cn: RefModelRec => { handle.vars.modelCount_ handle.vars.modelCount + 1; newModel_ NEW[modFuncBlk_ [ nextMFPtr: handle.vars.functionList, body: NEW[ModelBody_ [modelProc: cn.modelProc, modelResults: cn.modelResults, modelName: curName, oldArgVector: cn.modelOldArgVec]] ]]; handle.vars.functionList_ newModel; explodeModelFunc[handle, curName, newModel]; handle.vars.m_ newModel; putRealThing[handle, curName, realModel]; }; ENDCASE; curName_ curName.srchLink; ENDLOOP; curName_ cktDetails.names; UNTIL curName=NIL DO ENABLE ErrorSignal => { ErrorStrings[handle, error, treeError[handle, tree, curName], s]; curName_ curName.srchLink; LOOP; }; IF curName.expExpr=NIL OR eval[handle, curName.expExpr] # 0.0 THEN WITH curName.details SELECT FROM cn: RefBranchRec => { newB_ explodeBranch[handle, curName]; IF newB # NIL THEN { newB.brotherBranches_ tree.branches; newB.treeLevel_ tree; tree.branches_ newB; }; }; cn: RefCktInstRec => { newTree_ explodeInstance[handle, curName]; newTree.father_ tree; newTree.brothers_ tree.sons; tree.sons_ newTree; }; ENDCASE; curName_ curName.srchLink; ENDLOOP; }; -- explode 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 toRope THEN RETURN ELSE { 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 toRope THEN RETURN ELSE { 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]= { n: nodePtr; bLink: branchLinkPtr; handle.msgStream.PutF["\nNodes --\n"]; n_ handle.vars.nodeList; UNTIL n=NIL DO []_ printNode[handle, n, TRUE]; handle.msgStream.PutF["_ {"]; bLink_ n.branches; UNTIL bLink=NIL DO []_ printBranch[handle, bLink.branch, TRUE]; IF bLink.branch.posNode=n THEN handle.msgStream.PutF["+"] ELSE handle.msgStream.PutF["-"]; bLink_ bLink.nextLink; IF bLink # NIL THEN handle.msgStream.PutF[", "]; ENDLOOP; handle.msgStream.PutF["}.\n"]; n_ n.nextNode; ENDLOOP; }; -- printHole findNB: PROC[handle: Handle, tree: instTreePtr] RETURNS[n: nodePtr_ NIL, b: branchPtr_ NIL]= { i: instTreePtr; IF handle.vars.item=name THEN { i_ tree.sons; UNTIL i=NIL DO IF Rope.Equal[i.instance.name, RopeFrom.String[handle.vars.newString]] THEN EXIT; i_ i.brothers; 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 { n_ tree.nodes; UNTIL n=NIL DO IF Rope.Equal[n.nodeName.name, RopeFrom.String[handle.vars.newString]] THEN EXIT; n_ n.brotherNodes; ENDLOOP; IF n=NIL THEN { b_ tree.branches; UNTIL b=NIL DO IF Rope.Equal[b.branchName.name, RopeFrom.String[handle.vars.newString]] THEN EXIT; b_ b.brotherBranches; 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]= { nodes: nodePtr_ handle.vars.nodeList; links: branchLinkPtr; UNTIL nodes=NIL DO links_ nodes.branches; UNTIL links=NIL DO links.otherNode_ IF links.pos THEN links.branch.negNode ELSE links.branch.posNode; links_ links.nextLink; ENDLOOP; nodes_ nodes.nextNode; 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 <> <> <> <>