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, FunctionRec, Handle, keys, ModelRec, 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]= { -- enter a (one level unique) name string to the search link of currentCkt 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]= { -- enter (unique) name strings on the current circuits search link 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]= { -- search RefNodeRec or RefConRec with name newString on all levels of currentCkt 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]= { -- get na arguments and np parameters(expressions) iArg, iParm: NAT_ 0; aname: namePtr; newExpr: expressionPtr; IF handle.vars.item=leftB THEN { next[handle]; -- arguments IF na > 0 THEN { args_ NEW[namePtrSeq[na]]; 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; }; -- parameters 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: namePtr; 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 { fDetails: RefFunctionRec_ NEW[FunctionRec_ [branch: thisBranch] ]; f_ NEW[nameBlk_ [details: fDetails]]; -- get values for other fields in f.details, and assign f as the controller for this branch: [fDetails.functionProc, na, np]_ findFunction[RopeFrom.String[handle.vars.newString]]; IF fDetails.functionProc=NIL THEN error[handle, 502, FALSE]; next[handle]; bDetails.controller_ f; [fDetails.funcArgs, fDetails.funcParms]_ getFunction[handle, na, np]; fDetails.funcArgVec_ NEW[ValueSeq[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 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 { mDetails: RefModelRec_ NEW[ModelRec_ []]; [mDetails.modelProc, na, np, nr]_ findModel[RopeFrom.String[handle.vars.newString]]; IF mDetails.modelProc=NIL THEN error[handle, 501, FALSE]; next[handle]; [mDetails.modelArgs, mDetails.modelParms]_ getFunction[handle, na, np]; mDetails.modelResults_ NEW[spGlobals.ValueSeq[nr]]; mDetails.modelArgVec _ NEW[spGlobals.ValueSeq[na]]; mDetails.modelOldArgVec _ NEW[spGlobals.ValueSeq[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; IF handle.vars.item=leftArrow THEN { ENABLE ErrorSignal => { ErrorStrings[handle, error, GetCircuitTree[handle.vars.currentCkt], s]; n.details_ NEW[ParmRec_ [nextParm: plist]]; GOTO badEnd; }; next[handle]; n.details_ NEW[ParmRec_ [default: TRUE, dfltValue: eval[handle, expression[handle]], nextParm: plist ] ]; EXITS badEnd => NULL; } ELSE n.details_ NEW[ParmRec_ [nextParm: plist]]; 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 { -- enter (uniquie) names on currentCkt [ckt, curCktDetails.conCount]_ getNames[handle]; curCktDetails.fakeNodes_ ckt; UNTIL ckt=NIL DO ckt.details_ NEW[ConRec]; ckt_ ckt.nextName; 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 IO.PutF[stream, " "]; 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]; IO.PutF[handle.msgStream, "%g", IO.rope[np.name]]; WITH np.details SELECT FROM n: RefNodeRec => NULL; n: RefBranchRec => IO.PutF[handle.msgStream, ": branch[%s, %s]", IO.rope[n.posNode.name], IO.rope[n.negNode.name]]; n: RefCircuitRec => { IO.PutF[handle.msgStream, ": circuit.\n"]; output[handle, np, level + 1]; }; n: RefConRec => NULL; n: RefParmRec => { IO.PutF[handle.msgStream, ": parameter"]; IF n.default THEN IO.PutF[handle.msgStream, "_ %13.5f", IO.real[n.dfltValue]] }; n: RefCktInstRec => { IO.PutF[handle.msgStream, ": %g[", IO.rope[n.of.name]]; cLink_ n.connections; UNTIL cLink=NIL DO IO.PutF[handle.msgStream, "%g", IO.rope[cLink.namedNode.name]]; cLink_ cLink.nextLink; IF cLink # NIL THEN IO.PutF[handle.msgStream, ", "] ENDLOOP; IO.PutF[handle.msgStream, "]"] }; ENDCASE; np_ np.srchLink; IO.PutF[handle.msgStream, ".\n"]; ENDLOOP; }; -- output END. "File: [Cherry]Cedar5.2>System>spInput.mesa Last Edited by: SChen, September 6, 1984 3:11:03 pm PDT CHANGE LOG Wilhelm April 6, 1982 9:59 AM Barth, 7-May-82 12:20:02 PDT Chen, February 12, 1984 7:57 PM, to support oldArgVector. Chen, June 10, 1984 8:54:05 pm PDT, cedarized. Κΰ– "cedar" style˜J–"mycedar" stylešΠct1™1J–"mycedar" stylešœ7™7J–"mycedar" stylešœΟfρ˜ςJ–"mycedar" stylešOžΖJžΰ ž)žažφžbBžkžμ ž>œž±œ œžNž'ž° ž:QžœžΘ ž~2žˆ ž’œžͺœžΓ žƒž½\žΦž«žΰžžΝž¦ žžίžΌ&žΊ žΩž ž„ ž‡ž’  ž˜€J–"mycedar" style˜J–"mycedar" styleš ™ J–"mycedar" styleš™J–"mycedar" styleš™J–"mycedar" styleš:™:J–"mycedar" styleš.™.—…—B„E†