<> <> <> <> <> DIRECTORY Convert, Core, CoreClasses, CoreOps, CoreProperties, HashTable, IO USING [PutF, real, rope, STREAM], ElectricalCoreClasses, Real USING [FixC], RefText USING [Append, New], Rope, SinixOps, Sisyph, TerminalIO, ThymeGlobals 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, LevelType, ModelRec, ModelTableBlk, nameBlk, namePtr, namePtrSeq, Next, NodeRec, ParmRec, RefBranchRec, RefCircuitRec, RefCktInstRec, RefConRec, RefFunctionRec, RefModelRec, RefNodeRec, RefParmRec, SearchKey, ValueSeq]; ThymeInput: CEDAR PROGRAM IMPORTS Convert, CoreClasses, CoreOps, CoreProperties, HashTable, IO, ElectricalCoreClasses, Real, RefText, Rope, SinixOps, Sisyph, TerminalIO, ThymeGlobals EXPORTS ThymeGlobals = { InputGlobals: TYPE ~ RECORD [ gndNodeName, undefNode, <> currentCkt: ThymeGlobals.namePtr _ NIL ]; CellType: TYPE ~ Core.CellType; CellInstance: TYPE ~ CoreClasses.CellInstance; Wire: TYPE ~ Core.Wire; Wires: TYPE ~ Core.Wires; ROPE: TYPE ~ Rope.ROPE; WireFilterProc: TYPE = PROC [wire: Wire] RETURNS [BOOL]; wId, cId, iId: INT _ 0; -- Used in naming unnamed wires, cells and instances isPublic: ATOM _ CoreProperties.RegisterProperty[$CoreThymeIsPublic, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]]; pathNameProp: ATOM _ CoreProperties.RegisterProperty[$CoreThymePathName, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]]; probeWireProp: ATOM _ CoreProperties.RegisterProperty[$CoreThymeProbeWire, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]]; savedNameProp: ATOM _ CoreProperties.RegisterProperty[$CoreThymeSavedName, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]]; savedNameValidProp: ATOM _ CoreProperties.RegisterProperty[$CoreThymeSavedNameValid, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]]; PutTopLevelCircuit: PUBLIC PROC [cellType: CellType, handle: ThymeGlobals.Handle, cktRoot, gndNodeName: ThymeGlobals.namePtr] = { plotSpec, initSpec: ROPE; resultList: LIST OF CellInstance; thymePanelCT: CellType; thymePanel: ElectricalCoreClasses.Panel; inputGlobals: InputGlobals; inputGlobals.undefNode _ NEW[ThymeGlobals.nameBlk _ [name: "Undefined", details: NEW[ThymeGlobals.NodeRec] ] ]; inputGlobals.gndNodeName _ gndNodeName; <<>> <> <> <> <> <> [resultList, thymePanelCT] _ PutRecordCellType[cellType, handle, inputGlobals, cktRoot, TRUE]; IF thymePanelCT=NIL THEN {TerminalIO.PutRope["** Error: Sorry, no ThymePanel in cell\n"]; RETURN}; thymePanel _ NARROW[thymePanelCT.data, ElectricalCoreClasses.Panel]; <> FOR l: LIST OF CellInstance _ resultList, l.rest WHILE l#NIL DO inst: CellInstance _ l.first; instType: CellType _ RecastIcon[inst.type]; IF instType.class=ElectricalCoreClasses.initCellClass THEN { init: ElectricalCoreClasses.Init _ NARROW[instType.data]; pathName: ROPE _ NARROW[CoreProperties.GetCellInstanceProp[inst, pathNameProp]]; SELECT init.type FROM Voltage => initSpec _ Rope.Cat[ Rope.Cat["IC[", ElectricalCoreClasses.RopeFromns[init.time]], , Rope.Cat[", ", pathName], Rope.Cat["_ ", Convert.RopeFromReal[init.value], "];"]]; Current => ERROR; -- No Init Current for the moment ENDCASE => ERROR; }; ENDLOOP; <> <> <> <> <> <> <> handle.vars.plots[0].title _ thymePanel.title; handle.vars.plots[0].ymin _ thymePanel.yMin; handle.vars.plots[0].ymax _ thymePanel.yMax; FOR l: LIST OF CellInstance _ resultList, l.rest WHILE l#NIL DO inst: CellInstance _ l.first; instType: CellType _ RecastIcon[inst.type]; IF instType.class=ElectricalCoreClasses.probeCellClass THEN { probe: ElectricalCoreClasses.Probe _ NARROW[instType.data]; pathName: ROPE _ NARROW[CoreProperties.GetCellInstanceProp[inst, pathNameProp]]; SELECT probe.type FROM < plotSpec _ Rope.Cat[plotSpec, ", ", pathName, ": ", Convert.RopeFromReal[probe.scale]];>> Voltage => plotSpec _ Rope.Cat[plotSpec, ", ", pathName, ": ", Convert.RopeFromReal[probe.scale]]; Current => plotSpec _ Rope.Cat[plotSpec, ", ", pathName, "^: ", ElectricalCoreClasses.RopeFrommA[probe.scale]]; ENDCASE => ERROR; }; ENDLOOP; plotSpec _ Rope.Cat[plotSpec, "];"]; <> [] _ Rope.Cat["Run[", Rope.Cat["tMin _ ", ElectricalCoreClasses.RopeFromns[thymePanel.tMin], ", "], Rope.Cat["tMax _ ", ElectricalCoreClasses.RopeFromns[thymePanel.tMax], "];"]]; }; PutRecordCellType: PROC [cellType: CellType, handle: ThymeGlobals.Handle, inputGlobals: InputGlobals, ckt: ThymeGlobals.namePtr, topLevel: BOOL] RETURNS [resultList: LIST OF CellInstance _ NIL, thymePanel: CellType _ NIL] = { OPEN handle.vars; EnsureInternalNames: CoreOps.EachWireProc = { IF wire#recordCT.internal THEN [] _ EnsureWireName[wire] }; MarkPublicWire: CoreOps.EachWireProc = { [] _ CoreProperties.PutWireProp[wire, isPublic, isPublic] }; curCktDetails: ThymeGlobals.RefCircuitRec _ NEW[ThymeGlobals.CircuitRec_ [father: inputGlobals.currentCkt]]; recordCT: CoreClasses.RecordCellType _ NARROW[cellType.data]; subCellTypeTab: HashTable.Table _ HashTable.Create[]; cellTypeName: ROPE _ EnsureCellTypeName[cellType]; IF ThymeGlobals.Canned[handle] THEN SIGNAL ThymeGlobals.Aborted; ckt.details _ curCktDetails; inputGlobals.currentCkt _ ckt; IF topLevel THEN { curCktDetails.names _ inputGlobals.gndNodeName; EnterWires[recordCT.internal, Filter[WireToAtomicWires[recordCT.internal], VddOnly], handle, inputGlobals]; }; <> [] _ CoreOps.VisitWire[recordCT.internal, EnsureInternalNames]; [] _ CoreOps.VisitWire[cellType.public, MarkPublicWire]; CoreOps.FlushNameCaches[recordCT.internal]; CoreOps.FlushNameCaches[cellType.public]; <<>> <> IF ~topLevel THEN { <> <> fakes: ThymeGlobals.namePtr; [fakes, curCktDetails.conCount] _ GetWireNames[cellType.public, WireToAtomicWires[cellType.public], handle, inputGlobals]; curCktDetails.fakeNodes _ fakes; FOR fn: ThymeGlobals.namePtr _ fakes, fn.nextName UNTIL fn=NIL DO fn.details _ NEW[ThymeGlobals.ConRec]; ENDLOOP; }; <> EnterWires[recordCT.internal, Filter[WireToAtomicWires[recordCT.internal], IF topLevel THEN IsVddOrGnd ELSE IsPublic], handle, inputGlobals]; <> FOR i: NAT IN [0..recordCT.size) DO inst: CellInstance _ recordCT.instances[i]; <> instType: CellType _ CoreOps.ToBasic[inst.type]; curCktDetails: ThymeGlobals.RefCircuitRec _ NARROW[inputGlobals.currentCkt.details]; nPtr: ThymeGlobals.namePtr _ NEW[ThymeGlobals.nameBlk _ [srchLink: curCktDetails.names, name: EnsureCellTypeName[instType]]]; curCktDetails.names_ nPtr; SELECT instType.class FROM CoreClasses.recordCellClass => { instName: ROPE _ EnsureInstName[inst]; found: BOOL; value: HashTable.Value; subCellTypeResultList: LIST OF CellInstance; <> [found, value] _ HashTable.Fetch[subCellTypeTab, instType]; IF found THEN subCellTypeResultList _ NARROW[value, LIST OF CellInstance] ELSE { subCellTypeResultList _ PutRecordCellType[instType, handle, inputGlobals, nPtr, FALSE].resultList; [] _ HashTable.Insert[subCellTypeTab, instType, subCellTypeResultList] }; <<>> <> <<[] _ Rope.Cat[>> <> <<"[",>> <> <<"];"];>> <> FOR l: LIST OF CellInstance _ subCellTypeResultList, l.rest WHILE l#NIL DO subCellInst: CellInstance _ CopyCellInstance[l.first]; pathName: ROPE _ NARROW[CoreProperties.GetCellInstanceProp[subCellInst, pathNameProp]]; voltageProbeOnPublicWire: BOOL _ FALSE; subCellInstType: CellType _ RecastIcon[subCellInst.type]; <> IF subCellInstType.class=ElectricalCoreClasses.probeCellClass THEN { probe: ElectricalCoreClasses.Probe _ NARROW[subCellInstType.data]; IF probe.type=Voltage THEN { probeWire: Wire _ NARROW[CoreProperties.GetCellInstanceProp[subCellInst, probeWireProp]]; ForEachBinding: CoreOps.EachWirePairProc = { IF publicWire=probeWire THEN { voltageProbeOnPublicWire _ TRUE; pathName _ WiresToRope[recordCT.internal, WireToAtomicWires[actualWire]]; CoreProperties.PutCellInstanceProp[subCellInst, probeWireProp, actualWire]; }; }; [] _ CoreOps.VisitBinding[inst.actual, instType.public, ForEachBinding] }; }; IF ~voltageProbeOnPublicWire THEN pathName _ Rope.Cat[instName, "/", pathName]; [] _ CoreProperties.PutCellInstanceProp[subCellInst, pathNameProp, pathName]; resultList _ CONS[subCellInst, resultList]; ENDLOOP; }; CoreClasses.transistorCellClass => PutTransistorInstance[recordCT.internal, inst, instType, handle]; ElectricalCoreClasses.resistorCellClass => PutResistorInstance[recordCT.internal, inst, instType, handle]; ElectricalCoreClasses.inductorCellClass => PutInductorInstance[recordCT.internal, inst, instType, handle]; ElectricalCoreClasses.capacitorCellClass => PutCapacitorInstance[recordCT.internal, inst, instType, handle]; ElectricalCoreClasses.signalGeneratorCellClass => PutSignalGeneratorInstance[recordCT.internal, inst, instType, handle]; ElectricalCoreClasses.probeCellClass => { probe: ElectricalCoreClasses.Probe _ NARROW[instType.data]; SELECT probe.type FROM Voltage => { [] _ CoreProperties.PutCellInstanceProp[inst, pathNameProp, WiresToRope[recordCT.internal, WireToAtomicWires[inst.actual]]]; [] _ CoreProperties.PutCellInstanceProp[inst, probeWireProp, inst.actual.elements[0]]; }; Current => { useResistor: BOOL _ probe.resistance>0.001; instName: ROPE _ EnsureInstName[inst]; [] _ CoreProperties.PutCellInstanceProp[inst, pathNameProp, instName]; <> <<[] _ Rope.Cat[>> <> <> <<"] = ",>> <> <<";"];>> }; ENDCASE => ERROR; resultList _ CONS[inst, resultList]; }; ElectricalCoreClasses.initCellClass => { init: ElectricalCoreClasses.Init _ NARROW[instType.data]; SELECT init.type FROM Voltage => [] _ CoreProperties.PutCellInstanceProp[inst, pathNameProp, WiresToRope[recordCT.internal, WireToAtomicWires[inst.actual]]]; Current => ERROR; ENDCASE => ERROR; resultList _ CONS[inst, resultList]; }; ElectricalCoreClasses.panelCellClass => thymePanel _ instType; ENDCASE => ERROR; ENDLOOP; }; EnsureCellTypeName: PROC [cellType: CellType] RETURNS [name: ROPE] = { name _ CoreOps.GetCellTypeName[cellType]; IF CoreProperties.GetCellTypeProp[cellType, savedNameValidProp]#NIL THEN RETURN; CoreProperties.PutCellTypeProp[cellType, savedNameProp, name]; CoreProperties.PutCellTypeProp[cellType, savedNameValidProp, savedNameValidProp]; IF name=NIL THEN name _ Rope.Cat["Cell", Convert.RopeFromInt[cId]] ELSE name _ Rope.Cat[Rope.Translate[base: name, translator: NameTranslator], Convert.RopeFromInt[cId]]; cId _ cId+1; [] _ CoreOps.SetCellTypeName[cellType, name]; }; EnsureInstName: PROC [inst: CellInstance] RETURNS [name: ROPE] = { name _ CoreClasses.GetCellInstanceName[inst]; IF CoreProperties.GetCellInstanceProp[inst, savedNameValidProp]#NIL THEN RETURN; CoreProperties.PutCellInstanceProp[inst, savedNameProp, name]; CoreProperties.PutCellInstanceProp[inst, savedNameValidProp, savedNameValidProp]; IF name=NIL THEN {name _ Rope.Cat["Inst", Convert.RopeFromInt[iId]]; iId _ iId+1} ELSE name _ Rope.Translate[base: name, translator: NameTranslator]; [] _ CoreClasses.SetCellInstanceName[inst, name]; }; RecastIcon: PROC [ct: CellType] RETURNS [result: CellType] = { result _ ct; WHILE SinixOps.IsIcon[Sisyph.mode.decoration, result] DO result _ CoreOps.Recast[result]; ENDLOOP; }; PutTransistorInstance: PROC [rootWire: Wire, inst: CellInstance, instType: CellType, handle: ThymeGlobals.Handle] = { tNodeContents: ROPE; transistor: CoreClasses.Transistor _ NARROW[instType.data]; instName: ROPE _ EnsureInstName[inst]; tNodeContents _ Rope.Cat[ Rope.Cat[instName, ": "], SELECT transistor.type FROM nE => "ETran", pE => "CTran" ENDCASE => ERROR, Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], " | "], Rope.Cat["L _ ", Convert.RopeFromInt[transistor.length], ", "], Rope.Cat["W _ ", Convert.RopeFromInt[transistor.width], ", sdExtend _ 6];"] ]; }; PutResistorInstance: PROC [rootWire: Wire, inst: CellInstance, instType: CellType, handle: ThymeGlobals.Handle] = { tNodeContents: ROPE; resistor: ElectricalCoreClasses.Resistor _ NARROW[instType.data]; instName: ROPE _ EnsureInstName[inst]; tNodeContents _ Rope.Cat[ Rope.Cat[instName, ": Resistor"], Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], "] = "], Rope.Cat[ElectricalCoreClasses.RopeFromKOhms[resistor.value], ";"] ]; }; PutInductorInstance: PROC [rootWire: Wire, inst: CellInstance, instType: CellType, handle: ThymeGlobals.Handle] = { tNodeContents: ROPE; inductor: ElectricalCoreClasses.Inductor _ NARROW[instType.data]; instName: ROPE _ EnsureInstName[inst]; tNodeContents _ Rope.Cat[ Rope.Cat[instName, ": Inductor"], Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], "] = "], Rope.Cat[ElectricalCoreClasses.RopeFromuH[inductor.value], ";"] ]; }; PutCapacitorInstance: PROC [rootWire: Wire, inst: CellInstance, instType: CellType, handle: ThymeGlobals.Handle] = { tNodeContents: ROPE; capacitor: ElectricalCoreClasses.Capacitor _ NARROW[instType.data]; instName: ROPE _ EnsureInstName[inst]; tNodeContents _ Rope.Cat[ Rope.Cat[instName, ": Capacitor"], Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], "] = "], Rope.Cat[ElectricalCoreClasses.RopeFrompF[capacitor.value], ";"] ]; }; PutSignalGeneratorInstance: PROC [rootWire: Wire, inst: CellInstance, instType: CellType, handle: ThymeGlobals.Handle] = { tNodeContents: ROPE; signalGenerator: ElectricalCoreClasses.SignalGenerator _ NARROW[instType.data]; instName: ROPE _ EnsureInstName[inst]; SELECT signalGenerator.type FROM RectWave => { tNodeContents _ Rope.Cat[ Rope.Cat[instName, ": RectWave"], Rope.Cat[ Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], " | "], Rope.Cat["OnLevel _ ", ElectricalCoreClasses.RopeFromVolts[signalGenerator.onLevel], ", "], Rope.Cat["OffLevel _ ", ElectricalCoreClasses.RopeFromVolts[signalGenerator.offLevel], ", "], Rope.Cat["period _ ", ElectricalCoreClasses.RopeFromns[signalGenerator.period], ", "], Rope.Cat["width _ ", ElectricalCoreClasses.RopeFromns[signalGenerator.width], ", "]], Rope.Cat[ Rope.Cat["tRise _ ", ElectricalCoreClasses.RopeFromns[signalGenerator.tRise], ", "], Rope.Cat["tFall _ ", ElectricalCoreClasses.RopeFromns[signalGenerator.tFall], ", "], Rope.Cat["tDelay _ ", ElectricalCoreClasses.RopeFromns[signalGenerator.tDelay], "];"]] ]; }; OneShot => { tNodeContents _ Rope.Cat[ Rope.Cat[instName, ": OneShot"], Rope.Cat[ Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], " | "], Rope.Cat["OnLevel _ ", ElectricalCoreClasses.RopeFromVolts[signalGenerator.onLevel], ", "], Rope.Cat["OffLevel _ ", ElectricalCoreClasses.RopeFromVolts[signalGenerator.offLevel], ", "], Rope.Cat["width _ ", ElectricalCoreClasses.RopeFromns[signalGenerator.width], ", "]], Rope.Cat[ Rope.Cat["tRise _ ", ElectricalCoreClasses.RopeFromns[signalGenerator.tRise], ", "], Rope.Cat["tFall _ ", ElectricalCoreClasses.RopeFromns[signalGenerator.tFall], ", "], Rope.Cat["tDelay _ ", ElectricalCoreClasses.RopeFromns[signalGenerator.tDelay], "];"]] ]; }; Step => { tNodeContents _ Rope.Cat[ Rope.Cat[instName, ": Step"], Rope.Cat[ Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], " | "], Rope.Cat["OnLevel _ ", ElectricalCoreClasses.RopeFromVolts[signalGenerator.onLevel], ", "], Rope.Cat["OffLevel _ ", ElectricalCoreClasses.RopeFromVolts[signalGenerator.offLevel], ", "]], Rope.Cat[ Rope.Cat["tRise _ ", ElectricalCoreClasses.RopeFromns[signalGenerator.tRise], ", "], Rope.Cat["tDelay _ ", ElectricalCoreClasses.RopeFromns[signalGenerator.tDelay], "];"]] ]; }; DC => { tNodeContents _ Rope.Cat[ Rope.Cat[instName, ": Voltage"], Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], ", Gnd] = "], Rope.Cat[ElectricalCoreClasses.RopeFromVolts[signalGenerator.onLevel], ";"] ]; }; ENDCASE => ERROR; }; CopyCellInstance: PROC [inst: CellInstance] RETURNS [copy: CellInstance] = { ForEachProp: PROC [a: ATOM, v: REF ANY] = { copy.properties _ CoreProperties.PutProp[copy.properties, a, v] }; copy _ NEW [CoreClasses.CellInstanceRec]; copy.actual _ inst.actual; copy.type _ inst.type; copy.properties _ NIL; CoreProperties.Enumerate[inst.properties, ForEachProp] }; WireToAtomicWires: PROC [wire: Wire, unique: BOOL _ TRUE] RETURNS [wires: Wires] = { AddToWires: PROC [subWire: Wire] = { IF unique THEN FOR l: Wires _ wires, l.rest WHILE l#NIL DO IF l.first=subWire THEN RETURN; ENDLOOP; wires _ CONS[subWire, wires]; }; wires _ NIL; IF wire.size=0 THEN AddToWires[wire] ELSE CoreOps.VisitRootAtomics[wire, AddToWires]; wires _ CoreOps.Reverse[wires] }; Filter: PROC [in: Wires, filter: WireFilterProc] RETURNS [out: Wires] = { out _ NIL; FOR l: Wires _ in, l.rest WHILE l#NIL DO IF ~filter[l.first] THEN out _ CONS[l.first, out] ENDLOOP; out _ CoreOps.Reverse[out]; }; IsPublic: WireFilterProc = { RETURN [CoreProperties.GetWireProp[wire, isPublic]#NIL] }; IsVddOrGnd: WireFilterProc = { name: ROPE _ CoreOps.GetShortWireName[wire]; RETURN [Rope.Equal[name, "Vdd"] OR Rope.Equal[name, "Gnd"]]; }; VddOnly: WireFilterProc = { name: ROPE _ CoreOps.GetShortWireName[wire]; RETURN [~Rope.Equal[name, "Vdd"]]; }; GetWireNames: PROC[wire: Wire, wires: Wires, handle: ThymeGlobals.Handle, inputGlobals: InputGlobals] RETURNS[names: ThymeGlobals.namePtr_ NIL, nameCount: NAT_ 0]= { <> OPEN handle.vars; nPtr: ThymeGlobals.namePtr; FOR l: Wires _ wires, l.rest WHILE l#NIL DO <> curCktDetails: ThymeGlobals.RefCircuitRec _ NARROW[inputGlobals.currentCkt.details]; nPtr _ NEW[ThymeGlobals.nameBlk _ [srchLink: curCktDetails.names, name: Rope.Translate[base: CoreOps.GetFullWireName[wire, l.first], translator: NameTranslator]]]; curCktDetails.names _ nPtr; IF nPtr # NIL THEN { -- usually not nil nPtr.nextName _ names; names _ nPtr; }; nameCount _ nameCount + 1; ENDLOOP }; -- GetWireNames EnterWires: PROC[wire: Wire, wires: Wires, handle: ThymeGlobals.Handle, inputGlobals: InputGlobals]= { nPtr: ThymeGlobals.namePtr; [nPtr, ] _ GetWireNames[wire, wires, handle, inputGlobals]; UNTIL nPtr=NIL DO nPtr.details _ NEW[ThymeGlobals.NodeRec]; nPtr _ nPtr.nextName; ENDLOOP; }; -- EnterWires WiresToRope: PROC [root: Wire, wires: Wires] RETURNS [rope: ROPE] = { separator: ROPE _ ", "; rope _ NIL; FOR l: Wires _ wires, l.rest WHILE l#NIL DO rope _ Rope.Cat[rope, separator, CoreOps.GetFullWireName[root, l.first]] ENDLOOP; IF rope#NIL THEN rope _ Rope.Substr[rope, Rope.Length[separator], Rope.Length[rope]]; rope _ Rope.Translate[base: rope, translator: NameTranslator]; }; ActualsToRope: PROC [public, internal: Wire, wires: Wires, topLevel: BOOL] RETURNS [rope: ROPE] = { separator: ROPE _ ", "; rope _ NIL; FOR l: Wires _ wires, l.rest WHILE l#NIL DO rope _ Rope.Cat[rope, separator, CoreOps.GetFullWireName[IF IsPublic[l.first]AND~topLevel THEN public ELSE internal, l.first]] ENDLOOP; IF rope#NIL THEN rope _ Rope.Substr[rope, Rope.Length[separator], Rope.Length[rope]]; rope _ Rope.Translate[base: rope, translator: NameTranslator]; }; NameTranslator: Rope.TranslatorType = { SELECT old FROM '* => new _ 'X; '. => new _ 'x; '- => new _ 'Z; ENDCASE => new _ old; }; EnsureWireName: PROC [wire: Wire] RETURNS [name: ROPE] = { name _ CoreOps.GetShortWireName[wire]; IF CoreProperties.GetWireProp[wire, savedNameValidProp]#NIL THEN RETURN; CoreProperties.PutWireProp[wire, savedNameProp, name]; CoreProperties.PutWireProp[wire, savedNameValidProp, savedNameValidProp]; IF name=NIL THEN {name _ Rope.Cat["Node", Convert.RopeFromInt[wId]]; wId _ wId+1} ELSE name _ Rope.Translate[base: name, translator: NameTranslator]; [] _ CoreOps.SetShortWireName[wire, name]; }; EnterName: PROC[handle: ThymeGlobals.Handle, inputGlobals: InputGlobals] RETURNS[newCktNames: ThymeGlobals.namePtr_ NIL]= { <> OPEN handle.vars; IF SearchName[newString, oneLevel, inputGlobals.currentCkt]=NIL THEN { curCktDetails: ThymeGlobals.RefCircuitRec _ NARROW[inputGlobals.currentCkt.details]; newCktNames _ NEW[ThymeGlobals.nameBlk _ [srchLink: curCktDetails.names, name: Rope.FromRefText[newString]]]; curCktDetails.names_ newCktNames; } ELSE ThymeGlobals.Error[handle, 250]; }; -- EnterName SearchName: PROC[nameString: REF TEXT, level: ThymeGlobals.LevelType _ oneLevel, oldCktNames: ThymeGlobals.namePtr] RETURNS[newCktNames: ThymeGlobals.namePtr_ NIL]= { <> lastNamePtr: ThymeGlobals.namePtr; oldDetails: ThymeGlobals.RefCircuitRec; nameRope: Rope.ROPE _ Rope.FromRefText[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: ThymeGlobals.Handle, inputGlobals: InputGlobals] RETURNS[names: ThymeGlobals.namePtr_ NIL, nameCount: NAT_ 0]= { <> nPtr: ThymeGlobals.namePtr; UNTIL handle.vars.item # name DO nPtr _ EnterName[handle, inputGlobals]; IF nPtr # NIL THEN { -- usually not nil nPtr.nextName _ names; names _ nPtr; }; nameCount _ nameCount + 1; ThymeGlobals.Next[handle]; IF handle.vars.item # comma THEN EXIT ELSE ThymeGlobals.Next[handle]; IF handle.vars.item # name THEN ThymeGlobals.Error[handle, 208] ENDLOOP }; -- GetNames GetName: PROC[handle: ThymeGlobals.Handle, inputGlobals: InputGlobals] RETURNS[nPtr: ThymeGlobals.namePtr_ NIL]= { OPEN handle.vars; IF item # name THEN ThymeGlobals.Error[handle, 208] ELSE nPtr _ SearchName[newString, allLevels, inputGlobals.currentCkt]; IF nPtr=NIL THEN ThymeGlobals.Error[handle, 251]; ThymeGlobals.Next[handle]; }; -- GetName Variable: PUBLIC PROC[handle: ThymeGlobals.Handle, string: REF TEXT, context: ThymeGlobals.namePtr, level: ThymeGlobals.LevelType _ oneLevel] RETURNS[nPtr: ThymeGlobals.namePtr_ NIL]= { nPtr _ IF context # NIL THEN SearchName[string, level, context] ELSE ERROR; --Which thyme module did such an horror ? <> IF nPtr=NIL THEN ThymeGlobals.Error[handle, 252] ELSE -- check if nPtr has an acceptable type WITH nPtr.details SELECT FROM x: ThymeGlobals.RefParmRec => NULL; x: ThymeGlobals.RefNodeRec => NULL; x: ThymeGlobals.RefConRec => NULL; ENDCASE => ThymeGlobals.Error[handle, 221]; ThymeGlobals.Next[handle]; }; -- Variable FindNode: PROC[handle: ThymeGlobals.Handle, inputGlobals: InputGlobals] RETURNS[n: ThymeGlobals.namePtr]= { <> nPtr: ThymeGlobals.namePtr _ GetName[handle, inputGlobals]; IF nPtr=NIL THEN RETURN[inputGlobals.undefNode] ELSE WITH nPtr.details SELECT FROM x: ThymeGlobals.RefNodeRec => n _ nPtr; x: ThymeGlobals.RefConRec => n _ nPtr; ENDCASE => ThymeGlobals.Error[handle, 222]; }; -- FindNode GetFunction: PROC[handle: ThymeGlobals.Handle, inputGlobals: InputGlobals, na, np: NAT] RETURNS[args: ThymeGlobals.argNames_ NIL, actual: ThymeGlobals.expressionPtr_ NIL]= { <> iArg, iParm: NAT_ 0; aname: ThymeGlobals.namePtr; newExpr: ThymeGlobals.expressionPtr; IF handle.vars.item=leftB THEN { ThymeGlobals.Next[handle]; <> IF na > 0 THEN { args_ NEW[ThymeGlobals.namePtrSeq[na]]; args.visited _ FALSE; UNTIL iArg=na DO aname _ GetName[handle, inputGlobals]; args[iArg] _ aname; IF aname # NIL THEN WITH aname.details SELECT FROM x: ThymeGlobals.RefNodeRec => NULL; x: ThymeGlobals.RefConRec => NULL; ENDCASE => ThymeGlobals.Error[handle, 222]; IF handle.vars.item=quote THEN {ThymeGlobals.Next[handle]; ThymeGlobals.Error[handle, 299]}; iArg _ iArg + 1; IF handle.vars.item=comma THEN ThymeGlobals.Next[handle] ELSE EXIT; ENDLOOP; }; <> IF na=0 OR handle.vars.item=vertical THEN { IF handle.vars.item=vertical THEN ThymeGlobals.Next[handle]; UNTIL iParm=np DO newExpr _ ThymeGlobals.Expression[handle, inputGlobals.currentCkt]; newExpr.next _ actual; actual _ newExpr; iParm _ iParm + 1; IF handle.vars.item=comma THEN ThymeGlobals.Next[handle] ELSE EXIT; ENDLOOP; }; IF handle.vars.item=rightB THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 202, , TRUE]; }; IF iArg # na THEN ThymeGlobals.Error[handle, 231]; IF iParm # np THEN ThymeGlobals.Error[handle, 232]; }; -- GetFunction ControlFunc: PROC[handle: ThymeGlobals.Handle, inputGlobals: InputGlobals, thisBranch: ThymeGlobals.namePtr]= { nPtr, f: ThymeGlobals.namePtr; na, np: NAT; bDetails: ThymeGlobals.RefBranchRec_ NARROW[thisBranch.details]; ThymeGlobals.Next[handle]; IF handle.vars.item=name THEN { nPtr _ SearchName[handle.vars.newString, allLevels, inputGlobals.currentCkt]; IF nPtr=NIL THEN { fTableEntry: REF ThymeGlobals.FuncTableBlk = ThymeGlobals.FindFunction[Rope.FromRefText[handle.vars.newString]]; fDetails: ThymeGlobals.RefFunctionRec _ NEW[ThymeGlobals.FunctionRec_ [branch: thisBranch] ]; f _ NEW[ThymeGlobals.nameBlk _ [details: fDetails]]; <> fDetails.functionProc _ fTableEntry.proc; fDetails.data _ fTableEntry.data; na _ fTableEntry.numArgs; np _ fTableEntry.numParms; IF fDetails.functionProc=NIL THEN ThymeGlobals.Error[handle, 502, FALSE]; ThymeGlobals.Next[handle]; bDetails.controller _ f; [fDetails.funcArgs, fDetails.funcParms] _ GetFunction[handle, inputGlobals, na, np]; fDetails.funcArgVec _ InitArgList[na]; } ELSE WITH nPtr.details SELECT FROM n: ThymeGlobals.RefModelRec => { bDetails.controller_ nPtr; ThymeGlobals.Next[handle]; IF handle.vars.item=leftB THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.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 ThymeGlobals.Error[handle, 233] } ELSE IF handle.vars.value >= n.modelResults.size THEN ThymeGlobals.Error[handle, 233]; ThymeGlobals.Next[handle]; } ELSE ThymeGlobals.Error[handle, 209]; IF handle.vars.item=rightB THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 202,, TRUE]; }; ENDCASE => ThymeGlobals.Error[handle, 223]; } ELSE ThymeGlobals.Error[handle, 208]; }; -- ControlFunc InitArgList: PROC[size: NAT] RETURNS [a: ThymeGlobals.argList] = { a _ NEW[ThymeGlobals.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: ThymeGlobals.Handle, inputGlobals: InputGlobals, bName: ThymeGlobals.namePtr, branchKey: ThymeGlobals.keys]= { pNode, nNode: ThymeGlobals.namePtr; bDetails: ThymeGlobals.RefBranchRec; kind: ThymeGlobals.elements; IF handle.vars.item=leftB THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 201,, TRUE]; pNode _ FindNode[handle, inputGlobals]; IF handle.vars.item=comma THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 200,, TRUE]; nNode _ FindNode[handle, inputGlobals]; IF handle.vars.item=rightB THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 202,, TRUE]; kind _ SELECT branchKey FROM resKey => resistor, capKey => capacitor, indKey => inductor, vsKey => vSource, isKey => iSource, ENDCASE => nullElement; IF kind=nullElement THEN ThymeGlobals.Error[handle, 224, TRUE]; IF pNode=nNode THEN ThymeGlobals.Error[handle, 241]; IF bName # NIL THEN -- else error! ... bName.details _ bDetails _ NEW[ThymeGlobals.BranchRec_ [branchType: kind, posNode: pNode, negNode: nNode ] ]; IF handle.vars.item=equal THEN { ThymeGlobals.Next[handle]; bDetails.valExpr_ ThymeGlobals.Expression[handle, inputGlobals.currentCkt]; } ELSE IF handle.vars.item=leftArrow THEN ControlFunc[handle, inputGlobals, bName] ELSE ThymeGlobals.Error[handle, 205]; }; -- EnterBranches EnterModel: PROC[handle: ThymeGlobals.Handle, inputGlobals: InputGlobals, mName: ThymeGlobals.namePtr]= { na, np, nr: NAT; IF handle.vars.item=leftArrow THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 210]; IF handle.vars.item=name THEN { mTableEntry: REF ThymeGlobals.ModelTableBlk = ThymeGlobals.FindModel[Rope.FromRefText[handle.vars.newString]]; mDetails: ThymeGlobals.RefModelRec _ NEW[ThymeGlobals.ModelRec_ []]; mDetails.modelProc _ mTableEntry.proc; mDetails.data _ mTableEntry.data; na _ mTableEntry.numArgs; np _ mTableEntry.numParms; nr _ mTableEntry.numResults; IF mDetails.modelProc=NIL THEN ThymeGlobals.Error[handle, 501, FALSE]; ThymeGlobals.Next[handle]; [mDetails.modelArgs, mDetails.modelParms] _ GetFunction[handle, inputGlobals, na, np]; mDetails.modelResults _ InitArgList[nr]; mDetails.modelArgVec _ InitArgList[na]; mDetails.modelOldArgVec _ InitArgList[na]; mName.details _ mDetails; } ELSE ThymeGlobals.Error[handle, 208]; }; -- EnterModel GetCircuitTree: PROC[ckt: ThymeGlobals.namePtr] RETURNS[r: Rope.ROPE]= { GetTree: PROC[c: ThymeGlobals.namePtr]= { cktDetail: ThymeGlobals.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: ThymeGlobals.Handle, inputGlobals: InputGlobals] RETURNS[plist: ThymeGlobals.namePtr_ NIL]= { n: ThymeGlobals.namePtr; nparms: NAT_ 0; IF handle.vars.item=vertical THEN ThymeGlobals.Next[handle]; UNTIL handle.vars.item # name DO n _ EnterName[handle, inputGlobals]; ThymeGlobals.Next[handle]; nparms_ nparms + 1; n.details_ NEW[ThymeGlobals.ParmRec_ [nextParm: plist]]; IF handle.vars.item=leftArrow THEN { ENABLE ThymeGlobals.ErrorSignal => { ThymeGlobals.ErrorStrings[handle, error, GetCircuitTree[inputGlobals.currentCkt], s]; CONTINUE; -- GOTO badEnd }; nDetails: ThymeGlobals.RefParmRec _ NARROW[n.details]; ThymeGlobals.Next[handle]; nDetails.default _ TRUE; nDetails.dfltValue _ ThymeGlobals.Eval[handle, ThymeGlobals.Expression[handle, inputGlobals.currentCkt]]; }; plist_ n; IF handle.vars.item=comma THEN ThymeGlobals.Next[handle] ELSE EXIT; IF handle.vars.item # name THEN ThymeGlobals.Error[handle, 208] ENDLOOP; }; -- GetNewParameters <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <> <> <> <<[fakes, curCktDetails.conCount] _ GetNames[handle];>> <> <> <> <> <<};>> <> <> <> <> <> <> <> <> <> <> <> <> <> <<}>> <> <<};>> <> <> <> <> <> <> <> <> <<}; -- DefineCircuit>> DefineCircuit: PUBLIC PROC[handle: ThymeGlobals.Handle, cktRoot, gndNodeName: ThymeGlobals.namePtr]= { inputGlobals: InputGlobals; inputGlobals.undefNode _ NEW[ThymeGlobals.nameBlk _ [name: "Undefined", details: NEW[ThymeGlobals.NodeRec] ] ]; inputGlobals.gndNodeName _ gndNodeName; DefineCircuitInternal[handle, inputGlobals, cktRoot, TRUE]; }; DefineCircuitInternal: PROC[handle: ThymeGlobals.Handle, inputGlobals: InputGlobals, ckt: ThymeGlobals.namePtr, root: BOOL]= { OPEN handle.vars; exp: ThymeGlobals.expressionPtr; curCktDetails: ThymeGlobals.RefCircuitRec _ NEW[ThymeGlobals.CircuitRec_ [father: inputGlobals.currentCkt]]; IF ThymeGlobals.Canned[handle] THEN SIGNAL ThymeGlobals.Aborted; ckt.details _ curCktDetails; inputGlobals.currentCkt _ ckt; <> IF root THEN { <> <> <> curCktDetails.names _ inputGlobals.gndNodeName; ThymeGlobals.Next[handle]; }; IF item=leftB THEN { ThymeGlobals.Next[handle]; IF ~root AND item # vertical THEN { <> fakes: ThymeGlobals.namePtr; [fakes, curCktDetails.conCount] _ GetNames[handle, inputGlobals]; curCktDetails.fakeNodes_ fakes; FOR fn: ThymeGlobals.namePtr _ fakes, fn.nextName UNTIL fn=NIL DO fn.details _ NEW[ThymeGlobals.ConRec]; ENDLOOP; }; IF root OR item=vertical THEN curCktDetails.parms _ GetNewParameters[handle, inputGlobals]; IF item=rightB THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 202,, TRUE]; }; IF item=name AND ThymeGlobals.SearchKey[handle]=assertsKey THEN { ThymeGlobals.Next[handle]; IF item=leftB THEN { ThymeGlobals.Next[handle]; DO exp _ ThymeGlobals.Expression[handle, inputGlobals.currentCkt]; exp.next _ curCktDetails.assertions; curCktDetails.assertions _ exp; IF item=comma THEN ThymeGlobals.Next[handle] ELSE EXIT; ENDLOOP; IF item=rightB THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 202,, TRUE]; } ELSE ThymeGlobals.Error[handle, 201]; }; IF item=equal THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 205, TRUE, TRUE]; IF item=leftC THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 203, TRUE, FALSE]; DO IF item=name THEN EnterDefinition[handle, inputGlobals]; IF item=rightC OR item= eof THEN EXIT; IF item=semi THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 206, TRUE, FALSE]; ENDLOOP; curCktDetails _ NARROW[inputGlobals.currentCkt.details]; inputGlobals.currentCkt _ curCktDetails.father; ThymeGlobals.Next[handle]; }; -- DefineCircuit GetActualParameters: PROC[handle: ThymeGlobals.Handle, inputGlobals: InputGlobals, ckt: ThymeGlobals.namePtr] RETURNS[apList: ThymeGlobals.expressionPtr_ NIL]= { e: ThymeGlobals.expressionPtr; IF handle.vars.item=vertical THEN ThymeGlobals.Next[handle]; IF handle.vars.item=rightB THEN RETURN; DO IF handle.vars.item # name THEN GOTO nameErr; e _ ThymeGlobals.AssignExpr[handle, inputGlobals.currentCkt, ckt]; e.next _ apList; apList _ e; IF handle.vars.item=comma THEN ThymeGlobals.Next[handle] ELSE EXIT; REPEAT nameErr => ThymeGlobals.Error[handle, 208]; ENDLOOP; }; -- GetActualParameters DefCktInstance: PROC[handle: ThymeGlobals.Handle, inputGlobals: InputGlobals, cn: REF TEXT, iName: ThymeGlobals.namePtr]= { cktName: ThymeGlobals.namePtr; n: ThymeGlobals.namePtr; cons: ThymeGlobals.conLinkPtr_ NIL; cCnt: NAT_ 0; noConnections: BOOL; actuals: ThymeGlobals.expressionPtr_ NIL; cktName _ SearchName[cn, allLevels, inputGlobals.currentCkt]; IF cktName # NIL THEN WITH cktName.details SELECT FROM c: ThymeGlobals.RefCircuitRec => { IF handle.vars.item=leftB THEN { ThymeGlobals.Next[handle]; noConnections_ (c.conCount=0); IF ~noConnections THEN WHILE handle.vars.item=name DO n_ FindNode[handle, inputGlobals]; cons_ NEW[ThymeGlobals.conLink_ [nextLink: cons, namedNode: n]]; cCnt_ cCnt + 1; IF handle.vars.item=comma THEN ThymeGlobals.Next[handle] ELSE EXIT; ENDLOOP; IF noConnections OR handle.vars.item=vertical THEN actuals_ GetActualParameters[handle, inputGlobals, cktName]; IF handle.vars.item=rightB THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 202,, TRUE]; }; IF cCnt # c.conCount THEN ThymeGlobals.Error[handle, 260]; iName.details_ NEW[ThymeGlobals.CktInstance_ [of: cktName, connections: cons, actualParms: actuals] ]; }; ENDCASE => ThymeGlobals.Error[handle, 225, TRUE] ELSE ThymeGlobals.Error[handle, 251, TRUE]; }; -- DefCktInstance EnterDefinition: PROC[handle: ThymeGlobals.Handle, inputGlobals: InputGlobals]= { key: ThymeGlobals.keys; nameCount: NAT; nPtr: ThymeGlobals.namePtr; s: REF TEXT _ RefText.New[256]; explodeExpr: ThymeGlobals.expressionPtr _ NIL; [nPtr, nameCount] _ GetNames[handle, inputGlobals]; IF nPtr=NIL THEN ThymeGlobals.Error[handle, 208]; IF handle.vars.item # colon THEN ThymeGlobals.Error[handle, 207,, TRUE] ELSE ThymeGlobals.Next[handle]; IF handle.vars.item=leftP THEN { explodeExpr _ ThymeGlobals.Expression[handle, inputGlobals.currentCkt]; IF nPtr # NIL THEN nPtr.expExpr _ explodeExpr; IF handle.vars.item=implies THEN ThymeGlobals.Next[handle] ELSE ThymeGlobals.Error[handle, 215,, TRUE]; }; IF handle.vars.item=name THEN { key _ ThymeGlobals.SearchKey[handle]; s.length _ 0; s _ RefText.Append[s, handle.vars.newString]; ThymeGlobals.Next[handle]; IF key # nodeKey AND nameCount # 1 THEN ThymeGlobals.Error[handle, 261]; SELECT key FROM nodeKey => { IF nPtr.expExpr # NIL THEN ThymeGlobals.Error[handle, 253]; UNTIL nPtr=NIL DO nPtr.details _ NEW[ThymeGlobals.NodeRec]; nPtr _ nPtr.nextName; ENDLOOP; }; resKey, capKey, indKey, vsKey, isKey => EnterBranches[handle, inputGlobals, nPtr, key]; circuitKey => { IF nPtr.expExpr # NIL THEN ThymeGlobals.Error[handle, 253]; DefineCircuitInternal[handle: handle, inputGlobals: inputGlobals, ckt: nPtr, root: FALSE]; }; modelKey => { IF nPtr.expExpr # NIL THEN ThymeGlobals.Error[handle, 253]; EnterModel[handle, inputGlobals, nPtr]; }; ENDCASE => DefCktInstance[handle, inputGlobals, s, nPtr]; } ELSE ThymeGlobals.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: ThymeGlobals.Handle, ckt: ThymeGlobals.namePtr, level: NAT]= { cLink: ThymeGlobals.conLinkPtr; np: ThymeGlobals.namePtr; cktDetails: ThymeGlobals.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: ThymeGlobals.RefNodeRec => NULL; n: ThymeGlobals.RefBranchRec => handle.msgStream.PutF[": branch[%s, %s]", IO.rope[n.posNode.name], IO.rope[n.negNode.name]]; n: ThymeGlobals.RefCircuitRec => { handle.msgStream.PutF[": circuit.\n"]; Output[handle, np, level + 1]; }; n: ThymeGlobals.RefConRec => NULL; n: ThymeGlobals.RefParmRec => { handle.msgStream.PutF[": parameter"]; IF n.default THEN handle.msgStream.PutF["_ %13.5f", IO.real[n.dfltValue]]; }; n: ThymeGlobals.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 }. 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. Chen, July 22, 1985 8:09:51 pm PDT, => Cedar6.0. <<>>