<> <> <> <> <> <> <> <<>> DIRECTORY CommandTool, Convert, CoreOps, CoreClasses, CoreProperties, CoreThyme, HashTable, ElectricalCoreClasses, Rope, SinixOps, Sisyph, ThymeGlobals, TerminalIO, TiogaFileOps, ViewerTools; CoreThymeImpl: CEDAR PROGRAM IMPORTS Convert, CoreOps, CoreClasses, CoreProperties, HashTable, ElectricalCoreClasses, Rope, SinixOps, Sisyph, ThymeGlobals, TerminalIO, TiogaFileOps, ViewerTools EXPORTS CoreThyme = BEGIN OPEN CoreThyme; TNode: TYPE = TiogaFileOps.Ref; 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]]]; <> <> CreateThymeViewer: PUBLIC PROC [wDir: ROPE] RETURNS [handle: ThymeHandle] = BEGIN handle _ ThymeGlobals.MakeThymeViewers[wDir]; END; SetWorkingDirectory: PUBLIC PROC [wDir: ROPE, handle: ThymeHandle] = BEGIN ThymeGlobals.SetWorkingDirectory[wDir, handle]; END; Translate: PUBLIC PROC [cellType: CellType, outputFile: ROPE] = BEGIN root: TNode; wId _ 0; cId _ 0; iId _ 0; root _ TiogaFileOps.CreateRoot[]; PutHeader[outputFile, root]; PutTopLevelCircuit[cellType, root]; RestoreSavedNames[cellType]; TiogaFileOps.Store[root, outputFile] END; Simulate: PUBLIC PROC [inputFile: ROPE, handle: ThymeHandle] = BEGIN ViewerTools.SetContents[handle.input, inputFile]; ThymeGlobals.NormalRun[handle]; END; <> PutHeader: PROC [outputFile: ROPE, root: TNode] = BEGIN node: TNode; TiogaFileOps.SetStyle[root, "Cedar"]; node _ TiogaFileOps.InsertAsLastChild[root]; TiogaFileOps.SetContents[node, Rope.Cat["-- ", outputFile]]; [] _ TiogaFileOps.InsertAsLastChild[root]; END; PutTopLevelCircuit: PROC [cellType: CellType, root: TNode] = BEGIN tNode: TNode _ TiogaFileOps.InsertAsLastChild[root]; tSubNode: TNode; plotSpec, initSpec: ROPE; resultList: LIST OF CellInstance; thymePanelCT: CellType; thymePanel: ElectricalCoreClasses.Panel; IF cellType.class#CoreClasses.recordCellClass THEN ERROR; TiogaFileOps.SetContents[tNode, "CIRCUIT[Lambda _ 1, TDegC _ 25] = {"]; tSubNode _ TiogaFileOps.InsertAsLastChild[tNode]; TiogaFileOps.SetContents[tSubNode, "Vdd: Node;"]; tSubNode _ TiogaFileOps.InsertAsLastChild[tNode]; TiogaFileOps.SetContents[tSubNode, "! /DATools/DATools6.1/Thyme/SignalGenerators"]; tSubNode _ TiogaFileOps.InsertAsLastChild[tNode]; TiogaFileOps.SetContents[tSubNode, "! /DATools/DATools6.1/Thyme/BSIM"]; tSubNode _ TiogaFileOps.InsertAsLastChild[tNode]; TiogaFileOps.SetContents[tSubNode, "powerSupply: voltage[Vdd, Gnd] = 5.0;"]; [resultList, thymePanelCT] _ PutRecordCellType[cellType, root, 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]], ", Vdd_ 5.0", Rope.Cat[", ", pathName], Rope.Cat["_ ", Convert.RopeFromReal[init.value], "];"]]; Current => ERROR; -- No Init Current for the moment ENDCASE => ERROR; tNode _ TiogaFileOps.InsertAsLastChild[root]; TiogaFileOps.SetContents[tNode, initSpec]; }; ENDLOOP; <> tNode _ TiogaFileOps.InsertAsLastChild[root]; 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]]]; 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, "];"]; TiogaFileOps.SetContents[tNode, plotSpec]; <> tNode _ TiogaFileOps.InsertAsLastChild[root]; TiogaFileOps.SetContents[tNode, Rope.Cat["Run[", Rope.Cat["tMin _ ", ElectricalCoreClasses.RopeFromns[thymePanel.tMin], ", "], Rope.Cat["tMax _ ", ElectricalCoreClasses.RopeFromns[thymePanel.tMax], "];"] ]]; END; RestoreSavedNames: PROC [cellType: CellType] = BEGIN IF CoreProperties.GetCellTypeProp[cellType, savedNameValidProp]#NIL THEN { oName: ROPE _ NARROW[CoreProperties.GetCellTypeProp[cellType, savedNameProp]]; [] _ CoreOps.SetCellTypeName[cellType, oName]; CoreProperties.PutCellTypeProp[cellType, savedNameProp, NIL]; CoreProperties.PutCellTypeProp[cellType, savedNameValidProp, NIL]; } ELSE RETURN; IF cellType.class=CoreClasses.recordCellClass THEN { recordCT: CoreClasses.RecordCellType _ NARROW[cellType.data]; RestoreWireName: CoreOps.EachWireProc = { IF CoreProperties.GetWireProp[wire, savedNameValidProp]#NIL THEN { oName: ROPE _ NARROW[CoreProperties.GetWireProp[wire, savedNameProp]]; [] _ CoreOps.SetShortWireName[wire, oName]; CoreProperties.PutWireProp[wire, savedNameProp, NIL]; CoreProperties.PutWireProp[wire, savedNameValidProp, NIL]; }; }; [] _ CoreOps.VisitWire[recordCT.internal, RestoreWireName]; CoreOps.FlushNameCaches[recordCT.internal]; CoreOps.FlushNameCaches[cellType.public]; FOR i: NAT IN [0..recordCT.size) DO inst: CellInstance _ recordCT.instances[i]; instType: CellType _ RecastIcon[inst.type]; IF CoreProperties.GetCellInstanceProp[inst, savedNameValidProp]#NIL THEN { oName: ROPE _ NARROW[CoreProperties.GetCellInstanceProp[inst, savedNameProp]]; [] _ CoreClasses.SetCellInstanceName[inst, oName]; CoreProperties.PutCellInstanceProp[inst, savedNameProp, NIL]; CoreProperties.PutCellInstanceProp[inst, savedNameValidProp, NIL]; }; RestoreSavedNames[instType]; ENDLOOP; }; END; WireToAtomicWires: PROC [wire: Wire, unique: BOOL _ TRUE] RETURNS [wires: Wires] = BEGIN 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] END; Filter: PROC [in: Wires, filter: WireFilterProc] RETURNS [out: Wires] = BEGIN 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]; END; IsPublic: WireFilterProc = BEGIN RETURN [CoreProperties.GetWireProp[wire, isPublic]#NIL] END; IsVddOrGnd: WireFilterProc = BEGIN name: ROPE _ CoreOps.GetShortWireName[wire]; RETURN [Rope.Equal[name, "Vdd"] OR Rope.Equal[name, "Gnd"]]; END; WiresToRope: PROC [root: Wire, wires: Wires] RETURNS [rope: ROPE] = BEGIN 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]; END; ActualsToRope: PROC [public, internal: Wire, wires: Wires, topLevel: BOOL] RETURNS [rope: ROPE] = BEGIN 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]; END; NameTranslator: Rope.TranslatorType = BEGIN SELECT old FROM '* => new _ 'X; '. => new _ 'x; ENDCASE => new _ old; END; EnsureWireName: PROC [wire: Wire] RETURNS [name: ROPE] = BEGIN 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]; END; EnsureCellTypeName: PROC [cellType: CellType] RETURNS [name: ROPE] = BEGIN 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]; END; EnsureInstName: PROC [inst: CellInstance] RETURNS [name: ROPE] = BEGIN 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]; END; RecastIcon: PROC [ct: CellType] RETURNS [result: CellType] = BEGIN result _ ct; WHILE SinixOps.IsIcon[Sisyph.mode.decoration, result] DO result _ CoreOps.Recast[result]; ENDLOOP; END; <<>> <> PutRecordCellType: PROC [cellType: CellType, root: TNode, topLevel: BOOL] RETURNS [resultList: LIST OF CellInstance _ NIL, thymePanel: CellType _ NIL] = BEGIN tNode, subTNode: TNode; tNodeContents, subTNodeContents: ROPE; recordCT: CoreClasses.RecordCellType _ NARROW[cellType.data]; subCellTypeTab: HashTable.Table _ HashTable.Create[]; cellTypeName: ROPE _ EnsureCellTypeName[cellType]; EnsureInternalNames: CoreOps.EachWireProc = { IF wire#recordCT.internal THEN [] _ EnsureWireName[wire] }; MarkPublicWire: CoreOps.EachWireProc = { [] _ CoreProperties.PutWireProp[wire, isPublic, isPublic] }; <<>> <> [] _ CoreOps.VisitWire[recordCT.internal, EnsureInternalNames]; [] _ CoreOps.VisitWire[cellType.public, MarkPublicWire]; CoreOps.FlushNameCaches[recordCT.internal]; CoreOps.FlushNameCaches[cellType.public]; <<>> <> tNode _ TiogaFileOps.InsertAsLastChild[root]; IF ~topLevel THEN { tNodeContents _ Rope.Cat[ cellTypeName, ": CIRCUIT[", WiresToRope[cellType.public, WireToAtomicWires[cellType.public]], "] = {" ]; TiogaFileOps.SetContents[tNode, tNodeContents]; }; <> IF topLevel THEN subTNodeContents _ WiresToRope[recordCT.internal, Filter[WireToAtomicWires[recordCT.internal], IsVddOrGnd]] ELSE subTNodeContents _ WiresToRope[recordCT.internal, Filter[WireToAtomicWires[recordCT.internal], IsPublic]]; IF subTNodeContents#NIL AND ~Rope.Equal[subTNodeContents, ""] THEN { subTNode _ TiogaFileOps.InsertAsLastChild[tNode]; TiogaFileOps.SetContents[subTNode, Rope.Cat[subTNodeContents, ": Node;"]] }; <> FOR i: NAT IN [0..recordCT.size) DO inst: CellInstance _ recordCT.instances[i]; <> instType: CellType _ CoreOps.ToBasic[inst.type]; 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, tNode, FALSE].resultList; [] _ HashTable.Insert[subCellTypeTab, instType, subCellTypeResultList]}; <<>> <> subTNode _ TiogaFileOps.InsertAsLastChild[tNode]; subTNodeContents _ Rope.Cat[ Rope.Cat[instName, ": ", EnsureCellTypeName[instType]], "[", ActualsToRope[cellType.public, recordCT.internal, WireToAtomicWires[inst.actual, FALSE], topLevel], "];"]; TiogaFileOps.SetContents[subTNode, subTNodeContents]; <> 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, tNode]; ElectricalCoreClasses.resistorCellClass => PutResistorInstance[recordCT.internal, inst, instType, tNode]; ElectricalCoreClasses.inductorCellClass => PutInductorInstance[recordCT.internal, inst, instType, tNode]; ElectricalCoreClasses.capacitorCellClass => PutCapacitorInstance[recordCT.internal, inst, instType, tNode]; ElectricalCoreClasses.signalGeneratorCellClass => PutSignalGeneratorInstance[recordCT.internal, inst, instType, tNode]; 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]; subTNode _ TiogaFileOps.InsertAsLastChild[tNode]; subTNodeContents _ 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.RopeFromVolts[0.0], ";"]; TiogaFileOps.SetContents[subTNode, subTNodeContents]; }; 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; subTNode _ TiogaFileOps.InsertAsLastChild[tNode]; TiogaFileOps.SetContents[subTNode, "};"]; END; PutTransistorInstance: PROC [rootWire: Wire, inst: CellInstance, instType: CellType, rootTNode: TNode] = BEGIN tNode: TNode; tNodeContents: ROPE; transistor: CoreClasses.Transistor _ NARROW[instType.data]; instName: ROPE _ EnsureInstName[inst]; tNode _ TiogaFileOps.InsertAsLastChild[rootTNode]; 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];"] ]; TiogaFileOps.SetContents[tNode, tNodeContents]; END; PutResistorInstance: PROC [rootWire: Wire, inst: CellInstance, instType: CellType, rootTNode: TNode] = BEGIN tNode: TNode; tNodeContents: ROPE; resistor: ElectricalCoreClasses.Resistor _ NARROW[instType.data]; instName: ROPE _ EnsureInstName[inst]; tNode _ TiogaFileOps.InsertAsLastChild[rootTNode]; tNodeContents _ Rope.Cat[ Rope.Cat[instName, ": Resistor"], Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], "] = "], Rope.Cat[ElectricalCoreClasses.RopeFromKOhms[resistor.value], ";"] ]; TiogaFileOps.SetContents[tNode, tNodeContents]; END; PutInductorInstance: PROC [rootWire: Wire, inst: CellInstance, instType: CellType, rootTNode: TNode] = BEGIN tNode: TNode; tNodeContents: ROPE; inductor: ElectricalCoreClasses.Inductor _ NARROW[instType.data]; instName: ROPE _ EnsureInstName[inst]; tNode _ TiogaFileOps.InsertAsLastChild[rootTNode]; tNodeContents _ Rope.Cat[ Rope.Cat[instName, ": Inductor"], Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], "] = "], Rope.Cat[ElectricalCoreClasses.RopeFromuH[inductor.value], ";"] ]; TiogaFileOps.SetContents[tNode, tNodeContents]; END; PutCapacitorInstance: PROC [rootWire: Wire, inst: CellInstance, instType: CellType, rootTNode: TNode] = BEGIN tNode: TNode; tNodeContents: ROPE; capacitor: ElectricalCoreClasses.Capacitor _ NARROW[instType.data]; instName: ROPE _ EnsureInstName[inst]; tNode _ TiogaFileOps.InsertAsLastChild[rootTNode]; tNodeContents _ Rope.Cat[ Rope.Cat[instName, ": Capacitor"], Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], "] = "], Rope.Cat[ElectricalCoreClasses.RopeFrompF[capacitor.value], ";"] ]; TiogaFileOps.SetContents[tNode, tNodeContents]; END; PutSignalGeneratorInstance: PROC [rootWire: Wire, inst: CellInstance, instType: CellType, rootTNode: TNode] = BEGIN tNode: TNode; tNodeContents: ROPE; signalGenerator: ElectricalCoreClasses.SignalGenerator _ NARROW[instType.data]; instName: ROPE _ EnsureInstName[inst]; tNode _ TiogaFileOps.InsertAsLastChild[rootTNode]; 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; TiogaFileOps.SetContents[tNode, tNodeContents]; END; CopyCellInstance: PROC [inst: CellInstance] RETURNS [copy: CellInstance] = BEGIN 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] END; END.