SXOutputImplA.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Written by Shand, July 16, 1984 2:58:45 pm PDT
Last Edited by: Shand, March 12, 1985 1:23:35 am PST
Last Edited by: Spreitzer, January 16, 1985 11:53:05 am PST
Last Edited by: Jacobi, April 4, 1985 10:03:17 am PST
Last edited by: gbb March 15, 1986 5:52:20 pm PST
DIRECTORY
Ascii USING [Letter, Digit],
CD USING [Design, Instance, InstanceList, InterestRect, Object, Rect],
CDDirectory USING [Name],
CDIO USING [GetWorkingDirectory],
CDProperties USING [GetProp, GetPropFromInstance, PutPropOnInstance],
Convert USING [RopeFromInt, RopeFromRope],
FS USING [ComponentPositions, Error, ExpandName, FileInfo, StreamOpen],
IO USING [atom, char, Close, GetLength, int, Put, PutF, PutFR, PutR, PutRope, real, refAny, rope, RopeFromROS, ROS, STREAM, time],
Properties USING [GetProp, PropList, PutProp],
RefTab USING [Key, Pairs, Ref, Val],
Rope USING [Cat, Equal, Fetch, Find, Length, Replace, ROPE, Substr],
SX USING [AreaPerimRec, Circuit, CircuitNode, FindRootNode, LogicalCell, MergeRec, MergeRecList, NodeLinkage, NodeLocation, SignalName, TechHandle],
SXAccess USING [design, invocation, sxTech],
SXAccessInternal USING [GetSXData],
SXAtoms USING [fini, init, InstanceName, rosePrint, SignalName, spinifexCircuitDescription, thymePrint],
SXOutput USING [LinkageHousekeeper, LinkagePrintProc, NodePrintProc],
SXOutputPrivate,
SymTab USING [Create, Fetch, Ref, Store],
TerminalIO USING [WriteRope],
TiogaFileOps USING [AddLooks, CreateRoot, InsertAsLastChild, InsertNode, Ref, SetContents, SetFormat, SetStyle, Store],
TiogaOps USING [PutProp],
UserCredentials USING [Get];
SXOutputImplA:
CEDAR
PROGRAM
IMPORTS Ascii, CD, CDDirectory, CDIO, CDProperties, Convert, FS, IO, Properties, RefTab, Rope, SX, SXAccess, SXAccessInternal, SXAtoms, SXOutputPrivate, SymTab, TerminalIO, TiogaFileOps, TiogaOps, UserCredentials
EXPORTS SXOutput, SXOutputPrivate =
BEGIN OPEN SXOutputPrivate;
-- Name generator customization
CountSep: ROPE ~ "-";
portBase: ROPE ~ "p";
localBase: ROPE ~ "n";
stopperBase: ROPE ~ "tn";
transBase: ROPE ~ "Q";
circuitBase: ROPE ~ "C";
shortestNamesOnly: PUBLIC BOOL ← FALSE;
propCollisions: BOOL ← FALSE;
outputGeometricInfo: PUBLIC BOOL ← TRUE;
printLocalNodeLocation:
PUBLIC
BOOL ←
FALSE;
Note: This two switches are different, especially in the case of Rosemary output. Unfortunately they are not orthogonal
isPort: PUBLIC ATOM ← $SXIsPort;
actualCellInstanceName: PUBLIC ATOM ← $SXCellInstName;
actualSignalName: PUBLIC ATOM ← $SXActualSignalName;
releaseDirectory: ROPE;
PrintCircuit:
PUBLIC
PROCEDURE [cellList:
LIST
OF
REF LogicalCell, formatKey:
REF ANY] ~ {
HierarchyRoot:
PROCEDURE [cellList:
LIST
OF
REF LogicalCell]
RETURNS [
CD.Object] ~
INLINE {
FOR cl:
LIST
OF
REF LogicalCell ← cellList, cl.rest
WHILE cl #
NIL
DO
IF cl.rest = NIL THEN RETURN[cl.first.cellObj];
ENDLOOP;
ERROR
}; -- end HierarchyRoot
ReadGlobalSignals:
PROCEDURE [glob: SymTab.Ref] ~ {
-- SymTab keyed by signal names, value is use count.
globFile: IO.STREAM;
[] ← glob.Store[ "Gnd", $GlobalSignal];
globFile ← FS.StreamOpen[ FS.ExpandName["chip.wspec", desWDir].fullFName ! FS.Error => IF error.group = user THEN { GOTO NoFile } ];
TerminalIO.WriteRope[Rope.Cat["\nProcessing wiring spec file \"", "chip.wspec", "\"\n"]];
DO
tok: IO.TokenKind;
id: ROPE;
[tok, id] ← globFile.GetCedarTokenRope[ ! IO.Error => EXIT; IO.EndOfStream => EXIT];
IF tok = tokenID THEN
[] ← glob.Store[ id, $GlobalSignal];
ENDLOOP;
EXITS NoFile => NULL;
}; -- end ReadGlobalSignals
CheckFileName:
PROC [org:
ROPE]
RETURNS [full:
ROPE] =
BEGIN
cp: FS.ComponentPositions;
[full, cp, ] ← FS.ExpandName [org, desWDir];
IF NOT org.Equal[full.Substr[start: cp.base.start, len: cp.ext.start+cp.ext.length - cp.base.start]] THEN ERROR FS.Error[[user, $illegalName, IO.PutFR["%g not a valid base and extension", IO.refAny[org]] ]];
END; -- end CheckFileName
globals: SymTab.Ref;
desWDir: ROPE = CDIO.GetWorkingDirectory [SXAccess.design];
globals ← SymTab.Create [mod: 553, case: TRUE];
FOR cl:
LIST
OF
REF LogicalCell ← cellList, cl.rest
WHILE cl #
NIL
DO
NameObj:
PROC [obj:
CD.Object, name:
ROPE] =
BEGIN
naming: Naming ← NEW [NamingRep ← [next: NIL, named: obj, prefixes: NIL, name: name]];
IF ~globals.Store [name, naming]
THEN {
TerminalIO.WriteRope ["Collision on cell type name "];
TerminalIO.WriteRope [name];
TerminalIO.WriteRope [".\n"]};
-- Should be ERROR Duplicate name.
END; -- NameObj
NameObj [cl.first.cellObj, CDDirectory.Name[cl.first.cellObj]];
ENDLOOP;
ReadGlobalSignals [globals];
AddIntermediateNodes [cellList];
SELECT formatKey
FROM
--Thyme
SXAtoms.thymePrint => {
thymeFileName: ROPE;
thymeFile: TiogaFileOps.Ref ~ TiogaFileOps.CreateRoot [];
defnTextNode: TiogaFileOps.Ref;
{
ENABLE
FS.Error =>
IF error.group = user
THEN {
IF error.code = $illegalName
THEN {
thymeFileName ← FS.ExpandName ["ExtractedOutput.thy", desWDir].fullFName;
TerminalIO.WriteRope [Rope.Cat[ "\n\t", error.explanation, "\n\tExtracted output will appear in \"", thymeFileName, "\"\n"]];
GOTO AbleToOutput
}
ELSE { TerminalIO.WriteRope[error.explanation]; GOTO IOProblems }
};
thymeFileName ← CheckFileName [CDDirectory.Name[ HierarchyRoot[ cellList]].Cat[ ".thy"]];
EXITS AbleToOutput => NULL
};
TerminalIO.WriteRope [IO.PutR [IO.rope ["Commencing output of thyme file to \""], IO.rope [thymeFileName], IO.rope ["\""]] ];
thymeFile.SetStyle ["Cedar"];
defnTextNode ← thymeFile.InsertAsLastChild [];
defnTextNode.SetContents [IO.PutR [IO.rope[thymeFileName], IO.rope[", Written by Spinifex, "], IO.time[]] ];
-- Following LOOPHOLE caused by `opaque type' compiler problems.
TRUSTED { TiogaOps.PutProp[LOOPHOLE[defnTextNode], $Comment, NEW[BOOLEAN ← TRUE]] };
FOR cl:
LIST
OF
REF LogicalCell ← cellList, cl.rest
WHILE cl #
NIL
DO
defnTextNode ← thymeFile.InsertAsLastChild [defnTextNode];
defnTextNode.SetFormat ["unit"];
IF cl.first.circuit.properties.GetProp [SXAtoms.spinifexCircuitDescription] #
NIL
THEN {
defnTextNode.SetContents [IO.PutFR["-- Opaque cell \"%g\" elided from circuit description at this point --", IO.rope[CDDirectory.Name[cl.first.cellObj]]] ];
TRUSTED { TiogaOps.PutProp[LOOPHOLE[defnTextNode], $Comment, NEW[BOOLEAN ← TRUE]] }
}
ELSE {
PrintSubcircuit [desWDir, NIL, thymeFile, defnTextNode, cl.first.cellObj, globals, formatKey]
};
ENDLOOP;
thymeFile.Store [thymeFileName !
FS.Error => {
IF error.group = user
THEN {
IF error.code = $illegalName
THEN {
thymeFile.Store ["///temp/ThymeOut.thy" ];
TerminalIO.WriteRope [Rope.Cat[ "\n\t", error.explanation, "\n\tExtracted output will appear in \"///temp/ThymeOut.thy\""]];
CONTINUE
}
ELSE { TerminalIO.WriteRope[error.explanation]; GOTO IOProblems }
};
} ];
TerminalIO.WriteRope [" — done.\n"];
EXITS IOProblems => TerminalIO.WriteRope [" — failed.\n"];
};
--RoseMary
SXAtoms.rosePrint => {
GenKey: INT ← 0;
rootName: ROPE ← CDDirectory.Name [HierarchyRoot[cellList]];
fullRootName, DFFileName: ROPE;
DFfile: IO.STREAM;
{
ENABLE
FS.Error =>
IF error.group = user
THEN {
IF error.code = $illegalName
THEN {
rootName ← "ExtractedRoseOut";
fullRootName ← FS.ExpandName [rootName, desWDir].fullFName;
DFfile ← FS.StreamOpen [DFFileName ← fullRootName.Cat["-str.df"], $create];
TerminalIO.WriteRope [ Rope.Cat ["\n\t", error.explanation, "\n\tExtracted output will appear in \"", DFFileName, "\"\n"]];
GOTO AbleToOutput
}
ELSE { TerminalIO.WriteRope[error.explanation]; GOTO IOProblems }
};
Try the cell name
fullRootName ← CheckFileName [rootName];
DFfile ← FS.StreamOpen [DFFileName ← fullRootName.Cat["-str.df"], $create];
EXITS AbleToOutput => NULL
};
TerminalIO.WriteRope [IO.PutR [IO.rope["Commencing output rosemary file to \""], IO.rope[DFFileName], IO.rope["\""]] ];
DFfile.PutF ["-- %g.df written by Spinifex structure capturer, %g\n", IO.rope[rootName], IO.time[]];
DFfile.PutF ["-- from design %g\n\n\n", IO.rope[SXAccess.design.name]];
DFfile.PutF ["Directory ??\n\t%g-str.df\n", IO.rope[rootName]];
FOR cl:
LIST
OF
REF LogicalCell ← cellList, cl.rest
WHILE cl #
NIL
DO
KeepHouse [cl.first, DFfile, SXAtoms.init];
ENDLOOP;
FOR cl:
LIST
OF
REF LogicalCell ← cellList, cl.rest
WHILE cl #
NIL
DO
cellFileName: ROPE ← CDDirectory.Name [cl.first.cellObj];
IF cl.first.circuit.properties.GetProp [SXAtoms.spinifexCircuitDescription] #
NIL
THEN {
DFfile.PutF ["-- (CellType \"%g\") Opaque cell elided from output at this point\n", IO.rope[CDDirectory.Name[cl.first.cellObj]]]
}
ELSE {
cellFile: TiogaFileOps.Ref ~ TiogaFileOps.CreateRoot [];
firstNode: TiogaFileOps.Ref ~ cellFile.InsertAsLastChild [];
cellFile.SetStyle ["Cedar"];
firstNode.SetFormat ["unit"];
PrintSubcircuit [desWDir, DFfile, cellFile, firstNode, cl.first.cellObj, globals, formatKey];
{
ENABLE
FS.Error =>
IF error.group = user
THEN {
IF error.code = $illegalName
THEN {
cellFileName ← rootName.Cat ["-", Convert.RopeFromInt[GenKey]];
GenKey ← GenKey.SUCC;
cellFile.Store [FS.ExpandName[cellFileName.Cat[".sch"], desWDir].fullFName];
CONTINUE
}
ELSE { TerminalIO.WriteRope [error.explanation]; GOTO IOProblems }
};
fName: ROPE ~ CheckFileName [cellFileName.Cat[".sch"]];
cellFile.Store [fName]
};
DFfile.PutF ["-- (CellType \"%g\")\n %g.sch\n", IO.rope[CDDirectory.Name[cl.first.cellObj]], IO.rope[cellFileName]]
};
ENDLOOP;
FOR cl:
LIST
OF
REF LogicalCell ← cellList, cl.rest
WHILE cl #
NIL
DO
KeepHouse [cl.first, DFfile, SXAtoms.fini];
ENDLOOP;
DFfile.PutRope [Rope.Cat["\nExports Imports ", releaseDirectory, "StructuralPrimitives.DF Of ~=\n"]];
DFfile.Close [];
TerminalIO.WriteRope [" — done.\n"];
EXITS IOProblems => TerminalIO.WriteRope [" — failed.\n"];
};
ENDCASE => {
TerminalIO.WriteRope ["Warning: Unknown output format, no file written.\n"];
};
CleanUp [cellList];
}; -- end PrintCircuit
KeepHouse:
PROC [lc:
REF LogicalCell, dfStream:
IO.
STREAM, key:
ATOM] =
BEGIN
FOR links:
LIST
OF
REF NodeLinkage ← lc.circuit.linkages, links.rest
WHILE links #
NIL
DO
housekeeper: REF ANY ← CDProperties.GetProp[from: links.first.source.ob.class.properties, prop: key];
IF housekeeper#
NIL
THEN {
NARROW [housekeeper, REF SXOutput.LinkageHousekeeper]^[dfStream, links.first];
};
ENDLOOP;
END; -- end KeepHouse
QuoteRose: QuoteProc = {
RETURN [Convert.RopeFromRope [name]]
};
QuoteThyme: QuoteProc =
BEGIN
l: INT ~ name.Length[];
IF l = 0 THEN RETURN ["$$"];
FOR i:
INT
IN [0..l)
DO
c: CHAR = name.Fetch[i];
IF ~Ascii.Letter[c] AND ~Ascii.Digit[c] THEN EXIT;
REPEAT FINISHED => RETURN [name]
ENDLOOP;
{
--Name has non-alphanumerics.
constructedName: ROPE ← Rope.Cat ["$", name];
dollarPosnSUCC: INT ← 1;
WHILE (dollarPosnSUCC ← constructedName.Find["$", dollarPosnSUCC]) # -1
DO
constructedName ← constructedName.Replace[dollarPosnSUCC, 1, "$$"];
dollarPosnSUCC ← dollarPosnSUCC + 2 -- Jump over inserted $$
ENDLOOP;
RETURN [constructedName.Cat["$"]]
}
END; -- end QuoteThyme
PrintSubcircuit:
PROCEDURE [desWDir:
ROPE, dfStream:
IO.
STREAM, root, circuitDefn: TiogaFileOps.Ref, cellObj:
CD.Object, GlobalNames: SymTab.Ref, formatKey:
REF
ANY] ~ {
--Format specific routines.
PrintRoseStray: PrintStrayProc ~ {
[Stream: IO.STREAM, node: REF CircuitNode]
startedAPList: BOOLEAN ← FALSE;
FOR apList:
LIST
OF AreaPerimRec ← node.dim, apList.rest
WHILE apList #
NIL
DO
r: ROPE = tech.spinifexLayerNames [apList.first.layer].thymeName;
IF r = NIL THEN LOOP;
IF apList.first.area = 0 AND apList.first.perim = 0 THEN LOOP;
IF ~startedAPList
THEN {
Stream.Put [IO.rope[" (MOSStray"]];
};
IF apList.first.area # 0
THEN
Stream.PutF [" (a %g %g)", IO.rope[r], IO.int[apList.first.area/(SXAccess.design.technology.lambda*SXAccess.design.technology.lambda)]];
IF apList.first.perim # 0
THEN
Stream.PutF [" (p %g %g)", IO.rope[r], IO.int[apList.first.perim/SXAccess.design.technology.lambda]];
startedAPList ← TRUE
ENDLOOP;
IF startedAPList
THEN
Stream.PutRope [")"];
}; -- end PrintRoseStray
PrintThymeStray: PrintStrayProc ~ {
[Stream: IO.STREAM, node: REF CircuitNode]
startedAPList: BOOLEAN ← FALSE;
FOR apList:
LIST
OF AreaPerimRec ← node.dim, apList.rest
WHILE apList #
NIL
DO
r: ROPE ~ tech.spinifexLayerNames [apList.first.layer].thymeName;
IF r = NIL THEN LOOP;
IF apList.first.area = 0 AND apList.first.perim = 0 THEN LOOP;
IF ~startedAPList
THEN {
IF Stream.GetLength[] # 0 THEN Stream.PutRope [" "];
Stream.PutRope ["?: Stray["];
PrintNode [Stream, node];
Stream.Put [IO.rope["|"]]
}
ELSE
Stream.Put [IO.char[ ',]];
Stream.PutF [" a%g←N*%g, p%g←N*%g", IO.rope[r], IO.int[apList.first.area/(SXAccess.design.technology.lambda*SXAccess.design.technology.lambda)], IO.rope[r], IO.int[apList.first.perim/SXAccess.design.technology.lambda]];
startedAPList ← TRUE
ENDLOOP;
IF startedAPList
THEN
Stream.PutRope ["];"];
}; -- end PrintThymeStray
Print
Rose
NodeLoc: PrintNodeLocProc ~ {
[Stream: IO.STREAM, node: REF CircuitNode]
IF outputGeometricInfo
THEN {
a: ATOM ~ tech.spinifexLayerNames [node.loc.layer].layerId;
Stream.PutF [" (locHint %g %g %g)", IO.int[node.loc.xy.x/SXAccess.design.technology.lambda], IO.int[node.loc.xy.y/SXAccess.design.technology.lambda], IO.atom[a]]
}
}; -- end PrintRoseNodeLoc
Print
Thyme
NodeLoc: PrintNodeLocProc ~ {
[Stream: IO.STREAM, node: REF CircuitNode]
IF outputGeometricInfo
THEN {
a: ATOM ~ tech.spinifexLayerNames [node.loc.layer].layerId;
Stream.PutRope ["-- "];
PrintNode [Stream, node];
Stream.PutF [" in %g at %g %g --", IO.atom[a], IO.int[node.loc.xy.x/SXAccess.design.technology.lambda], IO.int[node.loc.xy.y/SXAccess.design.technology.lambda]]
}
}; -- end PrintThymeNodeLoc
SXOutput.NodePrintProc
QNodeName:
PROCEDURE [node:
REF CircuitNode]
RETURNS [name:
ROPE] ~ {
Returns Quoted name of node.
name ← Quote [GetAName[node]];
}; -- end QNodeName
PortHead: TiogaFileOps.Ref;
PrintRoseHead: PrintHeadProc ~ {
output.PutF ["-- %g", IO.rope[ name]];
circuitDefn.SetContents [output.RopeFromROS[]];
-- Following LOOPHOLE caused by `opaque type' compiler problems.
TRUSTED { TiogaOps.PutProp[LOOPHOLE[circuitDefn], $Comment, NEW[BOOLEAN ← TRUE]] };
output ← output.ROS [];
output.PutF ["(CreatingUser \"%g\")", IO.rope[UserCredentials.Get[].name]];
AppendTiogaNode [output];
output ← output.ROS [];
output.PutF ["(CreationTime \"%g\")", IO.time[]];
AppendTiogaNode [output];
output ← output.ROS [];
AppendTiogaNode [output];
output ← output.ROS [];
output.PutRope ["(DerivingProgram \"Spinifex\" \"July 6, 1985 6:50:16 pm PDT\")"];
AppendTiogaNode [output];
output ← output.ROS [];
output.PutF ["(CellTypeName %g)", IO.rope[name]];
AppendTiogaNode [output];
IF outputGeometricInfo
THEN {
b: CD.Rect ← CD.InterestRect [obj];
output ← output.ROS [];
output.PutF ["(scale %g \"lambda\")", IO.int[1]];
AppendTiogaNode [output];
output ← output.ROS [];
output.PutF ["(bb %g %g %g %g)",
IO.real [REAL[b.x1]/SXAccess.design.technology.lambda],
IO.real [REAL[b.y1]/SXAccess.design.technology.lambda],
IO.real [REAL[b.x2]/SXAccess.design.technology.lambda],
IO.real [REAL[b.y2]/SXAccess.design.technology.lambda]];
AppendTiogaNode[output];
};
output ← output.ROS [];
output.Put [IO.rope["(Ports"]];
AppendTiogaNode [output];
Introduce 3rd level sub-structure.
PortHead ← currLine;
output ← output.ROS []
}; -- end PrintRoseHead
PrintThymeHead: PrintHeadProc ~ {
[obj: CD.Object, name: ROPE]
output.Put [IO.rope [name], IO.rope [": circuit["]];
}; -- end PrintThymeHead
PrintRoseFormal: PrintFormalProc ~ {
[qName: ROPE, first: BOOL, node: REF CircuitNode]
portDef: TiogaFileOps.Ref ~ PortHead.InsertAsLastChild[];
naming: Naming ← GetANaming[node];
INTERIM, EC if present should go here.
output.PutRope ["("];
PrintNaming [output, naming];
output.PutRope [")"];
portDef.SetContents [output.RopeFromROS[]];
portDef.SetFormat ["code"];
output ← output.ROS [];
output.PutRope ["(N "];
PrintNaming [output, naming];
PrintStray [output, node];
PrintNodeLoc [output, node];
output.PutRope [")"];
AppendTiogaNode [output];
output ← output.ROS [];
Port node defs, e.g. (PN "Vdd" "Vdd")
output.PutF ["(PN %g %g)", IO.rope[qName], IO.rope[qName]];
AppendTiogaNode [output];
output ← output.ROS []
}; -- end PrintRoseFormal
PrintThymeFormal: PrintFormalProc ~ {
[qName: ROPE, first: BOOL, node: REF CircuitNode]
strayROS: IO.STREAM ~ IO.ROS[];
output.Put [IO.rope[IF first THEN " " ELSE ", "], IO.rope[qName]];
IF printLocalNodeLocation
THEN
BEGIN
locROS: IO.STREAM ~ IO.ROS[];
locLine: TiogaFileOps.Ref ← NIL;
PrintNodeLoc [locROS, node];
locLine ← circuitDefn.InsertAsLastChild [];
locLine.SetContents [locROS.RopeFromROS[]];
-- Following LOOPHOLE caused by `opaque type' compiler problems.
TRUSTED {TiogaOps.PutProp[LOOPHOLE[locLine], $Comment, NEW[BOOLEAN ← TRUE]]};
END;
PrintStray [strayROS, node];
IF strayROS.GetLength [] # 0
THEN
circuitDefn.InsertAsLastChild[].SetContents [strayROS.RopeFromROS[]];
}; -- end PrintThymeFormal
PrintRoseStartBody: PrintStartBodyProc ~ {
[cellName: ROPE]
portClose: TiogaFileOps.Ref ~ PortHead.InsertAsLastChild[];
privateStart: TiogaFileOps.Ref ~ PortHead.InsertNode[];
portClose.SetContents [")"];
portClose.SetFormat ["code"];
privateStart.SetContents ["(PrivateFollows)"];
portClose.SetFormat ["code"];
}; -- end PrintRoseStartBody
PrintThymeStartBody: PrintStartBodyProc ~ {
[cellName: ROPE]
output.Put [IO.rope["| N𡤁] = {"]];
circuitDefn.SetContents [output.RopeFromROS[]];
circuitDefn.AddLooks [0, cellName.Length[], 'b, root];
output ← output.ROS []
}; -- end PrintThymeStartBody
PrintRoseLocalNode: PrintLocalNodeProc ~ {
[node: REF CircuitNode]
Local node defs, e.g. (N "Vdd")
naming: Naming ← GetANaming [node];
output.PutRope ["(N "];
PrintNaming [output, naming];
PrintStray [output, node];
PrintNodeLoc [output, node];
output.PutRope [")"];
AppendTiogaNode [output];
output ← output.ROS [];
}; -- end PrintRoseLocalNode
PrintThymeLocalNode: PrintLocalNodeProc ~ {
[node: REF CircuitNode]
naming: Naming;
goodNode: BOOL ← FALSE;
FOR apList:
LIST
OF AreaPerimRec ← node.dim, apList.rest
WHILE apList #
NIL
DO
IF (tech.spinifexLayerNames [apList.first.layer].thymeName #
NIL)
THEN
BEGIN
goodNode ← TRUE; LOOP
END
ENDLOOP;
IF (
NOT goodNode)
THEN
BEGIN
TerminalIO.WriteRope ["\n Warning: Bogus node omitted from circuit, probably an unconnected well.\n"];
RETURN
END;
naming ← GetANaming[node];
IF printLocalNodeLocation
THEN
BEGIN
locROS: IO.STREAM ~ IO.ROS [];
locLine: TiogaFileOps.Ref ← NIL;
PrintNodeLoc [locROS, node];
locLine ← circuitDefn.InsertAsLastChild [];
locLine.SetContents [locROS.RopeFromROS[]];
-- Following LOOPHOLE caused by `opaque type' compiler problems.
TRUSTED { TiogaOps.PutProp[LOOPHOLE[locLine], $Comment, NEW[BOOLEAN ← TRUE]] };
END;
IF naming.next # NIL THEN PrintNodeAliases [node, naming.next];
PrintNode [output, node];
output.Put [IO.rope [": node;"]];
PrintStray [output, node];
AppendTiogaNode [output];
output ← output.ROS [];
}; -- end PrintThymeLocalNode
PrintRoseNodeAlias: PrintNodeAliasesProc ~ {
[node: REF CircuitNode, alias: Naming]
ERROR -- should have been taken care of by PrintNaming -- ;
}; -- end PrintRoseNodeAlias
PrintThymeNodeAlias: PrintNodeAliasesProc ~ {
[node: REF CircuitNode, alias: Naming]
IF node.properties.GetProp [isPort] = isPort THEN RETURN;
output.Put [IO.rope [ "-- ALIAS[ "]];
PrintNode [output, node];
FOR alias ← alias, alias.next
WHILE alias #
NIL
DO
IF Valid [alias] THEN output.Put [IO.rope [", "], IO.rope[Quote[NamingName[alias]]]];
ENDLOOP;
output.Put [IO.rope[ "] --"]];
AppendTiogaNode [output];
-- Following LOOPHOLE caused by `opaque type' compiler problems.
TRUSTED { TiogaOps.PutProp[LOOPHOLE[currLine], $Comment, NEW[BOOLEAN ← TRUE]] };
output ← output.ROS[]
}; -- end PrintThymeNodeAlias
PrintRoseInstanceHead: PrintInstanceHeadProc ~ {
[inst: CD.Instance, defName: ROPE]
naming: Naming ← GetANaming [inst];
output.PutRope ["(CI "];
PrintNaming [output, naming, Rope.Cat[" ", Quote[defName]]];
PrintRoseInstantiationTransformation [output, inst];
output.PutRope [" (CIC"];
}; -- end PrintRoseInstanceHead
PrintThymeInstanceHead: PrintInstanceHeadProc ~ {
[inst: CD.Instance, defName: ROPE]
output.PutF ["%g: %g[", IO.rope[Quote[GetAName[inst]]], IO.rope[Quote[defName]]];
}; -- end PrintThymeInstanceHead
PrintRoseActual: PrintActualProc ~ {
[qActualNode, qFormalPort: ROPE, actualNum: CARDINAL]
output.PutF [" (%g %g)", IO.rope[qFormalPort], IO.rope[qActualNode] ]
}; -- end PrintRoseActual
PrintThymeActual: PrintActualProc ~ {
[qActualNode, qFormalPort: ROPE, actualNum: CARDINAL]
IF actualNum # CountBase THEN output.PutRope[ ", "];
output.PutRope [qActualNode];
}; -- end PrintThymeActual
PrintRoseInstanceEnd: PrintInstanceEndProc ~ {
output.PutRope [ "))"];
AppendTiogaNode [output];
output ← output.ROS []
}; -- end PrintRoseInstanceEnd
PrintThymeInstanceEnd: PrintInstanceEndProc ~ {
output.PutRope ["| N←N];"];
AppendTiogaNode [output];
output ← output.ROS []
}; -- end PrintThymeInstanceEnd
PrintRoseBodyEnd: PrintBodyEndProc ~ {
};
PrintThymeBodyEnd: PrintBodyEndProc ~ {
output.PutRope ["};"];
AppendTiogaNode [output];
output ← output.ROS []
}; -- end PrintThymeBodyEnd
End of format specific routines
AppendTiogaNode:
PROCEDURE [Stream:
IO.
STREAM] ~ {
currLine ← circuitDefn.InsertAsLastChild [currLine];
currLine.SetContents [Stream.RopeFromROS[]];
currLine.SetFormat ["code"]
}; -- end AppendTiogaNode
Symbols: SymTab.Ref;
UsedSymbol:
PROCEDURE [r:
ROPE]
RETURNS [
BOOLEAN] ~ {
RETURN [GlobalNames.Fetch[r].found OR Symbols.Fetch[r].found]
}; -- end UsedSymbol
FindUnique:
PROCEDURE [ base:
ROPE, start:
INTEGER, val:
REF
ANY ←
NIL]
RETURNS [rope:
ROPE, count:
INTEGER] ~ {
-- Finds first string of form base-int where int>=start where base-int is not in Symbols. Enters the found string in Symbols.
count ← start;
DO
rope ← base.Cat [Convert.RopeFromInt[count]];
IF ~UsedSymbol [rope]
THEN {
[] ← Symbols.Store [rope, val];
RETURN
};
count ← count.SUCC;
ENDLOOP;
}; -- end FindUnique
Lookup:
PROC [name:
ROPE]
RETURNS [naming: Naming] = {
found: BOOL;
val: REF ANY;
[found, val] ← GlobalNames.Fetch [name];
IF found THEN RETURN [NARROW[val]];
[found, val] ← Symbols.Fetch [name];
IF found THEN RETURN [NARROW[val]];
naming ← NIL;
}; -- end Lookup
NameThing:
PROC [thing:
REF
ANY, qual:
ROPE ←
NIL, short:
ROPE, explicit, squash, onlyCollide:
BOOL ←
FALSE] = {
NoteNewNaming:
PROC = {
WITH thing
SELECT
FROM
node: REF CircuitNode => node.properties ← node.properties.PutProp [actualSignalName, this];
appl: CD.Instance => CDProperties.PutPropOnInstance [onto~appl, prop~actualCellInstanceName, val~this];
ENDCASE => ERROR
}; -- end NoteNewNaming
user: Naming ← Lookup [short];
next, this: Naming;
name: ROPE ← short;
doingNets: BOOL ← ISTYPE [thing, REF CircuitNode];
IF explicit AND qual # NIL THEN ERROR;
IF user #
NIL
AND user.named = thing
AND
NOT onlyCollide
THEN {
IF explicit # user.explicit THEN ERROR;
IF qual # NIL AND user.prefixes = NIL THEN user.prefixes ← LIST[NIL];
IF user.prefixes # NIL THEN user.prefixes ← CONS [qual, user.prefixes];
RETURN;
};
WITH thing
SELECT
FROM
node: REF CircuitNode => next ← NARROW[ node.properties.GetProp[ actualSignalName]];
appl: CD.Instance => next ← NARROW[ CDProperties.GetPropFromInstance[ from~appl, prop~actualCellInstanceName]];
ENDCASE => ERROR;
this ← NEW [NamingRep ← [next: next, named: IF NOT onlyCollide THEN thing ELSE NIL, prefixes: IF qual # NIL THEN LIST[qual] ELSE NIL, name: short, explicit: explicit, collided: onlyCollide, squash: squash]];
IF user # NIL THEN Rename [short, user, doingNets];
IF user =
NIL
OR onlyCollide
THEN {
[] ← Symbols.Store [short, this]; NoteNewNaming []; RETURN};
IF qual #
NIL
THEN {
long: ROPE ← qual.Cat [".", short];
NameThing [thing, NIL, long];
RETURN;
};
NoteNewNaming [];
this.explicit ← FALSE;
[this.name, user.count] ← FindUnique [base~IF squash THEN short ELSE (short.Cat[CountSep]), start~user.count+1, val~this];
}; -- end NameThing
Rename:
PROC [key:
ROPE, tomb: Naming, doingNets:
BOOL] = {
thing: REF ANY ← tomb.named;
nameNIL: BOOL ← FALSE;
IF tomb.collided THEN RETURN;
tomb.collided ← TRUE;
WITH tomb.named
SELECT
FROM
n: REF CircuitNode => NULL;
a: CD.Instance => IF doingNets THEN RETURN;
o: CD.Object => RETURN;
ENDCASE => ERROR;
tomb.named ← NIL;
IF tomb.prefixes =
NIL
THEN {
NameThing [thing~thing, short~key, squash~tomb.squash]; RETURN};
FOR prefixes: ROPEList ← tomb.prefixes, prefixes.rest
WHILE prefixes #
NIL
DO
IF prefixes.first = NIL THEN nameNIL ← TRUE ELSE NameThing [thing, NIL, prefixes.first.Cat[".", tomb.name]];
ENDLOOP;
tomb.prefixes ← NIL;
IF nameNIL THEN NameThing [thing~thing, short~tomb.name, squash~tomb.squash];
}; -- end Rename
-- Output format customization
PrintStray: PrintStrayProc ~
SELECT formatKey
FROM
SXAtoms.thymePrint => PrintThymeStray,
SXAtoms.rosePrint => PrintRoseStray,
ENDCASE => ERROR;
PrintNodeLoc: PrintNodeLocProc ~
SELECT formatKey
FROM
SXAtoms.thymePrint => PrintThymeNodeLoc,
SXAtoms.rosePrint => PrintRoseNodeLoc,
ENDCASE => ERROR;
Quote: QuoteProc ~
SELECT formatKey
FROM
SXAtoms.thymePrint => QuoteThyme,
SXAtoms.rosePrint => QuoteRose,
ENDCASE => ERROR;
PrintNode: SXOutput.NodePrintProc
-- [ stream: IO.STREAM, node: REF CircuitNode] -- ~ {
printName: ROPE ← GetAName [node];
stream.PutRope [Quote[printName]];
};
PrintHead: PrintHeadProc ~
SELECT formatKey
FROM
SXAtoms.thymePrint => PrintThymeHead,
SXAtoms.rosePrint => PrintRoseHead,
ENDCASE => ERROR;
PrintFormal: PrintFormalProc ~
SELECT formatKey
FROM
SXAtoms.thymePrint => PrintThymeFormal,
SXAtoms.rosePrint => PrintRoseFormal,
ENDCASE => ERROR;
PrintStartBody: PrintStartBodyProc ~
SELECT formatKey
FROM
SXAtoms.thymePrint => PrintThymeStartBody,
SXAtoms.rosePrint => PrintRoseStartBody,
ENDCASE => ERROR;
PrintLocalNode: PrintLocalNodeProc ~
SELECT formatKey
FROM
SXAtoms.thymePrint => PrintThymeLocalNode,
SXAtoms.rosePrint => PrintRoseLocalNode,
ENDCASE => ERROR;
PrintNodeAliases: PrintNodeAliasesProc ~
SELECT formatKey
FROM
SXAtoms.thymePrint => PrintThymeNodeAlias,
SXAtoms.rosePrint => PrintRoseNodeAlias,
ENDCASE => ERROR;
PrintInstanceHead: PrintInstanceHeadProc ~
SELECT formatKey
FROM
SXAtoms.thymePrint => PrintThymeInstanceHead,
SXAtoms.rosePrint => PrintRoseInstanceHead,
ENDCASE => ERROR;
PrintActual: PrintActualProc ~
SELECT formatKey
FROM
SXAtoms.thymePrint => PrintThymeActual,
SXAtoms.rosePrint => PrintRoseActual,
ENDCASE => ERROR;
PrintInstanceEnd: PrintInstanceEndProc ~
SELECT formatKey
FROM
SXAtoms.thymePrint => PrintThymeInstanceEnd,
SXAtoms.rosePrint => PrintRoseInstanceEnd,
ENDCASE => ERROR;
PrintBodyEnd: PrintBodyEndProc ~
SELECT formatKey
FROM
SXAtoms.thymePrint => PrintThymeBodyEnd,
SXAtoms.rosePrint => PrintRoseBodyEnd,
ENDCASE => ERROR;
ignoreChildNames: BOOLEAN ~ formatKey = SXAtoms.rosePrint;
sxData: REF SX.LogicalCell ← SXAccessInternal.GetSXData[cellObj];
circuit: REF Circuit ← sxData.circuit;
tech: REF TechHandle = SXAccess.sxTech;
localNodes: CARDINAL ← CountBase;
nodeStoppers: CARDINAL ← CountBase;
output: IO.STREAM ← IO.ROS[];
currLine: TiogaFileOps.Ref ← NIL;
-- First we must count how many times each symbol is used. The reason we do this is to avoid suffixing counts to symbols which are used only once.
{
count: INTEGER ← 17;
FOR nl:
LIST
OF
REF CircuitNode ← circuit.nodes, nl.rest
WHILE nl #
NIL
DO
count ← count.SUCC;
ENDLOOP;
Symbols ← SymTab.Create[mod~ count, case~ TRUE]
};
Naming of subcircuits.
FOR appls:
CD.InstanceList ← circuit.subcircuits, appls.rest
WHILE appls #
NIL
DO
WITH CDProperties.GetPropFromInstance[appls.first, SXAtoms.InstanceName]
SELECT
FROM
r: ROPE => NameThing [appls.first, NIL, r, TRUE];
ENDCASE => NameThing [thing~appls.first, short~circuitBase, squash~TRUE];
ENDLOOP;
Naming of linkages.
FOR links:
LIST
OF
REF NodeLinkage ← circuit.linkages, links.rest
WHILE links #
NIL
DO
PrintProc: REF ANY ← CDProperties.GetProp [from~links.first.source.ob.class.properties, prop~formatKey];
IF PrintProc #
NIL
THEN {
WITH CDProperties.GetPropFromInstance [links.first.source, SXAtoms.InstanceName]
SELECT
FROM
r: ROPE => NameThing [links.first.source, NIL, r, TRUE];
ENDCASE => NameThing [thing~links.first.source, short~transBase, squash~TRUE];
};
ENDLOOP;
Naming of Nodes.
FOR nl:
LIST
OF
REF CircuitNode ← circuit.nodes, nl.rest
WHILE nl #
NIL
DO
FOR signalName:
REF SignalName ←
NARROW [nl.first.properties.GetProp [SXAtoms.SignalName]], signalName.alias
WHILE signalName #
NIL
DO
IF signalName.depth # 0 THEN LOOP;
NameThing [nl.first, NIL, signalName.name, TRUE];
ENDLOOP;
ENDLOOP;
{
InheritNameFromConnections:
PROC [key: RefTab.Key, val: RefTab.Val]
RETURNS [quit:
BOOLEAN]
-- RefTab.EachPairAction -- ~ {
subNode: REF CircuitNode ← NARROW [key];
quit ← FALSE;
FOR ml: MergeRecList ←
NARROW [val], ml.rest
WHILE ml #
NIL
DO
supNode: REF CircuitNode ← ml.first.becomes;
instName: ROPE;
InheritName:
PROC [name:
ROPE, valid:
BOOL] = {
IF valid THEN NameThing [supNode, instName, name] ELSE
IF propCollisions THEN NameThing [thing: supNode, short: name, onlyCollide: TRUE];
};
IF NOT ValidMerge [ml.first] THEN LOOP;
IF HasAskedName [supNode]
THEN
LOOP;
Don't inherit for explicitly named nodes.
instName ← GetAName [ml.first.applChain.first];
EnumerateNames [thing: subNode, PerName: InheritName, onlyValid: FALSE];
ENDLOOP;
quit ← quit;
};
IF circuit.mergeDirectory # NIL THEN [] ← circuit.mergeDirectory.Pairs [action~ InheritNameFromConnections];
}; -- end InheritNameFromConnections
FOR nl:
LIST
OF
REF CircuitNode ← circuit.nodes, nl.rest
WHILE nl #
NIL
DO
IF GetAName [nl.first] = NIL THEN NameThing [thing~nl.first, short~localBase, squash~TRUE];
ENDLOOP;
Now we put the names in a good order.
FOR nl:
LIST
OF
REF CircuitNode ← circuit.nodes, nl.rest
WHILE nl #
NIL
DO
oldFirst: Naming ← NARROW [nl.first.properties.GetProp[ actualSignalName]];
newFirst: Naming ← SortNamings [oldFirst];
nl.first.properties ← nl.first.properties.PutProp [actualSignalName, newFirst];
ENDLOOP;
Now we start the actual output.
{
Cell name and formal Parameter list (ports).
logicalCellName: ROPE ~ Quote [CDDirectory.Name[cellObj]];
first: BOOL ← TRUE;
isRoot: BOOL;
PrintHead [cellObj, logicalCellName];
--Find out whether this is a root cell
isRoot ← sxData.rootOnInvocation = SXAccess.invocation;
-- Now check all nodes to determine whether they are formal parameters
FOR nl:
LIST
OF
REF CircuitNode ← circuit.nodes, nl.rest
WHILE nl #
NIL
DO
isRootPort: BOOL ← FALSE;
sn: REF SX.SignalName ← NIL;
IF isRoot THEN sn ← NARROW [Properties.GetProp[nl.first.properties, SXAtoms.SignalName], REF SX.SignalName];
isRootPort ← IF sn=NIL THEN FALSE ELSE (isRoot AND sn.makePort);
IF (nl.first.properties.GetProp[isPort] = isPort)
OR isRootPort
THEN {
PrintFormal [Quote[GetAName[nl.first]], first, nl.first];
first ← FALSE;
}
ENDLOOP;
PrintStartBody[logicalCellName]
};
Instantiation of local nodes.
FOR nl:
LIST
OF
REF CircuitNode ← circuit.nodes, nl.rest
WHILE nl #
NIL
DO
IF nl.first.properties.GetProp [isPort] =
NIL
THEN {
PrintLocalNode [nl.first];
}
ENDLOOP;
Instantiation of linkages.
FOR links:
LIST
OF
REF NodeLinkage ← circuit.linkages, links.rest
WHILE links #
NIL
DO
PrintProc: REF ANY ← CDProperties.GetProp [from~links.first.source.ob.class.properties, prop~formatKey];
IF PrintProc #
NIL
THEN {
qTName: ROPE;
qTName ← Quote [GetAName[links.first.source]];
NARROW [PrintProc, REF SXOutput.LinkagePrintProc]^[ desWDir, dfStream, output, links.first, qTName, PrintNode];
}
ELSE {
output.Put [IO.rope["Mystery object in Linkage List; ObjType ~ "], IO.atom[links.first.source.ob.class.objectType]];
};
{AppendTiogaNode[output]; output ← output.ROS[]};
ENDLOOP;
Instantiation of subcircuits.
FOR appls:
CD.InstanceList ← circuit.subcircuits, appls.rest
WHILE appls #
NIL
DO
actualsCount: CARDINAL ← CountBase;
subcircuit: REF Circuit = SXAccessInternal.GetSXData [appls.first.ob].circuit;
PrintInstanceHead [appls.first, CDDirectory.Name [appls.first.ob] ];
FOR nl:
LIST
OF
REF CircuitNode ← subcircuit.nodes, nl.rest
WHILE nl #
NIL
DO
IF nl.first.properties.GetProp[isPort] #
NIL
THEN {
parentNode: REF CircuitNode;
IF circuit.mergeDirectory #
NIL
THEN {
qual: LIST OF CD.Instance;
[node: parentNode, rootQualifier: qual] ← SX.FindRootNode [circuit: circuit, subcircuitNode: nl.first, qualifier: LIST[appls.first]];
IF qual # NIL THEN parentNode ← NIL
}
IF parentNode #
NIL
THEN
PrintActual [QNodeName[parentNode], QNodeName[nl.first], actualsCount]
ELSE ERROR;
actualsCount ← actualsCount.SUCC;
}
ENDLOOP;
PrintInstanceEnd[];
ENDLOOP;
PrintBodyEnd[];
}; -- end PrintSubcircuit
Start:
PROC = {
attachment, full: ROPE ← NIL;
cp: FS.ComponentPositions;
[attachedTo~attachment] ← FS.FileInfo [name~"SX.BCD", remoteCheck~FALSE !FS.Error => CONTINUE];
IF attachment #
NIL
THEN {
[full, cp, ] ← FS.ExpandName [attachment];
releaseDirectory ← full.Substr [start: 0, len: cp.base.start];
}
ELSE releaseDirectory ← NIL;
}; -- end Start
Start[];
END.
Edited on January 28, 1985 12:44:59 pm PST, by Beretta
Commented out April 1st joke.
Edited on February 15, 1985 2:05:23 pm PST, by Shand
Printing of stray capcitances associated with port nodes.
changes to: PrintRoseFormal (local of PrintSubcircuit) although PrintRoseStray is currently NULL calls to PrintStray were added for future consistency, PrintThymeFormal (local of PrintSubcircuit) calls to PrintStray to add child nodes to Thyme Port Defn line, PrintRoseLocalNode (local of PrintSubcircuit) as for PrintRoseFormal, DIRECTORY, PrintThymeStray (local of PrintSubcircuit), PrintThymeFormal (local of PrintSubcircuit), machineName, PrintRoseHead (local of PrintSubcircuit), IMPORTS
Edited on March 7, 1985 4:35:40 pm PST, by Shand
Thyme output changes: n* Multiplier for McCreight.
Edited on March 10, 1985 8:55:14 pm PST, by Shand
Rose format now includes node areas & perimeter.
changes to: PrintRoseStray (local of PrintSubcircuit), PrintThymeStray (local of PrintSubcircuit), PrintRoseFormal (local of PrintSubcircuit), PrintRoseLocalNode (local of PrintSubcircuit), PrintRoseInvented (local of PrintSubcircuit)
Edited on March 10, 1985 10:06:06 pm PST, by Shand
Added new procedures to output geometric node loactions.
Deleted obsolete procedures PrintRoseInvented PrintThymeInvented and variable lastNodeNode
changes to: PrintSubcircuit, PrintRoseNodeLoc (local of PrintSubcircuit) New proc, PrintThymeNodeLoc (local of PrintSubcircuit) New proc, PrintRoseFormal (local of PrintSubcircuit), PrintThymeFormal (local of PrintSubcircuit), PrintRoseLocalNode (local of PrintSubcircuit), PrintThymeLocalNode (local of PrintSubcircuit), PrintRoseHead (local of PrintSubcircuit)
Edited on March 12, 1985 1:23:35 am PST, by Shand
changes to: DIRECTORY, PrintCircuit, PrintCircuit
Edited on March 19, 1985 2:36:17 pm PST, by Beretta
Thyme output change: substituted `n' coefficient for Ed McCreight by `N'
changes to: PrintThymeStray (local of PrintSubcircuit), PrintThymeStartBody (local of PrintSubcircuit), PrintThymeInstanceEnd (local of PrintSubcircuit)
Edited on May 6, 1985 5:29:17 pm PDT, by Beretta
Converted to ChipNDale version CD20.
Edited on May 15, 1985 12:37:48 pm PDT, by Beretta
Added boolean printLocalNodeLocation
changes to: PrintThymeFormal, PrintThymeLocalNode (local of PrintSubcircuit): node location printed only if printLocalNodeLocation.
Edited on June 18, 1985 6:02:12 pm PDT, by Beretta
Spinifex.bcd has become SX.bcd.
changes to: Start
Edited on June 19, 1985 8:09:52 pm PDT, by Beretta
Output unit for measures now is lambda instead of CD units.
changes to: PrintRoseHead (local of PrintSubcircuit): scale now is 1 instead of 1/lambda. Divided coordinates for bounding box by lambda.
Edited on July 8, 1985 5:58:51 pm PDT, by Beretta
If an object has the property export and if the value is $TRUE and the cell is at the root of analysis, then the signal name of the node with this property will be used as a parameter (port).
changes to: PrintSubcircuit.
gbb July 31, 1985 6:45:16 pm PDT
Adding Core output.
changes to: DIRECTORY, PrintSubcircuit
gbb August 7, 1985 2:54:16 pm PDT
Due to storage overflow problems in the compiler, the stuff pertaining to Core has been move to a new module SXOutputImplC. The shared types are now declared in SXOutputPrivate.
changes to: DIRECTORY, SXOutputImplA, isPort, actualCellInstanceName, actualSignalName, releaseDirectory, PrintCircuit, KeepHouse, QuoteThyme, PrintSubcircuit, PrintThymeStray (local of PrintSubcircuit), PrintThymeHead (local of PrintSubcircuit), PrintThymeFormal (local of PrintSubcircuit), PrintThymeStartBody (local of PrintSubcircuit), PrintThymeLocalNode (local of PrintSubcircuit), PrintThymeNodeAlias (local of PrintSubcircuit), PrintThymeInstanceHead (local of PrintSubcircuit), PrintThymeActual (local of PrintSubcircuit), PrintRoseInstanceEnd (local of PrintSubcircuit), PrintRoseBodyEnd (local of PrintSubcircuit), Start, Start
gbb August 20, 1985 1:43:11 pm PDT
Core definition module was changed. CoreRecordCells became CoreClasses, RecordCell became RecordCellType, InstanceRec became CellInstanceRec, Instance became CellInstance, InstanceList became CellInstanceList, RecordCellRec became RecordCellTypeRec
gbb November 24, 1985 4:14:58 pm PST
Removed Core output.
changes to: DIRECTORY, PrintCircuit, PrintSubcircuit, Start
gbb March 15, 1986 5:08:54 pm PST
Unconnected wells caused a node without strays to be put in the Thyme file. Such nodes are now skipped and a warning is issued.
changes to: PrintThymeLocalNode (local of PrintSubcircuit): test whether there is any stray that goes in the Thyme file.