DIRECTORY Basics, CD, CDBasics, CDCells, CDDirectory, CDImports, CDInstances, CDLayers, CDOps, CDPanelFonts, CDPopUpMenus, CDProperties, CDRects, CDSatellites, CDSequencer, CDTexts, CDViewer, Core, CoreClasses, CoreOps, CoreGeometry, CoreProperties, GList, IO, Rope, RopeList, Sinix, SinixOps, Sisyph, TerminalIO, ViewerClasses, ViewerOps; SisyphCmdsImpl: CEDAR PROGRAM IMPORTS Basics, CD, CDBasics, CDCells, CDDirectory, CDImports, CDInstances, CDLayers, CDOps, CDPanelFonts, CDPopUpMenus, CDProperties, CDRects, CDSatellites, CDSequencer, CDTexts, CDViewer, CoreClasses, CoreOps, CoreGeometry, CoreProperties, GList, IO, Rope, RopeList, Sinix, SinixOps, Sisyph, TerminalIO, ViewerOps SHARES CDPopUpMenus, Sisyph = BEGIN ROPE: TYPE = Rope.ROPE; ROPES: TYPE = LIST OF ROPE; Wire: TYPE = Core.Wire; Wires: TYPE = Core.Wires; CellType: TYPE = Core.CellType; Icon: TYPE ~ REF IconRep; IconRep: TYPE ~ RECORD [ name: ROPE _ NIL, -- The short name of the icon, i.e. excluding the ".icon" part boxWidth: CD.Number, -- Width of lines for icon box pinRect: CD.Position, -- Size of pins (horizontal pin) guard: CD.Number, -- Spacing between pin and pin name grid: CD.Number, -- The grid on which pins should be aligned font: CDTexts.CDFont, -- ChipNDale font to be used for all texts pins: ARRAY CoreGeometry.Side OF ROPES -- The sorted pin names on all four sides ]; UnMakeIcon: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; FlushCache[selected.ob]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, StripResultExprs[exprs]]; CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, NIL]; CDProperties.PutObjectProp[selected.ob, $IconFor, NIL]; }; MakeCellIconWithCodeDef: PROC [comm: CDSequencer.Command] = { iconName: ROPE; selected: CD.Instance; multiple: BOOL; cellIconExprPrefix: ROPE _ Rope.Cat[Sisyph.cellIconRope, " _ "]; cellIconExpr: ROPE; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; FlushCache[selected.ob]; iconName _ CDDirectory.Name[selected.ob]; IF NOT Rope.Match["*.icon", iconName] THEN TerminalIO.PutF["*** Convention for icons is to suffix them with '.icon'.\n"]; cellIconExpr _ TerminalIO.RequestRope[Rope.Cat["Type code: ", cellIconExprPrefix]]; cellIconExpr _ Rope.Cat[cellIconExprPrefix, cellIconExpr]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; exprs _ CONS [cellIconExpr, StripResultExprs[exprs]]; CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, NIL]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs]; CDProperties.PutObjectProp[selected.ob, $IconFor, NIL]; }; MakeCellIconWithGeometryDef: PROC [comm: CDSequencer.Command] = { iconName: ROPE; selected: CD.Instance; multiple: BOOL; schematicName: ROPE; cellIconExprPrefix: ROPE _ Rope.Cat[Sisyph.cellIconRope, " _ "]; cellIconExpr: ROPE; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; FlushCache[selected.ob]; iconName _ CDDirectory.Name[selected.ob]; IF NOT Rope.Match["*.icon", iconName] THEN TerminalIO.PutF["*** Convention for icons is to suffix them with '.icon'.\n"]; schematicName _ TerminalIO.RequestRope["Type schematic name: "]; IF CDDirectory.Fetch[comm.design, schematicName].object = NIL THEN { TerminalIO.PutF["*** No such object in design.\n"]; RETURN; }; IF NOT Rope.Match["*.sch", schematicName] THEN TerminalIO.PutF["*** Convention for schematics is to suffix them with '.sch'.\n"]; cellIconExpr _ Rope.Cat[cellIconExprPrefix, "ES[\"", schematicName, "\", cx]"]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; exprs _ CONS [cellIconExpr, StripResultExprs[exprs]]; CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, NIL]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs]; CDProperties.PutObjectProp[selected.ob, $IconFor, schematicName]; }; MakeWireIconWithCodeDef: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; wireIconExprPrefix: ROPE _ Rope.Cat[Sisyph.wireIconRope, " _ "]; wireIconExpr: ROPE; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; FlushCache[selected.ob]; wireIconExpr _ TerminalIO.RequestRope[Rope.Cat["Type code: ", wireIconExprPrefix]]; wireIconExpr _ Rope.Cat[wireIconExprPrefix, wireIconExpr]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; exprs _ CONS [wireIconExpr, StripResultExprs[exprs]]; CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, NIL]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs]; CDProperties.PutObjectProp[selected.ob, $IconFor, NIL]; }; CreateIconCommand: PROC [comm: CDSequencer.Command] ~ { schematicName, iconShortName: ROPE; icon: CD.Object; cell: Core.CellType; selected: CD.Instance; multiple: BOOL; grid: CD.Number _ -1; cellRef: REF; viewer: ViewerClasses.Viewer _ CDViewer.GetViewer[comm]; IF viewer#NIL THEN WITH ViewerOps.GetViewer[viewer, $Grid] SELECT FROM rgrid: REF CD.Number => grid _ rgrid^; ENDCASE => NULL; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; schematicName _ CDDirectory.Name[selected.ob]; IF schematicName=NIL THEN { TerminalIO.PutF["*** Selected schematic has no name.\n"]; RETURN; }; IF NOT Rope.Match["*.sch", schematicName] THEN TerminalIO.PutF["*** Convention for schematics is to suffix them with '.sch'.\n"]; cellRef _ SinixOps.ExtractCDInstance[selected, comm.design, Sisyph.mode].result; IF ISTYPE [cellRef, Core.CellType] THEN cell _ NARROW [cellRef] ELSE { TerminalIO.PutF["*** Selected cell does not extract to Core CellType\n"]; RETURN; }; iconShortName _ TerminalIO.RequestRope["Type icon short name: "]; IF Rope.IsEmpty[iconShortName] THEN iconShortName _ IF Rope.Match["*.sch", schematicName] THEN Rope.Substr[schematicName, 0, Rope.Length[schematicName]-4] ELSE schematicName; IF Rope.IsEmpty[schematicName] THEN { TerminalIO.PutF["No name provided, no default from schematic.\n"]; RETURN; }; IF CDDirectory.Fetch[comm.design, Rope.Cat[iconShortName, ".icon"]].found THEN { TerminalIO.PutF["*** The icon %g.icon already exists!\n", IO.rope[iconShortName]]; RETURN; }; icon _ IconFromSchematic[cell, schematicName, iconShortName, comm.design, grid]; IF icon=NIL THEN RETURN; CDCells.SetSimplificationTreshhold[cell: icon, val: 30, inPixels: TRUE]; CDOps.IncludeObjectI[comm.design, icon, comm.pos]; }; MakeSequenceIcon: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; IF NOT CDCells.IsCell[selected.ob] THEN { TerminalIO.PutF["*** Selected object is not a cell.\n"]; RETURN; }; IF NOT ContainsSequenceResult[CDSatellites.GetSatelliteRopes[selected.ob]] THEN { TerminalIO.PutF["*** Warning: there is no satellite of the form 'Keyword: Expression', where 'Keyword' is one of the following:"]; FOR i: NAT IN [0 .. nbSequenceKeyWords) DO TerminalIO.PutF[" %g", IO.rope[sequenceKeyWords[i]]] ENDLOOP; TerminalIO.PutF["\n"]; } ELSE TerminalIO.PutF["Sequencing of %g done.\n", IO.rope[CDDirectory.Name[selected.ob]]]; FlushCache[selected.ob]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, StripResultExprs[exprs]]; CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, $SisyphExtractSequence]; CDProperties.PutObjectProp[selected.ob, $IconFor, NIL]; }; MakeInvisibleToExtractor: PROC [comm: CDSequencer.Command] = { nInstances: INT _ 0; FOR w: LIST OF CD.Instance _ CDOps.InstList[comm.design], w.rest WHILE w#NIL DO inst: CD.Instance _ w.first; IF inst.selected THEN { CDProperties.PutInstanceProp[inst, Sisyph.mode.extractProcProp, $ExtractNull]; nInstances _ nInstances+1; FlushCache[inst.ob] } ENDLOOP; TerminalIO.PutF["Made %g instances invisible to Sisyph\n", IO.int[nInstances]] }; MakeVisibleToExtractor: PROC [comm: CDSequencer.Command] = { nInstances: INT _ 0; FOR w: LIST OF CD.Instance _ CDOps.InstList[comm.design], w.rest WHILE w#NIL DO inst: CD.Instance _ w.first; IF inst.selected THEN { CDProperties.PutInstanceProp[inst, Sisyph.mode.extractProcProp, NIL]; nInstances _ nInstances+1; FlushCache[inst.ob] } ENDLOOP; TerminalIO.PutF["Made %g instances visible to Sisyph\n", IO.int[nInstances]] }; FlushCache: PROC [obj: CD.Object] = { FlushEachInstance: CDCells.InstEnumerator = {FlushCache[inst.ob]}; Sinix.FlushCache[obj]; IF CDCells.IsCell[obj] THEN [] _ CDCells.EnumerateInstances[obj, FlushEachInstance]; }; FlushSisyphCaches: PROC [comm: CDSequencer.Command] = { FOR w: LIST OF CD.Instance _ CDOps.InstList[comm.design], w.rest WHILE w#NIL DO IF w.first.selected THEN FlushCache[w.first.ob]; ENDLOOP; }; ShowInstExpressions: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Instance Expressions:\n"]; PutRopes[NARROW [CDProperties.GetInstanceProp[selected, Sisyph.expressionsProp]]]; }; AddInstExpression: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Add Instance Expression\n"]; exprs _ NARROW [CDProperties.GetInstanceProp[selected, Sisyph.expressionsProp]]; exprs _ CONS [TerminalIO.RequestRope[Rope.Cat[" New Expression: "]], exprs]; CDProperties.PutInstanceProp[selected, Sisyph.expressionsProp, exprs] }; EditInstExpressions: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Edit Instance Expressions\n"]; exprs _ NARROW[CDProperties.GetInstanceProp[selected, Sisyph.expressionsProp]]; exprs _ EditExpressions[exprs, "Expression"]; CDProperties.PutInstanceProp[selected, Sisyph.expressionsProp, exprs] }; ShowObjExpressions: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Object Expressions:\n"]; PutRopes[NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]]; IF NOT CDImports.IsImport[selected.ob] THEN RETURN; IF NARROW [selected.ob.specific, CDImports.ImportSpecific].boundInstance=NIL THEN {TerminalIO.PutF["Object is an unbound import.\n"]; RETURN}; TerminalIO.PutF["Object Expressions of the bound import:\n"]; PutRopes[NARROW [CDProperties.GetObjectProp[NARROW [selected.ob.specific, CDImports.ImportSpecific].boundInstance.ob, Sisyph.expressionsProp]]]; }; AddObjExpression: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Add Object Expression\n"]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; exprs _ CONS [TerminalIO.RequestRope[Rope.Cat[" New Expression: "]], exprs]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs] }; EditObjExpressions: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Edit Object Expressions\n"]; exprs _ NARROW[CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; exprs _ EditExpressions[exprs, "Expression"]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs] }; ShowParmNames: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; parms: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Parm Names:"]; parms _ NARROW[CDProperties.GetObjectProp[selected.ob, Sisyph.parmNamesProp]]; WHILE parms#NIL DO TerminalIO.PutF[Rope.Cat["\n ", parms.first]]; parms _ parms.rest; ENDLOOP; TerminalIO.PutF["\n"]; }; AddParmName: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; parms: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Add Parameter Name\n"]; parms _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.parmNamesProp]]; parms _ CONS [TerminalIO.RequestRope[Rope.Cat[" New Parameter: "]], parms]; CDProperties.PutObjectProp[selected.ob, Sisyph.parmNamesProp, parms] }; EditParmNames: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; parms: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Edit Object Expressions\n"]; parms _ NARROW[CDProperties.GetObjectProp[selected.ob, Sisyph.parmNamesProp]]; parms _ EditExpressions[parms, "Parameter"]; CDProperties.PutObjectProp[selected.ob, Sisyph.parmNamesProp, parms] }; AlignUpToGrid: PROC [x, grid: CD.Number] RETURNS [CD.Number] ~ { RETURN [IF x>=0 THEN ((x+grid-1)/grid)*grid ELSE (x/grid)*grid] }; AlignDownToGrid: PROC [x, grid: CD.Number] RETURNS [CD.Number] ~ { RETURN [IF x>=0 THEN (x/grid)*grid ELSE ((x-grid+1)/grid)*grid] }; AlignPositionUpToGrid: PROC [p: CD.Position, grid: CD.Number] RETURNS [CD.Position] ~ { RETURN [[AlignUpToGrid[p.x, grid], AlignUpToGrid[p.y, grid]]] }; AlignRectUpToGrid: PROC [r: CD.Rect, grid: CD.Number] RETURNS [CD.Rect] ~ { RETURN [[x1: AlignDownToGrid[r.x1, grid], x2: AlignUpToGrid[r.x2, grid], y1: AlignDownToGrid[r.y1, grid], y2: AlignUpToGrid[r.y2, grid]]] }; MoveInstances: PROC [list: CD.InstanceList, by: CD.Position] ~ { WHILE list#NIL DO list.first.trans.off _ CDBasics.AddPoints[list.first.trans.off, by]; list _ list.rest; ENDLOOP; }; BuildIconSides: PROC [icon: Icon] RETURNS [sideSize: ARRAY CoreGeometry.Side OF CD.Position, sideList: ARRAY CoreGeometry.Side OF CD.InstanceList] ~ { BuildSideGeometry: PROC [on: CoreGeometry.Side, rotate: CD.Orientation, useTextEnd: BOOL, textOffset: CD.Position, pinStartPos: CD.Position] ~ { iList: CD.InstanceList _ NIL; pinPos, satPos: CD.Position; -- real ones pinPos _ pinStartPos; FOR names: ROPES _ icon.pins[on], names.rest WHILE names#NIL DO satObject: CD.Object = CDTexts.Create[text: names.first, font: icon.font]; size: CD.Position = CDBasics.SizeOfRect[satObject.bbox]; pinObject: CD.Object = CDRects.CreateRect[size: icon.pinRect, l: CD.commentLayer]; satInst, pinInst: CD.Instance; pinInst _ CDInstances.NewInst[pinObject, [pinPos, rotate]]; satPos _ CDBasics.AddPoints[pinPos, textOffset]; satPos _ CDBasics.SubPoints[ satPos, IF CDBasics.IncludesOddRot90[rotate] THEN [size.y/2, IF useTextEnd THEN 0 ELSE -size.x] ELSE [IF useTextEnd THEN size.x ELSE 0, size.y/2] ]; satInst _ CDInstances.NewInst[satObject, [satPos, rotate]]; pinPos _ AlignPositionUpToGrid[CDBasics.AddPoints[pinPos, CDBasics.OrientedSize[[0, size.y], rotate]], icon.grid]; CDSatellites.Associate[master: pinInst, text: satInst]; iList _ CONS[pinInst, iList]; iList _ CONS[satInst, iList]; ENDLOOP; IF iList#NIL THEN { -- Compute size (not default) and set logical base at [0,0] r: CD.Rect = AlignRectUpToGrid[CDInstances.BoundingRectO[iList], icon.grid]; pos: CD.Position = CDBasics.BaseOfRect[r]; sideSize[on] _ CDBasics.SizeOfRect[r]; MoveInstances[iList, CDBasics.NegOffset[pos]]; } ELSE sideSize[on] _ [0, 0]; sideList[on] _ iList; }; BuildSideGeometry[on: top, rotate: rotate270, useTextEnd: TRUE, textOffset: [0, -icon.pinRect.x-icon.guard], pinStartPos: [0, -icon.pinRect.x]]; BuildSideGeometry[on: bottom, rotate: rotate270, useTextEnd: FALSE, textOffset: [0, icon.pinRect.x-icon.guard], pinStartPos: [0, 0]]; BuildSideGeometry[on: right, rotate: original, useTextEnd: TRUE, textOffset: [-icon.guard, 0], pinStartPos: [-icon.pinRect.x, 0]]; BuildSideGeometry[on: left, rotate: original, useTextEnd: FALSE, textOffset: [icon.pinRect.x+icon.guard, 0], pinStartPos: [0, 0]]; }; BuildIconFrame: PROC [icon: Icon, box: CD.Rect] RETURNS [list: CD.InstanceList _ NIL] ~ { BuildBoxSide: PROC [size, at: CD.Position, orient: CD.Orientation] ~ { list _ CONS [CDInstances.NewInst[CDRects.CreateRect[size: size, l: CD.commentLayer], [at, orient]], list]; CDProperties.PutInstanceProp[list.first, Sisyph.mode.extractProcProp, $ExtractNull]; }; w: CD.Number = icon.boxWidth; BuildBoxSide[size: [w, w+box.y2-box.y1], at: [box.x1, box.y1], orient: original]; -- left BuildBoxSide[size: [w, w+box.y2-box.y1], at: [box.x2, box.y1], orient: original]; -- right BuildBoxSide[size: [w, w+box.x2-box.x1], at: [box.x2+w, box.y1], orient: rotate90]; -- bottom BuildBoxSide[size: [w, w+box.x2-box.x1], at: [box.x2+w, box.y2], orient: rotate90]; -- top }; CommentText: PROC [text: ROPE, font: CDTexts.CDFont] RETURNS [ob: CD.Object] ~ { IsItalic: PROC [fontName: ROPE] RETURNS [BOOL] = { RETURN [Rope.Find[fontName, "i", Rope.Length[fontName]-1, FALSE]#-1] }; italicFont: CDTexts.CDFont _ IF ~IsItalic[font.supposedName] THEN CDTexts.MakeFont[ name: Rope.Cat[font.supposedName, "I"], scale: font.scaleI] ELSE font; ob _ CDTexts.Create[text: text, font: italicFont]; }; BuildIconObject: PROC [icon: Icon, design: CD.Design] RETURNS [obj: CD.Object] ~ { sideSize: ARRAY CoreGeometry.Side OF CD.Position; sideList: ARRAY CoreGeometry.Side OF CD.InstanceList; internalInstances: CD.InstanceList _ NIL; iconFullName: ROPE = Rope.Cat[icon.name, ".icon"]; iconTextObject: CD.Object = CommentText[text: icon.name, font: icon.font]; size: CD.Position = CDBasics.SizeOfRect[iconTextObject.bbox]; iconText: CD.Instance; inside, outside: CD.Rect; width, height: CD.Number; IF icon.grid<=0 THEN icon.grid _ design.technology.lambda; [sideSize, sideList] _ BuildIconSides[icon]; width _ sideSize[left].x+sideSize[right].x+MAX[ sideSize[bottom].x, sideSize[top].x, AlignUpToGrid[2*size.x, icon.grid]]; height _ MAX[ sideSize[left].y, sideSize[right].y, sideSize[bottom].y+sideSize[top].y+AlignUpToGrid[4*size.y, icon.grid]]; inside.x1 _ sideSize[left].x; inside.y1 _ sideSize[bottom].y; inside.x2 _ width+icon.pinRect.y-sideSize[right].x; inside.y2 _ height+icon.pinRect.y-sideSize[top].y; outside.x1 _ IF sideList[left]=NIL THEN 0 ELSE icon.pinRect.x; outside.y1 _ IF sideList[bottom]=NIL THEN 0 ELSE icon.pinRect.x; outside.x2 _ IF sideList[right]=NIL THEN width ELSE width-icon.pinRect.x; outside.y2 _ IF sideList[top]=NIL THEN height ELSE height-icon.pinRect.x; MoveInstances[ sideList[bottom], [AlignDownToGrid[(width+sideSize[left].x-sideSize[right].x-sideSize[bottom].x)/2, icon.grid], 0]]; MoveInstances[ sideList[top], [AlignDownToGrid[(width+sideSize[left].x-sideSize[right].x-sideSize[top].x)/2, icon.grid], inside.y2]]; MoveInstances[ sideList[left], [0, AlignDownToGrid[(height-sideSize[left].y)/2, icon.grid]]]; MoveInstances[ sideList[right], [inside.x2, AlignDownToGrid[(height-sideSize[right].y)/2, icon.grid]]]; iconText _ CDInstances.NewInst[ iconTextObject, [CDBasics.SubPoints[CDBasics.Center[inside], CDBasics.Center[CDBasics.RectAt[[0, 0], size]]]]]; internalInstances _ BuildIconFrame[icon, outside]; internalInstances _ CONS [iconText, internalInstances]; FOR on: CoreGeometry.Side IN CoreGeometry.Side DO FOR list: CD.InstanceList _ sideList[on], list.rest WHILE list#NIL DO internalInstances _ CONS [list.first, internalInstances]; ENDLOOP; ENDLOOP; obj _ CDCells.CreateCell[il: internalInstances]; -- of course, one would really like a sequence! IF CDDirectory.Fetch[design, iconFullName].found THEN { TerminalIO.PutF["*** The icon %g already exists!\n", IO.rope[iconFullName]]; ERROR; }; IF NOT CDDirectory.Include[design, obj, iconFullName] THEN { TerminalIO.PutF["*** Direction insertion of icon %g failed.\n", IO.rope[iconFullName]]; ERROR; }; }; IconFromSchematic: PROC [cell: Core.CellType, schematicName, iconName: ROPE, design: CD.Design, grid: CD.Number _ -1] RETURNS [obj: CD.Object] ~ { InternalPin: TYPE ~ REF InternalPinRep; InternalPinRep: TYPE ~ RECORD [ name: ROPE, rect: CD.Rect -- The InstRectO of the pin, used to sort along the side ]; Side: TYPE ~ RECORD [ border: CD.Rect, -- Representation of schematic side pins: LIST OF InternalPin _ NIL ]; SearchPins: CoreOps.EachWireProc ~ { pinGeom: CoreGeometry.Instances _ CoreGeometry.GetPins[Sisyph.mode.decoration, wire]; pinName: ROPE = CoreOps.GetShortWireName[wire]; IF pinGeom=NIL THEN RETURN; IF pinName=NIL THEN { TerminalIO.PutF["*** The wire %g has pins, but no short name\n", IO.rope[CoreOps.GetFullWireName[root: cell.public, wire: wire]]]; RETURN[quit: TRUE]; }; WHILE pinGeom#NIL DO -- Paranoid! the first pin should touch a side of the schematic pinRect: CD.Rect = CoreGeometry.BBox[pinGeom.first]; FOR on: CoreGeometry.Side IN CoreGeometry.Side DO IF CDBasics.Intersect[pinRect, sides[on].border] THEN { sides[on].pins _ CONS [NEW [InternalPinRep _ [name: pinName, rect: pinRect]], sides[on].pins]; RETURN [subWires: FALSE]; }; ENDLOOP; pinGeom _ pinGeom.rest; ENDLOOP; TerminalIO.PutF["*** The wire %g has pins, but none of them touches the icon of the schematic.\n", IO.rope[CoreOps.GetFullWireName[root: cell.public, wire: wire]]]; RETURN [quit: TRUE]; }; XSort: GList.CompareProc ~ { -- Reverse order comparison RETURN [Basics.CompareINT[NARROW[ref2, InternalPin].rect.x1, NARROW[ref1, InternalPin].rect.x1]]; }; YSort: GList.CompareProc ~ { -- Reverse order comparison RETURN [Basics.CompareINT[NARROW[ref2, InternalPin].rect.y1, NARROW[ref1, InternalPin].rect.y1]]; }; lineWidth: CD.Number = CDLayers.LayerWidth[design, CD.commentLayer]; icon: Icon _ NEW [IconRep _ [name: iconName, boxWidth: lineWidth, pinRect: [x: 4*lineWidth, y: lineWidth], guard: 2*lineWidth, grid: grid, font: CDPanelFonts.CurrentFont[design]]]; sides: ARRAY CoreGeometry.Side OF Side; cellIR: CD.Rect = CD.InterestRect[CoreGeometry.GetObject[Sisyph.mode.decoration, cell]]; exprs: ROPES _ NIL; sides[top].border _ [x1: cellIR.x1, x2: cellIR.x2, y1: cellIR.y2, y2: cellIR.y2]; sides[bottom].border _ [x1: cellIR.x1, x2: cellIR.x2, y1: cellIR.y1, y2: cellIR.y1]; sides[right].border _ [x1: cellIR.x2, x2: cellIR.x2, y1: cellIR.y1, y2: cellIR.y2]; sides[left].border _ [x1: cellIR.x1, x2: cellIR.x1, y1: cellIR.y1, y2: cellIR.y2]; IF CoreOps.VisitWireSeq[cell.public, SearchPins] THEN RETURN [NIL]; FOR on: CoreGeometry.Side IN CoreGeometry.Side DO icon.pins[on] _ NIL; FOR list: LIST OF InternalPin _ NARROW [GList.UniqueSort[list: sides[on].pins, compareProc: IF on=top OR on=bottom THEN XSort ELSE YSort]], list.rest WHILE list#NIL DO icon.pins[on] _ CONS [list.first.name, icon.pins[on]]; ENDLOOP; ENDLOOP; obj _ BuildIconObject[icon, design]; exprs _ CONS [Rope.Cat[Sisyph.cellIconRope, " _ ES[\"", schematicName, "\", cx]"], exprs]; CDProperties.PutObjectProp[obj, Sisyph.mode.extractProcProp, NIL]; CDProperties.PutObjectProp[obj, Sisyph.expressionsProp, exprs]; CDProperties.PutObjectProp[obj, $IconFor, schematicName]; }; nbSequenceKeyWords: NAT = 5; sequenceKeyWords: ARRAY [0 .. nbSequenceKeyWords) OF ROPE = ["Seq", "SeqX", "SeqY", "RSeqX", "RSeqY"]; sequenceLayoutAtoms: ARRAY [0 .. nbSequenceKeyWords) OF ATOM = [NIL, $ArrayX, $ArrayY, $ReverseArrayY, $ReverseArrayY]; -- At this point, there is a strange dependency between Sisyph and PWCore, but it is not worth the effort making a separate module FindMatchingKeyword: PROC [expr: ROPE] RETURNS [keyword: NAT _ nbSequenceKeyWords, sequencing: ROPE _ NIL] = { FOR i: NAT IN [0 .. nbSequenceKeyWords) DO IF Rope.Match[Rope.Cat[sequenceKeyWords[i], ":*"], expr] THEN RETURN [i, Rope.Substr[expr, Rope.Find[expr, ":"]+1]]; ENDLOOP; }; IsSequenceResult: PROC [expr: ROPE] RETURNS [BOOL] = { RETURN [FindMatchingKeyword[expr].keyword#nbSequenceKeyWords] }; ContainsSequenceResult: PROC [exprs: ROPES] RETURNS [BOOL _ FALSE] = { WHILE exprs#NIL DO IF IsSequenceResult[exprs.first] THEN RETURN [TRUE]; exprs _ exprs.rest ENDLOOP; }; FindPorts: PROC [baseCell: CellType, wires: Wires] RETURNS [set: CoreClasses.SequenceSet] = { nats: LIST OF NAT _ NIL; size: NAT _ 0; WHILE wires#NIL DO FOR w: NAT IN [0 .. baseCell.public.size) DO sequenceName: ROPE _ CoreOps.GetShortWireName[wires.first]; IF wires.first=baseCell.public[w] OR (sequenceName#NIL AND Rope.Equal[sequenceName, CoreOps.GetShortWireName[baseCell.public[w]]]) THEN { nats _ CONS [w, nats]; size _ size + 1; EXIT; }; REPEAT FINISHED => ERROR; ENDLOOP; wires _ wires.rest; ENDLOOP; set _ NEW [CoreClasses.SequenceSetRec[size]]; FOR i: INT IN [0 .. size) DO set[i] _ nats.first; nats _ nats.rest ENDLOOP; }; ExtractSequence: Sinix.ExtractProc = { AddProp: PROC [prop: ATOM, val: REF ANY] = { CoreProperties.PutCellTypeProp[cellType, prop, val]; }; cx: Sisyph.Context; resultRope: ROPE; cellType: CellType; name: ROPE = CDDirectory.Name[obj]; keyword: NAT; sequencing: ROPE; count: NAT; [cx, resultRope] _ Sisyph.EvaluateParameters[userData, obj, properties, IsSequenceResult]; IF resultRope=NIL THEN { TerminalIO.PutF["*** SisyphExtractSequence: Sequence does not contain any of sequencing information (e.g. an object satellite 'SeqX: 32').\n"]; ERROR; }; [keyword, sequencing] _ FindMatchingKeyword[resultRope]; Sisyph.Eval[cx, sequencing]; count _ NAT [Sisyph.FetchInt[cx, "&"].value]; TerminalIO.PutF["Extracting [Sisyph] cell %g (%g: %g)\n", IO.rope[CDDirectory.Name[obj]], IO.rope[sequenceKeyWords[keyword]], IO.int[count]]; cellType _ ExtractSequenceIcon[obj, cx, keyword, count]; props _ Sisyph.GetCoreInstProps[cx]; CoreProperties.Enumerate[Sisyph.GetCoreProps[cx], AddProp]; IF CoreOps.GetCellTypeName[cellType]=NIL AND name#NIL THEN [] _ CoreOps.SetCellTypeName[cellType, Rope.Substr[name, 0, Rope.Index[name, 0, "."]]]; result _ cellType; }; ExtractSequenceIcon: PROC [obj: CD.Object, cx: Sisyph.Context, keyword, count: NAT] RETURNS [sequence: CellType] = { iconCT: CellType = NARROW [Sinix.ExtractCell[obj, Sisyph.mode, NIL, cx].result]; iconRCT: CoreClasses.RecordCellType = NARROW [iconCT.data]; subCT: CellType; sequenceWires, flatSequenceWires: Wires _ NIL; IF iconRCT.size#1 THEN { TerminalIO.PutF["*** SisyphExtractSequence: Sequence should contain one and only one subcell.\n"]; ERROR; }; subCT _ iconRCT[0].type; Sisyph.ProcessGlobalNames[iconCT, cx]; FOR i: NAT IN [0 .. iconRCT.internal.size) DO wire: Wire = iconRCT.internal[i]; name: ROPE _ CoreOps.GetShortWireName[wire]; IF name=NIL THEN name _ "some wire"; IF NOT CoreOps.RecursiveMember[iconRCT[0].actual, wire] THEN { TerminalIO.PutF["*** SisyphExtractSequence: %g is not connected to subcell.\n", IO.rope[name]]; ERROR; }; IF NOT CoreOps.RecursiveMember[iconCT.public, wire] THEN { TerminalIO.PutF["*** SisyphExtractSequence: %g is not public.\n", IO.rope[name]]; ERROR; }; ENDLOOP; FOR i: NAT IN [0 .. subCT.public.size) DO IF CoreProperties.GetWireProp[iconRCT[0].actual[i], $Sequence]#NIL THEN sequenceWires _ CONS [subCT.public[i], sequenceWires]; IF CoreProperties.GetWireProp[iconRCT[0].actual[i], $FlatSequence]#NIL THEN flatSequenceWires _ CONS [subCT.public[i], flatSequenceWires]; ENDLOOP; sequence _ CoreClasses.CreateSequence[NEW [CoreClasses.SequenceCellTypeRec _ [base: subCT, count: count, sequence: FindPorts[subCT, sequenceWires], flatSequence: FindPorts[subCT, flatSequenceWires]]]]; FOR i: NAT IN [0 .. sequence.public.size) DO iconWire: Wire = CoreClasses.CorrespondingActual[iconRCT[0], subCT.public[i]]; IF iconWire=NIL THEN ERROR; CoreGeometry.PutIndirectLazyPins[Sisyph.mode.decoration, sequence.public[i], iconWire]; CoreGeometry.PutGeometry[Sisyph.mode.decoration, sequence.public[i], CoreGeometry.GetGeometry[Sisyph.mode.decoration, iconWire]]; ENDLOOP; CoreGeometry.PutObject[Sisyph.mode.decoration, sequence, obj]; CoreProperties.PutCellTypeProp[sequence, $Layout, sequenceLayoutAtoms[keyword]]; }; PutRopes: PROC [ropes: ROPES] = { WHILE ropes#NIL DO TerminalIO.PutF["\t%g\n", IO.rope[ropes.first]]; ropes _ ropes.rest; ENDLOOP; }; IsSingleSelectedAndCell: PROC [selected: CD.Instance, multiple: BOOL] RETURNS [BOOL] = { IF ~IsSingleSelected[selected, multiple] THEN RETURN [FALSE]; IF ~CDCells.IsCell[selected.ob] THEN { TerminalIO.PutF["*** Selected instance is not a cellcan't do it.\n"]; RETURN[FALSE]; }; RETURN[TRUE]; }; IsSingleSelected: PROC [selected: CD.Instance, multiple: BOOL] RETURNS [BOOL] = { IF selected=NIL THEN { TerminalIO.PutF["*** No current selection--can't do it.\n"]; RETURN[FALSE]; }; IF multiple THEN { TerminalIO.PutF["*** Multiple instances selected--can't do it.\n"]; RETURN[FALSE]; }; RETURN[TRUE]; }; StripResultExprs: PROC [in: ROPES] RETURNS [out: ROPES _ NIL] = { FOR l: ROPES _ in, l.rest WHILE l#NIL DO IF ~Sisyph.IsResultExpression[l.first] THEN out _ CONS [l.first, out] ENDLOOP; }; EditExpressions: PROC [oldExprs: ROPES, prompt: ROPE] RETURNS [allExprs: ROPES _ NIL] = { input: ROPE; noOldExprs: BOOL _ oldExprs=NIL; TerminalIO.PutF["\n"]; WHILE oldExprs#NIL DO input _ TerminalIO.RequestRope[Rope.Cat[" ", prompt, ": ", oldExprs.first, " Replacement: "]]; SELECT TRUE FROM Rope.Equal[input, "-"] => TerminalIO.PutF[" ** Deleted\n"]; Rope.IsEmpty[input] => allExprs _ CONS [oldExprs.first, allExprs]; ENDCASE => allExprs _ CONS [input, allExprs]; oldExprs _ oldExprs.rest; ENDLOOP; IF noOldExprs THEN { input _ TerminalIO.RequestRope[Rope.Cat[" New ", prompt, ": "]]; WHILE ~Rope.IsEmpty[input] AND ~Rope.Equal[input, "-"] DO allExprs _ CONS [input, allExprs]; input _ TerminalIO.RequestRope[Rope.Cat[" New ", prompt, ": "]]; ENDLOOP; }; allExprs _ RopeList.Reverse[allExprs]; }; Sinix.RegisterExtractProc[$SisyphExtractSequence, ExtractSequence]; CDSequencer.ImplementCommand[key: $FlushSisyphCaches, proc: FlushSisyphCaches]; SinixOps.RegisterModeCommands[mode: Sisyph.mode]; [] _ CDPopUpMenus.MakeMenu[$SisyphIconMenu, "Sisyph: Make Icon", NIL]; CDSequencer.ImplementCommand[key: $CreateIconCommand, proc: CreateIconCommand]; CDSequencer.ImplementCommand[key: $MakeCellIconWithGeometryDef, proc: MakeCellIconWithGeometryDef]; CDSequencer.ImplementCommand[key: $MakeCellIconWithCodeDef, proc: MakeCellIconWithCodeDef]; CDSequencer.ImplementCommand[key: $MakeSequenceIcon, proc: MakeSequenceIcon]; CDSequencer.ImplementCommand[key: $MakeWireIconWithCodeDef, proc: MakeWireIconWithCodeDef]; CDSequencer.ImplementCommand[key: $UnMakeIcon, proc: UnMakeIcon]; [] _ CDPopUpMenus.MakeMenu[$SisyphVisibilityMenu, "Sisyph: Change Visibility", NIL]; CDSequencer.ImplementCommand[key: $MakeInvisibleToExtractor, proc: MakeInvisibleToExtractor]; CDSequencer.ImplementCommand[key: $MakeVisibleToExtractor, proc: MakeVisibleToExtractor]; [] _ CDPopUpMenus.MakeMenu[$SisyphParameterMenu, "Sisyph: Parameter Specification", NIL]; CDSequencer.ImplementCommand[key: $SisyphShowParmNames, proc: ShowParmNames, queue: doQueue]; CDSequencer.ImplementCommand[key: $SisyphAddParmName, proc: AddParmName]; CDSequencer.ImplementCommand[key: $SisyphEditParmNames, proc: EditParmNames]; CDSequencer.ImplementCommand[key: $SisyphShowInstExpressions, proc: ShowInstExpressions, queue: doQueue]; CDSequencer.ImplementCommand[key: $SisyphAddInstExpression, proc: AddInstExpression]; CDSequencer.ImplementCommand[key: $SisyphEditInstExpressions, proc: EditInstExpressions]; CDSequencer.ImplementCommand[key: $SisyphShowObjExpressions, proc: ShowObjExpressions, queue: doQueue]; CDSequencer.ImplementCommand[key: $SisyphAddObjExpression, proc: AddObjExpression]; CDSequencer.ImplementCommand[key: $SisyphEditObjExpressions, proc: EditObjExpressions]; END. ��� .��SisyphCmdsImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Created by Pradeep Sindhu, December 9, 1985 10:01:52 pm PST Pradeep Sindhu, September 26, 1986 2:06:15 pm PDT Barth, January 13, 1986 3:30:05 pm PST Bertrand Serlet March 4, 1987 7:16:45 pm PST Jean-Marc Frailong June 20, 1986 8:25:11 pm PDT Last Edited by: Jacobi July 15, 1986 2:40:48 pm PDT Icon Commands User interface to create icon from schematic Other Commands Create icon from schematic Move all instances in the list by the required amount Build all the pins and pin names for the icon. Create geometry (pins and names) along an edge of the icon. All pins are aligned on grid coordinates. Text is centered on associated pin, at left or right according to request. Text is separated by guard CD units from the pin. The returned iLists alternates pins and names. Progress pin position Set satellite property and add to result list Build the geometry for the icon box Build the CD object for the icon in the design. The object is included in the design. Raises an ERROR if the object already existed (should be checked by caller). Compute a reasonable size for the inside and outside of the icon. Move the sides at their final locations and setup the icon name Build the icon object Build an icon straight from the schematic. Return NIL object if error. The schematicName had better be the right one. First, build rectangles representing the sides of the schematic Scan the public to build the sides structure Sort the pins on each side and setup the names in the icon structure Finally create the object from the icon structure Sequence Icons There should be only one subcell We deal with Global Variables we check that there is no internal only We compute which wires are going to be sequenced We create the sequence We copy the pins decorations The object decoration! We decorate with the appriopriate layout atom Internal Utilities Initialization FilterSch: SinixOps.FilterProc = {RETURN [Rope.Match["*.sch", name] OR Rope.Match["*.icon", name]]}; Main Menu SinixOps.RegisterBackgroundExtractionCommand[CD.FetchTechnology[$cmosB], Sisyph.mode, "Sch background extraction", $SchBackgroundExtract, FilterSch]; -- only works for CMosB. Not very clean Make Icon Menu Change Visibility Menu Make Parameter Menu (normally hidden) Expressions Menu Ê!Y��˜�™Jšœ Ïmœ7™BJšœ8Ïk™;Jšœ.ž™1Icodešœ#ž™&Kšœ,™,Kšœ,ž™/Kšœ0ž™3—J™�šž ˜ Jšœ˜Jšžœ¬˜®Jšœ9˜9Jšœžœ˜Jšœ˜Jšœ%˜%J˜�—šÏnœžœž˜Kšžœ žœçžœ@˜»Kšžœž˜#K™�Kšžœžœžœ˜Kš žœžœžœžœžœ˜Kšœžœ ˜Kšœžœ˜Kšœ žœ˜K˜�Kšœžœžœ ˜šœ žœžœ˜KšœžœžœÏc>˜PKšœ žœ ˜3Kšœ žœ ˜6Kšœžœ #˜5Kšœžœ +˜<Kšœ *˜@Kšœžœžœžœ )˜PK˜——head™ šŸ œžœ ˜0Kšœ žœ ˜Kšœ žœ˜Kšœžœ˜ Kšœ;˜;Kšžœ.žœžœ˜<Kšœ˜KšœžœC˜QKšœY˜YKšœEžœ˜JKšœ2žœ˜7Kšœ˜K˜�—šŸœžœ ˜=Kšœ žœ˜Kšœ žœ ˜Kšœ žœ˜Kšœžœ(˜@Kšœžœ˜Kšœžœ˜ K˜�Kšœ;˜;Kšžœ.žœžœ˜<Kšœ˜Kšœ)˜)Kšžœžœ žœO˜yK˜�KšœS˜SKšœ:˜:KšœžœC˜QKšœžœ)˜5KšœEžœ˜JKšœG˜GKšœ2žœ˜7Kšœ˜K˜�—šŸœžœ ˜AKšœ žœ˜Kšœ žœ ˜Kšœ žœ˜Kšœžœ˜Kšœžœ(˜@Kšœžœ˜Kšœžœ˜ K˜�Kšœ;˜;Kšžœ.žœžœ˜<Kšœ˜Kšœ)˜)Kšžœžœ žœO˜yK˜�Kšœ@˜@šžœ8žœžœ˜DKšœ3˜3Kšžœ˜K˜—K˜�Kšžœžœ$žœS˜KšœO˜OKšœžœC˜QKšœžœ)˜5KšœEžœ˜JKšœG˜GKšœA˜AKšœ˜K˜�—šŸœžœ ˜=Kšœ žœ ˜Kšœ žœ˜Kšœžœ(˜@Kšœžœ˜Kšœžœ˜ K˜�Kšœ;˜;Kšžœ.žœžœ˜<K˜�Kšœ˜KšœS˜SKšœ:˜:KšœžœC˜QKšœžœ)˜5KšœEžœ˜JKšœG˜GKšœ2žœ˜7Kšœ˜K˜�—šŸœžœ ˜7K™,Kšœžœ˜#Kšœžœ˜K˜Kšœ žœžœ˜&Kšœžœ ˜Kšœ žœ˜ Kšœ8˜8šžœžœžœžœ$žœž˜FKšœžœžœ˜&Kšžœžœ˜—Kšœ;˜;Kšžœ.žœžœ˜<Kšœ.˜.šžœžœžœ˜Kšœ9˜9Kšžœ˜K˜—Kšžœžœ$žœS˜KšœP˜PKšžœžœžœžœ ˜?šžœ˜KšœI˜IKšžœ˜K˜—KšœA˜Ašžœ˜šžœžœ$˜;Kšžœ=˜AKšžœ˜——šžœžœ˜%JšœB˜BKšžœ˜K˜—šžœHžœ˜PKšœ:žœ˜RKšžœ˜K˜—KšœP˜PK•StartOfExpansion9[cell: CD.Object, val: REAL, inPixels: BOOL _ TRUE]šžœžœžœžœ˜KšœBžœ˜HKšœ2˜2K˜K˜�—šŸœžœ ˜6Kšœ žœžœ˜&Kšœžœ˜ Kšœ;˜;Kšžœ.žœžœ˜<šžœžœžœ˜)Kšœ8˜8Kšžœ˜K˜—šžœžœEžœ˜QKšœ‚˜‚šžœžœžœ˜(Kšžœžœžœ˜@—Kšœ˜Kšœž˜Kšœ,žœ&˜T—Kšœ˜KšœžœC˜QKšœY˜YKšœ]˜]Kšœ2žœ˜7Kšœ˜——™šŸœžœ ˜>Kšœžœ˜š žœžœžœžœ0žœžœž˜OKšœžœ˜šžœžœ˜KšœN˜NKšœ˜K˜K˜—Kšžœ˜—Kšœ;žœ˜NKšœ˜K˜�—šŸœžœ ˜<Kšœžœ˜š žœžœžœžœ0žœžœž˜OKšœžœ˜šžœžœ˜Kšœ@žœ˜EKšœ˜K˜K˜—Kšžœ˜—Kšœ9žœ˜LKšœ˜—K˜�šŸ œžœžœ˜%KšŸœ1˜BJšœ˜Kšžœžœ9˜TK˜K˜�—šŸœžœ ˜7š žœžœžœžœ0žœžœž˜OKšžœžœ˜0Kšžœ˜—Kšœ˜K˜�—šŸœžœ ˜9Kšœ žœ ˜Kšœ žœ˜Kšœ;˜;Kšžœ'žœžœ˜5Kšœ+˜+Kšœ žœC˜RK˜—K˜�šŸœžœ ˜7Kšœ žœ ˜Kšœ žœ˜Kšœžœ˜ K˜�Kšœ;˜;Kšžœ'žœžœ˜5K˜�Kšœ-˜-KšœžœB˜PKšœžœA˜MKšœE˜EK˜—K˜�šŸœžœ ˜9Kšœ žœ ˜Kšœ žœ˜Kšœžœ˜ K˜�Kšœ;˜;Kšžœ'žœžœ˜5K˜�Kšœ/˜/KšœžœA˜OK˜-KšœE˜EK˜—K˜�šŸœžœ ˜8Kšœ žœ ˜Kšœ žœ˜Kšœ;˜;Kšžœ'žœžœ˜5Kšœ)˜)Kšœ žœD˜SKšžœžœ!žœžœ˜3šžœžœ@žœ˜MKšžœ5žœ˜A—Kšœ=˜=Kšœ žœžœ^˜K˜—K˜�šŸœžœ ˜6Kšœ žœ ˜Kšœ žœ˜Kšœžœ˜ K˜�Kšœ;˜;Kšžœ'žœžœ˜5K˜�Kšœ+˜+KšœžœC˜QKšœžœA˜MKšœF˜FK˜—K˜�šŸœžœ ˜8Kšœ žœ ˜Kšœ žœ˜Kšœžœ˜ K˜�Kšœ;˜;Kšžœ'žœžœ˜5K˜�Kšœ-˜-KšœžœB˜PK˜-KšœF˜FK˜—K˜�šŸ œžœ ˜3Kšœ žœ ˜Kšœ žœ˜Kšœžœ˜ K˜�Kšœ;˜;Kšžœ'žœžœ˜5K˜�Kšœ˜Kšœžœ@˜Nšžœžœž˜Kšœ/˜/K˜Kšžœ˜—Kšœ˜K˜—K™�šŸœžœ ˜1Kšœ žœ ˜Kšœ žœ˜Kšœžœ˜ K˜�Kšœ;˜;Kšžœ'žœžœ˜5K˜�Kšœ(˜(KšœžœA˜OKšœžœ@˜LKšœD˜DK˜—K™�šŸ œžœ ˜3Kšœ žœ ˜Kšœ žœ˜Kšœžœ˜ K˜�Kšœ;˜;Kšžœ'žœžœ˜5K˜�Kšœ-˜-Kšœžœ@˜NK˜,KšœD˜DK˜——™š Ÿ œžœžœ žœžœ˜@Kšžœžœžœžœ˜?K˜—K˜�š Ÿœžœžœ žœžœ˜BKšžœžœžœžœ˜?K˜—K˜�šŸœžœžœžœ žœžœ˜WKšžœ7˜=K˜—K˜�šŸœžœžœ žœ žœžœ ˜KKšžœƒ˜‰K˜—K˜�šŸ œžœžœžœ˜@K™5šœžœžœž˜KšœD˜DK˜Kšžœ˜—K˜—K˜�šŸœžœžœžœžœžœžœžœžœ˜–K™/K˜�šŸœžœ!žœžœžœžœ˜KšœÌžœC™‘Kšœžœžœ˜Kšœžœ ˜)Kšœ˜š žœžœžœžœž˜?Kšœžœ=˜JKšœžœ0˜8Kšœžœ4žœ˜RKšœžœ ˜Kšœ;˜;Kšœ0˜0šœ˜Kšœ˜šžœ#˜%Kšžœžœžœžœ ˜2Kšžœžœžœžœ ˜1—K˜—Kšœ;˜;Kšœ™Jšœr˜rJ™-Kšœ7˜7Jšœžœ˜Jšœžœ˜Kšžœ˜—šžœžœžœ ;˜OKšœžœG˜LKšœžœ#˜*Kšœ&˜&Kšœ.˜.K˜—Kšžœ˜K˜K˜—K˜�šœ˜Kšœ˜Kšœžœ˜Kšœ,˜,Kšœ#˜#—šœ˜Kšœ˜Kšœžœ˜Kšœ+˜+Kšœ˜—šœ˜Kšœ˜Kšœžœ˜Kšœ˜Kšœ#˜#—šœ˜Kšœ˜Kšœžœ˜Kšœ+˜+Kšœ˜—K˜—K˜�šŸœžœžœžœžœžœ˜YK™#šŸœžœžœžœ˜FKšœžœ8žœ%˜jKšœT˜TK˜—Kšœžœ˜KšœR ˜YKšœR ˜ZKšœT ˜]KšœT ˜ZK˜—K˜�š Ÿœžœžœžœžœ˜Pš Ÿœžœžœžœžœ˜2Jšžœ4žœ˜DJ˜—šœ˜šžœžœ˜6Jšœ'˜'Jšœ˜—Kšžœ˜ —Kšœ2˜2K˜—K˜�š Ÿœžœžœ žœžœ˜RKšœ žœTžœ=™¢Kšœ žœžœžœ ˜1Kšœ žœžœžœ˜5Kšœžœžœ˜)Kšœžœ ˜2Kšœžœ8˜JKšœžœ5˜=Kšœ žœ ˜Kšœžœ˜Kšœžœ˜Kšžœžœ&˜:Kšœ,˜,KšœA™Ašœ+žœ˜/Jšœ˜Jšœ˜Jšœ$˜$—šœ žœ˜ Jšœ˜Jšœ˜JšœG˜G—Jšœ˜Jšœ˜Jšœ3˜3Jšœ2˜2Kš œ žœžœžœžœ˜>Kš œ žœžœžœžœ˜@Kš œ žœžœžœžœ˜IKš œ žœžœžœžœ˜IK™?šœ˜Jšœ˜Jšœb˜b—šœ˜Jšœ˜Jšœg˜g—šœ˜Jšœ˜Jšœ>˜>—šœ˜Jšœ˜JšœG˜G—šœ˜Jšœ˜Jšœ_˜_—J™Kšœ2˜2Jšœžœ˜7šžœžœž˜1š žœžœ(žœžœž˜EKšœžœ!˜9Kšžœ˜—Kšžœ˜—Kšœ1 /˜`šžœ/žœ˜7Kšœ5žœ˜LKšžœ˜K˜—–b[design: CD.Design, object: CD.Object, alternateName: ROPE _ NIL, fiddleName: BOOL _ TRUE]šžœžœ0žœ˜<Kšœ@žœ˜WKšžœ˜K˜—K˜—K˜�šŸœžœ0žœ žœžœžœžœ˜’Jšœ2žœ@™uK˜�Kšœ žœžœ˜'šœžœžœ˜Kšœžœ˜Kšœžœ 8˜FKšœ˜—šœžœžœ˜Kšœžœ #˜4Kšœžœžœž˜K˜—K˜�šŸ œ˜$KšœU˜UKšœ žœ"˜/Kšžœ žœžœžœ˜šžœ žœžœ˜K–&[root: Core.Wire, wire: Core.Wire]šœAžœ?˜‚Kšžœžœ˜K˜—šžœ žœžœ ?˜TKšœ žœ)˜4šžœžœž˜1šžœ/žœ˜7KšœžœžœD˜^Kšžœžœ˜K˜—Kšžœ˜—Kšœ˜Kšžœ˜—Kšœcžœ?˜¤Kšžœžœ˜K˜—K˜�šŸœ ˜8Kšžœžœžœ˜aK˜—K˜�šŸœ ˜8Kšžœžœžœ˜aK˜—K˜�Kšœžœ&žœ˜DJšœ žœ¤˜´Kšœžœžœ˜'KšœžœžœD˜XKšœžœžœ˜K™?KšœQ˜QKšœT˜TKšœS˜SKšœR˜RK˜�K™,–5[wire: Core.Wire, eachWire: CoreOps.EachWireProc]šžœ/ž˜5Kšžœžœ˜ —K™Dšžœžœž˜1Kšœžœ˜šžœžœžœžœ6žœžœžœžœžœžœž˜§Kšœžœ"˜6Kšžœ˜—Kšžœ˜—K˜�K™1K˜$KšœžœN˜ZKšœ=žœ˜BKšœ?˜?Kšœ9˜9K˜——™Kšœžœ˜Kšœžœžœžœ-˜fš œžœžœžœžœ5 ‚˜úK˜�—šŸœžœžœžœžœ#žœžœ˜nšžœžœžœž˜*Kšžœ7žœžœ0˜tKšžœ˜—Kšœ˜K˜�—š Ÿœžœžœžœžœ˜6Kšžœ7˜=Kšœ˜K˜�—šŸœžœ žœžœžœžœ˜Fšžœžœžœ˜Jš žœžœžœžœžœ˜P—Kšœ˜K˜�—šŸ œžœ$žœ#˜]Kš œžœžœžœžœ˜Kšœžœ˜šžœžœž˜šžœžœžœž˜,Kšœžœ*˜<š žœ žœžœžœIžœ˜‰Kšœžœ˜'Kšžœ˜Kšœ˜—Kšžœžœžœ˜Kšžœ˜ —Kšœ˜Kšžœ˜—Kšœžœ$˜-Kš žœžœžœ žœ'žœ˜KK˜K˜�—šŸœ˜&š Ÿœžœžœžœžœ˜,Kšœ4˜4K˜—Jšœ˜Jšœžœ˜Jšœ˜Jšœžœ˜#Kšœ žœžœ žœ˜+JšœZ˜Zšžœžœžœ˜Kšœ˜Kšžœ˜K˜—Jšœ8˜8Jšœ˜Jšœžœ"˜-Jšœ:žœžœ"žœ ˜Jšœ9˜9J˜$Jšœ;˜;Jš žœ#žœžœžœžœX˜’Jšœ˜K˜K˜�—–¡ -- [obj: CD.Object, mode: Sinix.Mode, properties: PropertyLists.PropList _ NIL, userData: REF ANY _ NIL] RETURNS [result: REF ANY, props: Core.Properties _ NIL]š Ÿœžœžœ-žœžœ˜tJšœžœ&žœ˜PJšœ&žœ˜;Jšœ˜Jšœ*žœ˜.Jšœ ™ šžœžœ˜Kšœb˜bKšžœ˜K˜—Jšœ˜J™Jšœ&˜&Jšœ'™'šžœžœžœž˜-Jšœ!˜!Jšœžœ"˜,Jšžœžœžœ˜$šžœžœ2žœ˜>KšœPžœ ˜_Kšžœ˜Kšœ˜—šžœžœ.žœ˜:KšœBžœ ˜QKšžœ˜Kšœ˜—Jšžœ˜—Jšœ0™0šžœžœžœž˜)šžœ=žœ˜CJšžœžœ"˜;—šžœAžœ˜GJšžœžœ&˜C—Jšžœ˜—Jšœ™Jšœ&žœ ˜ÉJšœ™šžœžœžœž˜,JšœN˜NJšžœ žœžœžœ˜JšœW˜WJšœ˜Jšžœ˜—J™Jšœ>˜>J™-JšœP˜PJ˜——™šŸœžœ žœ˜!šžœžœž˜Kšœžœ(˜DKšžœ˜—K˜K˜�—šŸœžœžœžœžœžœ˜XKšžœ'žœžœžœ˜=šžœžœ˜&KšœF˜FKšžœžœ˜K˜—Kšžœžœ˜ Kšœ˜—K˜�šŸœžœžœžœžœžœ˜Qšžœ žœžœ˜Kšœ<˜<Kšžœžœ˜K˜—šžœ žœ˜KšœC˜CKšžœžœ˜K˜—Kšžœžœ˜ Kšœ˜—K˜�K˜�šŸœžœžœžœžœžœ˜Aš žœžœžœžœž˜(Kšžœ%žœžœ˜EKšžœ˜—K˜K˜�—šŸœžœžœ žœžœžœžœ˜YKšœžœ˜Kšœžœžœ˜ Kšœ˜šžœ žœž˜Kšœ`˜`šžœžœž˜Kšœ<˜<Kšœ"žœ˜BKšžœžœ˜-—K˜Kšžœ˜—K˜�šžœžœ˜KšœA˜Ašžœžœž˜9Kšœžœ˜"KšœA˜AKšžœ˜—K˜—J˜�Jšœ&˜&K˜——™JšŸ œžœžœ™dL™ KšœC˜CKšœO˜OKšœ1˜1Kšœ-žœg (™¾L™KšœAžœ˜FKšœO˜OKšœc˜cKšœ[˜[KšœM˜MKšœ[˜[KšœA˜AL™KšœOžœ˜TKšœ]˜]KšœY˜YL™%KšœTžœ˜YKšœ]˜]KšœI˜IKšœM˜ML™Kšœi˜iKšœU˜UKšœY˜YKšœg˜gKšœS˜SKšœW˜WK˜�Kšžœ˜——�…—����}‚��¨ ��