<> <> <> <> <> <> <> 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]; SXOutputImplA: CEDAR PROGRAM IMPORTS Ascii, Atom, CD, CDDirectory, CDIO, CDObjectProcs, CDProperties, Convert, FS, IO, 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; outputGeometricInfo: PUBLIC BOOL _ TRUE; printLocalNodeLocation: PUBLIC BOOL _ FALSE; propCollisions: BOOL _ FALSE; isPort: PUBLIC ATOM _ $SpinifexIsPort; actualCellInstanceName: PUBLIC ATOM _ $SpinifexActualCellInstanceName; actualSignalName: PUBLIC ATOM _ $SpinifexActualSignalName; releaseDirectory: ROPE; 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.>> <> <<[] _ glob.Store[ "Gnd", $GlobalSignal];>> < IF error.group = user THEN { GOTO NoFile } ];>> <> <> <> <> <<[tok, id] _ globFile.GetCedarTokenRope[ ! IO.Error => EXIT; IO.EndOfStream => EXIT];>> <> <<[] _ glob.Store[ id, $GlobalSignal];>> <> < 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 } }; <> 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.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 _ CDObjectProcs.FetchFurther[p: links.first.source.ob.p, key: key]; IF housekeeper#NIL THEN { NARROW[housekeeper, REF SXOutput.LinkageHousekeeper]^[dfStream, links.first]; }; ENDLOOP; END; -- end KeepHouse QuoteProc: TYPE ~ PROCEDURE [name: ROPE] RETURNS [ROPE]; 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.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]; <> 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 PrintRoseNodeLoc: 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 PrintThymeNodeLoc: 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 <> QNodeName: PROCEDURE [node: REF CircuitNode] RETURNS [name: ROPE] ~ { <> 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]; <> 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]; <> 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[]; <> 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_1] = {"]]; circuitDefn.SetContents[ output.RopeFromROS[]]; circuitDefn.AddLooks[0, cellName.Length[], 'b, root]; output _ output.ROS[] }; -- end PrintThymeStartBody PrintRoseLocalNode: PrintLocalNodeProc ~ { <<[node: REF CircuitNode]>> <> 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 <> 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] }; <> 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; <> 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; <> 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; <> 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; <> 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; <> { <> 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] }; <> 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; <> 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; <> 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 } ELSE 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. <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>>