DIRECTORY Convert, Core, CoreClasses, CoreOps, CoreProperties, IO USING [PutF, real, rope, STREAM], ElectricalCoreClasses, Real USING [InlineFixC], RefTab, 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, IO, ElectricalCoreClasses, Real, RefTab, 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 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: RefTab.Ref _ RefTab.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; val: RefTab.Val; subCellTypeResultList: LIST OF CellInstance; [found, val] _ RefTab.Fetch[subCellTypeTab, instType]; IF found THEN subCellTypeResultList _ NARROW[val, LIST OF CellInstance] ELSE { subCellTypeResultList _ PutRecordCellType[instType, handle, inputGlobals, nPtr, FALSE].resultList; [] _ RefTab.Insert[subCellTypeTab, instType, subCellTypeResultList] }; 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]; }; 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]; transistorLength: INT _ NARROW[CoreProperties.GetCellTypeProp[instType, CoreClasses.lengthProp], REF INT]^; transistorWidth: INT _ NARROW[CoreProperties.GetCellTypeProp[instType, CoreClasses.widthProp], REF INT]^; 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[transistorLength], ", "], Rope.Cat["W _ ", Convert.RopeFromInt[transistorWidth], ", 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.RopeFromV[signalGenerator.onLevel], ", "], Rope.Cat["OffLevel _ ", ElectricalCoreClasses.RopeFromV[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.RopeFromV[signalGenerator.onLevel], ", "], Rope.Cat["OffLevel _ ", ElectricalCoreClasses.RopeFromV[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.RopeFromV[signalGenerator.onLevel], ", "], Rope.Cat["OffLevel _ ", ElectricalCoreClasses.RopeFromV[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.RopeFromV[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.InlineFixC[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 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. ΔThymeInput.mesa Copyright Σ 1985, 1987 by Xerox Corporation. All rights reserved. Last Edited by: Barth, July 8, 1988 11:47:26 am PDT Christian Le Cocq April 29, 1987 10:47:02 am PDT Sweetsun Chen, July 22, 1985 8:10:02 pm PDT cktRoot, PutGlobalParameters[tNode, "CIRCUIT[Lambda _ 1, TDegC _ 25] = {"]; InsertNode["Vdd: Node;"]; InsertFunctions["! /DATools/DATools6.1/Thyme/SignalGenerators"]; InsertModels["! /DATools/DATools6.1/Thyme/BSIM"]; InsertPower["powerSupply: voltage[Vdd, Gnd] = 5.0;"]; Put Init Specs from the init CellType Put Plot Specs plotSpec _ Rope.Cat[ Rope.Cat["Plot[\"", thymePanel.title, "\", "], Rope.Cat[":", ElectricalCoreClasses.RopeFromns[thymePanel.tScale], ", "], Rope.Cat[Convert.RopeFromReal[thymePanel.yMin], ", "], Rope.Cat[Convert.RopeFromReal[thymePanel.yMax], ", "], Rope.Cat["powerSupply^: ", ElectricalCoreClasses.RopeFrommA[thymePanel.iScale]]]; Voltage => plotSpec _ Rope.Cat[plotSpec, ", ", pathName, ": ", Convert.RopeFromReal[probe.scale]]; Put Run Specs Ensure names on internal, mark public, and delete fullname caches Put circuit header if needed cellTypeName, was written there WiresToRope[cellType.public, WireToAtomicWires[cellType.public]] If top-level then put internal nodes except Vdd&Gnd else put internal minus public Now put the instances instType: CellType _ RecastIcon[inst.type]; Put the definition if it isn't there already Put the instance [] _ Rope.Cat[ Rope.Cat[instName, ": ", EnsureCellTypeName[instType]], "[", ActualsToRope[cellType.public, recordCT.internal, WireToAtomicWires[inst.actual, FALSE], topLevel], "];"]; Put the results in subCellTypeResultList onto resultList Compute the new path name if its a voltage probe on a public wire; this new path name will be the path name of the actual PutResistorInstance[... [] _ Rope.Cat[ Rope.Cat[instName, IF useResistor THEN ": Resistor[" ELSE ": Voltage["], ActualsToRope[cellType.public, recordCT.internal, WireToAtomicWires[inst.actual, FALSE], topLevel], "] = ", IF useResistor THEN ElectricalCoreClasses.RopeFromKOhms[probe.resistance] ELSE ElectricalCoreClasses.RopeFromV[0.0], ";"]; enter (unique) name strings on the current circuits search link nPtr _ EnterName[handle]; enter a (one level unique) name string to the search link of currentCkt usually oldCktNames=currentCkt and nameString=newString enter (unique) name strings on the current circuits search link ELSE SearchName[string, allLevels, inputGlobals.currentCkt]; search RefNodeRec or RefConRec with name newString on all levels of currentCkt get na arguments and np parameters(expressions) arguments parameters get values for other fields in f.details, and assign f as the controller for this branch: DefineCircuit: PUBLIC PROC[handle: ThymeGlobals.Handle, ckt: ThymeGlobals.namePtr, root: BOOL]= { OPEN handle.vars; exp: ThymeGlobals.expressionPtr; curCktDetails: ThymeGlobals.RefCircuitRec _ NEW[ThymeGlobals.CircuitRec_ [father: currentCkt]]; IF ThymeGlobals.Canned[handle] THEN SIGNAL ThymeGlobals.Aborted; ckt.details _ curCktDetails; currentCkt _ ckt; IF root AND cktRoot=NIL THEN { cktRoot _ currentCkt; undefNode _ NEW[ThymeGlobals.nameBlk _ [name: "Undefined", details: NEW[ThymeGlobals.NodeRec] ] ]; gndNodeName _ NEW[ThymeGlobals.nameBlk _ [name: "Gnd", details: NEW[ThymeGlobals.NodeRec] ] ]; curCktDetails.names _ gndNodeName; }; IF ~root THEN { enter (unique) connection names on currentCkt: Get public names fakes: ThymeGlobals.namePtr; [fakes, curCktDetails.conCount] _ GetNames[handle]; 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]; Get parameters from cell.data and/or cell.properties 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]; }; Then explore the instances and internals of the cell 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; }; -- DefineCircuit IF root AND inputGlobals.cktRoot=NIL THEN { inputGlobals.cktRoot _ inputGlobals.currentCkt; inputGlobals.undefNode _ NEW[ThymeGlobals.nameBlk _ [name: "Undefined", details: NEW[ThymeGlobals.NodeRec] ] ]; inputGlobals.gndNodeName _ NEW[ThymeGlobals.nameBlk _ [name: "Gnd", details: NEW[ThymeGlobals.NodeRec] ] ]; enter (unique) connection names on currentCkt Κ"‘– "cedar" style˜codešœ™KšœB™BKšœ™K™#Kšœ0™0Kšœ+™+—šΟk ˜ K˜K˜K˜ K˜K˜Kšœœœ˜$Kšœ˜Kšœœ˜K˜Kšœœ˜K˜K˜ K˜K˜ Kšœ œη˜ω—šΟn œœ˜Kš˜K˜K˜ K˜K˜Kšœ˜Kšœ˜K˜K˜K˜K˜K˜ K˜K˜ K˜ Kš˜K˜ ˜K˜—šœœœ˜K˜ K˜ K™Kšœ#˜&K˜—Kšœ œ˜Kšœœ˜.Kšœœ ˜Kšœœ˜Kšœœœ˜Kš œœœœœ˜8KšœœΟc4˜LKšœ œ‡˜•Kšœœ‡˜™Kšœœˆ˜›Kšœœˆ˜›Kšœœ˜₯K˜šžœ œb˜Kšœœ˜Kšœ œœ˜!K˜Kšœ(˜(K˜Kšœœ5œ˜oKšœ'˜'K™KšœB™BKšœ™K˜Kšœ@™@Kšœ1™1Kšœ5™5K˜KšœXœ˜^Kšœ˜KšœBœ˜NKšœ œ1˜DK˜Kšœ%™%š œœœ#œœ˜?K˜K˜+šœ4œ˜˜>Kšœœ˜—Kšœ˜—K˜—K˜šžœœœœ˜FK˜)Kšœ>œœœ˜PK˜>K˜QKšœ˜ šœ2˜6Kšœc˜g—K˜ K˜-K˜—K˜šžœœœœ˜BK˜-Kšœ>œœœ˜PK˜>K˜QKšœ˜ KšœA˜EKšœ?˜CK˜1K˜—K˜šž œœœ˜>K˜ šœ1˜8K˜ Kšœ˜—K˜—K˜šžœœZ˜uKšœœ˜Kšœ%œ˜;Kšœ œ˜&Kš œœœCœœ˜kKš œœœBœœ˜i˜K˜šœ˜K˜—K˜ Kšœœ˜K˜LKšœ>˜>KšœJ˜JK˜—K˜—šžœœZ˜sKšœœ˜Kšœ+œ˜AKšœ œ˜&K˜˜K˜!K˜MKšœB˜BK˜—K˜—šžœœZ˜sKšœœ˜Kšœ+œ˜AKšœ œ˜&K˜˜K˜!K˜MKšœ?˜?K˜—K˜—šžœœZ˜tKšœœ˜Kšœ-œ˜CKšœ œ˜&K˜˜K˜"K˜MKšœ@˜@K˜—K˜—šžœœZ˜zKšœœ˜Kšœ9œ˜OKšœ œ˜&K˜šœ˜ ˜ ˜K˜!˜ K˜LKšœW˜WKšœY˜YKšœV˜VKšœU˜U—˜ KšœT˜TKšœT˜TKšœV˜V—K˜—K˜—˜ ˜K˜ ˜ K˜LKšœW˜WKšœY˜YKšœU˜U—˜ KšœT˜TKšœT˜TKšœV˜V—K˜—K˜—˜ ˜K˜˜ K˜LKšœW˜WKšœZ˜Z—˜ KšœT˜TKšœV˜V—K˜—K˜—šœ˜˜K˜ K˜RKšœG˜GK˜—K˜—Kšœœ˜—K˜K˜—šžœœœ˜Lš ž œœœœœ˜+˜?K˜——Kšœœ˜)K˜K˜Kšœœ˜K˜6K˜—K˜š žœœœœœ˜Tšž œœ˜$š œœœœœ˜:Kšœœœ˜Kšœ˜—Kšœœ˜K˜—Kšœœ˜ Kšœ œœ,˜U˜K˜——šžœœ%œ˜IKšœœ˜ šœœœ˜(Kšœœœ˜1Kšœ˜—K˜K˜K˜—šžœ˜Kšœ-œ˜7K˜K˜—šž œ˜Kšœœ"˜,Kšœœ˜K˜—š ž œœ2œœœ˜cKšœ œ˜Kšœœ˜ šœœœ˜+Kš œ9œœ œœ˜~Kšœ˜—KšœœœE˜UK˜>K˜—šžœ˜'šœ˜K˜K˜K˜Kšœ˜—K˜—šžœœœœ˜:K˜&Kšœ6œœœ˜HK˜6K˜IKšœ˜ KšœA˜EKšœ?˜CK˜*K˜—K˜šž œœ:œ$œ˜{šœG™GKšœ ˜—šœ:œœ˜FKšœ,œ"˜TKšœœ\˜mK˜!K˜—Kšœ!˜%KšœŸ ˜—K˜š ž œœ œœOœ$œ˜¦Kšœ7™7K˜"K˜'Kšœœ ˜3šœ œ˜Kšœ œ˜)K˜Kšœœ˜šœ œ˜Kšœ(œœ˜:K˜K˜#Kšœ˜—Kšœœœ˜K˜ Kš˜K˜šœœœ˜K˜,K˜(K˜K˜—Kšœ˜—KšœŸ ˜—š žœœ:œœ œ˜‡Kšœ?™?K˜šœ˜ Kšœ'˜'šœœœŸ˜'K˜K˜ K˜—K˜K˜Kšœœœœ˜EKšœœ ˜?Kš˜—KšœŸ ˜—šžœœ:œœ˜rKšœ ˜Kšœ œ ˜3KšœB˜FKšœœœ!˜1K˜KšœŸ ˜ K˜—šžœœœ&œœJœœ˜Ήšœœ œœ#˜?KšœœŸ)˜5Kšœ8™<—Kšœœœ ˜0KšœŸ'˜,šœœ˜Kšœœ˜#Kšœœ˜#Kšœœ˜"Kšœ$˜+—K˜KšœŸ ˜K˜—šžœœ:œ˜kKšœN™NKšœ;˜;Kšœœœœ˜/šœœœ˜"K˜'K˜'Kšœ$˜+—KšœŸ ˜K˜—Kšž œœBœ˜Wšœœ&œ˜UKšœ/™/Kšœ œ˜K˜K˜$šœœ˜ K˜Kšœ ™ šœœ˜Kšœœ˜'Kšœœ˜šœ ˜K˜&K˜Kšœ œ˜šœœ˜Kšœœ˜#Kšœœ˜#Kšœ$˜+—Kšœœ>˜\K˜Kšœœœœ˜CKšœ˜—K˜—Kšœ ™ šœœœ˜+Kšœœ˜<šœ ˜KšœC˜CK˜K˜K˜Kšœœœœ˜CKšœ˜—K˜—Kšœœœ#œ˜gK˜—Kšœ œ!˜2Kšœ œ!˜3KšœŸ˜K˜—šž œœ^˜oK˜Kšœœ˜ Kšœ%œ˜@K˜šœœ˜KšœM˜Mšœœœ˜Kšœ œ`˜pKšœ(œ2˜]Kšœœ-˜4KšœY™YK˜)K˜!K˜K˜Kšœœœ!œ˜IK˜K˜K˜TK˜&K˜—Kš˜šœœ˜˜ K˜K˜Kšœœ˜8Kšœ"œ˜,šœœ˜!K˜8šœœœŸ˜/Kšœœ ˜=K˜—Kšœœ)˜0Kšœ!˜%K˜K˜—Kšœ!˜%Kšœœ˜9Kšœ"œ˜,K˜—Kšœ$˜+—K˜—Kšœ!˜%KšœŸ˜—šž œœœœ˜BKšœœ˜%Kšœ œ˜Kšœ œ˜Kšœ œ˜šœœœ ˜Kšœœ˜—KšœŸ˜—šž œœw˜ŠK˜#K˜$K˜Kšœœœ"œ˜eK˜'Kšœœœ"œ˜eK˜'Kšœœœ"œ˜fšœœ ˜K˜K˜K˜K˜K˜Kšœ˜—Kšœœ!œ˜?Kšœ œ!˜4Kšœ œœŸ˜&šœœ˜6˜K˜K˜——šœœ˜ K˜KšœK˜KK˜—š˜Kšœœ)˜KKšœ!˜%—KšœŸ˜K˜—šž œœY˜iKšœ œ˜Kšœœœ!˜bšœœ˜Kšœ œ^˜nKšœ%œ˜DK˜&K˜!K˜K˜K˜Kšœœœ!œ˜FK˜K˜VK˜(K˜'K˜*K˜K˜—Kšœ!˜%KšœŸ ˜K˜—šžœœœ œ˜Hšžœœ˜)Kšœ'œ ˜9šœœœ œœœœ˜@K˜K˜K˜—KšœŸ ˜ —K˜ KšœŸ˜K˜—šžœœ:œœ˜|K˜Kšœœ˜Kšœœ˜<šœ˜ K˜$K˜K˜Kšœ œ*˜8šœœ˜$šœ˜$KšœU˜UKšœŸ˜K˜—Kšœ$œ ˜6K˜Kšœœ˜Kšœi˜iK˜—K˜ Kšœœœœ˜CKšœœ ˜?Kšœ˜—KšœŸ˜—šž œœœ?œ™aKšœ ™K™ Kšœ,œ0™_Kšœœœ™@K™K™šœœ œœ™K™Kšœ œ5œ™bKšœœ/œ™^K™"K™—šœœ™Kšœ?™?K™K™3K™ šœ/œœ™AKšœ œ™&Kšœ™—K™—KšœM™MKšœ4™4Kšœ4™4Kšœ ™ Kšœ™Kšœ ™ Kšœ™Kšœ™Kšœ$™$Kšœ™Kšœ*™*Kšœ™Kšœ@™@Kšœ™Kšœ™Kšœ™Kšœ4™4š™Kšœ œ™*Kšœ&™&KšœD™DKšœ™—Kšœœ™+K™"KšœŸ™—K˜šž œœœL˜fKšœ˜Kšœœ5œ˜oKšœ'˜'Kšœ5œ˜;K˜K˜—šžœœ[œ˜~Kšœ ˜Kšœ ˜ Kšœ,œ=˜lKšœœœ˜@K˜Kšœ˜Kšœœœœ™+šœœ˜Kšœ/™/Kšœœ5œ™oKšœœ/œ™kKšœ/˜/Kšœ˜K˜—šœ œ˜Kšœ˜šœœœ˜#Kšœ-™-Kšœ˜KšœA˜AK˜šœ/œœ˜AKšœ œ˜&Kšœ˜—K˜—Kšœœœ>˜[Kšœ œœ"œ˜ZK˜—šœ œ+œ˜AKšœ˜šœ œ˜Kšœ˜š˜Kšœ?˜?K˜$K˜Kšœ œœœ˜7Kšœ˜—Kšœ œœ"œ˜ZK˜—Kšœ!˜%K˜—Kš œ œœ!œœ˜^Kš œ œœ!œœ˜_š˜Kšœ œ'˜8Kšœ œ œœ˜&Kš œ œœ!œœ˜^Kšœ˜—Kšœœ"˜8Kšœ/˜/Kšœ˜KšœŸ˜—šžœœUœ%œ˜‘K˜Kšœœ˜œœ!˜{K˜K˜Kšœœ˜#Kšœœ˜ Kšœœ˜Kšœ%œ˜)Kšœ=˜=Kšœ œ˜šœœ˜ ˜"šœœ˜ K˜K˜Kšœ˜šœ˜Kšœ"˜"Kšœœ7˜@K˜Kšœœœœ˜CKšœ˜—Kšœœ˜2K˜