DIRECTORY
Ascii USING [Letter, Digit],
Atom USING [GetPropFromList, PropList, PutPropOnList],
CD USING [Application, ApplicationList, ApplicationPtr, DesignRect, InterestRect, lambda, ObPtr],
CDDirectory USING [Name],
CDIO USING [GetWorkingDirectory],
CDObjectProcs USING [FetchFurther],
CDProperties USING [GetPropFromApplication, PutPropOnApplication],
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],
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, SignalName, TechHandle],
SXAccess,
SXAccessInternal,
SXAtoms USING [fini, init, InstanceName, rosePrint, SignalName, spinifexCircuitDescription, thymePrint],
SXOutput,
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];
PrintCircuit:
PUBLIC
PROCEDURE [cellList:
LIST
OF
REF LogicalCell, formatKey:
REF ANY] ~ {
HierarchyRoot:
PROCEDURE [cellList:
LIST
OF
REF LogicalCell]
RETURNS [
CD.ObPtr] ~
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];
IF cellList=NIL OR formatKey=NIL THEN RETURN;
globals ← SymTab.Create[mod: 553, case: TRUE];
FOR cl:
LIST
OF
REF LogicalCell ← cellList, cl.rest
WHILE cl #
NIL
DO
NameObj:
PROC [obj:
CD.ObPtr, 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.GetPropFromList[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.GetPropFromList[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
PrintSubcircuit:
PROCEDURE [desWDir:
ROPE, dfStream:
IO.
STREAM, root, circuitDefn: TiogaFileOps.Ref, cellObj:
CD.ObPtr, GlobalNames: SymTab.Ref, formatKey:
REF
ANY] ~ {
--Format specific routines.
PrintStrayProc: TYPE ~ PROCEDURE [Stream: IO.STREAM, node: REF CircuitNode];
PrintNodeLocProc: TYPE ~ PROCEDURE [Stream: IO.STREAM, node: REF CircuitNode];
SXOutput.NodePrintProc
PrintHeadProc: TYPE ~ PROCEDURE [obj: CD.ObPtr, name: ROPE];
PrintFormalProc: TYPE ~ PROCEDURE [qName: ROPE, first: BOOL, node: REF CircuitNode];
PrintStartBodyProc: TYPE ~ PROCEDURE [cellName: ROPE];
PrintLocalNodeProc: TYPE ~ PROCEDURE [node: REF CircuitNode];
PrintNodeAliasesProc: TYPE ~ PROCEDURE [node: REF CircuitNode, alias: Naming];
PrintInstanceHeadProc: TYPE ~ PROCEDURE [inst: CD.ApplicationPtr, defName: ROPE];
PrintActualProc: TYPE ~ PROCEDURE [qActualNode, qFormalPort: ROPE, actualNum: CARDINAL];
PrintInstanceEndProc: TYPE ~ PROCEDURE [];
PrintBodyEndProc: TYPE ~ PROCEDURE [];
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/(CD.lambda*CD.lambda)]];
IF apList.first.perim # 0
THEN
Stream.PutF[ " (p %g %g)", IO.rope[r], IO.int[apList.first.perim/CD.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/(CD.lambda*CD.lambda)], IO.rope[r], IO.int[apList.first.perim/CD.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/CD.lambda], IO.int[node.loc.xy.y/CD.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/CD.lambda], IO.int[node.loc.xy.y/CD.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.DesignRect ← 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]/CD.lambda],
IO.real [REAL[b.y1]/CD.lambda],
IO.real [REAL[b.x2]/CD.lambda],
IO.real [REAL[b.y2]/CD.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.ObPtr, 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 ← 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.GetPropFromList[ 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.ApplicationPtr, 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.ApplicationPtr, 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.PutPropOnList[ actualSignalName, this];
appl: CD.ApplicationPtr => CDProperties.PutPropOnApplication[ 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.GetPropFromList[ actualSignalName]];
appl: CD.ApplicationPtr => next ← NARROW[ CDProperties.GetPropFromApplication[ 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.ApplicationPtr => IF doingNets THEN RETURN;
o: CD.ObPtr => 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.ApplicationList ← circuit.subcircuits, appls.rest
WHILE appls #
NIL
DO
WITH CDProperties.GetPropFromApplication[ 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 ← CDObjectProcs.FetchFurther[ p~links.first.source.ob.p, key~formatKey];
IF PrintProc #
NIL
THEN {
WITH CDProperties.GetPropFromApplication[ 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.GetPropFromList[ 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.GetPropFromList[ actualSignalName]];
newFirst: Naming ← SortNamings[oldFirst];
nl.first.properties ← nl.first.properties.PutPropOnList[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 [Atom.GetPropFromList[nl.first.properties, SXAtoms.SignalName], REF SX.SignalName];
isRootPort ← IF sn=NIL THEN FALSE ELSE (isRoot AND sn.makePort);
IF (nl.first.properties.GetPropFromList[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.GetPropFromList[ 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 ← CDObjectProcs.FetchFurther[ p~links.first.source.ob.p, key~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.p.objectType]];
};
AppendTiogaNode[output];
output ← output.ROS[];
ENDLOOP;
Instantiation of subcircuits.
FOR appls:
CD.ApplicationList ← 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.GetPropFromList[ isPort] #
NIL
THEN {
parentNode: REF CircuitNode;
IF circuit.mergeDirectory #
NIL
THEN {
qual: LIST OF CD.ApplicationPtr;
[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