<Cedar5.2>System>spInput.mesa>> <> DIRECTORY IO USING [PutF, real, rope, STREAM], Real USING [FixC], RefText USING [Append, New], Rope USING [Cat, Equal, ROPE], RopeFrom USING [String], spGlobals USING [Aborted, argList, argNames, assignExpr, BranchRec, Canned, CircuitRec, CktInstance, conLink, conLinkPtr, ConRec, elements, error, ErrorSignal, ErrorStrings, eval, expression, expressionPtr, findFunction, findModel, function, FuncTableBlk, FunctionRec, Handle, keys, ModelRec, ModelTableBlk, nameBlk, namePtr, namePtrSeq, next, NodeRec, ParmRec, RefBranchRec, RefCircuitRec, RefCktInstRec, RefConRec, RefFunctionRec, RefModelRec, RefNodeRec, RefParmRec, searchKey, ValueSeq]; spInput: CEDAR PROGRAM IMPORTS IO, Real, RefText, Rope, RopeFrom, spGlobals EXPORTS spGlobals= BEGIN OPEN spGlobals; enterName: PROC[handle: Handle] RETURNS[newCktNames: namePtr_ NIL]= { <> OPEN handle.vars; IF searchName[newString, oneLevel, currentCkt]=NIL THEN { curCktDetails: RefCircuitRec_ NARROW[currentCkt.details]; newCktNames_ NEW[nameBlk_ [srchLink: curCktDetails.names, name: RopeFrom.String[newString]]]; curCktDetails.names_ newCktNames; } ELSE error[handle, 250]; }; -- enterName searchName: PROC[nameString: REF TEXT, -- usually newString level: {oneLevel, allLevels}_ oneLevel, oldCktNames: namePtr] -- usually currentCkt RETURNS[newCktNames: namePtr_ NIL]= { lastNamePtr: namePtr; oldDetails: RefCircuitRec; nameRope: Rope.ROPE_ RopeFrom.String[nameString]; UNTIL oldCktNames=NIL DO oldDetails_ NARROW[oldCktNames.details]; newCktNames_ oldDetails.names; lastNamePtr_ NIL; UNTIL newCktNames=NIL DO IF Rope.Equal[nameRope, newCktNames.name] THEN GOTO found; lastNamePtr_ newCktNames; newCktNames_ newCktNames.srchLink; ENDLOOP; IF level=oneLevel THEN EXIT; oldCktNames_ oldDetails.father; REPEAT found => IF lastNamePtr # NIL THEN { lastNamePtr.srchLink_ newCktNames.srchLink; newCktNames.srchLink_ oldDetails.names; oldDetails.names_ newCktNames; }; ENDLOOP; }; -- searchName getNames: PROC[handle: Handle] RETURNS[names: namePtr_ NIL, nameCount: NAT_ 0]= { <> nPtr: namePtr; UNTIL handle.vars.item # name DO nPtr_ enterName[handle]; IF nPtr # NIL THEN { -- usually not nil nPtr.nextName_ names; names_ nPtr; }; nameCount_ nameCount + 1; next[handle]; IF handle.vars.item # comma THEN EXIT ELSE next[handle]; IF handle.vars.item # name THEN error[handle, 208] ENDLOOP }; -- getNames getName: PROC[handle: Handle] RETURNS[nPtr: namePtr_ NIL]= { OPEN handle.vars; IF item # name THEN error[handle, 208] ELSE nPtr_ searchName[newString, allLevels, currentCkt]; IF nPtr=NIL THEN error[handle, 251]; next[handle]; }; -- getName variable: PUBLIC PROC[handle: Handle, string: REF TEXT, -- often newString context: namePtr] RETURNS[nPtr: namePtr_ NIL]= { nPtr_ IF context # NIL THEN searchName[string, oneLevel, context] ELSE searchName[string, allLevels, handle.vars.currentCkt]; IF nPtr=NIL THEN error[handle, 252] ELSE -- check if nPtr has an acceptable type WITH nPtr.details SELECT FROM x: RefParmRec => NULL; x: RefNodeRec => NULL; x: RefConRec => NULL; ENDCASE => error[handle, 221]; next[handle]; }; -- variable findNode: PROC[handle: Handle] RETURNS[n: namePtr]= { <> nPtr: namePtr_ getName[handle]; IF nPtr=NIL THEN RETURN[handle.vars.undefNode] ELSE WITH nPtr.details SELECT FROM x: RefNodeRec => n_ nPtr; x: RefConRec => n_ nPtr; ENDCASE => error[handle, 222]; }; -- findNode getFunction: PROC[handle: Handle, na, np: NAT] RETURNS[args: argNames_ NIL, actual: expressionPtr_ NIL]= { <> iArg, iParm: NAT_ 0; aname: namePtr; newExpr: expressionPtr; IF handle.vars.item=leftB THEN { next[handle]; <> IF na > 0 THEN { args_ NEW[namePtrSeq[na]]; args.visited _ FALSE; UNTIL iArg=na DO aname _ getName[handle]; args[iArg]_ aname; IF aname # NIL THEN WITH aname.details SELECT FROM x: RefNodeRec => NULL; x: RefConRec => NULL; ENDCASE => error[handle, 222]; IF handle.vars.item=quote THEN {next[handle]; error[handle, 299]}; iArg_ iArg + 1; IF handle.vars.item=comma THEN next[handle] ELSE EXIT; ENDLOOP; }; <> IF na=0 OR handle.vars.item=vertical THEN { IF handle.vars.item=vertical THEN next[handle]; UNTIL iParm=np DO newExpr_ expression[handle]; newExpr.next_ actual; actual_ newExpr; iParm_ iParm + 1; IF handle.vars.item=comma THEN next[handle] ELSE EXIT; ENDLOOP; }; IF handle.vars.item=rightB THEN next[handle] ELSE error[handle, 202, , TRUE]; }; IF iArg # na THEN error[handle, 231]; IF iParm # np THEN error[handle, 232]; }; -- getFunction controlFunc: PROC[handle: Handle, thisBranch: namePtr]= { nPtr, f: namePtr; na, np: NAT; bDetails: RefBranchRec_ NARROW[thisBranch.details]; next[handle]; IF handle.vars.item=name THEN { nPtr_ searchName[handle.vars.newString, allLevels, handle.vars.currentCkt]; IF nPtr=NIL THEN { fTableEntry: REF FuncTableBlk = findFunction[RopeFrom.String[handle.vars.newString]]; fDetails: RefFunctionRec_ NEW[FunctionRec_ [branch: thisBranch] ]; f_ NEW[nameBlk_ [details: fDetails]]; <> fDetails.functionProc _ fTableEntry.proc; fDetails.data _ fTableEntry.data; na _ fTableEntry.numArgs; np _ fTableEntry.numParms; IF fDetails.functionProc=NIL THEN error[handle, 502, FALSE]; next[handle]; bDetails.controller_ f; [fDetails.funcArgs, fDetails.funcParms]_ getFunction[handle, na, np]; fDetails.funcArgVec_ InitArgList[na]; } ELSE WITH nPtr.details SELECT FROM n: RefModelRec => { bDetails.controller_ nPtr; next[handle]; IF handle.vars.item=leftB THEN next[handle] ELSE error[handle, 201,, TRUE]; IF handle.vars.item=number THEN { bDetails.modelIndex_ Real.FixC[handle.vars.value]; IF n.modelResults=NIL THEN {-- unlikely, though IF handle.vars.value > 0 THEN error[handle, 233]} ELSE IF handle.vars.value >= n.modelResults.size THEN error[handle, 233]; next[handle]; } ELSE error[handle, 209]; IF handle.vars.item=rightB THEN next[handle] ELSE error[handle, 202,, TRUE]; }; ENDCASE => error[handle, 223]; } ELSE error[handle, 208]; }; -- controlFunc InitArgList: PROC[size: NAT] RETURNS [a: argList] = { a _ NEW[spGlobals.ValueSeq[size]]; a.visited _ FALSE; a.handle _ NIL; a.modFunc _ NIL; FOR i: NAT IN [0..size) DO a.value[i] _ 0.0; ENDLOOP; }; -- InitArgList enterBranches: PROC[handle: Handle, bName: namePtr, branchKey: keys]= { pNode, nNode: namePtr; bDetails: RefBranchRec; kind: elements; IF handle.vars.item=leftB THEN next[handle] ELSE error[handle, 201,, TRUE]; pNode_ findNode[handle]; IF handle.vars.item=comma THEN next[handle] ELSE error[handle, 200,, TRUE]; nNode_ findNode[handle]; IF handle.vars.item=rightB THEN next[handle] ELSE error[handle, 202,, TRUE]; kind_ SELECT branchKey FROM resKey => resistor, capKey => capacitor, indKey => inductor, vsKey => vSource, isKey => iSource, ENDCASE => nullElement; IF kind=nullElement THEN error[handle, 224, TRUE]; IF pNode=nNode THEN error[handle, 241]; IF bName # NIL THEN -- else error! ... bName.details_ bDetails_ NEW[BranchRec_ [branchType: kind, posNode: pNode, negNode: nNode ] ]; IF handle.vars.item=equal THEN { next[handle]; bDetails.valExpr_ expression[handle]; } ELSE IF handle.vars.item=leftArrow THEN controlFunc[handle, bName] ELSE error[handle, 205]; }; -- enterBranches enterModel: PROC[handle: Handle, mName: namePtr]= { na, np, nr: NAT; IF handle.vars.item=leftArrow THEN next[handle] ELSE error[handle, 210]; IF handle.vars.item=name THEN { mTableEntry: REF ModelTableBlk = findModel[RopeFrom.String[handle.vars.newString]]; mDetails: RefModelRec_ NEW[ModelRec_ []]; mDetails.modelProc _ mTableEntry.proc; mDetails.data _ mTableEntry.data; na _ mTableEntry.numArgs; np _ mTableEntry.numParms; nr _ mTableEntry.numResults; IF mDetails.modelProc=NIL THEN error[handle, 501, FALSE]; next[handle]; [mDetails.modelArgs, mDetails.modelParms]_ getFunction[handle, na, np]; mDetails.modelResults_ InitArgList[nr]; mDetails.modelArgVec _ InitArgList[na]; mDetails.modelOldArgVec _ InitArgList[na]; mName.details_ mDetails; } ELSE error[handle, 208]; }; -- enterModel GetCircuitTree: PROC[ckt: namePtr] RETURNS[r: Rope.ROPE]= { GetTree: PROC[c: namePtr]= { cktDetail: RefCircuitRec_ NARROW[c.details]; IF c # NIL AND cktDetail # NIL AND cktDetail.father # NIL THEN { GetTree[cktDetail.father]; r_ Rope.Cat[r, c.name, "."]; }; }; -- GetTree GetTree[ckt]; }; -- GetCircuitTree getNewParameters: PROC[handle: Handle] RETURNS[plist: namePtr_ NIL]= { n: namePtr; nparms: NAT_ 0; IF handle.vars.item=vertical THEN next[handle]; UNTIL handle.vars.item # name DO n_ enterName[handle]; next[handle]; nparms_ nparms + 1; n.details_ NEW[ParmRec_ [nextParm: plist]]; IF handle.vars.item=leftArrow THEN { ENABLE ErrorSignal => { ErrorStrings[handle, error, GetCircuitTree[handle.vars.currentCkt], s]; CONTINUE; -- GOTO badEnd }; nDetails: RefParmRec _ NARROW[n.details]; next[handle]; nDetails.default _ TRUE; nDetails.dfltValue _ eval[handle, expression[handle]]; }; plist_ n; IF handle.vars.item=comma THEN next[handle] ELSE EXIT; IF handle.vars.item # name THEN error[handle, 208] ENDLOOP; }; -- getNewParameters defineCircuit: PUBLIC PROC[handle: Handle, ckt: namePtr, root: BOOL]= { OPEN handle.vars; exp: expressionPtr; curCktDetails: RefCircuitRec_ NEW[CircuitRec_ [father: currentCkt]]; IF Canned[handle] THEN SIGNAL Aborted; ckt.details_ curCktDetails; currentCkt_ ckt; IF root AND cktRoot=NIL THEN { cktRoot_ currentCkt; undefNode_ NEW[nameBlk_ [name: "Undefined", details: NEW[NodeRec] ] ]; gndNodeName_ NEW[nameBlk_ [name: "Gnd", details: NEW[NodeRec] ] ]; curCktDetails.names_ gndNodeName; next[handle]; }; IF item=leftB THEN { next[handle]; IF ~root AND item # vertical THEN { <> fakes: namePtr; [fakes, curCktDetails.conCount]_ getNames[handle]; curCktDetails.fakeNodes_ fakes; FOR fn: namePtr_ fakes, fn.nextName UNTIL fn=NIL DO fn.details_ NEW[ConRec]; ENDLOOP; }; IF root OR item=vertical THEN curCktDetails.parms_ getNewParameters[handle]; IF item=rightB THEN next[handle] ELSE error[handle, 202,, TRUE]; }; IF item=name AND searchKey[handle]=assertsKey THEN { next[handle]; IF item=leftB THEN { next[handle]; DO exp_ expression[handle]; exp.next_ curCktDetails.assertions; curCktDetails.assertions_ exp; IF item=comma THEN next[handle] ELSE EXIT; ENDLOOP; IF item=rightB THEN next[handle] ELSE error[handle, 202,, TRUE]; } ELSE error[handle, 201]; }; IF item=equal THEN next[handle] ELSE error[handle, 205, TRUE, TRUE]; IF item=leftC THEN next[handle] ELSE error[handle, 203, TRUE, FALSE]; DO IF item=name THEN enterDefinition[handle]; IF item=rightC OR item= eof THEN EXIT; IF item=semi THEN next[handle] ELSE error[handle, 206, TRUE, FALSE]; ENDLOOP; curCktDetails_ NARROW[currentCkt.details]; currentCkt_ curCktDetails.father; next[handle]; }; -- defineCircuit getActualParameters: PROC[handle: Handle, ckt: namePtr] RETURNS[apList: expressionPtr_ NIL]= { e: expressionPtr; IF handle.vars.item=vertical THEN next[handle]; IF handle.vars.item=rightB THEN RETURN; DO IF handle.vars.item # name THEN GOTO nameErr; e_ assignExpr[handle, ckt]; e.next_ apList; apList_ e; IF handle.vars.item=comma THEN next[handle] ELSE EXIT; REPEAT nameErr => error[handle, 208]; ENDLOOP; }; -- getActualParameters defCktInstance: PROC[handle: Handle, cn: REF TEXT, iName: namePtr]= { cktName: namePtr; n: namePtr; cons: conLinkPtr_ NIL; cCnt: NAT_ 0; noConnections: BOOL; actuals: expressionPtr_ NIL; cktName_ searchName[cn, allLevels, handle.vars.currentCkt]; IF cktName # NIL THEN WITH cktName.details SELECT FROM c: RefCircuitRec => { IF handle.vars.item=leftB THEN { next[handle]; noConnections_ (c.conCount=0); IF ~noConnections THEN WHILE handle.vars.item=name DO n_ findNode[handle]; cons_ NEW[conLink_ [nextLink: cons, namedNode: n]]; cCnt_ cCnt + 1; IF handle.vars.item=comma THEN next[handle] ELSE EXIT; ENDLOOP; IF noConnections OR handle.vars.item=vertical THEN actuals_ getActualParameters[handle, cktName]; IF handle.vars.item=rightB THEN next[handle] ELSE error[handle, 202,, TRUE]; }; IF cCnt # c.conCount THEN error[handle, 260]; iName.details_ NEW[CktInstance_ [of: cktName, connections: cons, actualParms: actuals] ]; }; ENDCASE => error[handle, 225, TRUE] ELSE error[handle, 251, TRUE]; }; -- defCktInstance enterDefinition: PROC[handle: Handle]= { key: keys; nameCount: NAT; nPtr: namePtr; s: REF TEXT_ RefText.New[256]; explodeExpr: expressionPtr_ NIL; [nPtr, nameCount]_ getNames[handle]; IF nPtr=NIL THEN error[handle, 208]; IF handle.vars.item # colon THEN error[handle, 207,, TRUE] ELSE next[handle]; IF handle.vars.item=leftP THEN { explodeExpr_ expression[handle]; IF nPtr # NIL THEN nPtr.expExpr_ explodeExpr; IF handle.vars.item=implies THEN next[handle] ELSE error[handle, 215,, TRUE]; }; IF handle.vars.item=name THEN { key_ searchKey[handle]; s.length_ 0; s_ RefText.Append[s, handle.vars.newString]; next[handle]; IF key # nodeKey AND nameCount # 1 THEN error[handle, 261]; SELECT key FROM nodeKey => { IF nPtr.expExpr # NIL THEN error[handle, 253]; UNTIL nPtr=NIL DO nPtr.details_ NEW[NodeRec]; nPtr_ nPtr.nextName; ENDLOOP; }; resKey, capKey, indKey, vsKey, isKey => enterBranches[handle, nPtr, key]; circuitKey => { IF nPtr.expExpr # NIL THEN error[handle, 253]; defineCircuit[handle: handle, ckt: nPtr, root: FALSE]; }; modelKey => { IF nPtr.expExpr # NIL THEN error[handle, 253]; enterModel[handle, nPtr]; }; ENDCASE => defCktInstance[handle, s, nPtr]; } ELSE error[handle, 208, TRUE] }; -- enterDefinition levelSpace: PROC[stream: IO.STREAM, level: NAT]= { UNTIL level=0 DO stream.PutF[" "]; level_ level - 1 ENDLOOP }; -- levelSpace output: PUBLIC PROC[handle: Handle, ckt: namePtr, level: NAT]= { cLink: conLinkPtr; np: namePtr; cktDetails: RefCircuitRec_ NARROW[ckt.details]; np_ cktDetails.names; UNTIL np=NIL DO levelSpace[handle.msgStream, level]; handle.msgStream.PutF["%g", IO.rope[np.name]]; WITH np.details SELECT FROM n: RefNodeRec => NULL; n: RefBranchRec => handle.msgStream.PutF[": branch[%s, %s]", IO.rope[n.posNode.name], IO.rope[n.negNode.name]]; n: RefCircuitRec => { handle.msgStream.PutF[": circuit.\n"]; output[handle, np, level + 1]; }; n: RefConRec => NULL; n: RefParmRec => { handle.msgStream.PutF[": parameter"]; IF n.default THEN handle.msgStream.PutF["_ %13.5f", IO.real[n.dfltValue]]; }; n: RefCktInstRec => { handle.msgStream.PutF[": %g[", IO.rope[n.of.name]]; cLink_ n.connections; UNTIL cLink=NIL DO handle.msgStream.PutF["%g", IO.rope[cLink.namedNode.name]]; cLink_ cLink.nextLink; IF cLink # NIL THEN handle.msgStream.PutF[", "] ENDLOOP; handle.msgStream.PutF["]"] }; ENDCASE; np_ np.srchLink; handle.msgStream.PutF[".\n"]; ENDLOOP; }; -- output END. <> <> <> <> <> <<>>