File: [Cherry]<Thyme>Cedar5.2>System>spInput.mesa
Last Edited by: SChen, May 17, 1985 4:50:11 pm PDT
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]= {
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]];
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;
};
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, 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]];
get values for other fields in f.details, and assign f as the controller for this branch:
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 {
enter (uniquie) connection names on currentCkt
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.
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.