DIRECTORY Ascii USING [Letter, Digit], Atom USING [GetPropFromList, PropList, PutPropOnList], CD USING [Design, Instance, InstanceList, InterestRect, lambda, Object, Rect], CDDirectory USING [Name], CDIO USING [GetWorkingDirectory], CDObjectProcs USING [FetchFurther], CDProperties USING [GetPropFromInstance, PutPropOnInstance], Core USING [CellType, Design, StructureError], CoreOps USING [CreateDesign, CreateRecordWire, InsertCellType], CoreRecord USING [CellInstance, RecordCellType, RecordCellTypeRec], 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, Concat, Equal, Fetch, Find, Length, Replace, ROPE, Substr], SX USING [AreaPerimRec, Circuit, CircuitNode, FindRootNode, LogicalCell, MergeRec, MergeRecList, NodeLinkage, NodeLocation, SignalName, TechHandle], SXAccess USING [design, invocation, sxTech], SXAccessInternal USING [GetSXData], SXAtoms USING [coreOut, fini, init, InstanceName, rosePrint, SignalName, spinifexCircuitDescription, thymePrint], SXOutput USING [LinkageHousekeeper, LinkagePrintProc, NodePrintProc], SXOutputPrivate, SymTab USING [Create, Fetch, Ref, Store], TerminalIO USING [WriteRope], TiogaFileOps USING [AddLooks, CreateRoot, InsertAsLastChild, InsertNode, Ref, SetContents, SetFormat, SetStyle, Store], TiogaOps USING [PutProp], UserCredentials USING [Get]; SXOutputImplA: CEDAR PROGRAM IMPORTS Ascii, Atom, CD, CDDirectory, CDIO, CDObjectProcs, CDProperties, Convert, Core, CoreOps, FS, IO, 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; outputGeometricInfo: PUBLIC BOOL _ TRUE; printLocalNodeLocation: PUBLIC BOOL _ FALSE; propCollisions: 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]; 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.Object, name: ROPE] = BEGIN naming: Naming _ NEW [NamingRep _ [next: NIL, named: obj, prefixes: NIL, name: name]]; IF ~globals.Store[name, naming] THEN { TerminalIO.WriteRope["Collision on cell type name "]; TerminalIO.WriteRope[name]; TerminalIO.WriteRope[".\n"]}; 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.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[]] ]; 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"]; }; 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"]; }; SXAtoms.coreOut => BEGIN coreDesignName: Rope.ROPE _ Rope.Concat [base: "SX", rest: SXAccess.design.name]; TerminalIO.WriteRope ["Commencing creation of Core structure "]; TerminalIO.WriteRope [coreDesignName]; coreDesign _ CoreOps.CreateDesign [name: coreDesignName ! Core.StructureError => CONTINUE]; SetDesignProp [cdD: SXAccess.design, coreD: coreDesign]; FOR cells: LIST OF REF LogicalCell _ cellList, cells.rest WHILE cells # NIL DO description: Core.CellType = NARROW [Atom.GetPropFromList [cells.first.circuit.properties, SXAtoms.spinifexCircuitDescription]]; IF description # NIL THEN CoreOps.InsertCellType [coreDesign, description] ELSE PrintSubcircuit [desWDir, NIL, NIL, NIL, cells.first.cellObj, globals, formatKey] ENDLOOP; TerminalIO.WriteRope [ "  done.\n"]; END; 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.class, key: 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/(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 ~ { 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 ~ { 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 ~ { 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[]]; 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]/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 ~ { 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 _ 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[]]; 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.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]; 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.PutPropOnList[ actualSignalName, this]; appl: CD.Instance => CDProperties.PutPropOnInstance[ onto~appl, prop~actualCellInstanceName, val~this]; ENDCASE => ERROR }; -- end NoteNewNaming user: Naming _ Lookup[short]; next, this: Naming; name: ROPE _ short; doingNets: BOOL _ ISTYPE[thing, REF CircuitNode]; IF explicit AND qual # NIL THEN ERROR; IF user # NIL AND user.named = thing AND NOT onlyCollide THEN { IF explicit # user.explicit THEN ERROR; IF qual # NIL AND user.prefixes = NIL THEN user.prefixes _ LIST[NIL]; IF user.prefixes # NIL THEN user.prefixes _ CONS[qual, user.prefixes]; RETURN; }; WITH thing SELECT FROM node: REF CircuitNode => next _ NARROW[ node.properties.GetPropFromList[ actualSignalName]]; appl: CD.Instance => next _ NARROW[ CDProperties.GetPropFromInstance[ from~appl, prop~actualCellInstanceName]]; ENDCASE => ERROR; this _ NEW [NamingRep _ [next: next, named: IF NOT onlyCollide THEN thing ELSE NIL, prefixes: IF qual # NIL THEN LIST[qual] ELSE NIL, name: short, explicit: explicit, collided: onlyCollide, squash: squash]]; IF user # NIL THEN Rename[short, user, doingNets]; IF user = NIL OR onlyCollide THEN { [] _ Symbols.Store[short, this]; NoteNewNaming[]; RETURN}; IF qual # NIL THEN { long: ROPE _ qual.Cat[".", short]; NameThing[thing, NIL, long]; RETURN; }; NoteNewNaming[]; this.explicit _ FALSE; [this.name, user.count] _ FindUnique[base~IF squash THEN short ELSE (short.Cat[CountSep]), start~user.count+1, val~this]; }; -- end NameThing Rename: PROC [key: ROPE, tomb: Naming, doingNets: BOOL] = { thing: REF ANY _ tomb.named; nameNIL: BOOL _ FALSE; IF tomb.collided THEN RETURN; tomb.collided _ TRUE; WITH tomb.named SELECT FROM n: REF CircuitNode => NULL; a: CD.Instance => IF doingNets THEN RETURN; o: CD.Object => RETURN; ENDCASE => ERROR; tomb.named _ NIL; IF tomb.prefixes = NIL THEN { NameThing[thing~thing, short~key, squash~tomb.squash]; RETURN}; FOR prefixes: ROPEList _ tomb.prefixes, prefixes.rest WHILE prefixes # NIL DO IF prefixes.first = NIL THEN nameNIL _ TRUE ELSE NameThing[thing, NIL, prefixes.first.Cat[".", tomb.name]]; ENDLOOP; tomb.prefixes _ NIL; IF nameNIL THEN NameThing[thing~thing, short~tomb.name, squash~tomb.squash]; }; -- end Rename PrintStray: PrintStrayProc ~ SELECT formatKey FROM SXAtoms.thymePrint => PrintThymeStray, SXAtoms.rosePrint => PrintRoseStray, SXAtoms.coreOut => ComputeStray, ENDCASE => ERROR; PrintNodeLoc: PrintNodeLocProc ~ SELECT formatKey FROM SXAtoms.thymePrint => PrintThymeNodeLoc, SXAtoms.rosePrint => PrintRoseNodeLoc, SXAtoms.coreOut => PrintRoseNodeLoc, -- not yet used ENDCASE => ERROR; Quote: QuoteProc ~ SELECT formatKey FROM SXAtoms.thymePrint => QuoteThyme, SXAtoms.rosePrint => QuoteRose, SXAtoms.coreOut => QuoteCore, 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, SXAtoms.coreOut => InsertCell, ENDCASE => ERROR; PrintFormal: PrintFormalProc ~ SELECT formatKey FROM SXAtoms.thymePrint => PrintThymeFormal, SXAtoms.rosePrint => PrintRoseFormal, SXAtoms.coreOut => InsertPort, ENDCASE => ERROR; PrintStartBody: PrintStartBodyProc ~ SELECT formatKey FROM SXAtoms.thymePrint => PrintThymeStartBody, SXAtoms.rosePrint => PrintRoseStartBody, SXAtoms.coreOut => EndPortList, ENDCASE => ERROR; PrintLocalNode: PrintLocalNodeProc ~ SELECT formatKey FROM SXAtoms.thymePrint => PrintThymeLocalNode, SXAtoms.rosePrint => PrintRoseLocalNode, SXAtoms.coreOut => InsertNode, ENDCASE => ERROR; PrintNodeAliases: PrintNodeAliasesProc ~ SELECT formatKey FROM SXAtoms.thymePrint => PrintThymeNodeAlias, SXAtoms.rosePrint => PrintRoseNodeAlias, SXAtoms.coreOut => PrintRoseNodeAlias, -- not yet used ENDCASE => ERROR; PrintInstanceHead: PrintInstanceHeadProc ~ SELECT formatKey FROM SXAtoms.thymePrint => PrintThymeInstanceHead, SXAtoms.rosePrint => PrintRoseInstanceHead, SXAtoms.coreOut => CreateInstance, ENDCASE => ERROR; PrintActual: PrintActualProc ~ SELECT formatKey FROM SXAtoms.thymePrint => PrintThymeActual, SXAtoms.rosePrint => PrintRoseActual, SXAtoms.coreOut => InsertPortInstance, ENDCASE => ERROR; PrintInstanceEnd: PrintInstanceEndProc ~ SELECT formatKey FROM SXAtoms.thymePrint => PrintThymeInstanceEnd, SXAtoms.rosePrint => PrintRoseInstanceEnd, SXAtoms.coreOut => EndPortInstanceList, ENDCASE => ERROR; PrintBodyEnd: PrintBodyEndProc ~ SELECT formatKey FROM SXAtoms.thymePrint => PrintThymeBodyEnd, SXAtoms.rosePrint => PrintRoseBodyEnd, SXAtoms.coreOut => PrintRoseBodyEnd, -- i.e. do nothing 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; { 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.GetPropFromInstance[ appls.first, SXAtoms.InstanceName] SELECT FROM r: ROPE => NameThing[appls.first, NIL, r, TRUE]; ENDCASE => NameThing[thing~appls.first, short~circuitBase, squash~TRUE]; ENDLOOP; FOR links: LIST OF REF NodeLinkage _ circuit.linkages, links.rest WHILE links # NIL DO PrintProc: REF ANY _ CDObjectProcs.FetchFurther[ p~links.first.source.ob.class, key~formatKey]; IF PrintProc # NIL THEN { WITH CDProperties.GetPropFromInstance[ links.first.source, SXAtoms.InstanceName] SELECT FROM r: ROPE => NameThing[links.first.source, NIL, r, TRUE]; ENDCASE => NameThing[thing~links.first.source, short~transBase, squash~TRUE]; }; ENDLOOP; 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]; 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 [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; IF formatKey=SXAtoms.coreOut THEN BEGIN coreCellInstance _ NEW [CoreRecord.RecordCellTypeRec]; coreCellInstance.internalWire _ CoreOps.CreateRecordWire [name: "internal nodes", components: coreNodeBuffer]; coreCellBuffer.data _ coreCellInstance; coreNodeBuffer _ NIL END; FOR links: LIST OF REF NodeLinkage _ circuit.linkages, links.rest WHILE links # NIL DO PrintProc: REF ANY _ CDObjectProcs.FetchFurther [p~links.first.source.ob.class, 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.class.objectType]]; }; IF (formatKey=SXAtoms.thymePrint) OR (formatKey=SXAtoms.rosePrint) THEN {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.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.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: gbb August 13, 1985 3:32:17 pm PDT -- Name generator customization -- SymTab keyed by signal names, value is use count. globFile: IO.STREAM; [] _ glob.Store[ "Gnd", $GlobalSignal]; globFile _ FS.StreamOpen[ FS.ExpandName["chip.wspec", desWDir].fullFName ! FS.Error => IF error.group = user THEN { GOTO NoFile } ]; TerminalIO.WriteRope[Rope.Cat["\nProcessing wiring spec file \"", "chip.wspec", "\"\n"]]; DO tok: IO.TokenKind; id: ROPE; [tok, id] _ globFile.GetCedarTokenRope[ ! IO.Error => EXIT; IO.EndOfStream => EXIT]; IF tok = tokenID THEN [] _ glob.Store[ id, $GlobalSignal]; ENDLOOP; EXITS NoFile => NULL; -- 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"]]; We force the creation of a new design. Core takes care of old versions lieing around. --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] -- 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. TRUSTED {numberOfPlaceNames _ List.Length[LOOPHOLE[placeNames]]}; 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 CoreRecord, RecordCell became RecordCellType, InstanceRec became CellInstanceRec, Instance became CellInstance, InstanceList became CellInstanceList, RecordCellRec became RecordCellTypeRec Κ(T˜™Icodešœ Οmœ7™BK™.K™4J™;J™5K™2—unitšΟk ˜ Kšœžœ˜Kšœžœ,˜6KšžœžœF˜NKšœ žœ˜Kšœžœ˜!Kšœžœ˜#Kšœ žœ*˜˜>Kšžœ˜—Lšœ˜Kšœ˜šžœ ž˜LšΟl™šœ˜Kšœžœ˜Kšœ8˜8Kšœ˜šœžœžœ ˜šžœžœ˜šžœžœ˜#Kšœžœ6˜HKšœ}˜}Kšžœ ˜K˜—Kšžœ,žœ ˜AKšœ˜—KšœY˜YKšžœž˜K˜—Lš œžœžœ0žœžœ˜zLšœ˜Lšœ-˜-Kš œžœžœžœ"žœ ˜lK™@Kš žœžœžœžœžœ˜Tš žœžœžœžœ!žœžœž˜EKšœ:˜:Kšœ ˜ šžœSžœžœ˜_KšœžœQžœ-˜›Kš žœžœžœžœžœ˜SK˜—šžœ˜Kšœžœ@˜\Kšœ˜—Kšžœ˜—šœ!žœ ˜.šžœžœ˜šžœžœ˜#Kšœ*˜*Kšœ|˜|Kšž˜K˜—Kšžœ,žœ ˜AKšœ˜—Kšœ˜—Kšœ$˜$Kšžœ5˜:K˜—Lš€ ™ šœ˜Kšœžœ˜Kšœ žœ-˜;Kšœžœ˜Kšœžœžœ˜šœžœžœ ˜šžœžœ˜šžœžœ˜#Kšœ˜Kšœžœ)˜:Kšœ žœ?˜JKšœz˜zKšžœ ˜K˜—Kšžœ,žœ ˜AKšœ˜—K™Kšœ'˜'Kšœ žœ?˜JKšžœž˜K˜—Lš œžœžœ0žœžœ˜wLšœEžœžœ ˜cKšœ'žœ˜FKšœ+žœ˜>š žœžœžœžœ!žœžœž˜EKšœ*˜*Kšžœ˜—š žœžœžœžœ!žœžœž˜EKšœžœ&˜8šžœSžœžœ˜_KšœSžœ+˜€K˜—šžœ˜Kšœ7˜7Kšœ;˜;Lšœ˜Lšœ˜Kšœ\˜\šœžœžœ ˜šžœžœ˜šžœžœ˜#Kšœ>˜>Kšœžœ˜Kšœžœ:˜LKšž˜K˜—Kšžœ,žœ ˜AKšœ˜—Kšœžœ+˜6Kšœ˜K˜—Kšœ0žœ+žœ˜sKšœ˜—Kšžœ˜—š žœžœžœžœ!žœžœž˜EKšœ*˜*Kšžœ˜—K™dKšœ˜Kšœ$˜$Kšžœ5˜:K˜—šœ˜Kšž˜K•StartOfExpansion([base: ROPE _ NIL, rest: ROPE _ NIL]šœžœ8˜QKšœ@˜@Kšœ&˜&K™UKšœ>žœžœ˜[Kšœ8˜8š žœžœžœžœ$žœ žœž˜NKšœžœ]˜€Kšžœžœžœ1˜JKšžœžœžœžœ*˜VKšžœ˜—Kšœ%˜%Kšžœ˜—šžœ˜ KšœL˜LK˜——Lšœ˜Kšœ’œ˜—š Πbn œžœžœžœžœžœ˜GKšž˜š žœžœžœžœ/žœ žœž˜YK–%[p: CD.ObjectProcs, key: REF ANY]šœ žœžœH˜\šžœ žœžœ˜Kšžœžœ6˜MK˜—Kšžœ˜—Kšžœ’˜—šΟb œ˜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]šœžœ9˜@Kšžœžœžœžœ˜Kšžœžœžœžœ˜>šžœžœ˜Kšœ žœ˜"K˜—šžœž˜Kš œžœ žœžœžœ ˜W—šžœž˜Kšœžœ žœžœ ˜M—Kšœž˜Kšžœ˜—šžœž˜Kšœ˜—Kšœ’˜—š¦œ˜#Kšœ žœžœžœ ™*Kšœžœžœ˜š žœ žœžœ&žœ žœž˜NK–,[propList: Atom.PropList, prop: REF ANY]šœžœ:˜AKšžœžœžœžœ˜Kšžœžœžœžœ˜>šžœžœ˜Kšžœžœ˜3Kšœ˜Kšœ˜Kšœ žœ ˜K˜—šž˜Kšœ žœ ˜—Kšœ$žœ žœžœžœ žœ žœžœ ˜“Kšœž˜Kšžœ˜—šžœž˜Kšœ˜—Kšœ’˜—š‘¦‘œ˜&Kšœ žœžœžœ ™*–,[propList: Atom.PropList, prop: REF ANY]šžœžœ˜Kšœžœ4˜;Kš œ$žœžœ žœžœ žœ ˜qK˜—Kšœ’˜—š‘¦‘œ˜'Kšœ žœžœžœ ™*–,[propList: Atom.PropList, prop: REF ANY]šžœžœ˜Kšœžœ4˜;Kšœ˜Kšœ˜Kš œ#žœ žœžœ žœžœ ˜pK˜—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šœD˜D—Kšœ’˜—š¦œ˜*Kšœ žœ™Kšœ;˜;Kšœ7˜7Kšœ˜Kšœ˜Kšœ-˜-Kšœ˜Kšœ’˜—š¦œ˜+Kšœ žœ™Kšœ žœ˜#Kšœ/˜/Kšœ5˜5Kšœžœ˜Kšœ’˜—š¦œ˜*Kšœžœ ™Jšœ™K˜"Kšœ˜K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜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šžœ3žœžœ˜AKšœ žœ˜$Kšœ˜šžœžœ žœž˜2Kšžœžœ žœžœ#˜VKšžœ˜—Kšœ žœ˜Kšœ˜K™@Kš žœžœžœžœžœ˜PKšœžœ˜Kšœ’˜—š¦œ˜0Kšœžœžœ™"K˜"Kšœ˜Kšœ;˜;Kšœ3˜3K˜Kšœ’˜—š¦œ˜1Kšœžœžœ™"Kšœžœžœ˜QKšœ’˜ —š¦œ˜$Kšœžœ žœ™5Kšœžœžœ˜EKšœ’˜—š¦œ˜%Kšœžœ žœ™5Kšžœžœ˜4Kšœ˜Kšœ’˜—š¦œ˜.Kšœ˜Kšœ˜Kšœžœ˜Kšœ’˜—š¦œ˜/Kšœ˜Kšœ˜Kšœžœ˜Kšœ’˜—š¦œ˜&K˜—š¦œ˜'Kšœ˜Kšœ˜Kšœžœ˜Kšœ’˜—Lšœ™—š‘œž œ žœžœ˜2Kšœ3˜3Kšœ+˜+Kšœ˜Kšœ’˜—L˜š ‘ œž œžœžœžœ˜5Kšžœžœ˜=Kšœ’˜—š‘ œž œ žœ žœžœžœžœžœžœ žœ˜pKš œ§œ§œ§œ§œ §œ§œ™~Kšœ˜šž˜Kšœ,˜,šžœžœ˜Kšœ˜Kšž˜K˜—Kšœžœ˜Kšžœ˜—Kšœ’˜—š‘œžœžœžœ˜6Kšœžœ˜ Kšœžœžœ˜ K˜'Kšžœžœžœžœ˜#Kšœ#˜#Kšžœžœžœžœ˜#Kšœ žœ˜ Kšœ’ ˜—š‘ œžœ žœžœžœžœ žœ!žœžœ˜pš‘ œžœ˜šžœžœž˜KšœžœY˜bKšœžœ_˜gKšžœž˜Kšœ’˜——L˜Kšœ˜Kšœžœ ˜Lšœ žœžœžœ˜1Kš žœ žœžœžœžœ˜&š žœžœžœžœžœ žœ˜?Kšžœžœžœ˜'Kšžœžœžœžœžœžœžœ˜EKšžœžœžœžœ˜FKšžœ˜Kšœ˜—šžœžœž˜Kšœžœžœ6˜\KšœžœžœM˜oKšžœžœ˜—Kšœžœ"žœžœ žœžœžœ žœžœžœžœžœžœK˜ΟKšžœžœžœ ˜2šžœžœžœ žœ˜#Kšœ1žœ˜:—šžœžœžœ˜Kšœžœ˜"Kšœžœ˜Kšžœ˜K˜—K˜Kšœžœ˜Kšœ*žœžœžœ6˜yKšœ’˜—š‘œžœžœžœ˜;Kšœžœžœ˜Kšœ žœžœ˜Kšžœžœžœ˜Kšœžœ˜šžœ žœž˜Kšœžœžœ˜Kš œžœ žœ žœžœ˜+Kšœžœ žœ˜Kšžœžœ˜—Kšœ žœ˜šžœžœžœ˜Kšœ7žœ˜?—šžœ3žœ žœž˜MKš žœžœžœ žœžœžœ&˜kKšžœ˜—Kšœžœ˜Kšžœ žœ=˜LKšœ’ ˜—Lš ™šœžœ ž˜2Kšœ&˜&Kšœ$˜$Kšœ ˜ Kšžœžœ˜—šœ!žœ ž˜6Kšœ(˜(Kšœ&˜&Kšœ%’˜4Kšžœžœ˜—šœžœ ž˜(Kšœ!˜!Kšœ˜Kšœ˜Kšžœžœ˜—šœ"’1œ˜WKšœ žœ˜!K˜!Kšœ˜—šœžœ ž˜0Kšœ%˜%Kšœ#˜#Kšœ˜Kšžœžœ˜—šœžœ ž˜4Kšœ'˜'Kšœ%˜%Kšœ˜Kšžœžœ˜—šœ%žœ ž˜:Kšœ*˜*Kšœ(˜(Kšœ˜Kšžœžœ˜—šœ%žœ ž˜:Kšœ*˜*Kšœ(˜(Kšœ˜Kšžœžœ˜—šœ)žœ ž˜>Kšœ*˜*Kšœ(˜(Kšœ'’˜6Kšžœžœ˜—šœ+žœ ž˜@Kšœ-˜-Kšœ+˜+Kšœ"˜"Kšžœžœ˜—šœžœ ž˜4Kšœ'˜'Kšœ%˜%Kšœ&˜&Kšžœžœ˜—šœ)žœ ž˜>Kšœ,˜,Kšœ*˜*Kšœ'˜'Kšžœžœ˜—šœ!žœ ž˜6Kšœ(˜(Kšœ&˜&Kšœ%’˜7Kšžœžœ˜—Kšœžœ!˜:Kšœžœ6˜AKšœ žœ˜&Kšœžœ˜'Kšœ žœ ˜!Kšœžœ ˜#Kš œžœžœžœžœ˜Kšœžœ˜!L™“šœ˜Kšœžœ˜š žœžœžœžœ&žœžœž˜JKšœžœ˜Kšžœ˜—Kšœ*žœ˜/K˜—Lš€™š žœžœ0žœ žœž˜QšžœFžœž˜UKšœžœžœžœ˜0Kšžœ;žœ˜H—Kšžœ˜—Lš€™š žœžœžœžœ,žœ žœž˜VK–%[p: CD.ObjectProcs, key: REF ANY]šœ žœžœM˜_šžœ žœžœ˜šžœMžœž˜\Kšœžœ"žœžœ˜7Kšžœ@žœ˜M—K˜—Kšžœ˜—Lš€™š žœžœžœžœ&žœžœž˜Jš žœ žœžœMžœžœž˜Kšžœžœžœ˜"Kšœžœžœ˜0Kšžœ˜—Kšžœ˜—šœ˜š ‘œžœ$žœžœ’œ˜{Kšœ žœžœ˜'Kšœžœ˜ š žœžœžœžœž˜=Kšœ žœ ˜,Kšœ žœ˜š‘ œžœžœ žœ˜/Kšžœžœ$ž˜5Kšžœžœ5žœ˜QKšœ˜—Kšžœžœžœžœ˜&šžœžœžœ˜#K™)—K˜.Kšœ@žœ˜GKšžœ˜—K˜ K˜—KšžœžœžœH˜lKšœ’!˜$—š žœžœžœžœ&žœžœž˜JKšžœžœžœ3žœ˜YKšžœ˜—Lš€%™%š žœžœžœžœ&žœžœž˜JKšœžœ9˜RK˜)KšœT˜TKšžœ˜—Lš€™˜Kš€,™,Kšœžœ%˜:Kšœžœžœ˜Kšœžœ˜ Lšœ$˜$K™&Kšœ5˜5K™Fš žœžœžœžœ&žœžœž˜JKšœ žœžœ˜Kšœžœžœ˜Kš žœžœžœAžœžœ ˜nKš œ žœžœžœžœžœ žœ˜@šžœ8žœ žœ˜NKšœ9˜9Kšœžœ˜K˜—Kšžœ˜—Lšœ˜K˜—Lš€™š žœžœžœžœ&žœžœž˜Jšžœ/žœžœ˜;Kšœ˜K˜—Kšžœ˜—šžœž˜!Jšž˜Kšœžœ ˜6Kšœn˜nKšœ'˜'Kšœž˜Jšžœ˜—Lš€™š žœžœžœžœ,žœ žœž˜VK–%[p: CD.ObjectProcs, key: REF ANY]šœ žœžœM˜_šžœ žœžœ˜Kšœžœ˜ Kšœ.˜.Kšžœ žœY˜oK˜—šžœ˜Kšœ žœ5žœ/˜tK˜—šžœ žœž˜GKšœ*žœ˜1—Kšžœ˜—Lš€™š žœžœ0žœ žœž˜QJšœžœ ˜#Kšœ žœ>˜MKšœC˜Cš žœžœžœžœ)žœžœž˜Mšžœ/žœžœ˜;Kšœ žœ ˜šžœžœžœ˜&Kšœžœžœžœ ˜Kšœqžœ˜„Kšžœžœžœž˜#K˜—šž˜Kšœ žœ˜—šžœžœž˜KšœE˜E—Kšžœžœ˜ Kšœžœ˜!K˜—Kšžœ˜—Kšœ˜Kšžœ˜—Lšœ˜Kšœ’˜—š‘œžœ˜Kšœžœžœ˜Kšœžœ˜Kš œžœ%žœžœ žœ˜^šžœžœžœ˜Kšœžœ˜)K˜=K˜—Kšžœžœ˜Kšžœ#žœ™AKšœ’ ˜—L˜Kšžœ˜™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™—…—vςΌ\