CoreThymeImpl.mesa
Written by: Pradeep Sindhu March 27, 1986 3:52:07 pm PST
Last Edited by:
Christian LeCocq February 13, 1987 10:31:03 am PST
Bertrand Serlet October 20, 1986 8:53:19 pm PDT
Pradeep Sindhu December 8, 1986 11:12:44 pm PST
Christian Jacobi, June 11, 1986 4:01:24 pm PDT
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]]];
The implementation is relatively straightforward except for the following point. The translation from Core to Thyme must be done in a way that the Core is not modified. Unfortunately, we need to at least modify names of wires, celltypes, and instances because Core names are not understood by Thyme. Furthermore, this name modification must be done in place (at least for wires) because we want to use Core primitives like GetFullWireNames when naming nodes. The way we handle this problem is to keep the old name around whenever we modify a name, and then to restore the old name after the translation from Core to Thyme is complete. The old name is kept in the property savedNameProp. The procedure that does the name fixup after translation is RestoreSavedNames. The reason we need the savedNameValidProp property is to discriminate between the cases savedNameProp=NIL because the property hasn't yet been put there and savedNameProp=NIL because the savedName is NIL.
Public Procs
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;
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: 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];
Put Init Specs
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: ROPENARROW[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;
Put Plot Specs
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: ROPENARROW[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];
Put Run Specs
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: ROPENARROW[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: ROPENARROW[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: ROPENARROW[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: BOOLTRUE] 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;
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[];
cellTypeName: ROPE ← EnsureCellTypeName[cellType];
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];
Put circuit header if needed
tNode ← TiogaFileOps.InsertAsLastChild[root];
IF ~topLevel THEN {
tNodeContents ← Rope.Cat[
cellTypeName,
": 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];
instType: CellType ← RecastIcon[inst.type];
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;
Put the definition if it isn't there already
[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]};
Put the instance
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];
Put the results in subCellTypeResultList onto resultList
FOR l: LIST OF CellInstance ← subCellTypeResultList, l.rest WHILE l#NIL DO
subCellInst: CellInstance ← CopyCellInstance[l.first];
pathName: ROPENARROW[CoreProperties.GetCellInstanceProp[subCellInst, pathNameProp]];
voltageProbeOnPublicWire: BOOLFALSE;
subCellInstType: CellType ← RecastIcon[subCellInst.type];
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
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.