<> <> <> <> <> <> <> <> DIRECTORY Ascii USING [Letter, Digit], CD USING [Describe, Design, Instance, InstanceList, InterestRect, Object, Rect], CDDirectory USING [Name], CDIO USING [GetWorkingDirectory], CDProperties USING [GetProp, GetInstanceProp, PutInstanceProp], 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 [GetLogicalCell], SXAtoms USING [fini, init, InstanceName, rosePrint, SignalName, spinifexCircuitDescription, thymePrint], SXOutput USING [LinkageHousekeeper, LinkagePrintProc, NodePrintProc], SXOutputPrivate, SymTab USING [Create, Fetch, Ref, Store], TerminalIO USING [PutRope], 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; <> 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; <> 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] ~ { <> <> <<[] _ 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]; 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.PutRope ["Cell "]; TerminalIO.PutRope [name]; TerminalIO.PutRope [" was reported twice by ChipNDale. Inserting two copies of the first circuit reported.\n"]}; <> END; -- NameObj NameObj [cl.first.cellObj, CDDirectory.Name[cl.first.cellObj, SXAccess.design]]; ENDLOOP; ReadGlobalSignals [globals]; AddIntermediateNodes [cellList]; SELECT formatKey FROM <> 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.PutRope [Rope.Cat[ "\n\t", error.explanation, "\n\tExtracted output will appear in \"", thymeFileName, "\"\n"]]; GOTO AbleToOutput } ELSE { TerminalIO.PutRope[error.explanation]; GOTO IOProblems } }; thymeFileName _ CheckFileName [CDDirectory.Name[ HierarchyRoot[ cellList], SXAccess.design].Cat[ ".thy"]]; EXITS AbleToOutput => NULL }; TerminalIO.PutRope [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[]] ]; <> 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[CD.Describe[cl.first.cellObj, NIL, SXAccess.design]]] ]; 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.PutRope [Rope.Cat[ "\n\t", error.explanation, "\n\tExtracted output will appear in \"///temp/ThymeOut.thy\""]]; CONTINUE } ELSE { TerminalIO.PutRope[error.explanation]; GOTO IOProblems } }; } ]; TerminalIO.PutRope ["  done.\n"]; EXITS IOProblems => TerminalIO.PutRope ["  failed.\n"]; }; <> SXAtoms.rosePrint => { GenKey: INT _ 0; rootName: ROPE _ CDDirectory.Name [HierarchyRoot[cellList], SXAccess.design]; 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.PutRope [ Rope.Cat ["\n\t", error.explanation, "\n\tExtracted output will appear in \"", DFFileName, "\"\n"]]; GOTO AbleToOutput } ELSE { TerminalIO.PutRope[error.explanation]; GOTO IOProblems } }; <> fullRootName _ CheckFileName [rootName]; DFfile _ FS.StreamOpen [DFFileName _ fullRootName.Cat["-str.df"], $create]; EXITS AbleToOutput => NULL }; TerminalIO.PutRope [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, SXAccess.design]; 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, SXAccess.design]]] } 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.PutRope [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, SXAccess.design]], 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.PutRope ["  done.\n"]; EXITS IOProblems => TerminalIO.PutRope ["  failed.\n"]; }; ENDCASE => { TerminalIO.PutRope ["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; { <> 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] ~ { <> 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 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/SXAccess.design.technology.lambda], IO.int[node.loc.xy.y/SXAccess.design.technology.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/SXAccess.design.technology.lambda], IO.int[node.loc.xy.y/SXAccess.design.technology.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[]]; <> 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]; <> 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]; <> 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; 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; <> <> <> <> naming _ GetANaming[node]; IF (NOT goodNode) THEN BEGIN TerminalIO.PutRope ["\nNode "]; TerminalIO.PutRope [naming.name]; TerminalIO.PutRope [" has no strays. "] END; IF printLocalNodeLocation THEN BEGIN locROS: IO.STREAM ~ IO.ROS []; locLine: TiogaFileOps.Ref _ NIL; PrintNodeLoc [locROS, node]; locLine _ circuitDefn.InsertAsLastChild []; locLine.SetContents [locROS.RopeFromROS[]]; <> 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]; <> 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 <> 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.PutInstanceProp [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.GetInstanceProp[ 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 <> 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.GetLogicalCell [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; <> { 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.InstanceList _ circuit.subcircuits, appls.rest WHILE appls # NIL DO WITH CDProperties.GetInstanceProp[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 _ CDProperties.GetProp [from~links.first.source.ob.class.properties, prop~formatKey]; IF PrintProc # NIL THEN { WITH CDProperties.GetInstanceProp [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.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; <> 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.GetProp[ actualSignalName]]; newFirst: Naming _ SortNamings [oldFirst]; nl.first.properties _ nl.first.properties.PutProp [actualSignalName, newFirst]; ENDLOOP; <> { <> logicalCellName: ROPE ~ Quote [CDDirectory.Name[cellObj, SXAccess.design]]; first: BOOL _ TRUE; isRoot: BOOL; PrintHead [cellObj, logicalCellName]; <> isRoot _ sxData.rootOnInvocation = SXAccess.invocation; <> 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] }; <> 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; <> 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; <> FOR appls: CD.InstanceList _ circuit.subcircuits, appls.rest WHILE appls # NIL DO actualsCount: CARDINAL _ CountBase; subcircuit: REF Circuit = SXAccessInternal.GetLogicalCell [appls.first.ob].circuit; PrintInstanceHead [appls.first, CDDirectory.Name [appls.first.ob, SXAccess.design] ]; 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 } 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. <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <<>>