DIRECTORY Ascii USING [Letter, Digit], CD USING [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], PropertyLists 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, PropertyLists, 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] ~ { }; -- 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]]; 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]].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[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.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]]; 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]; IF cl.first.circuit.properties.GetProp [SXAtoms.spinifexCircuitDescription] # NIL THEN { DFfile.PutF ["-- (CellType \"%g\") Opaque cell elided from output at this point\n", IO.rope[CDDirectory.Name[cl.first.cellObj]]] } ELSE { cellFile: TiogaFileOps.Ref ~ TiogaFileOps.CreateRoot []; firstNode: TiogaFileOps.Ref ~ cellFile.InsertAsLastChild []; cellFile.SetStyle ["Cedar"]; firstNode.SetFormat ["unit"]; PrintSubcircuit [desWDir, DFfile, cellFile, firstNode, cl.first.cellObj, globals, formatKey]; { ENABLE FS.Error => IF error.group = user THEN { IF error.code = $illegalName THEN { cellFileName _ rootName.Cat ["-", Convert.RopeFromInt[GenKey]]; GenKey _ GenKey.SUCC; cellFile.Store [FS.ExpandName[cellFileName.Cat[".sch"], desWDir].fullFName]; CONTINUE } ELSE { TerminalIO.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]], 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 ~ { 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 ~ { 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 ~ { 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 ~ { 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 ~ { output.Put [IO.rope [name], IO.rope [": circuit["]]; }; -- end PrintThymeHead PrintRoseFormal: PrintFormalProc ~ { 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 ~ { 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[]]; 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 ~ { 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 ~ { output.Put [IO.rope["| N_1] = {"]]; circuitDefn.SetContents [output.RopeFromROS[]]; circuitDefn.AddLooks [0, cellName.Length[], 'b, root]; output _ output.ROS [] }; -- end PrintThymeStartBody PrintRoseLocalNode: PrintLocalNodeProc ~ { 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 ~ { 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 ~ { ERROR -- should have been taken care of by PrintNaming -- ; }; -- end PrintRoseNodeAlias PrintThymeNodeAlias: PrintNodeAliasesProc ~ { 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 ~ { naming: Naming _ GetANaming [inst]; output.PutRope ["(CI "]; PrintNaming [output, naming, Rope.Cat[" ", Quote[defName]]]; PrintRoseInstantiationTransformation [output, inst]; output.PutRope [" (CIC"]; }; -- end PrintRoseInstanceHead PrintThymeInstanceHead: PrintInstanceHeadProc ~ { output.PutF ["%g: %g[", IO.rope[Quote[GetAName[inst]]], IO.rope[Quote[defName]]]; }; -- end PrintThymeInstanceHead PrintRoseActual: PrintActualProc ~ { output.PutF [" (%g %g)", IO.rope[qFormalPort], IO.rope[qActualNode] ] }; -- end PrintRoseActual PrintThymeActual: PrintActualProc ~ { 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] ~ { 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]]; 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 [PropertyLists.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] ]; 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. ‚SXOutputImplA.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Written by Shand, July 16, 1984 2:58:45 pm PDT Last Edited by: Shand, March 12, 1985 1:23:35 am PST Last Edited by: Spreitzer, January 16, 1985 11:53:05 am PST Last Edited by: Jacobi, April 4, 1985 10:03:17 am PST Last edited by: Christian Jacobi, November 7, 1986 11:50:50 am PST Last edited by: gbb June 6, 1986 7:41:03 pm PDT Name generator customization Note: This two switches are different, especially in the case of Rosemary output. Unfortunately they are not orthogonal 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.PutRope[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; Should be ERROR Duplicate name. Thyme Following LOOPHOLE caused by `opaque type' compiler problems. Rosemary Try the cell name DFfile.PutRope [Rope.Cat["\nExports Imports ", releaseDirectory, "StructuralPrimitives.DF Of ~=\n"]]; Name has non-alphanumerics. Format specific routines. [Stream: IO.STREAM, node: REF CircuitNode] [Stream: IO.STREAM, node: REF CircuitNode] [Stream: IO.STREAM, node: REF CircuitNode] [Stream: IO.STREAM, node: REF CircuitNode] SXOutput.NodePrintProc Returns Quoted name of node. Following LOOPHOLE caused by `opaque type' compiler problems. Introduce 3rd level sub-structure. [obj: CD.Object, name: ROPE] [qName: ROPE, first: BOOL, node: REF CircuitNode] INTERIM, EC if present should go here. Port node defs, e.g. (PN "Vdd" "Vdd") [qName: ROPE, first: BOOL, node: REF CircuitNode] -- Following LOOPHOLE caused by `opaque type' compiler problems. [cellName: ROPE] [cellName: ROPE] [node: REF CircuitNode] Local node defs, e.g. (N "Vdd") [node: REF CircuitNode] IF (NOT goodNode) THEN BEGIN TerminalIO.PutRope ["\n Warning: Empty node omitted from circuit, probably an unconnected well.\n"]; RETURN END; Following LOOPHOLE caused by `opaque type' compiler problems. [node: REF CircuitNode, alias: Naming] [node: REF CircuitNode, alias: Naming] Following LOOPHOLE caused by `opaque type' compiler problems. [inst: CD.Instance, defName: ROPE] [inst: CD.Instance, defName: ROPE] [qActualNode, qFormalPort: ROPE, actualNum: CARDINAL] [qActualNode, qFormalPort: ROPE, actualNum: CARDINAL] End of format specific routines -- Finds first string of form base-int where int>=start where base-int is not in Symbols. Enters the found string in Symbols. Output format customization 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. Naming of subcircuits. Naming of linkages. Naming of Nodes. Don't inherit for explicitly named nodes. Now we put the names in a good order. Now we start the actual output. Cell name and formal Parameter list (ports). Find out whether this is a root cell Now check all nodes to determine whether they are formal parameters Instantiation of local nodes. Instantiation of linkages. Instantiation of subcircuits. Edited on January 28, 1985 12:44:59 pm PST, by Beretta Commented out April 1st joke. Edited on February 15, 1985 2:05:23 pm PST, by Shand Printing of stray capcitances associated with port nodes. changes to: PrintRoseFormal (local of PrintSubcircuit) although PrintRoseStray is currently NULL calls to PrintStray were added for future consistency, PrintThymeFormal (local of PrintSubcircuit) calls to PrintStray to add child nodes to Thyme Port Defn line, PrintRoseLocalNode (local of PrintSubcircuit) as for PrintRoseFormal, DIRECTORY, PrintThymeStray (local of PrintSubcircuit), PrintThymeFormal (local of PrintSubcircuit), machineName, PrintRoseHead (local of PrintSubcircuit), IMPORTS Edited on March 7, 1985 4:35:40 pm PST, by Shand Thyme output changes: n* Multiplier for McCreight. Edited on March 10, 1985 8:55:14 pm PST, by Shand Rose format now includes node areas & perimeter. changes to: PrintRoseStray (local of PrintSubcircuit), PrintThymeStray (local of PrintSubcircuit), PrintRoseFormal (local of PrintSubcircuit), PrintRoseLocalNode (local of PrintSubcircuit), PrintRoseInvented (local of PrintSubcircuit) Edited on March 10, 1985 10:06:06 pm PST, by Shand Added new procedures to output geometric node loactions. Deleted obsolete procedures PrintRoseInvented PrintThymeInvented and variable lastNodeNode changes to: PrintSubcircuit, PrintRoseNodeLoc (local of PrintSubcircuit) New proc, PrintThymeNodeLoc (local of PrintSubcircuit) New proc, PrintRoseFormal (local of PrintSubcircuit), PrintThymeFormal (local of PrintSubcircuit), PrintRoseLocalNode (local of PrintSubcircuit), PrintThymeLocalNode (local of PrintSubcircuit), PrintRoseHead (local of PrintSubcircuit) Edited on March 12, 1985 1:23:35 am PST, by Shand changes to: DIRECTORY, PrintCircuit, PrintCircuit Edited on March 19, 1985 2:36:17 pm PST, by Beretta Thyme output change: substituted `n' coefficient for Ed McCreight by `N' changes to: PrintThymeStray (local of PrintSubcircuit), PrintThymeStartBody (local of PrintSubcircuit), PrintThymeInstanceEnd (local of PrintSubcircuit) Edited on May 6, 1985 5:29:17 pm PDT, by Beretta Converted to ChipNDale version CD20. Edited on May 15, 1985 12:37:48 pm PDT, by Beretta Added boolean printLocalNodeLocation changes to: PrintThymeFormal, PrintThymeLocalNode (local of PrintSubcircuit): node location printed only if printLocalNodeLocation. Edited on June 18, 1985 6:02:12 pm PDT, by Beretta Spinifex.bcd has become SX.bcd. changes to: Start Edited on June 19, 1985 8:09:52 pm PDT, by Beretta Output unit for measures now is lambda instead of CD units. changes to: PrintRoseHead (local of PrintSubcircuit): scale now is 1 instead of 1/lambda. Divided coordinates for bounding box by lambda. Edited on July 8, 1985 5:58:51 pm PDT, by Beretta If an object has the property export and if the value is $TRUE and the cell is at the root of analysis, then the signal name of the node with this property will be used as a parameter (port). changes to: PrintSubcircuit. gbb July 31, 1985 6:45:16 pm PDT Adding Core output. changes to: DIRECTORY, PrintSubcircuit gbb August 7, 1985 2:54:16 pm PDT Due to storage overflow problems in the compiler, the stuff pertaining to Core has been move to a new module SXOutputImplC. The shared types are now declared in SXOutputPrivate. changes to: DIRECTORY, SXOutputImplA, isPort, actualCellInstanceName, actualSignalName, releaseDirectory, PrintCircuit, KeepHouse, QuoteThyme, PrintSubcircuit, PrintThymeStray (local of PrintSubcircuit), PrintThymeHead (local of PrintSubcircuit), PrintThymeFormal (local of PrintSubcircuit), PrintThymeStartBody (local of PrintSubcircuit), PrintThymeLocalNode (local of PrintSubcircuit), PrintThymeNodeAlias (local of PrintSubcircuit), PrintThymeInstanceHead (local of PrintSubcircuit), PrintThymeActual (local of PrintSubcircuit), PrintRoseInstanceEnd (local of PrintSubcircuit), PrintRoseBodyEnd (local of PrintSubcircuit), Start, Start gbb August 20, 1985 1:43:11 pm PDT Core definition module was changed. CoreRecordCells became CoreClasses, RecordCell became RecordCellType, InstanceRec became CellInstanceRec, Instance became CellInstance, InstanceList became CellInstanceList, RecordCellRec became RecordCellTypeRec gbb November 24, 1985 4:14:58 pm PST Removed Core output. changes to: DIRECTORY, PrintCircuit, PrintSubcircuit, Start gbb March 15, 1986 5:08:54 pm PST Unconnected wells caused a node without strays to be put in the Thyme file. Such nodes are now skipped and a warning is issued. changes to: PrintThymeLocalNode (local of PrintSubcircuit): test whether there is any stray that goes in the Thyme file. gbb June 6, 1986 7:41:04 pm PDT The same thing happens also if there are instances with unconnected ports. An empty node is now inserted in the Thyme output and the warning message is much less visible (people complained they were anoyed by it). changes to: PrintThymeLocalNode (local of PrintSubcircuit)., NameObj (local of PrintCircuit) Κ'5˜™Icodešœ Οmœ7™BK™.K™4J™;J™5K™BK™/—unitšΟk ˜ Kšœžœ˜Kšžœžœ>˜FKšœ žœ˜Kšœžœ˜!Kšœ žœ-˜?Kšœžœ˜*Kšžœžœ?˜GKšžœžœgžœžœ˜‚Kšœžœ˜1Kšœžœ˜$Kšœžœ,žœ ˜DKšžœžœŒ˜”Kšœ žœ˜,Kšœžœ˜(Kšœžœ[˜hKšœ žœ7˜EKšœ˜Kšœžœ˜)Kšœ žœ ˜Kšœ žœe˜wKšœ žœ ˜Kšœžœ˜—code2š›€ œžœž˜Lš žœžœžœžœžœžœs˜ΧKšžœ˜#—Lšžœžœ˜MšΟx™Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Lšœžœžœžœ˜'Kšœžœžœ˜Lšœžœžœžœ˜(šœžœžœžœ˜,K™w—Lšœžœžœ ˜ Kšœžœžœ˜6Kšœžœžœ˜4Lšœžœ˜šΟn œžœž œ žœžœžœžœ˜Zš‘ œž œ žœžœžœžœžœ žœ˜[š žœžœžœžœ!žœžœž˜EKšžœ žœžœžœ˜/Kšžœ˜—Kšž˜KšœΟc˜—š‘œž œ˜3K™1Kšœ žœžœ™Kšœ'™'Kš œ žœ žœ/žœ žœžœžœ ™„KšœW™Wšž™Kšœžœ ™Kšœ ™ Kš œ*žœ žœžœžœ™Tšžœž™Kšœ$™$—Kšžœ™—Kšžœ žœ™Kšœ’˜—š ‘ œžœžœžœžœž˜š¦ œž˜Kšœžœ˜Kšžœžœžœ˜šžœžœžœž˜Kšœžœ˜Kšžœžœžœžœ˜2Kšžœžœžœ˜ Kšžœ˜—šœ˜K™Kšœžœ˜-Kšœžœ˜šžœCž˜JKšœC˜CKšœ%’˜=Kšžœ˜—Kšžœ˜!K˜—Kšžœ’˜—š‘œž œ žœ žœžœ0žœ-žœžœ˜©™š¦œ˜"Kšœ žœžœžœ ™*Jšœžœžœ˜š žœ žœžœ&žœ žœž˜NK–,[propList: Atom.PropList, prop: REF ANY]šœžœ:˜AKšžœžœžœžœ˜Kšžœžœžœžœ˜>šžœžœ˜Kšœ žœ˜#K˜—šžœž˜Kšœžœ žœ_˜ˆ—šžœž˜Kšœžœ žœ<˜e—Kšœž˜Kšžœ˜—šžœž˜Kšœ˜—Kšœ’˜—š¦œ˜#Kšœ žœžœžœ ™*Kšœžœžœ˜š žœ žœžœ&žœ žœž˜NK–,[propList: Atom.PropList, prop: REF ANY]šœžœ:˜AKšžœžœžœžœ˜Kšžœžœžœžœ˜>šžœžœ˜Kšžœžœ˜4Kšœ˜Kšœ˜Kšœ žœ ˜K˜—šž˜Kšœ žœ ˜—Kš œ$žœ žœ_žœ žœ<˜ΫKšœž˜Kšžœ˜—šžœž˜Kšœ˜—Kšœ’˜—š‘¦‘œ˜&Kšœ žœžœžœ ™*–,[propList: Atom.PropList, prop: REF ANY]šžœžœ˜Kšœžœ4˜;Kšœ$žœ7žœ7žœ ˜‘K˜—Kšœ’˜—š‘¦‘œ˜'Kšœ žœžœžœ ™*–,[propList: Atom.PropList, prop: REF ANY]šžœžœ˜Kšœžœ4˜;Kšœ˜Kšœ˜Kšœ#žœ žœ7žœ6˜ K˜—Kšœ’˜—Lšœ™š ‘ œž œžœžœžœ˜FKšœΟoœ™K˜Kšœ’˜—Lšœ˜š‘ œ˜ Kšœžœ˜&Kšœ/˜/K™=Kš žœžœžœžœžœ˜SKšœžœ˜Kšœ&žœ#˜KKšœ˜Kšœžœ˜Kšœ&žœ ˜1Kšœ˜Kšœžœ˜Kšœ˜Kšœžœ˜KšœR˜RKšœ˜Kšœžœ˜Kšœ"žœ ˜1Kšœ˜šžœžœ˜Kšœžœ˜#Kšœžœ˜Kšœ&žœ ˜1Kšœ˜Kšœžœ˜Kšœ!žœžœ+žœžœ+žœžœ+žœžœ+˜Kšœ˜K˜—Kšœžœ˜Kšœ žœ˜Kšœ˜K™"Kšœ˜Kšœžœ˜Kšœ’˜—š¦œ˜!Kšœžœžœ™Kšœ žœžœ˜4Kšœ’˜—š¦œ˜$Kšœžœ žœžœ ™1Kšœ9˜9K˜"KšΠblœ™&K˜K˜K˜Kšœ+˜+Kšœ˜Kšœžœ˜Kšœ˜K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœžœ˜J™%Kšœžœžœ˜;Kšœ˜Kšœžœ˜Kšœ’˜—š¦œ˜%Kšœžœ žœžœ ™1Kš œ žœžœžœžœ˜Lš œ žœžœžœžœžœ˜Bšžœž˜Jšž˜Jš œžœžœžœžœ˜Kšœžœ˜ Lšœ˜Kšœ+˜+Kšœ+˜+K™@Kš žœžœžœžœžœ˜MJšžœ˜—Lšœ˜šžœž˜!KšœE˜E—Kšœ’˜—š¦œ˜*Kšœ žœ™Kšœ;˜;Kšœ7˜7Kšœ˜Kšœ˜Kšœ.˜.Kšœ˜Kšœ’˜—š¦œ˜+Kšœ žœ™Kšœ žœ˜#Kšœ/˜/Kšœ6˜6Kšœžœ˜Kšœ’˜—š¦œ˜*Kšœžœ ™Jšœ™K˜#Kšœ˜K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœžœ˜Kšœ’˜—š¦œ˜+Kšœžœ ™K˜Kšœ žœžœ˜š žœ žœžœ&žœ žœž˜Nšžœ;žœžœž˜LKšœ žœž˜Kšž˜—Kšžœ˜—šžœžœ žœž™Kšœe™eKšž™Kšžœ™—L˜šžœžœ žœž˜Kšœ˜Kšœ!˜!Kšœ'˜'Kšžœ˜—šžœž˜Jšž˜Jš œžœžœžœžœ˜Kšœžœ˜ Lšœ˜Kšœ+˜+Kšœ+˜+K™=Kš žœžœžœžœžœ˜OJšžœ˜—Kšžœžœžœ&˜?Kšœ˜Kšœ žœ˜!Kšœ˜Kšœ˜Kšœžœ˜Kšœ’˜—š¦œ˜,Kšœžœ™&Kšžœ’3œ˜;Kšœ’˜—š¦œ˜-Kšœžœ™&Kšžœ+žœžœ˜9Kšœ žœ˜%Kšœ˜šžœžœ žœž˜2Kšžœžœ žœžœ!˜UKšžœ˜—Kšœ žœ˜Kšœ˜K™=Kš žœžœžœžœžœ˜PKšœžœ˜Kšœ’˜—š¦œ˜0Kšœžœžœ™"K˜#Kšœ˜Kšœ<˜˜MKšœ’ ˜—Mš ™šœžœ ž˜2Kšœ&˜&Kšœ$˜$Kšžœžœ˜—šœ!žœ ž˜6Kšœ(˜(Kšœ&˜&Kšžœžœ˜—šœžœ ž˜(Kšœ!˜!Kšœ˜Kšžœžœ˜—šœ"’1œ˜WKšœ žœ˜"K˜"Kšœ˜—šœžœ ž˜0Kšœ%˜%Kšœ#˜#Kšžœžœ˜—šœžœ ž˜4Kšœ'˜'Kšœ%˜%Kšžœžœ˜—šœ%žœ ž˜:Kšœ*˜*Kšœ(˜(Kšžœžœ˜—šœ%žœ ž˜:Kšœ*˜*Kšœ(˜(Kšžœžœ˜—šœ)žœ ž˜>Kšœ*˜*Kšœ(˜(Kšžœžœ˜—šœ+žœ ž˜@Kšœ-˜-Kšœ+˜+Kšžœžœ˜—šœžœ ž˜4Kšœ'˜'Kšœ%˜%Kšžœžœ˜—šœ)žœ ž˜>Kšœ,˜,Kšœ*˜*Kšžœžœ˜—šœ!žœ ž˜6Kšœ(˜(Kšœ&˜&Kšžœžœ˜—Kšœžœ!˜:Kšœžœžœ9˜GKšœ žœ˜&Kšœžœ˜'Kšœ žœ ˜!Kšœžœ ˜#Kš œžœžœžœžœ˜Kšœžœ˜!L™šœ˜Kšœžœ˜š žœžœžœžœ&žœžœž˜JKšœžœ˜Kšžœ˜—Kšœ*žœ˜/K˜—Lš€™š žœžœ0žœ žœž˜QšžœAžœž˜PKšœžœžœžœ˜1Kšžœ<žœ˜I—Kšžœ˜—Lš€™š žœžœžœžœ,žœ žœž˜VK–%[p: CD.ObjectProcs, key: REF ANY]šœ žœžœV˜hšžœ žœžœ˜šžœIžœž˜XKšœžœ#žœžœ˜8KšžœAžœ˜N—K˜—Kšžœ˜—Lš€™š žœžœžœžœ&žœžœž˜Jš žœ žœžœFžœžœž˜†Kšžœžœžœ˜"Kšœžœžœ˜1Kšžœ˜—Kšžœ˜—šœ˜š ‘œžœ$žœžœ’œ˜{Kšœ žœžœ˜(Kšœžœ˜ š žœžœžœžœž˜>Kšœ žœ ˜,Kšœ žœ˜š‘ œžœžœ žœ˜/Kšžœžœ%ž˜6Kšžœžœ6žœ˜RKšœ˜—Kšžœžœžœžœ˜'šžœžœžœ˜$K™)—K˜/KšœAžœ˜HKšžœ˜—K˜ K˜—KšžœžœžœH˜lKšœ’!˜$—š žœžœžœžœ&žœžœž˜JKšžœžœžœ4žœ˜[Kšžœ˜—Lš€%™%š žœžœžœžœ&žœžœž˜JKšœžœ2˜KK˜*KšœO˜OKšžœ˜—Lš€™˜Kš€,™,Kšœžœ%˜:Kšœžœžœ˜Kšœžœ˜ Lšœ%˜%K™$Kšœ7˜7K™Cš žœžœžœžœ&žœžœž˜JKšœ žœžœ˜Kšœžœžœ˜Kš žœžœžœBžœžœ ˜oKš œ žœžœžœžœžœ žœ˜@šžœ0žœ žœ˜FKšœ9˜9Kšœžœ˜K˜—Kšžœ˜—Lšœ˜K˜—Lš€™š žœžœžœžœ&žœžœž˜Jšžœ(žœžœ˜4Kšœ˜K˜—Kšžœ˜—Lš€™š žœžœžœžœ,žœ žœž˜VK–%[p: CD.ObjectProcs, key: REF ANY]šœ žœžœV˜hšžœ žœžœ˜Kšœžœ˜ Kšœ.˜.Kšžœ žœY˜oK˜—šžœ˜Kšœ žœ5žœ/˜tK˜—Kšœ*žœ˜1Kšžœ˜—Lš€™š žœžœ0žœ žœž˜QJšœžœ ˜#Kšœ žœD˜SKšœD˜Dš žœžœžœžœ)žœžœž˜Mšžœ'žœžœ˜3Kšœ žœ ˜šžœžœžœ˜&Kšœžœžœžœ ˜Kšœržœ˜…Kšžœžœžœž˜#K˜—šž˜Kšœ žœ˜—šžœžœž˜KšœF˜F—Kšžœžœ˜ Kšœžœ˜!K˜—Kšžœ˜—Kšœ˜Kšžœ˜—Lšœ˜Kšœ’˜—š‘œžœ˜Kšœžœžœ˜Kšœžœ˜Kš œžœ&žœžœ žœ˜_šžœžœžœ˜Kšœžœ˜*K˜>K˜—Kšžœžœ˜Kšœ’ ˜—M˜ Mšžœ˜™6K™—šœ4™4K™9Kšœ Οrœ{©œZ©œ2©œ©œ©œ© ™μ—™0K™2—™1K™0Kš œ ©œ©œ©œ©œ©œ™κ—™2K™8Kšœ©œ©œ© ™ZKšœ ©!œ$©œ$©œ©œ©œ©œ©œ™κ—™1Kšœ ©%™1—™3K™HKšœ ©œ©œ©œ™˜—™0K™$—™2KšœΟe™$Kšœ ©%œ;ͺ™ƒ—™2K™Kšœ ©™—™2K™;Kšœ © œp™‰—™1Kšœͺœ’“™ΏKšœ ©œ™—™ K™Kšœ ©™&—™!Kšœmͺ œ'ͺœ™±Kšœ ©£œ©œ©œ©œ©œ©œ©œ©œ©œ©œ©™ώ—™"K™ψ—™$K™Kšœ ©/™;—™!K™Kšœ ©œY™x—™K™ΦKšœ ©œ© œ™\—K™K™—…—rΚΊ