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šžœ˜——�…—����}‚��¨	��