CoreThymeImpl.mesa
Written by: Pradeep Sindhu March 27, 1986 3:52:07 pm PST
Last Edited by:
Pradeep Sindhu May 6, 1986 11:32:01 am PDT
Christian Jacobi, June 11, 1986 4:01:24 pm PDT
DIRECTORY
CommandTool, Convert, CoreOps, CoreClasses, CoreProperties, CoreThyme, HashTable, NewCoreClasses, Rope, spGlobals, TerminalIO, TiogaFileOps, ViewerTools;
CoreThymeImpl: CEDAR PROGRAM    
IMPORTS Convert, CoreOps, CoreClasses, CoreProperties, HashTable, NewCoreClasses, Rope, spGlobals, 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.propCopy, CoreProperties.PropDoCopy]]];
pathNameProp: ATOM ← CoreProperties.RegisterProperty[$CoreThymePathName, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy]]];
probeWireProp: ATOM ← CoreProperties.RegisterProperty[$CoreThymeProbeWire, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy]]];
alreadyNamedProp: ATOM ← CoreProperties.RegisterProperty[$CoreThymeAlreadyNamed, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy]]];
Public Procs
CreateThymeViewer: PUBLIC PROC [wDir: ROPE] RETURNS [handle: ThymeHandle] = BEGIN
handle ← spGlobals.MakeThymeViewers[wDir];
END;
SetWorkingDirectory: PUBLIC PROC [wDir: ROPE, handle: ThymeHandle] = BEGIN
spGlobals.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];
TiogaFileOps.Store[root, outputFile]
END;
Simulate: PUBLIC PROC [inputFile: ROPE, handle: ThymeHandle] = BEGIN
ViewerTools.SetContents[handle.input, inputFile];
spGlobals.NormalRun[handle];
END;
Internal Procs
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: NewCoreClasses.ThymePanel;
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.0/Thyme/SignalGenerators"];
tSubNode ← TiogaFileOps.InsertAsLastChild[tNode];
TiogaFileOps.SetContents[tSubNode, "! /DATools/DATools6.0/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.WriteRope["** Error: Sorry, no ThymePanel in cell\n"]; RETURN};
thymePanel ← NARROW[thymePanelCT.data, NewCoreClasses.ThymePanel];
Put Init Specs
FOR l: LIST OF CellInstance ← resultList, l.rest WHILE l#NIL DO
IF l.first.type.class=NewCoreClasses.initCellClass THEN {
init: NewCoreClasses.Init ← NARROW[l.first.type.data];
pathName: ROPENARROW[CoreProperties.GetCellInstanceProp[l.first, pathNameProp]];
SELECT init.type FROM
Voltage => initSpec ← Rope.Cat[
Rope.Cat["IC[", NewCoreClasses.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;
Put Plot Specs
tNode ← TiogaFileOps.InsertAsLastChild[root];
plotSpec ← Rope.Cat[
Rope.Cat["Plot[\"", thymePanel.title, "\", "],
Rope.Cat[":", NewCoreClasses.RopeFromns[thymePanel.tScale], ", "],
Rope.Cat[Convert.RopeFromReal[thymePanel.yMin], ", "],
Rope.Cat[Convert.RopeFromReal[thymePanel.yMax], ", "],
Rope.Cat["powerSupply^: ", NewCoreClasses.RopeFrommA[thymePanel.iScale]]];
FOR l: LIST OF CellInstance ← resultList, l.rest WHILE l#NIL DO
IF l.first.type.class=NewCoreClasses.probeCellClass THEN {
probe: NewCoreClasses.Probe ← NARROW[l.first.type.data];
pathName: ROPENARROW[CoreProperties.GetCellInstanceProp[l.first, pathNameProp]];
SELECT probe.type FROM
Voltage => plotSpec ← Rope.Cat[plotSpec, ", ", pathName, ": ", Convert.RopeFromReal[probe.scale]];
Current => plotSpec ← Rope.Cat[plotSpec, ", ", pathName, "^: ", NewCoreClasses.RopeFrommA[probe.scale]];
ENDCASE => ERROR;
};
ENDLOOP;
plotSpec ← Rope.Cat[plotSpec, "];"];
TiogaFileOps.SetContents[tNode, plotSpec];
Put Run Specs
tNode ← TiogaFileOps.InsertAsLastChild[root];
TiogaFileOps.SetContents[tNode, Rope.Cat["Run[",
Rope.Cat["tMin ← ", NewCoreClasses.RopeFromns[thymePanel.tMin], ", "],
Rope.Cat["tMax ← ", NewCoreClasses.RopeFromns[thymePanel.tMax], "];"]
]];
END;
WireToAtomicWires: PROC [wire: Wire] RETURNS [wires: Wires] = BEGIN
AddToWires: PROC [subWire: Wire] = {
wires ← CONS[subWire, wires];
};
wires ← NIL;
CoreOps.VisitAtomicWires[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] 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] 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, alreadyNamedProp]#NIL THEN RETURN;
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];
CoreProperties.PutWireProp[wire, alreadyNamedProp, alreadyNamedProp];
END;
EnsureCTName: PROC [cellType: CellType] RETURNS [name: ROPE] = BEGIN
name ← CoreOps.GetCellTypeName[cellType];
IF CoreProperties.GetCellTypeProp[cellType, alreadyNamedProp]#NIL THEN RETURN;
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];
CoreProperties.PutCellTypeProp[cellType, alreadyNamedProp, alreadyNamedProp];
END;
EnsureInstName: PROC [inst: CellInstance] RETURNS [name: ROPE] = BEGIN
name ← CoreClasses.GetCellInstanceName[inst];
IF CoreProperties.GetCellInstanceProp[inst, alreadyNamedProp]#NIL THEN RETURN;
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];
CoreProperties.PutCellInstanceProp[inst, alreadyNamedProp, alreadyNamedProp];
END;
Root is tioga node into which the recordCell definition will be inserted as a child
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[];
EnsureInternalNames: CoreOps.EachWireProc = {
IF wire#recordCT.internal THEN [] ← EnsureWireName[wire]
};
MarkPublicWire: CoreOps.EachWireProc = {
[] ← CoreProperties.PutWireProp[wire, isPublic, isPublic]
};
Ensure names on internal, mark public, and delete fullname caches
[] ← CoreOps.VisitWire[recordCT.internal, EnsureInternalNames];
[] ← CoreOps.VisitWire[cellType.public, MarkPublicWire];
CoreOps.FlushNameCaches[recordCT.internal];
CoreOps.FlushNameCaches[cellType.public];
[] ← EnsureCTName[cellType];
Put circuit header if needed
tNode ← TiogaFileOps.InsertAsLastChild[root];
IF ~topLevel THEN {
tNodeContents ← Rope.Cat[
CoreOps.GetCellTypeName[cellType],
": CIRCUIT[",
WiresToRope[cellType.public, WireToAtomicWires[cellType.public]],
"] = {"
];
TiogaFileOps.SetContents[tNode, tNodeContents];
};
If top-level then put internal nodes except Vdd&Gnd else put internal minus public
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;"]]
};
Now put the instances
FOR i: NAT IN [0..recordCT.size) DO
inst: CellInstance ← recordCT.instances[i];
WHILE inst.type.class=CoreClasses.identityCellClass DO
inst.type ← CoreOps.Recast[inst.type];
ENDLOOP;
SELECT inst.type.class FROM
CoreClasses.recordCellClass => {
instName: ROPE ← EnsureInstName[inst];
found: BOOL;
value: HashTable.Value;
subCellTypeResultList: LIST OF CellInstance;
Put the definition if it isn't there already
[found, value] ← HashTable.Fetch[subCellTypeTab, inst.type];
IF found
THEN subCellTypeResultList ← NARROW[value, LIST OF CellInstance]
ELSE {
subCellTypeResultList ← PutRecordCellType[inst.type, tNode, FALSE].resultList;
[] ← HashTable.Insert[subCellTypeTab, inst.type, subCellTypeResultList]};
Put the instance
subTNode ← TiogaFileOps.InsertAsLastChild[tNode];
subTNodeContents ← Rope.Cat[
Rope.Cat[instName, ": ", CoreOps.GetCellTypeName[inst.type]],
"[",
ActualsToRope[cellType.public, recordCT.internal, WireToAtomicWires[inst.actual]],
"];"];
TiogaFileOps.SetContents[subTNode, subTNodeContents];
Put the results in subCellTypeResultList onto resultList
FOR l: LIST OF CellInstance ← subCellTypeResultList, l.rest WHILE l#NIL DO
pathName: ROPENARROW[CoreProperties.GetCellInstanceProp[l.first, pathNameProp]];
voltageProbeOnPublicWire: BOOLFALSE;
Compute the replacementPathName if its a voltage probe on a public wire
IF l.first.type.class=NewCoreClasses.probeCellClass THEN {
probe: NewCoreClasses.Probe ← NARROW[l.first.type.data];
IF probe.type=Voltage THEN {
probeWire: Wire ← NARROW[CoreProperties.GetCellInstanceProp[l.first, probeWireProp]];
ForEachBinding: CoreOps.EachWirePairProc = {
IF publicWire=probeWire THEN {
voltageProbeOnPublicWire ← TRUE;
pathName ← WiresToRope[recordCT.internal, WireToAtomicWires[actualWire]];
CoreProperties.PutCellInstanceProp[l.first, probeWireProp, actualWire];
};
};
[] ← CoreOps.VisitBinding[inst.actual, inst.type.public, ForEachBinding]
};
};
IF ~voltageProbeOnPublicWire THEN pathName ← Rope.Cat[instName, "/", pathName];
[] ← CoreProperties.PutCellInstanceProp[l.first, pathNameProp, pathName];
resultList ← CONS[l.first, resultList];
ENDLOOP;
};
CoreClasses.transistorCellClass =>
PutTransistorInstance[recordCT.internal, inst, tNode];
NewCoreClasses.resistorCellClass =>
PutResistorInstance[recordCT.internal, inst, tNode];
NewCoreClasses.inductorCellClass =>
PutInductorInstance[recordCT.internal, inst, tNode];
NewCoreClasses.capacitorCellClass =>
PutCapacitorInstance[recordCT.internal, inst, tNode];
NewCoreClasses.signalGeneratorCellClass =>
PutSignalGeneratorInstance[recordCT.internal, inst, tNode];
NewCoreClasses.probeCellClass => {
probe: NewCoreClasses.Probe ← NARROW[inst.type.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]],
"] = ",
IF useResistor THEN NewCoreClasses.RopeFromKOhms[probe.resistance] ELSE NewCoreClasses.RopeFromVolts[0.0],
";"];
TiogaFileOps.SetContents[subTNode, subTNodeContents];
};
ENDCASE => ERROR;
resultList ← CONS[inst, resultList];
};
NewCoreClasses.initCellClass => {
init: NewCoreClasses.Init ← NARROW[inst.type.data];
SELECT init.type FROM
Voltage => [] ← CoreProperties.PutCellInstanceProp[inst, pathNameProp, WiresToRope[recordCT.internal, WireToAtomicWires[inst.actual]]];
Current => ERROR;
ENDCASE => ERROR;
resultList ← CONS[inst, resultList];
};
NewCoreClasses.thymePanelCellClass => thymePanel ← inst.type;
ENDCASE => ERROR;
ENDLOOP;
subTNode ← TiogaFileOps.InsertAsLastChild[tNode];
TiogaFileOps.SetContents[subTNode, "};"];
END;
PutTransistorInstance: PROC [rootWire: Wire, inst: CellInstance, rootTNode: TNode] = BEGIN
tNode: TNode;
tNodeContents: ROPE;
transistor: CoreClasses.Transistor ← NARROW[inst.type.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, rootTNode: TNode] = BEGIN
tNode: TNode;
tNodeContents: ROPE;
resistor: NewCoreClasses.Resistor ← NARROW[inst.type.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[NewCoreClasses.RopeFromKOhms[resistor.value], ";"]
];
TiogaFileOps.SetContents[tNode, tNodeContents];
END;
PutInductorInstance: PROC [rootWire: Wire, inst: CellInstance, rootTNode: TNode] = BEGIN
tNode: TNode;
tNodeContents: ROPE;
inductor: NewCoreClasses.Inductor ← NARROW[inst.type.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[NewCoreClasses.RopeFromuH[inductor.value], ";"]
];
TiogaFileOps.SetContents[tNode, tNodeContents];
END;
PutCapacitorInstance: PROC [rootWire: Wire, inst: CellInstance, rootTNode: TNode] = BEGIN
tNode: TNode;
tNodeContents: ROPE;
capacitor: NewCoreClasses.Capacitor ← NARROW[inst.type.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[NewCoreClasses.RopeFrompF[capacitor.value], ";"]
];
TiogaFileOps.SetContents[tNode, tNodeContents];
END;
PutSignalGeneratorInstance: PROC [rootWire: Wire, inst: CellInstance, rootTNode: TNode] = BEGIN
tNode: TNode;
tNodeContents: ROPE;
signalGenerator: NewCoreClasses.SignalGenerator ← NARROW[inst.type.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 ← ", NewCoreClasses.RopeFromVolts[signalGenerator.onLevel], ", "],
Rope.Cat["OffLevel ← ", NewCoreClasses.RopeFromVolts[signalGenerator.offLevel], ", "],
Rope.Cat["period ← ", NewCoreClasses.RopeFromns[signalGenerator.period], ", "],
Rope.Cat["width ← ", NewCoreClasses.RopeFromns[signalGenerator.width], ", "]],
Rope.Cat[
Rope.Cat["tRise ← ", NewCoreClasses.RopeFromns[signalGenerator.tRise], ", "],
Rope.Cat["tFall ← ", NewCoreClasses.RopeFromns[signalGenerator.tFall], ", "],
Rope.Cat["tDelay ← ", NewCoreClasses.RopeFromns[signalGenerator.tDelay], "];"]]
];
};
OneShot => {
tNodeContents ← Rope.Cat[
Rope.Cat[instName, ": OneShot"],
Rope.Cat[
Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], " | "],
Rope.Cat["OnLevel ← ", NewCoreClasses.RopeFromVolts[signalGenerator.onLevel], ", "],
Rope.Cat["OffLevel ← ", NewCoreClasses.RopeFromVolts[signalGenerator.offLevel], ", "],
Rope.Cat["width ← ", NewCoreClasses.RopeFromns[signalGenerator.width], ", "]],
Rope.Cat[
Rope.Cat["tRise ← ", NewCoreClasses.RopeFromns[signalGenerator.tRise], ", "],
Rope.Cat["tFall ← ", NewCoreClasses.RopeFromns[signalGenerator.tFall], ", "],
Rope.Cat["tDelay ← ", NewCoreClasses.RopeFromns[signalGenerator.tDelay], "];"]]
];
};
Step => {
tNodeContents ← Rope.Cat[
Rope.Cat[instName, ": Step"],
Rope.Cat[
Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], " | "],
Rope.Cat["OnLevel ← ", NewCoreClasses.RopeFromVolts[signalGenerator.onLevel], ", "],
Rope.Cat["OffLevel ← ", NewCoreClasses.RopeFromVolts[signalGenerator.offLevel], ", "]],
Rope.Cat[
Rope.Cat["tRise ← ", NewCoreClasses.RopeFromns[signalGenerator.tRise], ", "],
Rope.Cat["tDelay ← ", NewCoreClasses.RopeFromns[signalGenerator.tDelay], "];"]]
];
};
DC => {
tNodeContents ← Rope.Cat[
Rope.Cat[instName, ": Voltage"],
Rope.Cat["[", WiresToRope[rootWire, WireToAtomicWires[inst.actual]], ", Gnd] = "],
Rope.Cat[NewCoreClasses.RopeFromVolts[signalGenerator.onLevel], ";"]
];
};
ENDCASE => ERROR;
TiogaFileOps.SetContents[tNode, tNodeContents];
END;
END.